Merge "Camera: Add doc for combined stream usage flags"
diff --git a/audio/2.0/default/StreamIn.cpp b/audio/2.0/default/StreamIn.cpp
index a8229d3..b641e82 100644
--- a/audio/2.0/default/StreamIn.cpp
+++ b/audio/2.0/default/StreamIn.cpp
@@ -103,7 +103,6 @@
     // This implementation doesn't return control back to the Thread until it decides to stop,
     // as the Thread uses mutexes, and this can lead to priority inversion.
     while(!std::atomic_load_explicit(mStop, std::memory_order_acquire)) {
-        // TODO: Remove manual event flag handling once blocking MQ is implemented. b/33815422
         uint32_t efState = 0;
         mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL), &efState);
         if (!(efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_FULL))) {
@@ -321,7 +320,6 @@
                 CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(), threadInfo);
         return Void();
     }
-    // TODO: Remove event flag management once blocking MQ is implemented. b/33815422
     status = EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &mEfGroup);
     if (status != OK || !mEfGroup) {
         ALOGE("failed creating event flag for data MQ: %s", strerror(-status));
diff --git a/audio/2.0/default/StreamOut.cpp b/audio/2.0/default/StreamOut.cpp
index 6ccdbcd..d820f3c 100644
--- a/audio/2.0/default/StreamOut.cpp
+++ b/audio/2.0/default/StreamOut.cpp
@@ -101,7 +101,6 @@
     // This implementation doesn't return control back to the Thread until it decides to stop,
     // as the Thread uses mutexes, and this can lead to priority inversion.
     while(!std::atomic_load_explicit(mStop, std::memory_order_acquire)) {
-        // TODO: Remove manual event flag handling once blocking MQ is implemented. b/33815422
         uint32_t efState = 0;
         mEfGroup->wait(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY), &efState);
         if (!(efState & static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY))) {
@@ -304,7 +303,6 @@
                 CommandMQ::Descriptor(), DataMQ::Descriptor(), StatusMQ::Descriptor(), threadInfo);
         return Void();
     }
-    // TODO: Remove event flag management once blocking MQ is implemented. b/33815422
     status = EventFlag::createEventFlag(tempDataMQ->getEventFlagWord(), &mEfGroup);
     if (status != OK || !mEfGroup) {
         ALOGE("failed creating event flag for data MQ: %s", strerror(-status));
diff --git a/audio/2.0/vts/functional/AudioPrimaryHidlHalTest.cpp b/audio/2.0/vts/functional/AudioPrimaryHidlHalTest.cpp
index 6270c9c..1021569 100644
--- a/audio/2.0/vts/functional/AudioPrimaryHidlHalTest.cpp
+++ b/audio/2.0/vts/functional/AudioPrimaryHidlHalTest.cpp
@@ -769,6 +769,9 @@
 TEST_IO_STREAM(SetHwAvSync, "Try to set hardware sync to an invalid value",
                ASSERT_RESULT(invalidArgsOrNotSupported, stream->setHwAvSync(666)))
 
+TEST_IO_STREAM(GetHwAvSync, "Get hardware sync can not fail",
+               ASSERT_TRUE(device->getHwAvSync().isOk()))
+
 static void checkGetParameter(IStream* stream, hidl_vec<hidl_string> keys,
                               vector<Result> expectedResults) {
     hidl_vec<ParameterValue> parameters;
@@ -915,6 +918,14 @@
     testPrepareForReading(stream.get(), uintMax, uintMax);
 }
 
+TEST_P(InputStreamTest, GetInputFramesLost) {
+    doc::test("The number of frames lost on a never started stream should be 0");
+    auto ret = stream->getInputFramesLost();
+    ASSERT_TRUE(ret.isOk());
+    uint32_t framesLost{ret};
+    ASSERT_EQ(0U, framesLost);
+}
+
 TEST_P(InputStreamTest, getCapturePosition) {
     doc::test("The capture position of a non prepared stream should not be retrievable");
     uint64_t frames;
@@ -995,13 +1006,12 @@
 
 TEST_P(OutputStreamTest, GetNextWriteTimestamp) {
     uint64_t timestampUs;
-    ASSERT_OK(stream->getRenderPosition(returnIn(res, timestampUs)));
+    ASSERT_OK(stream->getNextWriteTimestamp(returnIn(res, timestampUs)));
     if (res == Result::NOT_SUPPORTED) {
-        doc::partialTest("getRenderPosition is not supported");
+        doc::partialTest("getNextWriteTimestamp is not supported");
         return;
     }
-    ASSERT_OK(res);
-    ASSERT_EQ(0U, timestampUs);
+    ASSERT_EQ(Result::INVALID_STATE, res);
 }
 
 /** Stub implementation of out stream callback. */
@@ -1071,13 +1081,13 @@
 }
 
 TEST_P(OutputStreamTest, FlushStop) {
-    ASSERT_OK(stream->flush());
-}
-
-/** Return thee difference in us of two TimeSpec */
-uint64_t operator-(TimeSpec left, TimeSpec right) {
-    auto toMicroSec = [](auto ts) { return ts.tvSec * 1e+6 + ts.tvNSec / 1e+3; };
-    return toMicroSec(left) - toMicroSec(right);
+    auto ret = stream->flush();
+    ASSERT_TRUE(ret.isOk());
+    if (ret == Result::NOT_SUPPORTED) {
+        doc::partialTest("Flush is not supported");
+        return;
+    }
+    ASSERT_OK(ret);
 }
 
 TEST_P(OutputStreamTest, GetPresentationPositionStop) {
diff --git a/audio/common/2.0/types.hal b/audio/common/2.0/types.hal
index 8760a58..dd7281d 100644
--- a/audio/common/2.0/types.hal
+++ b/audio/common/2.0/types.hal
@@ -89,7 +89,6 @@
 enum AudioStreamType : int32_t {
     // These values must kept in sync with
     //  frameworks/base/media/java/android/media/AudioSystem.java
-    // TODO: Synchronization should be done automatically by tools
     DEFAULT          = -1,
     MIN              = 0,
     VOICE_CALL       = 0,
@@ -169,10 +168,8 @@
     OUTPUT_MIX = 0,
     /*
      * Application does not specify an explicit session ID to be used, and
-     * requests a new session ID to be allocated TODO use unique values for
-     * AUDIO_SESSION_OUTPUT_MIX and AUDIO_SESSION_ALLOCATE, after all uses have
-     * been updated from 0 to the appropriate symbol, and have been tested.
-     * Corresponds to AudioManager.AUDIO_SESSION_ID_GENERATE and
+     * requests a new session ID to be allocated. Corresponds to
+     * AudioManager.AUDIO_SESSION_ID_GENERATE and
      * AudioSystem.AUDIO_SESSION_ALLOCATE.
      */
     ALLOCATE = 0,
@@ -565,6 +562,7 @@
             OUT_IP |
             OUT_BUS |
             OUT_PROXY |
+            OUT_USB_HEADSET |
             OUT_DEFAULT),
     OUT_ALL_A2DP = (OUT_BLUETOOTH_A2DP |
             OUT_BLUETOOTH_A2DP_HEADPHONES |
@@ -572,7 +570,7 @@
     OUT_ALL_SCO  = (OUT_BLUETOOTH_SCO |
             OUT_BLUETOOTH_SCO_HEADSET |
             OUT_BLUETOOTH_SCO_CARKIT),
-    OUT_ALL_USB  = (OUT_USB_ACCESSORY | OUT_USB_DEVICE),
+    OUT_ALL_USB  = (OUT_USB_ACCESSORY | OUT_USB_DEVICE | OUT_USB_HEADSET),
     /* input devices */
     IN_COMMUNICATION         = BIT_IN | 0x1,
     IN_AMBIENT               = BIT_IN | 0x2,
@@ -629,9 +627,10 @@
             IN_IP |
             IN_BUS |
             IN_PROXY |
+            IN_USB_HEADSET |
             IN_DEFAULT),
     IN_ALL_SCO = IN_BLUETOOTH_SCO_HEADSET,
-    IN_ALL_USB  = (IN_USB_ACCESSORY | IN_USB_DEVICE),
+    IN_ALL_USB  = (IN_USB_ACCESSORY | IN_USB_DEVICE | IN_USB_HEADSET),
 };
 
 /*
@@ -696,7 +695,6 @@
 enum AudioUsage : int32_t {
     // These values must kept in sync with
     //  frameworks/base/media/java/android/media/AudioAttributes.java
-    // TODO: Synchronization should be done automatically by tools
     UNKNOWN                            = 0,
     MEDIA                              = 1,
     VOICE_COMMUNICATION                = 2,
diff --git a/audio/effect/2.0/IEffectBufferProviderCallback.hal b/audio/effect/2.0/IEffectBufferProviderCallback.hal
index 545e2e5..53f4d6e 100644
--- a/audio/effect/2.0/IEffectBufferProviderCallback.hal
+++ b/audio/effect/2.0/IEffectBufferProviderCallback.hal
@@ -27,7 +27,6 @@
      *
      * @return buffer audio buffer for processing
      */
-    // TODO(mnaganov): replace with FMQ version.
     getBuffer() generates (AudioBuffer buffer);
 
     /*
@@ -35,6 +34,5 @@
      *
      * @param buffer audio buffer for processing
      */
-    // TODO(mnaganov): replace with FMQ version.
     putBuffer(AudioBuffer buffer);
 };
diff --git a/audio/effect/2.0/default/Effect.cpp b/audio/effect/2.0/default/Effect.cpp
index 6704239..2d36604 100644
--- a/audio/effect/2.0/default/Effect.cpp
+++ b/audio/effect/2.0/default/Effect.cpp
@@ -205,7 +205,7 @@
     halConfig->buffer.raw = NULL;
     halConfig->samplingRate = config.samplingRateHz;
     halConfig->channels = static_cast<uint32_t>(config.channels);
-    // TODO(mnaganov): The framework code currently does not use BP, implement later.
+    // Note: The framework code does not use BP.
     halConfig->bufferProvider.cookie = NULL;
     halConfig->bufferProvider.getBuffer = NULL;
     halConfig->bufferProvider.releaseBuffer = NULL;
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.cpp
index e6a3e56..03a65f3 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.cpp
@@ -104,7 +104,7 @@
 
         for (auto& prop : mProps) {
             emulator::VehiclePropValue* protoVal = respMsg.add_value();
-            populateProtoVehiclePropValue(protoVal, prop.second.get());
+            populateProtoVehiclePropValue(protoVal, prop.second->get());
         }
     }
 }
@@ -175,7 +175,7 @@
 
     auto prop = mProps.find(std::make_pair(propId, areaId));
     if (prop != mProps.end()) {
-        return prop->second.get();
+        return prop->second->get();
     }
     ALOGW("%s: Property not found:  propId = 0x%x, areaId = 0x%x", __func__, propId, areaId);
     return nullptr;
@@ -530,6 +530,13 @@
     return status;
 }
 
+V2_0::StatusCode DefaultVehicleHal::addCustomProperty(int32_t property,
+    std::unique_ptr<CustomVehiclePropertyHandler>&& handler) {
+    mProps[std::make_pair(property, 0)] = std::move(handler);
+    ALOGW("%s: Added custom property: propId = 0x%x", __func__, property);
+    return StatusCode::OK;
+}
+
 // Parse supported properties list and generate vector of property values to hold current values.
 void DefaultVehicleHal::onCreate() {
     // Initialize member variables
@@ -598,7 +605,11 @@
             prop->areaId = curArea;
             prop->prop = cfg.prop;
             setDefaultValue(prop.get());
-            mProps[std::make_pair(prop->prop, prop->areaId)] = std::move(prop);
+            std::unique_ptr<CustomVehiclePropertyHandler> handler;
+            handler.reset(new StoredValueCustomVehiclePropertyHandler());
+            handler->set(*prop);
+            mProps[std::make_pair(prop->prop, prop->areaId)] =
+                    std::move(handler);
         } while (supportedAreas != 0);
     }
 
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.h
index bbbe955..c8310b3 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultVehicleHal.h
@@ -44,7 +44,31 @@
 
 class DefaultVehicleHal : public VehicleHal {
 public:
-    DefaultVehicleHal() : mRecurrentTimer(
+    class CustomVehiclePropertyHandler {
+    public:
+        virtual VehiclePropValue* get() = 0;
+        virtual StatusCode set(const VehiclePropValue& propValue) = 0;
+        virtual ~CustomVehiclePropertyHandler() = default;
+    };
+
+protected:
+    class StoredValueCustomVehiclePropertyHandler :
+        public CustomVehiclePropertyHandler {
+    public:
+        VehiclePropValue* get() override {
+            return mPropValue.get();
+        }
+
+        StatusCode set(const VehiclePropValue& propValue) {
+            *mPropValue = propValue;
+            return StatusCode::OK;
+        }
+private:
+    std::unique_ptr<VehiclePropValue> mPropValue{new VehiclePropValue()};
+};
+
+public:
+  DefaultVehicleHal() : mRecurrentTimer(
             std::bind(&DefaultVehicleHal::onContinuousPropertyTimer, this, std::placeholders::_1)) {
         for (size_t i = 0; i < arraysize(kVehicleProperties); i++) {
             mPropConfigMap[kVehicleProperties[i].prop] = &kVehicleProperties[i];
@@ -77,6 +101,43 @@
 
     StatusCode unsubscribe(int32_t property) override;
 
+    /**
+     * Add custom property information to this HAL instance.
+     *
+     * This is useful for allowing later versions of Vehicle HAL to coalesce
+     * the list of properties they support with a previous version of the HAL.
+     *
+     * @param property The identifier of the new property
+     * @param handler The object that will handle get/set requests
+     * @return OK on success, an error code on failure
+     */
+    virtual StatusCode addCustomProperty(int32_t,
+        std::unique_ptr<CustomVehiclePropertyHandler>&&);
+
+    /**
+     * Add custom property information to this HAL instance.
+     *
+     * This is useful for allowing later versions of Vehicle HAL to coalesce
+     * the list of properties they support with a previous version of the HAL.
+     *
+     * @param initialValue The initial value for the new property. This is not
+     *                     constant data, as later set() operations can change
+     *                     this value at will
+     * @return OK on success, an error code on failure
+     */
+    virtual StatusCode addCustomProperty(
+        const VehiclePropValue& initialValue) {
+        std::unique_ptr<CustomVehiclePropertyHandler> handler;
+        handler.reset(new StoredValueCustomVehiclePropertyHandler());
+        StatusCode setResponse = handler->set(initialValue);
+        if (StatusCode::OK == setResponse) {
+          return addCustomProperty(initialValue.prop,
+                                   std::move(handler));
+        } else {
+          return setResponse;
+        }
+    }
+
 private:
     void doGetConfig(emulator::EmulatorMessage& rxMsg, emulator::EmulatorMessage& respMsg);
     void doGetConfigAll(emulator::EmulatorMessage& rxMsg, emulator::EmulatorMessage& respMsg);
@@ -106,7 +167,7 @@
 private:
     std::map<
         std::pair<int32_t /*VehicleProperty*/, int32_t /*areaId*/>,
-        std::unique_ptr<VehiclePropValue>> mProps;
+        std::unique_ptr<CustomVehiclePropertyHandler>> mProps;
     std::atomic<int> mExit;
     std::unordered_set<int32_t> mHvacPowerProps;
     std::mutex mPropsMutex;
diff --git a/automotive/vehicle/2.1/Android.bp b/automotive/vehicle/2.1/Android.bp
index dcf395c..cf4d8b0 100644
--- a/automotive/vehicle/2.1/Android.bp
+++ b/automotive/vehicle/2.1/Android.bp
@@ -51,6 +51,7 @@
         "libutils",
         "libcutils",
         "android.hardware.automotive.vehicle@2.0",
+        "android.hidl.base@1.0",
     ],
     export_shared_lib_headers: [
         "libhidlbase",
@@ -58,5 +59,6 @@
         "libhwbinder",
         "libutils",
         "android.hardware.automotive.vehicle@2.0",
+        "android.hidl.base@1.0",
     ],
 }
diff --git a/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultVehicleHal.cpp b/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultVehicleHal.cpp
index d4eae7f..b147ce7 100644
--- a/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultVehicleHal.cpp
+++ b/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultVehicleHal.cpp
@@ -120,12 +120,12 @@
     return sensorStore;
 }
 
-void DefaultVehicleHal::initObd2LiveFrame(V2_0::VehiclePropConfig& propConfig) {
+void DefaultVehicleHal::initObd2LiveFrame(V2_0::VehiclePropConfig& propConfig,
+    V2_0::VehiclePropValue* liveObd2Frame) {
     auto sensorStore = fillDefaultObd2Frame(propConfig.configArray[0],
             propConfig.configArray[1]);
-    mLiveObd2Frame = createVehiclePropValue(
-            V2_0::VehiclePropertyType::COMPLEX, 0);
-    sensorStore->fillPropValue(mLiveObd2Frame.get(), "");
+    sensorStore->fillPropValue(liveObd2Frame, "");
+    liveObd2Frame->prop = V2_0::toInt(VehicleProperty::OBD2_LIVE_FRAME);
 }
 
 void DefaultVehicleHal::initObd2FreezeFrame(V2_0::VehiclePropConfig& propConfig) {
@@ -144,14 +144,6 @@
     sensorStore->fillPropValue(mFreezeObd2Frames[2].get(), "P0123");
 }
 
-V2_0::StatusCode DefaultVehicleHal::fillObd2LiveFrame(V2_0::VehiclePropValue* v) {
-    v->prop = V2_0::toInt(VehicleProperty::OBD2_LIVE_FRAME);
-    v->value.int32Values = mLiveObd2Frame->value.int32Values;
-    v->value.floatValues = mLiveObd2Frame->value.floatValues;
-    v->value.bytes = mLiveObd2Frame->value.bytes;
-    return V2_0::StatusCode::OK;
-}
-
 template<typename Iterable>
 typename Iterable::const_iterator findPropValueAtTimestamp(
         const Iterable& frames,
@@ -224,8 +216,11 @@
     std::vector<V2_0::VehiclePropConfig> configs = listProperties();
     for (auto& cfg : configs) {
         switch(cfg.prop) {
-            case V2_0::toInt(V2_1::VehicleProperty::OBD2_LIVE_FRAME):
-                initObd2LiveFrame(cfg);
+            case V2_0::toInt(V2_1::VehicleProperty::OBD2_LIVE_FRAME): {
+                auto liveObd2Frame = createVehiclePropValue(V2_0::VehiclePropertyType::COMPLEX, 0);
+                initObd2LiveFrame(cfg, liveObd2Frame.get());
+                mVehicleHal20->addCustomProperty(*liveObd2Frame);
+            }
                 break;
             case V2_0::toInt(V2_1::VehicleProperty::OBD2_FREEZE_FRAME):
                 initObd2FreezeFrame(cfg);
@@ -245,10 +240,6 @@
     auto& pool = *getValuePool();
 
     switch (propId) {
-    case V2_0::toInt(V2_1::VehicleProperty::OBD2_LIVE_FRAME):
-        v = pool.obtainComplex();
-        *outStatus = fillObd2LiveFrame(v.get());
-        return v;
     case V2_0::toInt(V2_1::VehicleProperty::OBD2_FREEZE_FRAME):
         v = pool.obtainComplex();
         *outStatus = fillObd2FreezeFrame(requestedPropValue, v.get());
diff --git a/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultVehicleHal.h b/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultVehicleHal.h
index ac65fc6..af21138 100644
--- a/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultVehicleHal.h
+++ b/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultVehicleHal.h
@@ -39,7 +39,8 @@
 
 class DefaultVehicleHal : public V2_0::VehicleHal {
 public:
-    DefaultVehicleHal(V2_0::VehicleHal* vhal20) : mVehicleHal20(vhal20) {}
+    DefaultVehicleHal(V2_0::impl::DefaultVehicleHal* vhal20) :
+          mVehicleHal20(vhal20) {}
 
     std::vector<V2_0::VehiclePropConfig> listProperties() override {
         std::vector<V2_0::VehiclePropConfig> propConfigs(mVehicleHal20->listProperties());
@@ -70,17 +71,16 @@
     void onCreate() override;
 
 private:
-    void initObd2LiveFrame(V2_0::VehiclePropConfig& propConfig);
+    void initObd2LiveFrame(V2_0::VehiclePropConfig& propConfig,
+        V2_0::VehiclePropValue* liveObd2Frame);
     void initObd2FreezeFrame(V2_0::VehiclePropConfig& propConfig);
-    V2_0::StatusCode fillObd2LiveFrame(V2_0::VehiclePropValue* v);
     V2_0::StatusCode fillObd2FreezeFrame(const V2_0::VehiclePropValue& requestedPropValue,
             V2_0::VehiclePropValue* v);
     V2_0::StatusCode fillObd2DtcInfo(V2_0::VehiclePropValue *v);
     V2_0::StatusCode clearObd2FreezeFrames(const V2_0::VehiclePropValue& propValue);
 
 private:
-    V2_0::VehicleHal* mVehicleHal20;
-    std::unique_ptr<V2_0::VehiclePropValue> mLiveObd2Frame {nullptr};
+    V2_0::impl::DefaultVehicleHal* mVehicleHal20;
     std::vector<std::unique_ptr<V2_0::VehiclePropValue>> mFreezeObd2Frames;
 };
 
diff --git a/biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp b/biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp
index b106481..5b00675 100644
--- a/biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp
+++ b/biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp
@@ -264,27 +264,35 @@
         case FINGERPRINT_ERROR: {
                 int32_t vendorCode = 0;
                 FingerprintError result = VendorErrorFilter(msg->data.error, &vendorCode);
-                thisPtr->mClientCallback->onError(devId, result, vendorCode);
+                if (!thisPtr->mClientCallback->onError(devId, result, vendorCode).isOk()) {
+                    ALOGE("failed to invoke fingerprint onError callback");
+                }
             }
             break;
         case FINGERPRINT_ACQUIRED: {
                 int32_t vendorCode = 0;
                 FingerprintAcquiredInfo result =
                     VendorAcquiredFilter(msg->data.acquired.acquired_info, &vendorCode);
-                thisPtr->mClientCallback->onAcquired(devId, result, vendorCode);
+                if (!thisPtr->mClientCallback->onAcquired(devId, result, vendorCode).isOk()) {
+                    ALOGE("failed to invoke fingerprint onAcquired callback");
+                }
             }
             break;
         case FINGERPRINT_TEMPLATE_ENROLLING:
-            thisPtr->mClientCallback->onEnrollResult(devId,
-                msg->data.enroll.finger.fid,
-                msg->data.enroll.finger.gid,
-                msg->data.enroll.samples_remaining);
+            if (!thisPtr->mClientCallback->onEnrollResult(devId,
+                    msg->data.enroll.finger.fid,
+                    msg->data.enroll.finger.gid,
+                    msg->data.enroll.samples_remaining).isOk()) {
+                ALOGE("failed to invoke fingerprint onEnrollResult callback");
+            }
             break;
         case FINGERPRINT_TEMPLATE_REMOVED:
-            thisPtr->mClientCallback->onRemoved(devId,
-                msg->data.removed.finger.fid,
-                msg->data.removed.finger.gid,
-                msg->data.removed.remaining_templates);
+            if (!thisPtr->mClientCallback->onRemoved(devId,
+                    msg->data.removed.finger.fid,
+                    msg->data.removed.finger.gid,
+                    msg->data.removed.remaining_templates).isOk()) {
+                ALOGE("failed to invoke fingerprint onRemoved callback");
+            }
             break;
         case FINGERPRINT_AUTHENTICATED:
             if (msg->data.authenticated.finger.fid != 0) {
@@ -292,23 +300,29 @@
                     reinterpret_cast<const uint8_t *>(&msg->data.authenticated.hat);
                 const hidl_vec<uint8_t> token(
                     std::vector<uint8_t>(hat, hat + sizeof(msg->data.authenticated.hat)));
-                thisPtr->mClientCallback->onAuthenticated(devId,
-                    msg->data.authenticated.finger.fid,
-                    msg->data.authenticated.finger.gid,
-                    token);
+                if (!thisPtr->mClientCallback->onAuthenticated(devId,
+                        msg->data.authenticated.finger.fid,
+                        msg->data.authenticated.finger.gid,
+                        token).isOk()) {
+                    ALOGE("failed to invoke fingerprint onAuthenticated callback");
+                }
             } else {
                 // Not a recognized fingerprint
-                thisPtr->mClientCallback->onAuthenticated(devId,
-                    msg->data.authenticated.finger.fid,
-                    msg->data.authenticated.finger.gid,
-                    hidl_vec<uint8_t>());
+                if (!thisPtr->mClientCallback->onAuthenticated(devId,
+                        msg->data.authenticated.finger.fid,
+                        msg->data.authenticated.finger.gid,
+                        hidl_vec<uint8_t>()).isOk()) {
+                    ALOGE("failed to invoke fingerprint onAuthenticated callback");
+                }
             }
             break;
         case FINGERPRINT_TEMPLATE_ENUMERATING:
-            thisPtr->mClientCallback->onEnumerate(devId,
-                msg->data.enumerated.finger.fid,
-                msg->data.enumerated.finger.gid,
-                msg->data.enumerated.remaining_templates);
+            if (!thisPtr->mClientCallback->onEnumerate(devId,
+                    msg->data.enumerated.finger.fid,
+                    msg->data.enumerated.finger.gid,
+                    msg->data.enumerated.remaining_templates).isOk()) {
+                ALOGE("failed to invoke fingerprint onEnumerate callback");
+            }
             break;
     }
 }
diff --git a/bluetooth/1.0/default/bluetooth_hci.cc b/bluetooth/1.0/default/bluetooth_hci.cc
index 5a282bf..8eccfc7 100644
--- a/bluetooth/1.0/default/bluetooth_hci.cc
+++ b/bluetooth/1.0/default/bluetooth_hci.cc
@@ -15,9 +15,10 @@
 //
 
 #define LOG_TAG "android.hardware.bluetooth@1.0-impl"
+#include "bluetooth_hci.h"
+
 #include <utils/Log.h>
 
-#include "bluetooth_hci.h"
 #include "vendor_interface.h"
 
 namespace android {
@@ -30,36 +31,85 @@
 static const uint8_t HCI_DATA_TYPE_ACL = 2;
 static const uint8_t HCI_DATA_TYPE_SCO = 3;
 
+class BluetoothDeathRecipient : public hidl_death_recipient {
+ public:
+  BluetoothDeathRecipient(const sp<IBluetoothHci> hci) : mHci(hci) {}
+
+  virtual void serviceDied(
+      uint64_t /*cookie*/,
+      const wp<::android::hidl::base::V1_0::IBase>& /*who*/) {
+    ALOGE("BluetoothDeathRecipient::serviceDied - Bluetooth service died");
+    has_died_ = true;
+    mHci->close();
+  }
+  sp<IBluetoothHci> mHci;
+  bool getHasDied() const { return has_died_; }
+  void setHasDied(bool has_died) { has_died_ = has_died; }
+
+ private:
+  bool has_died_;
+};
+
 BluetoothHci::BluetoothHci()
-    : deathRecipient(new BluetoothDeathRecipient(this)) {}
+    : death_recipient_(new BluetoothDeathRecipient(this)) {}
 
 Return<void> BluetoothHci::initialize(
     const ::android::sp<IBluetoothHciCallbacks>& cb) {
-  ALOGW("BluetoothHci::initialize()");
-  cb->linkToDeath(deathRecipient, 0);
-  event_cb_ = cb;
+  ALOGI("BluetoothHci::initialize()");
+  if (cb == nullptr) {
+    ALOGE("cb == nullptr! -> Unable to call initializationComplete(ERR)");
+    return Void();
+  }
+
+  death_recipient_->setHasDied(false);
+  cb->linkToDeath(death_recipient_, 0);
 
   bool rc = VendorInterface::Initialize(
-      [this](bool status) {
-        event_cb_->initializationComplete(
+      [cb](bool status) {
+        auto hidl_status = cb->initializationComplete(
             status ? Status::SUCCESS : Status::INITIALIZATION_ERROR);
+        if (!hidl_status.isOk()) {
+          ALOGE("VendorInterface -> Unable to call initializationComplete()");
+        }
       },
-      [this](const hidl_vec<uint8_t>& packet) {
-        event_cb_->hciEventReceived(packet);
+      [cb](const hidl_vec<uint8_t>& packet) {
+        auto hidl_status = cb->hciEventReceived(packet);
+        if (!hidl_status.isOk()) {
+          ALOGE("VendorInterface -> Unable to call hciEventReceived()");
+        }
       },
-      [this](const hidl_vec<uint8_t>& packet) {
-        event_cb_->aclDataReceived(packet);
+      [cb](const hidl_vec<uint8_t>& packet) {
+        auto hidl_status = cb->aclDataReceived(packet);
+        if (!hidl_status.isOk()) {
+          ALOGE("VendorInterface -> Unable to call aclDataReceived()");
+        }
       },
-      [this](const hidl_vec<uint8_t>& packet) {
-        event_cb_->scoDataReceived(packet);
+      [cb](const hidl_vec<uint8_t>& packet) {
+        auto hidl_status = cb->scoDataReceived(packet);
+        if (!hidl_status.isOk()) {
+          ALOGE("VendorInterface -> Unable to call scoDataReceived()");
+        }
       });
-  if (!rc) event_cb_->initializationComplete(Status::INITIALIZATION_ERROR);
+  if (!rc) {
+    auto hidl_status = cb->initializationComplete(Status::INITIALIZATION_ERROR);
+    if (!hidl_status.isOk()) {
+      ALOGE("VendorInterface -> Unable to call initializationComplete(ERR)");
+    }
+  }
+
+  unlink_cb_ = [cb](sp<BluetoothDeathRecipient>& death_recipient) {
+    if (death_recipient->getHasDied())
+      ALOGI("Skipping unlink call, service died.");
+    else
+      cb->unlinkToDeath(death_recipient);
+  };
+
   return Void();
 }
 
 Return<void> BluetoothHci::close() {
-  ALOGW("BluetoothHci::close()");
-  event_cb_->unlinkToDeath(deathRecipient);
+  ALOGI("BluetoothHci::close()");
+  unlink_cb_(death_recipient_);
   VendorInterface::Shutdown();
   return Void();
 }
diff --git a/bluetooth/1.0/default/bluetooth_hci.h b/bluetooth/1.0/default/bluetooth_hci.h
index 67d6c37..6912405 100644
--- a/bluetooth/1.0/default/bluetooth_hci.h
+++ b/bluetooth/1.0/default/bluetooth_hci.h
@@ -30,16 +30,7 @@
 using ::android::hardware::Return;
 using ::android::hardware::hidl_vec;
 
-struct BluetoothDeathRecipient : hidl_death_recipient {
-  BluetoothDeathRecipient(const sp<IBluetoothHci> hci) : mHci(hci) {}
-
-  virtual void serviceDied(
-      uint64_t /*cookie*/,
-      const wp<::android::hidl::base::V1_0::IBase>& /*who*/) {
-    mHci->close();
-  }
-  sp<IBluetoothHci> mHci;
-};
+class BluetoothDeathRecipient;
 
 class BluetoothHci : public IBluetoothHci {
  public:
@@ -53,8 +44,8 @@
 
  private:
   void sendDataToController(const uint8_t type, const hidl_vec<uint8_t>& data);
-  ::android::sp<IBluetoothHciCallbacks> event_cb_;
-  ::android::sp<BluetoothDeathRecipient> deathRecipient;
+  ::android::sp<BluetoothDeathRecipient> death_recipient_;
+  std::function<void(sp<BluetoothDeathRecipient>&)> unlink_cb_;
 };
 
 extern "C" IBluetoothHci* HIDL_FETCH_IBluetoothHci(const char* name);
diff --git a/broadcastradio/1.1/Android.bp b/broadcastradio/1.1/Android.bp
index c9a8b10..570d1ae 100644
--- a/broadcastradio/1.1/Android.bp
+++ b/broadcastradio/1.1/Android.bp
@@ -65,6 +65,7 @@
         "libutils",
         "libcutils",
         "android.hardware.broadcastradio@1.0",
+        "android.hidl.base@1.0",
     ],
     export_shared_lib_headers: [
         "libhidlbase",
@@ -72,5 +73,6 @@
         "libhwbinder",
         "libutils",
         "android.hardware.broadcastradio@1.0",
+        "android.hidl.base@1.0",
     ],
 }
diff --git a/camera/device/3.2/ICameraDeviceCallback.hal b/camera/device/3.2/ICameraDeviceCallback.hal
index 753d085..bf51da2 100644
--- a/camera/device/3.2/ICameraDeviceCallback.hal
+++ b/camera/device/3.2/ICameraDeviceCallback.hal
@@ -35,7 +35,8 @@
     /**
      * processCaptureResult:
      *
-     * Send results from a completed capture to the framework.
+     * Send results from one or more completed or partially completed captures
+     * to the framework.
      * processCaptureResult() may be invoked multiple times by the HAL in
      * response to a single capture request. This allows, for example, the
      * metadata and low-resolution buffers to be returned in one call, and
@@ -61,11 +62,14 @@
      * acceptable and expected that the buffer for request 5 for stream A may be
      * returned after the buffer for request 6 for stream B is. And it is
      * acceptable that the result metadata for request 6 for stream B is
-     * returned before the buffer for request 5 for stream A is.
+     * returned before the buffer for request 5 for stream A is. If multiple
+     * capture results are included in a single call, camera framework must
+     * process results sequentially from lower index to higher index, as if
+     * these results were sent to camera framework one by one, from lower index
+     * to higher index.
      *
      * The HAL retains ownership of result structure, which only needs to be
-     * valid to access during this call. The framework must copy whatever it
-     * needs before this call returns.
+     * valid to access during this call.
      *
      * The output buffers do not need to be filled yet; the framework must wait
      * on the stream buffer release sync fence before reading the buffer
@@ -93,20 +97,23 @@
      *
      * Performance requirements:
      *
-     * This is a non-blocking call. The framework must return this call in 5ms.
+     * This is a non-blocking call. The framework must handle each CaptureResult
+     * within 5ms.
      *
      * The pipeline latency (see S7 for definition) should be less than or equal to
      * 4 frame intervals, and must be less than or equal to 8 frame intervals.
      *
      */
-    processCaptureResult(CaptureResult result);
+    processCaptureResult(vec<CaptureResult> results);
 
     /**
      * notify:
      *
      * Asynchronous notification callback from the HAL, fired for various
      * reasons. Only for information independent of frame capture, or that
-     * require specific timing.
+     * require specific timing. Multiple messages may be sent in one call; a
+     * message with a higher index must be considered to have occurred after a
+     * message with a lower index.
      *
      * Multiple threads may call notify() simultaneously.
      *
@@ -119,8 +126,8 @@
      * ------------------------------------------------------------------------
      * Performance requirements:
      *
-     * This is a non-blocking call. The framework must return this call in 5ms.
+     * This is a non-blocking call. The framework must handle each message in 5ms.
      */
-    notify(NotifyMsg msg);
+    notify(vec<NotifyMsg> msgs);
 
 };
diff --git a/camera/device/3.2/ICameraDeviceSession.hal b/camera/device/3.2/ICameraDeviceSession.hal
index a4816b4..e186c8d 100644
--- a/camera/device/3.2/ICameraDeviceSession.hal
+++ b/camera/device/3.2/ICameraDeviceSession.hal
@@ -172,14 +172,16 @@
     /**
      * processCaptureRequest:
      *
-     * Send a new capture request to the HAL. The HAL must not return from
-     * this call until it is ready to accept the next request to process. Only
-     * one call to processCaptureRequest() must be made at a time by the
-     * framework, and the calls must all be from the same thread. The next call
-     * to processCaptureRequest() must be made as soon as a new request and
-     * its associated buffers are available. In a normal preview scenario, this
-     * means the function is generally called again by the framework almost
-     * instantly.
+     * Send a list of capture requests to the HAL. The HAL must not return from
+     * this call until it is ready to accept the next set of requests to
+     * process. Only one call to processCaptureRequest() must be made at a time
+     * by the framework, and the calls must all be from the same thread. The
+     * next call to processCaptureRequest() must be made as soon as a new
+     * request and its associated buffers are available. In a normal preview
+     * scenario, this means the function is generally called again by the
+     * framework almost instantly. If more than one request is provided by the
+     * client, the HAL must process the requests in order of lowest index to
+     * highest index.
      *
      * The actual request processing is asynchronous, with the results of
      * capture being returned by the HAL through the processCaptureResult()
@@ -230,10 +232,14 @@
      *         If the camera device has encountered a serious error. After this
      *         error is returned, only the close() method can be successfully
      *         called by the framework.
+     * @return numRequestProcessed Number of requests successfully processed by
+     *     camera HAL. When status is OK, this must be equal to the size of
+     *     requests. When the call fails, this number is the number of requests
+     *     that HAL processed successfully before HAL runs into an error.
      *
      */
-    processCaptureRequest(CaptureRequest request)
-            generates (Status status);
+    processCaptureRequest(vec<CaptureRequest> requests)
+            generates (Status status, uint32_t numRequestProcessed);
 
     /**
      * flush:
diff --git a/camera/device/3.2/default/CameraDevice.cpp b/camera/device/3.2/default/CameraDevice.cpp
index 0a457ad..a742335 100644
--- a/camera/device/3.2/default/CameraDevice.cpp
+++ b/camera/device/3.2/default/CameraDevice.cpp
@@ -229,7 +229,18 @@
             return Void();
         }
 
-        session = new CameraDeviceSession(device, callback);
+        struct camera_info info;
+        res = mModule->getCameraInfo(mCameraIdInt, &info);
+        if (res != OK) {
+            ALOGE("%s: Could not open camera: getCameraInfo failed", __FUNCTION__);
+            device->common.close(&device->common);
+            mLock.unlock();
+            _hidl_cb(Status::ILLEGAL_ARGUMENT, nullptr);
+            return Void();
+        }
+
+        session = new CameraDeviceSession(
+                device, info.static_camera_characteristics, callback);
         if (session == nullptr) {
             ALOGE("%s: camera device session allocation failed", __FUNCTION__);
             mLock.unlock();
diff --git a/camera/device/3.2/default/CameraDeviceSession.cpp b/camera/device/3.2/default/CameraDeviceSession.cpp
index ae5d576..fb1d1ff 100644
--- a/camera/device/3.2/default/CameraDeviceSession.cpp
+++ b/camera/device/3.2/default/CameraDeviceSession.cpp
@@ -17,6 +17,7 @@
 #define LOG_TAG "CamDevSession@3.2-impl"
 #include <android/log.h>
 
+#include <set>
 #include <utils/Trace.h>
 #include <hardware/gralloc.h>
 #include <hardware/gralloc1.h>
@@ -30,12 +31,25 @@
 namespace implementation {
 
 HandleImporter& CameraDeviceSession::sHandleImporter = HandleImporter::getInstance();
+const int CameraDeviceSession::ResultBatcher::NOT_BATCHED;
 
 CameraDeviceSession::CameraDeviceSession(
-    camera3_device_t* device, const sp<ICameraDeviceCallback>& callback) :
+    camera3_device_t* device,
+    const camera_metadata_t* deviceInfo,
+    const sp<ICameraDeviceCallback>& callback) :
         camera3_callback_ops({&sProcessCaptureResult, &sNotify}),
         mDevice(device),
-        mCallback(callback) {
+        mResultBatcher(callback) {
+
+    mDeviceInfo = deviceInfo;
+    uint32_t numPartialResults = 1;
+    camera_metadata_entry partialResultsCount =
+            mDeviceInfo.find(ANDROID_REQUEST_PARTIAL_RESULT_COUNT);
+    if (partialResultsCount.count > 0) {
+        numPartialResults = partialResultsCount.data.i32[0];
+    }
+    mResultBatcher.setNumPartialResults(numPartialResults);
+
     mInitFail = initialize();
 }
 
@@ -177,6 +191,354 @@
     }
 }
 
+CameraDeviceSession::ResultBatcher::ResultBatcher(
+        const sp<ICameraDeviceCallback>& callback) : mCallback(callback) {};
+
+bool CameraDeviceSession::ResultBatcher::InflightBatch::allDelivered() const {
+    if (!mShutterDelivered) return false;
+
+    if (mPartialResultProgress < mNumPartialResults) {
+        return false;
+    }
+
+    for (const auto& pair : mBatchBufs) {
+        if (!pair.second.mDelivered) {
+            return false;
+        }
+    }
+    return true;
+}
+
+void CameraDeviceSession::ResultBatcher::setNumPartialResults(uint32_t n) {
+    Mutex::Autolock _l(mLock);
+    mNumPartialResults = n;
+}
+
+void CameraDeviceSession::ResultBatcher::setBatchedStreams(
+        const std::vector<int>& streamsToBatch) {
+    Mutex::Autolock _l(mLock);
+    mStreamsToBatch = streamsToBatch;
+}
+
+void CameraDeviceSession::ResultBatcher::registerBatch(
+        const hidl_vec<CaptureRequest>& requests) {
+    auto batch = std::make_shared<InflightBatch>();
+    batch->mFirstFrame = requests[0].frameNumber;
+    batch->mBatchSize = requests.size();
+    batch->mLastFrame = batch->mFirstFrame + batch->mBatchSize - 1;
+    batch->mNumPartialResults = mNumPartialResults;
+    for (int id : mStreamsToBatch) {
+        batch->mBatchBufs[id] = InflightBatch::BufferBatch();
+    }
+    Mutex::Autolock _l(mLock);
+    mInflightBatches.push_back(batch);
+}
+
+std::pair<int, std::shared_ptr<CameraDeviceSession::ResultBatcher::InflightBatch>>
+CameraDeviceSession::ResultBatcher::getBatch(
+        uint32_t frameNumber) {
+    Mutex::Autolock _l(mLock);
+    int numBatches = mInflightBatches.size();
+    if (numBatches == 0) {
+        return std::make_pair(NOT_BATCHED, nullptr);
+    }
+    uint32_t frameMin = mInflightBatches[0]->mFirstFrame;
+    uint32_t frameMax = mInflightBatches[numBatches - 1]->mLastFrame;
+    if (frameNumber < frameMin || frameNumber > frameMax) {
+        return std::make_pair(NOT_BATCHED, nullptr);
+    }
+    for (int i = 0; i < numBatches; i++) {
+        if (frameNumber >= mInflightBatches[i]->mFirstFrame &&
+                frameNumber <= mInflightBatches[i]->mLastFrame) {
+            return std::make_pair(i, mInflightBatches[i]);
+        }
+    }
+    return std::make_pair(NOT_BATCHED, nullptr);
+}
+
+void CameraDeviceSession::ResultBatcher::checkAndRemoveFirstBatch() {
+    Mutex::Autolock _l(mLock);
+    if (mInflightBatches.size() > 0) {
+        std::shared_ptr<InflightBatch> batch = mInflightBatches[0];
+        bool shouldRemove = false;
+        {
+            Mutex::Autolock _l(batch->mLock);
+            if (batch->allDelivered()) {
+                batch->mRemoved = true;
+                shouldRemove = true;
+            }
+        }
+        if (shouldRemove) {
+            mInflightBatches.pop_front();
+        }
+    }
+}
+
+void CameraDeviceSession::ResultBatcher::sendBatchShutterCbsLocked(std::shared_ptr<InflightBatch> batch) {
+    if (batch->mShutterDelivered) {
+        ALOGW("%s: batch shutter callback already sent!", __FUNCTION__);
+        return;
+    }
+
+    mCallback->notify(batch->mShutterMsgs);
+    batch->mShutterDelivered = true;
+    batch->mShutterMsgs.clear();
+}
+
+void CameraDeviceSession::ResultBatcher::freeReleaseFences(hidl_vec<CaptureResult>& results) {
+    for (auto& result : results) {
+        if (result.inputBuffer.releaseFence.getNativeHandle() != nullptr) {
+            native_handle_t* handle = const_cast<native_handle_t*>(
+                    result.inputBuffer.releaseFence.getNativeHandle());
+            native_handle_delete(handle);
+        }
+        for (auto& buf : result.outputBuffers) {
+            if (buf.releaseFence.getNativeHandle() != nullptr) {
+                native_handle_t* handle = const_cast<native_handle_t*>(
+                        buf.releaseFence.getNativeHandle());
+                native_handle_delete(handle);
+            }
+        }
+    }
+    return;
+}
+
+void CameraDeviceSession::ResultBatcher::sendBatchBuffersLocked(std::shared_ptr<InflightBatch> batch) {
+    sendBatchBuffersLocked(batch, mStreamsToBatch);
+}
+
+void CameraDeviceSession::ResultBatcher::sendBatchBuffersLocked(
+        std::shared_ptr<InflightBatch> batch, const std::vector<int>& streams) {
+    size_t batchSize = 0;
+    for (int streamId : streams) {
+        auto it = batch->mBatchBufs.find(streamId);
+        if (it != batch->mBatchBufs.end()) {
+            InflightBatch::BufferBatch& bb = it->second;
+            if (bb.mDelivered) {
+                continue;
+            }
+            if (bb.mBuffers.size() > batchSize) {
+                batchSize = bb.mBuffers.size();
+            }
+        } else {
+            ALOGE("%s: stream ID %d is not batched!", __FUNCTION__, streamId);
+            return;
+        }
+    }
+
+    if (batchSize == 0) {
+        ALOGW("%s: there is no buffer to be delivered for this batch.", __FUNCTION__);
+        for (int streamId : streams) {
+            InflightBatch::BufferBatch& bb = batch->mBatchBufs[streamId];
+            bb.mDelivered = true;
+        }
+        return;
+    }
+
+    hidl_vec<CaptureResult> results;
+    results.resize(batchSize);
+    for (size_t i = 0; i < batchSize; i++) {
+        results[i].frameNumber = batch->mFirstFrame + i;
+        results[i].partialResult = 0; // 0 for buffer only results
+        results[i].inputBuffer.streamId = -1;
+        results[i].inputBuffer.bufferId = 0;
+        results[i].inputBuffer.buffer = nullptr;
+        std::vector<StreamBuffer> outBufs;
+        for (int streamId : streams) {
+            InflightBatch::BufferBatch& bb = batch->mBatchBufs[streamId];
+            if (bb.mDelivered) {
+                continue;
+            }
+            if (i < bb.mBuffers.size()) {
+                outBufs.push_back(bb.mBuffers[i]);
+            }
+        }
+        results[i].outputBuffers = outBufs;
+    }
+    mCallback->processCaptureResult(results);
+    freeReleaseFences(results);
+    for (int streamId : streams) {
+        InflightBatch::BufferBatch& bb = batch->mBatchBufs[streamId];
+        bb.mDelivered = true;
+        bb.mBuffers.clear();
+    }
+}
+
+void CameraDeviceSession::ResultBatcher::sendBatchMetadataLocked(
+    std::shared_ptr<InflightBatch> batch, uint32_t lastPartialResultIdx) {
+    if (lastPartialResultIdx <= batch->mPartialResultProgress) {
+        // Result has been delivered. Return
+        ALOGW("%s: partial result %u has been delivered", __FUNCTION__, lastPartialResultIdx);
+        return;
+    }
+
+    std::vector<CaptureResult> results;
+    std::vector<uint32_t> toBeRemovedIdxes;
+    for (auto& pair : batch->mResultMds) {
+        uint32_t partialIdx = pair.first;
+        if (partialIdx > lastPartialResultIdx) {
+            continue;
+        }
+        toBeRemovedIdxes.push_back(partialIdx);
+        InflightBatch::MetadataBatch& mb = pair.second;
+        for (const auto& p : mb.mMds) {
+            CaptureResult result;
+            result.frameNumber = p.first;
+            result.result = std::move(p.second);
+            result.inputBuffer.streamId = -1;
+            result.inputBuffer.bufferId = 0;
+            result.inputBuffer.buffer = nullptr;
+            result.partialResult = partialIdx;
+            results.push_back(std::move(result));
+        }
+        mb.mMds.clear();
+    }
+    mCallback->processCaptureResult(results);
+    batch->mPartialResultProgress = lastPartialResultIdx;
+    for (uint32_t partialIdx : toBeRemovedIdxes) {
+        batch->mResultMds.erase(partialIdx);
+    }
+}
+
+void CameraDeviceSession::ResultBatcher::notifySingleMsg(NotifyMsg& msg) {
+    mCallback->notify({msg});
+    return;
+}
+
+void CameraDeviceSession::ResultBatcher::notify(NotifyMsg& msg) {
+    uint32_t frameNumber;
+    if (CC_LIKELY(msg.type == MsgType::SHUTTER)) {
+        frameNumber = msg.msg.shutter.frameNumber;
+    } else {
+        frameNumber = msg.msg.error.frameNumber;
+    }
+
+    auto pair = getBatch(frameNumber);
+    int batchIdx = pair.first;
+    if (batchIdx == NOT_BATCHED) {
+        notifySingleMsg(msg);
+        return;
+    }
+
+    // When error happened, stop batching for all batches earlier
+    if (CC_UNLIKELY(msg.type == MsgType::ERROR)) {
+        Mutex::Autolock _l(mLock);
+        for (int i = 0; i <= batchIdx; i++) {
+            // Send batched data up
+            std::shared_ptr<InflightBatch> batch = mInflightBatches[0];
+            {
+                Mutex::Autolock _l(batch->mLock);
+                sendBatchShutterCbsLocked(batch);
+                sendBatchBuffersLocked(batch);
+                sendBatchMetadataLocked(batch, mNumPartialResults);
+                if (!batch->allDelivered()) {
+                    ALOGE("%s: error: some batch data not sent back to framework!",
+                            __FUNCTION__);
+                }
+                batch->mRemoved = true;
+            }
+            mInflightBatches.pop_front();
+        }
+        // Send the error up
+        notifySingleMsg(msg);
+        return;
+    }
+    // Queue shutter callbacks for future delivery
+    std::shared_ptr<InflightBatch> batch = pair.second;
+    {
+        Mutex::Autolock _l(batch->mLock);
+        // Check if the batch is removed (mostly by notify error) before lock was acquired
+        if (batch->mRemoved) {
+            // Fall back to non-batch path
+            notifySingleMsg(msg);
+            return;
+        }
+
+        batch->mShutterMsgs.push_back(msg);
+        if (frameNumber == batch->mLastFrame) {
+            sendBatchShutterCbsLocked(batch);
+        }
+    } // end of batch lock scope
+
+    // see if the batch is complete
+    if (frameNumber == batch->mLastFrame) {
+        checkAndRemoveFirstBatch();
+    }
+}
+
+void CameraDeviceSession::ResultBatcher::processOneCaptureResult(CaptureResult& result) {
+    hidl_vec<CaptureResult> results = {result};
+    mCallback->processCaptureResult(results);
+    freeReleaseFences(results);
+    return;
+}
+
+void CameraDeviceSession::ResultBatcher::processCaptureResult(CaptureResult& result) {
+    auto pair = getBatch(result.frameNumber);
+    int batchIdx = pair.first;
+    if (batchIdx == NOT_BATCHED) {
+        processOneCaptureResult(result);
+        return;
+    }
+    std::shared_ptr<InflightBatch> batch = pair.second;
+    {
+        Mutex::Autolock _l(batch->mLock);
+        // Check if the batch is removed (mostly by notify error) before lock was acquired
+        if (batch->mRemoved) {
+            // Fall back to non-batch path
+            processOneCaptureResult(result);
+            return;
+        }
+
+        // queue metadata
+        if (result.result.size() != 0) {
+            // Save a copy of metadata
+            batch->mResultMds[result.partialResult].mMds.push_back(
+                    std::make_pair(result.frameNumber, result.result));
+        }
+
+        // queue buffer
+        std::vector<int> filledStreams;
+        std::vector<StreamBuffer> nonBatchedBuffers;
+        for (auto& buffer : result.outputBuffers) {
+            auto it = batch->mBatchBufs.find(buffer.streamId);
+            if (it != batch->mBatchBufs.end()) {
+                InflightBatch::BufferBatch& bb = it->second;
+                bb.mBuffers.push_back(buffer);
+                filledStreams.push_back(buffer.streamId);
+            } else {
+                nonBatchedBuffers.push_back(buffer);
+            }
+        }
+
+        // send non-batched buffers up
+        if (nonBatchedBuffers.size() > 0 || result.inputBuffer.streamId != -1) {
+            CaptureResult nonBatchedResult;
+            nonBatchedResult.frameNumber = result.frameNumber;
+            nonBatchedResult.outputBuffers = nonBatchedBuffers;
+            nonBatchedResult.inputBuffer = result.inputBuffer;
+            nonBatchedResult.partialResult = 0; // 0 for buffer only results
+            processOneCaptureResult(nonBatchedResult);
+        }
+
+        if (result.frameNumber == batch->mLastFrame) {
+            // Send data up
+            if (result.partialResult > 0) {
+                sendBatchMetadataLocked(batch, result.partialResult);
+            }
+            // send buffer up
+            if (filledStreams.size() > 0) {
+                sendBatchBuffersLocked(batch, filledStreams);
+            }
+        }
+    } // end of batch lock scope
+
+    // see if the batch is complete
+    if (result.frameNumber == batch->mLastFrame) {
+        checkAndRemoveFirstBatch();
+    }
+}
+
 // Methods from ::android::hardware::camera::device::V3_2::ICameraDeviceSession follow.
 Return<void> CameraDeviceSession::constructDefaultRequestSettings(
         RequestTemplate type, constructDefaultRequestSettings_cb _hidl_cb)  {
@@ -283,6 +645,16 @@
                 ++it;
             }
         }
+
+        // Track video streams
+        mVideoStreamIds.clear();
+        for (const auto& stream : requestedConfiguration.streams) {
+            if (stream.streamType == StreamType::OUTPUT &&
+                    stream.usage & graphics::allocator::V2_0::ConsumerUsage::VIDEO_ENCODER) {
+                mVideoStreamIds.push_back(stream.id);
+            }
+        }
+        mResultBatcher.setBatchedStreams(mVideoStreamIds);
     }
 
     if (ret == -EINVAL) {
@@ -306,7 +678,26 @@
     mCirculatingBuffers.erase(id);
 }
 
-Return<Status> CameraDeviceSession::processCaptureRequest(const CaptureRequest& request)  {
+Return<void> CameraDeviceSession::processCaptureRequest(
+        const hidl_vec<CaptureRequest>& requests, processCaptureRequest_cb _hidl_cb)  {
+    uint32_t numRequestProcessed = 0;
+    Status s = Status::OK;
+    for (size_t i = 0; i < requests.size(); i++, numRequestProcessed++) {
+        s = processOneCaptureRequest(requests[i]);
+        if (s != Status::OK) {
+            break;
+        }
+    }
+
+    if (s == Status::OK && requests.size() > 1) {
+        mResultBatcher.registerBatch(requests);
+    }
+
+    _hidl_cb(s, numRequestProcessed);
+    return Void();
+}
+
+Status CameraDeviceSession::processOneCaptureRequest(const CaptureRequest& request)  {
     Status status = initStatus();
     if (status != Status::OK) {
         ALOGE("%s: camera init failed or disconnected", __FUNCTION__);
@@ -437,7 +828,7 @@
     bool hasInputBuf = (hal_result->input_buffer != nullptr);
     size_t numOutputBufs = hal_result->num_output_buffers;
     size_t numBufs = numOutputBufs + (hasInputBuf ? 1 : 0);
-    {
+    if (numBufs > 0) {
         Mutex::Autolock _l(d->mInflightLock);
         if (hasInputBuf) {
             int streamId = static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
@@ -463,10 +854,7 @@
     }
     // We don't need to validate/import fences here since we will be passing them to camera service
     // within the scope of this function
-
     CaptureResult result;
-    hidl_vec<native_handle_t*> releaseFences;
-    releaseFences.resize(numBufs);
     result.frameNumber = frameNumber;
     result.partialResult = hal_result->partial_result;
     convertToHidl(hal_result->result, &result.result);
@@ -477,11 +865,11 @@
         result.inputBuffer.status = (BufferStatus) hal_result->input_buffer->status;
         // skip acquire fence since it's no use to camera service
         if (hal_result->input_buffer->release_fence != -1) {
-            releaseFences[numOutputBufs] = native_handle_create(/*numFds*/1, /*numInts*/0);
-            releaseFences[numOutputBufs]->data[0] = hal_result->input_buffer->release_fence;
-            result.inputBuffer.releaseFence = releaseFences[numOutputBufs];
+            native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
+            handle->data[0] = hal_result->input_buffer->release_fence;
+            result.inputBuffer.releaseFence = handle;
         } else {
-            releaseFences[numOutputBufs] = nullptr;
+            result.inputBuffer.releaseFence = nullptr;
         }
     } else {
         result.inputBuffer.streamId = -1;
@@ -495,11 +883,11 @@
         result.outputBuffers[i].status = (BufferStatus) hal_result->output_buffers[i].status;
         // skip acquire fence since it's of no use to camera service
         if (hal_result->output_buffers[i].release_fence != -1) {
-            releaseFences[i] = native_handle_create(/*numFds*/1, /*numInts*/0);
-            releaseFences[i]->data[0] = hal_result->output_buffers[i].release_fence;
-            result.outputBuffers[i].releaseFence = releaseFences[i];
+            native_handle_t* handle = native_handle_create(/*numFds*/1, /*numInts*/0);
+            handle->data[0] = hal_result->output_buffers[i].release_fence;
+            result.outputBuffers[i].releaseFence = handle;
         } else {
-            releaseFences[i] = nullptr;
+            result.outputBuffers[i].releaseFence = nullptr;
         }
     }
 
@@ -507,21 +895,17 @@
     // Do this before call back to camera service because camera service might jump to
     // configure_streams right after the processCaptureResult call so we need to finish
     // updating inflight queues first
-    {
+    if (numBufs > 0) {
         Mutex::Autolock _l(d->mInflightLock);
         if (hasInputBuf) {
             int streamId = static_cast<Camera3Stream*>(hal_result->input_buffer->stream)->mId;
             auto key = std::make_pair(streamId, frameNumber);
-            // TODO (b/34169301): currently HAL closed the fence
-            //sHandleImporter.closeFence(d->mInflightBuffers[key].acquire_fence);
             d->mInflightBuffers.erase(key);
         }
 
         for (size_t i = 0; i < numOutputBufs; i++) {
             int streamId = static_cast<Camera3Stream*>(hal_result->output_buffers[i].stream)->mId;
             auto key = std::make_pair(streamId, frameNumber);
-            // TODO (b/34169301): currently HAL closed the fence
-            //sHandleImporter.closeFence(d->mInflightBuffers[key].acquire_fence);
             d->mInflightBuffers.erase(key);
         }
 
@@ -530,12 +914,7 @@
         }
     }
 
-    d->mCallback->processCaptureResult(result);
-
-    for (size_t i = 0; i < releaseFences.size(); i++) {
-        // We don't close the FD here as HAL needs to signal it later.
-        native_handle_delete(releaseFences[i]);
-    }
+    d->mResultBatcher.processCaptureResult(result);
 }
 
 void CameraDeviceSession::sNotify(
@@ -545,15 +924,16 @@
             const_cast<CameraDeviceSession*>(static_cast<const CameraDeviceSession*>(cb));
     NotifyMsg hidlMsg;
     convertToHidl(msg, &hidlMsg);
+
     if (hidlMsg.type == (MsgType) CAMERA3_MSG_ERROR &&
             hidlMsg.msg.error.errorStreamId != -1) {
         if (d->mStreamMap.count(hidlMsg.msg.error.errorStreamId) != 1) {
             ALOGE("%s: unknown stream ID %d reports an error!",
                     __FUNCTION__, hidlMsg.msg.error.errorStreamId);
+            return;
         }
-        return;
     }
-    d->mCallback->notify(hidlMsg);
+    d->mResultBatcher.notify(hidlMsg);
 }
 
 } // namespace implementation
diff --git a/camera/device/3.2/default/CameraDeviceSession.h b/camera/device/3.2/default/CameraDeviceSession.h
index 3786e4b..8923c05 100644
--- a/camera/device/3.2/default/CameraDeviceSession.h
+++ b/camera/device/3.2/default/CameraDeviceSession.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_HARDWARE_CAMERA_DEVICE_V3_2_CAMERADEVICE3SESSION_H
 #define ANDROID_HARDWARE_CAMERA_DEVICE_V3_2_CAMERADEVICE3SESSION_H
 
+#include <deque>
+#include <map>
 #include <unordered_map>
 #include "hardware/camera_common.h"
 #include "hardware/camera3.h"
@@ -27,6 +29,7 @@
 #include <hidl/MQDescriptor.h>
 #include <include/convert.h>
 #include "HandleImporter.h"
+#include "CameraMetadata.h"
 
 namespace android {
 namespace hardware {
@@ -64,7 +67,9 @@
 
 struct CameraDeviceSession : public ICameraDeviceSession, private camera3_callback_ops  {
 
-    CameraDeviceSession(camera3_device_t*, const sp<ICameraDeviceCallback>&);
+    CameraDeviceSession(camera3_device_t*,
+                        const camera_metadata_t* deviceInfo,
+                        const sp<ICameraDeviceCallback>&);
     ~CameraDeviceSession();
     // Call by CameraDevice to dump active device states
     void dumpState(const native_handle_t* fd);
@@ -75,9 +80,12 @@
     bool isClosed();
 
     // Methods from ::android::hardware::camera::device::V3_2::ICameraDeviceSession follow.
-    Return<void> constructDefaultRequestSettings(RequestTemplate type, constructDefaultRequestSettings_cb _hidl_cb) override;
-    Return<void> configureStreams(const StreamConfiguration& requestedConfiguration, configureStreams_cb _hidl_cb) override;
-    Return<Status> processCaptureRequest(const CaptureRequest& request) override;
+    Return<void> constructDefaultRequestSettings(
+            RequestTemplate type, constructDefaultRequestSettings_cb _hidl_cb) override;
+    Return<void> configureStreams(
+            const StreamConfiguration& requestedConfiguration, configureStreams_cb _hidl_cb) override;
+    Return<void> processCaptureRequest(
+            const hidl_vec<CaptureRequest>& requests, processCaptureRequest_cb _hidl_cb) override;
     Return<Status> flush() override;
     Return<void> close() override;
 
@@ -94,7 +102,6 @@
     bool mDisconnected = false;
 
     camera3_device_t* mDevice;
-    const sp<ICameraDeviceCallback> mCallback;
     // Stream ID -> Camera3Stream cache
     std::map<int, Camera3Stream> mStreamMap;
 
@@ -114,6 +121,104 @@
     static HandleImporter& sHandleImporter;
 
     bool mInitFail;
+
+    common::V1_0::helper::CameraMetadata mDeviceInfo;
+
+    class ResultBatcher {
+    public:
+        ResultBatcher(const sp<ICameraDeviceCallback>& callback);
+        void setNumPartialResults(uint32_t n);
+        void setBatchedStreams(const std::vector<int>& streamsToBatch);
+
+        void registerBatch(const hidl_vec<CaptureRequest>& requests);
+        void notify(NotifyMsg& msg);
+        void processCaptureResult(CaptureResult& result);
+
+    private:
+        struct InflightBatch {
+            // Protect access to entire struct. Acquire this lock before read/write any data or
+            // calling any methods. processCaptureResult and notify will compete for this lock
+            // HIDL IPCs might be issued while the lock is held
+            Mutex mLock;
+
+            bool allDelivered() const;
+
+            uint32_t mFirstFrame;
+            uint32_t mLastFrame;
+            uint32_t mBatchSize;
+
+            bool mShutterDelivered = false;
+            std::vector<NotifyMsg> mShutterMsgs;
+
+            struct BufferBatch {
+                bool mDelivered = false;
+                // This currently assumes every batched request will output to the batched stream
+                // and since HAL must always send buffers in order, no frameNumber tracking is
+                // needed
+                std::vector<StreamBuffer> mBuffers;
+            };
+            // Stream ID -> VideoBatch
+            std::unordered_map<int, BufferBatch> mBatchBufs;
+
+            struct MetadataBatch {
+                //                   (frameNumber, metadata)
+                std::vector<std::pair<uint32_t, CameraMetadata>> mMds;
+            };
+            // Partial result IDs that has been delivered to framework
+            uint32_t mNumPartialResults;
+            uint32_t mPartialResultProgress = 0;
+            // partialResult -> MetadataBatch
+            std::map<uint32_t, MetadataBatch> mResultMds;
+
+            // Set to true when batch is removed from mInflightBatches
+            // processCaptureResult and notify must check this flag after acquiring mLock to make
+            // sure this batch isn't removed while waiting for mLock
+            bool mRemoved = false;
+        };
+
+        static const int NOT_BATCHED = -1;
+
+        // Get the batch index and pointer to InflightBatch (nullptrt if the frame is not batched)
+        // Caller must acquire the InflightBatch::mLock before accessing the InflightBatch
+        // It's possible that the InflightBatch is removed from mInflightBatches before the
+        // InflightBatch::mLock is acquired (most likely caused by an error notification), so
+        // caller must check InflightBatch::mRemoved flag after the lock is acquried.
+        // This method will hold ResultBatcher::mLock briefly
+        std::pair<int, std::shared_ptr<InflightBatch>> getBatch(uint32_t frameNumber);
+
+        // Check if the first batch in mInflightBatches is ready to be removed, and remove it if so
+        // This method will hold ResultBatcher::mLock briefly
+        void checkAndRemoveFirstBatch();
+
+        // The following sendXXXX methods must be called while the InflightBatch::mLock is locked
+        // HIDL IPC methods will be called during these methods.
+        void sendBatchShutterCbsLocked(std::shared_ptr<InflightBatch> batch);
+        // send buffers for all batched streams
+        void sendBatchBuffersLocked(std::shared_ptr<InflightBatch> batch);
+        // send buffers for specified streams
+        void sendBatchBuffersLocked(
+                std::shared_ptr<InflightBatch> batch, const std::vector<int>& streams);
+        void sendBatchMetadataLocked(
+                std::shared_ptr<InflightBatch> batch, uint32_t lastPartialResultIdx);
+        // End of sendXXXX methods
+
+        // helper methods
+        void freeReleaseFences(hidl_vec<CaptureResult>&);
+        void notifySingleMsg(NotifyMsg& msg);
+        void processOneCaptureResult(CaptureResult& result);
+
+        // Protect access to mInflightBatches, mNumPartialResults and mStreamsToBatch
+        // processCaptureRequest, processCaptureResult, notify will compete for this lock
+        // Do NOT issue HIDL IPCs while holding this lock (except when HAL reports error)
+        mutable Mutex mLock;
+        std::deque<std::shared_ptr<InflightBatch>> mInflightBatches;
+        uint32_t mNumPartialResults;
+        std::vector<int> mStreamsToBatch;
+        const sp<ICameraDeviceCallback> mCallback;
+    } mResultBatcher;
+
+    std::vector<int> mVideoStreamIds;
+
     bool initialize();
 
     Status initStatus() const;
@@ -129,6 +234,7 @@
 
     void cleanupBuffersLocked(int id);
 
+    Status processOneCaptureRequest(const CaptureRequest& request);
     /**
      * Static callback forwarding methods from HAL to instance
      */
diff --git a/camera/provider/2.4/Android.bp b/camera/provider/2.4/Android.bp
index 3369a3c..1656325 100644
--- a/camera/provider/2.4/Android.bp
+++ b/camera/provider/2.4/Android.bp
@@ -57,6 +57,8 @@
         "android.hardware.camera.common@1.0",
         "android.hardware.camera.device@1.0",
         "android.hardware.camera.device@3.2",
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.common@1.0",
         "android.hidl.base@1.0",
     ],
     export_shared_lib_headers: [
@@ -67,6 +69,8 @@
         "android.hardware.camera.common@1.0",
         "android.hardware.camera.device@1.0",
         "android.hardware.camera.device@3.2",
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.common@1.0",
         "android.hidl.base@1.0",
     ],
 }
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 598127f..a79c9fa 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -445,13 +445,13 @@
     hidl_vec<hidl_string> getCameraDeviceNames();
 
     struct EmptyDeviceCb : public ICameraDeviceCallback {
-        virtual Return<void> processCaptureResult(const CaptureResult& /*result*/) override {
+        virtual Return<void> processCaptureResult(const hidl_vec<CaptureResult>& /*results*/) override {
             ALOGI("processCaptureResult callback");
             ADD_FAILURE(); // Empty callback should not reach here
             return Void();
         }
 
-        virtual Return<void> notify(const NotifyMsg& /*msg*/) override {
+        virtual Return<void> notify(const hidl_vec<NotifyMsg>& /*msgs*/) override {
             ALOGI("notify callback");
             ADD_FAILURE(); // Empty callback should not reach here
             return Void();
@@ -460,8 +460,8 @@
 
     struct DeviceCb : public ICameraDeviceCallback {
         DeviceCb(CameraHidlTest *parent) : mParent(parent) {}
-        Return<void> processCaptureResult(const CaptureResult& result) override;
-        Return<void> notify(const NotifyMsg& msg) override;
+        Return<void> processCaptureResult(const hidl_vec<CaptureResult>& results) override;
+        Return<void> notify(const hidl_vec<NotifyMsg>& msgs) override;
 
      private:
         CameraHidlTest *mParent;               // Parent object
@@ -667,12 +667,13 @@
 }
 
 Return<void> CameraHidlTest::DeviceCb::processCaptureResult(
-        const CaptureResult& result) {
+        const hidl_vec<CaptureResult>& results) {
     if (nullptr == mParent) {
         return Void();
     }
 
     std::unique_lock<std::mutex> l(mParent->mLock);
+    const CaptureResult& result = results[0];
 
     if(mParent->mResultFrameNumber != result.frameNumber) {
         ALOGE("%s: Unexpected frame number! Expected: %u received: %u",
@@ -695,7 +696,8 @@
 }
 
 Return<void> CameraHidlTest::DeviceCb::notify(
-        const NotifyMsg& message) {
+        const hidl_vec<NotifyMsg>& messages) {
+    const NotifyMsg& message = messages[0];
 
     if (MsgType::ERROR == message.type) {
         {
@@ -2477,10 +2479,17 @@
                 mResultFrameNumber = frameNumber;
             }
 
-            Return<Status> returnStatus = session->processCaptureRequest(
-                    request);
+            Status status = Status::INTERNAL_ERROR;
+            uint32_t numRequestProcessed = 0;
+            Return<void> returnStatus = session->processCaptureRequest(
+                    {request},
+                    [&status, &numRequestProcessed] (auto s, uint32_t n) {
+                        status = s;
+                        numRequestProcessed = n;
+                    });
             ASSERT_TRUE(returnStatus.isOk());
-            ASSERT_EQ(Status::OK, returnStatus);
+            ASSERT_EQ(Status::OK, status);
+            ASSERT_EQ(numRequestProcessed, 1u);
 
             {
                 std::unique_lock<std::mutex> l(mLock);
@@ -2503,9 +2512,14 @@
             }
 
             returnStatus = session->processCaptureRequest(
-                    request);
+                    {request},
+                    [&status, &numRequestProcessed] (auto s, uint32_t n) {
+                        status = s;
+                        numRequestProcessed = n;
+                    });
             ASSERT_TRUE(returnStatus.isOk());
-            ASSERT_EQ(Status::OK, returnStatus);
+            ASSERT_EQ(Status::OK, status);
+            ASSERT_EQ(numRequestProcessed, 1u);
 
             {
                 std::unique_lock<std::mutex> l(mLock);
@@ -2563,12 +2577,19 @@
                     emptyInputBuffer, outputBuffers};
 
             //Settings were not correctly initialized, we should fail here
-            Return<Status> returnStatus = session->processCaptureRequest(
-                    request);
-            ASSERT_TRUE(returnStatus.isOk());
-            ASSERT_EQ(Status::INTERNAL_ERROR, returnStatus);
+            Status status = Status::OK;
+            uint32_t numRequestProcessed = 0;
+            Return<void> ret = session->processCaptureRequest(
+                    {request},
+                    [&status, &numRequestProcessed] (auto s, uint32_t n) {
+                        status = s;
+                        numRequestProcessed = n;
+                    });
+            ASSERT_TRUE(ret.isOk());
+            ASSERT_EQ(Status::INTERNAL_ERROR, status);
+            ASSERT_EQ(numRequestProcessed, 0u);
 
-            Return<void> ret = session->close();
+            ret = session->close();
             ASSERT_TRUE(ret.isOk());
         }
     }
@@ -2609,11 +2630,17 @@
                     emptyInputBuffer, emptyOutputBuffers};
 
             //Output buffers are missing, we should fail here
-            Return<Status> returnStatus = session->processCaptureRequest(
-                    request);
-            ASSERT_TRUE(returnStatus.isOk());
-            ASSERT_EQ(Status::INTERNAL_ERROR,
-                      returnStatus);
+            Status status = Status::OK;
+            uint32_t numRequestProcessed = 0;
+            ret = session->processCaptureRequest(
+                    {request},
+                    [&status, &numRequestProcessed] (auto s, uint32_t n) {
+                        status = s;
+                        numRequestProcessed = n;
+                    });
+            ASSERT_TRUE(ret.isOk());
+            ASSERT_EQ(Status::INTERNAL_ERROR, status);
+            ASSERT_EQ(numRequestProcessed, 0u);
 
             ret = session->close();
             ASSERT_TRUE(ret.isOk());
@@ -2672,12 +2699,20 @@
                 mResultFrameNumber = frameNumber;
             }
 
-            Return<Status> returnStatus = session->processCaptureRequest(
-                    request);
-            ASSERT_TRUE(returnStatus.isOk());
-            ASSERT_EQ(Status::OK, returnStatus);
+            Status status = Status::INTERNAL_ERROR;
+            uint32_t numRequestProcessed = 0;
+            ret = session->processCaptureRequest(
+                    {request},
+                    [&status, &numRequestProcessed] (auto s, uint32_t n) {
+                        status = s;
+                        numRequestProcessed = n;
+                    });
+
+            ASSERT_TRUE(ret.isOk());
+            ASSERT_EQ(Status::OK, status);
+            ASSERT_EQ(numRequestProcessed, 1u);
             //Flush before waiting for request to complete.
-            returnStatus = session->flush();
+            Return<Status> returnStatus = session->flush();
             ASSERT_TRUE(returnStatus.isOk());
             ASSERT_EQ(Status::OK, returnStatus);
 
diff --git a/configstore/1.0/ISurfaceFlingerConfigs.hal b/configstore/1.0/ISurfaceFlingerConfigs.hal
index 43c96ee..3b5c1b0 100644
--- a/configstore/1.0/ISurfaceFlingerConfigs.hal
+++ b/configstore/1.0/ISurfaceFlingerConfigs.hal
@@ -40,8 +40,6 @@
     vsyncEventPhaseOffsetNs() generates (OptionalInt64 value);
     vsyncSfEventPhaseOffsetNs() generates (OptionalInt64 value);
 
-    useTripleFramebuffer() generates (OptionalBool value);
-
     /*
      * Instruct the Render Engine to use EGL_IMG_context_priority hint if
      * availabe.
@@ -96,4 +94,18 @@
      * mechanism which significantly reduces buffer processing latency.
      */
     hasSyncFramework() generates(OptionalBool value);
+
+    /*
+     * Return true if surface flinger should use vr flinger for compatible vr
+     * apps, false otherwise. Devices that will never be running vr apps should
+     * return false to avoid extra resource usage. Daydream ready devices must
+     * return true for full vr support.
+     */
+    useVrFlinger() generates (OptionalBool value);
+
+    /*
+     * Controls the number of buffers SurfaceFlinger will allocate for use in
+     * FramebufferSurface.
+     */
+    maxFrameBufferAcquiredBuffers() generates(OptionalInt64 value);
 };
diff --git a/configstore/1.0/default/Android.mk b/configstore/1.0/default/Android.mk
index b168029..e017cfd 100644
--- a/configstore/1.0/default/Android.mk
+++ b/configstore/1.0/default/Android.mk
@@ -2,25 +2,6 @@
 
 ################################################################################
 include $(CLEAR_VARS)
-LOCAL_MODULE := android.hardware.configstore@1.0-impl
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_MODULE_CLASS := SHARED_LIBRARIES
-LOCAL_MODULE_RELATIVE_PATH := hw
-
-include $(LOCAL_PATH)/surfaceflinger.mk
-
-LOCAL_SHARED_LIBRARIES := \
-    libbase \
-    libhidlbase \
-    libhidltransport \
-    libutils \
-    android.hardware.configstore@1.0 \
-    android.hidl.base@1.0
-
-include $(BUILD_SHARED_LIBRARY)
-
-################################################################################
-include $(CLEAR_VARS)
 LOCAL_MODULE := android.hardware.configstore@1.0-service
 LOCAL_PROPRIETARY_MODULE := true
 LOCAL_MODULE_CLASS := EXECUTABLES
@@ -28,13 +9,14 @@
 LOCAL_INIT_RC := android.hardware.configstore@1.0-service.rc
 LOCAL_SRC_FILES:= service.cpp
 
+include $(LOCAL_PATH)/surfaceflinger.mk
+
 LOCAL_SHARED_LIBRARIES := \
-    liblog \
-    libdl \
-    libutils \
+    android.hardware.configstore@1.0 \
     libhidlbase \
     libhidltransport \
-    android.hardware.configstore@1.0 \
+    libbase \
+    liblog \
+    libutils \
 
 include $(BUILD_EXECUTABLE)
-
diff --git a/configstore/1.0/default/SurfaceFlingerConfigs.cpp b/configstore/1.0/default/SurfaceFlingerConfigs.cpp
index e8872e8..9469ab4 100644
--- a/configstore/1.0/default/SurfaceFlingerConfigs.cpp
+++ b/configstore/1.0/default/SurfaceFlingerConfigs.cpp
@@ -29,16 +29,6 @@
     return Void();
 }
 
-Return<void> SurfaceFlingerConfigs::useTripleFramebuffer(useTripleFramebuffer_cb _hidl_cb) {
-    bool value = false;
-#ifdef USE_TRIPLE_FRAMEBUFFER
-    value = true;
-#endif
-    _hidl_cb({true, value});
-    LOG(INFO) << "SurfaceFlinger FrameBuffer: " << (value ? "triple" : "double");
-    return Void();
-}
-
 Return<void> SurfaceFlingerConfigs::useContextPriority(useContextPriority_cb _hidl_cb) {
 #ifdef USE_CONTEXT_PRIORITY
     _hidl_cb({true, USE_CONTEXT_PRIORITY});
@@ -49,6 +39,16 @@
     return Void();
 }
 
+Return<void> SurfaceFlingerConfigs::maxFrameBufferAcquiredBuffers(maxFrameBufferAcquiredBuffers_cb _hidl_cb) {
+#ifdef NUM_FRAMEBUFFER_SURFACE_BUFFERS
+    _hidl_cb({true, NUM_FRAMEBUFFER_SURFACE_BUFFERS});
+    LOG(INFO) << "SurfaceFlinger FrameBuffer max acquired buffers : " << NUM_FRAMEBUFFER_SURFACE_BUFFERS;
+#else
+    _hidl_cb({false, 0});
+#endif
+    return Void();
+}
+
 Return<void> SurfaceFlingerConfigs::hasWideColorDisplay(hasWideColorDisplay_cb _hidl_cb) {
     bool value = false;
 #ifdef HAS_WIDE_COLOR_DISPLAY
@@ -111,9 +111,16 @@
   return Void();
 }
 
-// Methods from ::android::hidl::base::V1_0::IBase follow.
-ISurfaceFlingerConfigs* HIDL_FETCH_ISurfaceFlingerConfigs(const char* /* name */) {
-    return new SurfaceFlingerConfigs();
+Return<void> SurfaceFlingerConfigs::useVrFlinger(useVrFlinger_cb _hidl_cb) {
+    bool value = false;
+    bool specified = false;
+#ifdef USE_VR_FLINGER
+    value = true;
+    specified = true;
+#endif
+    _hidl_cb({specified, value});
+    LOG(INFO) << "SurfaceFlinger UseVrFlinger: " << (value ? "true" : "false");
+    return Void();
 }
 
 }  // namespace implementation
diff --git a/configstore/1.0/default/SurfaceFlingerConfigs.h b/configstore/1.0/default/SurfaceFlingerConfigs.h
index bea1ab1..9300511 100644
--- a/configstore/1.0/default/SurfaceFlingerConfigs.h
+++ b/configstore/1.0/default/SurfaceFlingerConfigs.h
@@ -26,7 +26,6 @@
     // Methods from ::android::hardware::configstore::V1_0::ISurfaceFlingerConfigs follow.
     Return<void> vsyncEventPhaseOffsetNs(vsyncEventPhaseOffsetNs_cb _hidl_cb) override;
     Return<void> vsyncSfEventPhaseOffsetNs(vsyncEventPhaseOffsetNs_cb _hidl_cb) override;
-    Return<void> useTripleFramebuffer(useTripleFramebuffer_cb _hidl_cb) override;
     Return<void> useContextPriority(useContextPriority_cb _hidl_cb) override;
     Return<void> hasWideColorDisplay(hasWideColorDisplay_cb _hidl_cb) override;
     Return<void> hasHDRDisplay(hasHDRDisplay_cb _hidl_cb) override;
@@ -34,13 +33,13 @@
     Return<void> useHwcForRGBtoYUV(useHwcForRGBtoYUV_cb _hidl_cb) override;
     Return<void> maxVirtualDisplaySize(maxVirtualDisplaySize_cb _hidl_cb) override;
     Return<void> hasSyncFramework(hasSyncFramework_cb _hidl_cb) override;
+    Return<void> useVrFlinger(useVrFlinger_cb _hidl_cb) override;
+    Return<void> maxFrameBufferAcquiredBuffers(maxFrameBufferAcquiredBuffers_cb _hidl_cb) override;
 
     // Methods from ::android::hidl::base::V1_0::IBase follow.
 
 };
 
-extern "C" ISurfaceFlingerConfigs* HIDL_FETCH_ISurfaceFlingerConfigs(const char* name);
-
 }  // namespace implementation
 }  // namespace V1_0
 }  // namespace configstore
diff --git a/configstore/1.0/default/service.cpp b/configstore/1.0/default/service.cpp
index caec0ba..60b69ab 100644
--- a/configstore/1.0/default/service.cpp
+++ b/configstore/1.0/default/service.cpp
@@ -17,17 +17,26 @@
 #define LOG_TAG "android.hardware.configstore@1.0-service"
 
 #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
-#include <hidl/LegacySupport.h>
+#include <hidl/HidlTransportSupport.h>
 
-using android::hardware::configstore::V1_0::ISurfaceFlingerConfigs;
+#include "SurfaceFlingerConfigs.h"
+
 using android::hardware::configureRpcThreadpool;
-using android::hardware::registerPassthroughServiceImplementation;
 using android::hardware::joinRpcThreadpool;
+using android::hardware::configstore::V1_0::ISurfaceFlingerConfigs;
+using android::hardware::configstore::V1_0::implementation::SurfaceFlingerConfigs;
+using android::sp;
+using android::status_t;
+using android::OK;
 
 int main() {
     // TODO(b/34857894): tune the max thread count.
     configureRpcThreadpool(10, true);
-    registerPassthroughServiceImplementation<ISurfaceFlingerConfigs>();
+
+    sp<ISurfaceFlingerConfigs> surfaceFlingerConfigs = new SurfaceFlingerConfigs;
+    status_t status = surfaceFlingerConfigs->registerAsService();
+    LOG_ALWAYS_FATAL_IF(status != OK, "Could not register ISurfaceFlingerConfigs");
+
     // other interface registration comes here
     joinRpcThreadpool();
     return 0;
diff --git a/configstore/1.0/default/surfaceflinger.mk b/configstore/1.0/default/surfaceflinger.mk
index 6e63fdc..9e3d4d4 100644
--- a/configstore/1.0/default/surfaceflinger.mk
+++ b/configstore/1.0/default/surfaceflinger.mk
@@ -9,10 +9,6 @@
     LOCAL_CFLAGS += -DSF_VSYNC_EVENT_PHASE_OFFSET_NS=$(SF_VSYNC_EVENT_PHASE_OFFSET_NS)
 endif
 
-ifeq ($(NUM_FRAMEBUFFER_SURFACE_BUFFERS),3)
-    LOCAL_CFLAGS += -DUSE_TRIPLE_FRAMEBUFFER
-endif
-
 ifeq ($(TARGET_BOARD_PLATFORM),omap4)
     LOCAL_CFLAGS += -DUSE_CONTEXT_PRIORITY=1
 endif
@@ -46,3 +42,11 @@
 ifeq ($(TARGET_RUNNING_WITHOUT_SYNC_FRAMEWORK),true)
     LOCAL_CFLAGS += -DRUNNING_WITHOUT_SYNC_FRAMEWORK
 endif
+
+ifneq ($(USE_VR_FLINGER),)
+    LOCAL_CFLAGS += -DUSE_VR_FLINGER
+endif
+
+ifneq ($(NUM_FRAMEBUFFER_SURFACE_BUFFERS),)
+    LOCAL_CFLAGS += -DNUM_FRAMEBUFFER_SURFACE_BUFFERS=$(NUM_FRAMEBUFFER_SURFACE_BUFFERS)
+endif
diff --git a/gnss/1.0/default/Gnss.cpp b/gnss/1.0/default/Gnss.cpp
index 9493737..afb659c 100644
--- a/gnss/1.0/default/Gnss.cpp
+++ b/gnss/1.0/default/Gnss.cpp
@@ -46,7 +46,11 @@
     .gnss_sv_status_cb = gnssSvStatusCb,
 };
 
-Gnss::Gnss(gps_device_t* gnssDevice) {
+uint32_t Gnss::sCapabilitiesCached = 0;
+uint16_t Gnss::sYearOfHwCached = 0;
+
+Gnss::Gnss(gps_device_t* gnssDevice) :
+        mDeathRecipient(new GnssHidlDeathRecipient(this)) {
     /* Error out if an instance of the interface already exists. */
     LOG_ALWAYS_FATAL_IF(sInterfaceExists);
     sInterfaceExists = true;
@@ -271,6 +275,9 @@
     if (!ret.isOk()) {
         ALOGE("%s: Unable to invoke callback", __func__);
     }
+
+    // Save for reconnection when some legacy hal's don't resend this info
+    sCapabilitiesCached = capabilities;
 }
 
 void Gnss::acquireWakelockCb() {
@@ -373,6 +380,9 @@
     if (!ret.isOk()) {
             ALOGE("%s: Unable to invoke callback", __func__);
     }
+
+    // Save for reconnection when some legacy hal's don't resend this info
+    sYearOfHwCached = info->year_of_hw;
 }
 
 
@@ -383,7 +393,30 @@
         return false;
     }
 
+    if (callback == nullptr)  {
+        ALOGE("%s: Null callback ignored", __func__);
+        return false;
+    }
+
+    if (sGnssCbIface != NULL) {
+        ALOGW("%s called more than once. Unexpected unless test.", __func__);
+        sGnssCbIface->unlinkToDeath(mDeathRecipient);
+    }
+
     sGnssCbIface = callback;
+    callback->linkToDeath(mDeathRecipient, 0 /*cookie*/);
+
+    // If this was received in the past, send it up again to refresh caller.
+    // mGnssIface will override after init() is called below, if needed
+    // (though it's unlikely the gps.h capabilities or system info will change.)
+    if (sCapabilitiesCached != 0) {
+        setCapabilitiesCb(sCapabilitiesCached);
+    }
+    if (sYearOfHwCached != 0) {
+        LegacyGnssSystemInfo info;
+        info.year_of_hw = sYearOfHwCached;
+        setSystemInfoCb(&info);
+    }
 
     return (mGnssIface->init(&sGnssCb) == 0);
 }
@@ -676,6 +709,30 @@
     return mGnssBatching;
 }
 
+void Gnss::handleHidlDeath() {
+    ALOGW("GNSS service noticed HIDL death. Stopping all GNSS operations.");
+
+    // commands down to the HAL implementation
+    stop(); // stop ongoing GPS tracking
+    if (mGnssMeasurement != nullptr) {
+        mGnssMeasurement->close();
+    }
+    if (mGnssNavigationMessage != nullptr) {
+        mGnssNavigationMessage->close();
+    }
+    if (mGnssBatching != nullptr) {
+        mGnssBatching->stop();
+        mGnssBatching->cleanup();
+    }
+    cleanup();
+
+    /*
+     * This has died, so close it off in case (race condition) callbacks happen
+     * before HAL processes above messages.
+     */
+    sGnssCbIface = nullptr;
+}
+
 IGnss* HIDL_FETCH_IGnss(const char* /* hal */) {
     hw_module_t* module;
     IGnss* iface = nullptr;
diff --git a/gnss/1.0/default/Gnss.h b/gnss/1.0/default/Gnss.h
index 63614fa..faf903c 100644
--- a/gnss/1.0/default/Gnss.h
+++ b/gnss/1.0/default/Gnss.h
@@ -52,7 +52,8 @@
  * Represents the standard GNSS interface. Also contains wrapper methods to allow methods from
  * IGnssCallback interface to be passed into the conventional implementation of the GNSS HAL.
  */
-struct Gnss : public IGnss {
+class Gnss : public IGnss {
+  public:
     Gnss(gps_device_t* gnss_device);
     ~Gnss();
 
@@ -122,6 +123,22 @@
     static GpsCallbacks sGnssCb;
 
  private:
+    /*
+     * For handling system-server death while GNSS service lives on.
+     */
+    class GnssHidlDeathRecipient : public hidl_death_recipient {
+      public:
+        GnssHidlDeathRecipient(const sp<Gnss> gnss) : mGnss(gnss) {
+        }
+
+        virtual void serviceDied(uint64_t /*cookie*/,
+                const wp<::android::hidl::base::V1_0::IBase>& /*who*/) {
+            mGnss->handleHidlDeath();
+        }
+      private:
+        sp<Gnss> mGnss;
+    };
+
     // for wakelock consolidation, see above
     static void acquireWakelockGnss();
     static void releaseWakelockGnss();
@@ -129,6 +146,11 @@
     static bool sWakelockHeldGnss;
     static bool sWakelockHeldFused;
 
+    /*
+     * Cleanup for death notification
+     */
+    void handleHidlDeath();
+
     sp<GnssXtra> mGnssXtraIface = nullptr;
     sp<AGnssRil> mGnssRil = nullptr;
     sp<GnssGeofencing> mGnssGeofencingIface = nullptr;
@@ -139,10 +161,17 @@
     sp<GnssDebug> mGnssDebug = nullptr;
     sp<GnssConfiguration> mGnssConfig = nullptr;
     sp<GnssBatching> mGnssBatching = nullptr;
+
+    sp<GnssHidlDeathRecipient> mDeathRecipient;
+
     const GpsInterface* mGnssIface = nullptr;
     static sp<IGnssCallback> sGnssCbIface;
     static std::vector<std::unique_ptr<ThreadFuncArgs>> sThreadFuncArgsList;
     static bool sInterfaceExists;
+
+    // Values saved for resend
+    static uint32_t sCapabilitiesCached;
+    static uint16_t sYearOfHwCached;
 };
 
 extern "C" IGnss* HIDL_FETCH_IGnss(const char* name);
diff --git a/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp b/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp
index 8f131cf..21b7136 100644
--- a/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp
+++ b/gnss/1.0/vts/functional/VtsHalGnssV1_0TargetTest.cpp
@@ -33,17 +33,16 @@
 using android::hardware::gnss::V1_0::IGnssCallback;
 using android::sp;
 
-#define TIMEOUT_SECONDS 5  // for basic commands/responses
+#define TIMEOUT_SEC 3  // for basic commands/responses
 
 // The main test class for GNSS HAL.
 class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase {
  public:
   virtual void SetUp() override {
-    /* TODO(b/35678469): Setup the init.rc for VTS such that there's a
-     * single caller
-     * to the GNSS HAL - as part of confirming that the info & capabilities
-     * callbacks trigger.
-     */
+    // Clean between tests
+    capabilities_called_count_ = 0;
+    location_called_count_ = 0;
+    info_called_count_ = 0;
 
     gnss_hal_ = ::testing::VtsHalHidlTargetTestBase::getService<IGnss>();
     ASSERT_NE(gnss_hal_, nullptr);
@@ -53,15 +52,35 @@
 
     auto result = gnss_hal_->setCallback(gnss_cb_);
     if (!result.isOk()) {
-      ALOGE("result of failed callback set %s", result.description().c_str());
+      ALOGE("result of failed setCallback %s", result.description().c_str());
     }
 
     ASSERT_TRUE(result.isOk());
     ASSERT_TRUE(result);
 
-    /* TODO(b/35678469): Implement the capabilities & info (year) checks &
-     * value store here.
+    /*
+     * At least one callback should trigger - it may be capabilites, or
+     * system info first, so wait again if capabilities not received.
      */
+    EXPECT_EQ(std::cv_status::no_timeout, wait(TIMEOUT_SEC));
+    if (capabilities_called_count_ == 0) {
+      EXPECT_EQ(std::cv_status::no_timeout, wait(TIMEOUT_SEC));
+    }
+
+    /*
+     * Generally should be 1 capabilites callback -
+     * or possibly 2 in some recovery cases (default cached & refreshed)
+     */
+    EXPECT_GE(capabilities_called_count_, 1);
+    EXPECT_LE(capabilities_called_count_, 2);
+
+    /*
+     * Clear notify/waiting counter, allowing up till the timeout after
+     * the last reply for final startup messages to arrive (esp. system
+     * info.)
+     */
+    while (wait(TIMEOUT_SEC) == std::cv_status::no_timeout) {
+    }
   }
 
   virtual void TearDown() override {
@@ -93,9 +112,9 @@
 
   /* Callback class for data & Event. */
   class GnssCallback : public IGnssCallback {
+   public:
     GnssHalTest& parent_;
 
-   public:
     GnssCallback(GnssHalTest& parent) : parent_(parent){};
 
     virtual ~GnssCallback() = default;
@@ -171,16 +190,33 @@
  * Sets up the callback, awaits the capabilities, and calls cleanup
  *
  * Since this is just the basic operation of SetUp() and TearDown(),
- * the function definition is intentionally kept empty
+ * the function definition is intentionally empty
  */
 TEST_F(GnssHalTest, SetCallbackCapabilitiesCleanup) {}
 
-void CheckLocation(GnssLocation& location) {
+/*
+ * CheckLocation:
+ * Helper function to vet Location fields
+ */
+
+void CheckLocation(GnssLocation& location, bool checkAccuracies) {
   EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_LAT_LONG);
   EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_ALTITUDE);
   EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_SPEED);
   EXPECT_TRUE(location.gnssLocationFlags &
               GnssLocationFlags::HAS_HORIZONTAL_ACCURACY);
+  // New uncertainties available in O must be provided,
+  // at least when paired with modern hardware (2017+)
+  if (checkAccuracies) {
+    EXPECT_TRUE(location.gnssLocationFlags &
+                GnssLocationFlags::HAS_VERTICAL_ACCURACY);
+    EXPECT_TRUE(location.gnssLocationFlags &
+                GnssLocationFlags::HAS_SPEED_ACCURACY);
+    if (location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) {
+      EXPECT_TRUE(location.gnssLocationFlags &
+                  GnssLocationFlags::HAS_BEARING_ACCURACY);
+    }
+  }
   EXPECT_GE(location.latitudeDegrees, -90.0);
   EXPECT_LE(location.latitudeDegrees, 90.0);
   EXPECT_GE(location.longitudeDegrees, -180.0);
@@ -190,12 +226,17 @@
   EXPECT_GE(location.speedMetersPerSec, 0.0);
   EXPECT_LE(location.speedMetersPerSec, 5.0);  // VTS tests are stationary.
 
+  // Non-zero speeds must be reported with an associated bearing
+  if (location.speedMetersPerSec > 0.0) {
+    EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING);
+  }
+
   /*
    * Tolerating some especially high values for accuracy estimate, in case of
-   * first fix with especially poor geoemtry (happens occasionally)
+   * first fix with especially poor geometry (happens occasionally)
    */
   EXPECT_GT(location.horizontalAccuracyMeters, 0.0);
-  EXPECT_LE(location.horizontalAccuracyMeters, 200.0);
+  EXPECT_LE(location.horizontalAccuracyMeters, 250.0);
 
   /*
    * Some devices may define bearing as -180 to +180, others as 0 to 360.
@@ -220,11 +261,6 @@
 
   // Check timestamp > 1.48e12 (47 years in msec - 1970->2017+)
   EXPECT_GT(location.timestamp, 1.48e12);
-
-  /* TODO(b/35678469): Check if the hardware year is 2017+, and if so,
-   * that bearing, plus vertical, speed & bearing accuracy are present.
-   * And allow bearing to be not present, only if associated with a speed of 0.0
-   */
 }
 
 /*
@@ -241,6 +277,9 @@
 #define LOCATION_TIMEOUT_SUBSEQUENT_SEC 3
 #define LOCATIONS_TO_CHECK 5
 
+  bool checkMoreAccuracies =
+      (info_called_count_ > 0 && last_info_.yearOfHw >= 2017);
+
   auto result = gnss_hal_->setPositionMode(
       IGnss::GnssPositionMode::MS_BASED,
       IGnss::GnssPositionRecurrence::RECURRENCE_PERIODIC, MIN_INTERVAL_MSEC,
@@ -254,15 +293,18 @@
   ASSERT_TRUE(result.isOk());
   ASSERT_TRUE(result);
 
-  EXPECT_EQ(std::cv_status::no_timeout, wait(LOCATION_TIMEOUT_FIRST_SEC));
-  EXPECT_EQ(location_called_count_, 1);
-  CheckLocation(last_location_);
+  // GPS signals initially optional for this test, so don't expect no timeout
+  // yet
+  wait(LOCATION_TIMEOUT_FIRST_SEC);
+  if (location_called_count_ > 0) {
+    CheckLocation(last_location_, checkMoreAccuracies);
+  }
 
   for (int i = 1; i < LOCATIONS_TO_CHECK; i++) {
-    EXPECT_EQ(std::cv_status::no_timeout,
-              wait(LOCATION_TIMEOUT_SUBSEQUENT_SEC));
-    EXPECT_EQ(location_called_count_, i + 1);
-    CheckLocation(last_location_);
+    wait(LOCATION_TIMEOUT_SUBSEQUENT_SEC);
+    if (location_called_count_ > 0) {
+      CheckLocation(last_location_, checkMoreAccuracies);
+    }
   }
 
   result = gnss_hal_->stop();
@@ -276,4 +318,4 @@
   int status = RUN_ALL_TESTS();
   ALOGI("Test result = %d", status);
   return status;
-}
+}
\ No newline at end of file
diff --git a/graphics/composer/2.1/default/Android.bp b/graphics/composer/2.1/default/Android.bp
index d5da943..0367fcd 100644
--- a/graphics/composer/2.1/default/Android.bp
+++ b/graphics/composer/2.1/default/Android.bp
@@ -37,6 +37,7 @@
         "liblog",
         "libsync",
         "libutils",
+        "libhwc2on1adapter"
     ],
 }
 
diff --git a/graphics/composer/2.1/default/ComposerClient.cpp b/graphics/composer/2.1/default/ComposerClient.cpp
index a2d5d4b..d599b44 100644
--- a/graphics/composer/2.1/default/ComposerClient.cpp
+++ b/graphics/composer/2.1/default/ComposerClient.cpp
@@ -21,7 +21,7 @@
 #include <log/log.h>
 
 #include "ComposerClient.h"
-#include "Hwc.h"
+#include "ComposerBase.h"
 #include "IComposerCommandBuffer.h"
 
 namespace android {
diff --git a/graphics/composer/2.1/default/ComposerClient.h b/graphics/composer/2.1/default/ComposerClient.h
index 14da1f8..c973351 100644
--- a/graphics/composer/2.1/default/ComposerClient.h
+++ b/graphics/composer/2.1/default/ComposerClient.h
@@ -21,8 +21,9 @@
 #include <unordered_map>
 #include <vector>
 
-#include "Hwc.h"
+#include <hardware/hwcomposer2.h>
 #include "IComposerCommandBuffer.h"
+#include "ComposerBase.h"
 
 namespace android {
 namespace hardware {
diff --git a/graphics/composer/2.1/default/Hwc.cpp b/graphics/composer/2.1/default/Hwc.cpp
index cf82967..1497065 100644
--- a/graphics/composer/2.1/default/Hwc.cpp
+++ b/graphics/composer/2.1/default/Hwc.cpp
@@ -16,12 +16,14 @@
 
 #define LOG_TAG "HwcPassthrough"
 
-#include <type_traits>
+#include "Hwc.h"
 
+#include <type_traits>
 #include <log/log.h>
 
 #include "ComposerClient.h"
-#include "Hwc.h"
+#include "hardware/hwcomposer.h"
+#include "hwc2on1adapter/HWC2On1Adapter.h"
 
 namespace android {
 namespace hardware {
@@ -30,13 +32,36 @@
 namespace V2_1 {
 namespace implementation {
 
+
 HwcHal::HwcHal(const hw_module_t* module)
-    : mDevice(nullptr), mDispatch()
+    : mDevice(nullptr), mDispatch(), mAdapter()
 {
-    int status = hwc2_open(module, &mDevice);
-    if (status) {
-        LOG_ALWAYS_FATAL("failed to open hwcomposer2 device: %s",
-                strerror(-status));
+    // Determine what kind of module is available (HWC2 vs HWC1.X).
+    hw_device_t* device = nullptr;
+    int error = module->methods->open(module, HWC_HARDWARE_COMPOSER, &device);
+    if (error != 0) {
+        ALOGE("Failed to open HWC device (%s), aborting", strerror(-error));
+        abort();
+    }
+    uint32_t majorVersion = (device->version >> 24) & 0xF;
+
+    // If we don't have a HWC2, we need to wrap whatever we have in an adapter.
+    if (majorVersion != 2) {
+        uint32_t minorVersion = device->version & HARDWARE_API_VERSION_2_MAJ_MIN_MASK;
+        minorVersion = (minorVersion >> 16) & 0xF;
+        ALOGI("Found HWC implementation v%d.%d", majorVersion, minorVersion);
+        if (minorVersion < 1) {
+            ALOGE("Cannot adapt to HWC version %d.%d. Minimum supported is 1.1",
+                  majorVersion, minorVersion);
+            abort();
+        }
+        mAdapter = std::make_unique<HWC2On1Adapter>(
+                reinterpret_cast<hwc_composer_device_1*>(device));
+
+        // Place the adapter in front of the device module.
+        mDevice = mAdapter.get();
+    } else {
+        mDevice = reinterpret_cast<hwc2_device_t*>(device);
     }
 
     initCapabilities();
diff --git a/graphics/composer/2.1/default/Hwc.h b/graphics/composer/2.1/default/Hwc.h
index ca08cf0..b45389a 100644
--- a/graphics/composer/2.1/default/Hwc.h
+++ b/graphics/composer/2.1/default/Hwc.h
@@ -18,15 +18,23 @@
 #define ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_HWC_H
 
 #include <mutex>
+#include <memory>
 #include <unordered_set>
 #include <vector>
 
 #include <android/hardware/graphics/composer/2.1/IComposer.h>
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
 #include <hardware/hwcomposer2.h>
-
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
 #include "ComposerBase.h"
 
 namespace android {
+    class HWC2On1Adapter;
+}
+
+namespace android {
 namespace hardware {
 namespace graphics {
 namespace composer {
@@ -204,6 +212,10 @@
 
     std::mutex mClientMutex;
     wp<ComposerClient> mClient;
+
+    // If the HWC implementation version is < 2.0, use an adapter to interface
+    // between HWC 2.0 <-> HWC 1.X.
+    std::unique_ptr<HWC2On1Adapter> mAdapter;
 };
 
 extern "C" IComposer* HIDL_FETCH_IComposer(const char* name);
diff --git a/keymaster/3.0/default/KeymasterDevice.cpp b/keymaster/3.0/default/KeymasterDevice.cpp
index 24cf53a..01f0795 100644
--- a/keymaster/3.0/default/KeymasterDevice.cpp
+++ b/keymaster/3.0/default/KeymasterDevice.cpp
@@ -525,6 +525,8 @@
             case Tag::ATTESTATION_ID_SERIAL:
             case Tag::ATTESTATION_ID_IMEI:
             case Tag::ATTESTATION_ID_MEID:
+            case Tag::ATTESTATION_ID_MANUFACTURER:
+            case Tag::ATTESTATION_ID_MODEL:
                 // Device id attestation may only be supported if the device is able to permanently
                 // destroy its knowledge of the ids. This device is unable to do this, so it must
                 // never perform any device id attestation.
@@ -583,6 +585,9 @@
 }
 
 Return<ErrorCode> KeymasterDevice::deleteKey(const hidl_vec<uint8_t>& keyBlob) {
+    if (keymaster_device_->delete_key == nullptr) {
+        return ErrorCode::UNIMPLEMENTED;
+    }
     auto kmKeyBlob = hidlVec2KmKeyBlob(keyBlob);
     return legacy_enum_conversion(keymaster_device_->delete_key(keymaster_device_, &kmKeyBlob));
 }
diff --git a/keymaster/3.0/types.hal b/keymaster/3.0/types.hal
index 9f29b6a..1f4a0cc 100644
--- a/keymaster/3.0/types.hal
+++ b/keymaster/3.0/types.hal
@@ -135,7 +135,10 @@
                                                     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 */
 
     /* 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. */
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_misc.cpp b/radio/1.0/vts/functional/radio_hidl_hal_misc.cpp
index 5fa11fc..f704520 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_misc.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_misc.cpp
@@ -417,6 +417,23 @@
 }
 
 /*
+ * Test IRadio.setCdmaSubscriptionSource() for the response returned.
+ */
+TEST_F(RadioHidlTest, setCdmaSubscriptionSource) {
+    int serial = 1;
+
+    radio->setCdmaSubscriptionSource(++serial, CdmaSubscriptionSource::RUIM_SIM);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp->rspInfo.serial);
+
+    if (cardStatus.cardState == CardState::ABSENT) {
+        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::SIM_ABSENT
+                || radioRsp->rspInfo.error == RadioError::SUBSCRIPTION_NOT_AVAILABLE);
+    }
+}
+
+/*
  * Test IRadio.getVoiceRadioTechnology() for the response returned.
  */
 TEST_F(RadioHidlTest, getVoiceRadioTechnology) {
@@ -455,7 +472,7 @@
     int serial = 1;
 
     // TODO(sanketpadawe): RIL crashes with value of rate = 10
-    radio->setCellInfoListRate(++serial, 0);
+    radio->setCellInfoListRate(++serial, 10);
     EXPECT_EQ(std::cv_status::no_timeout, wait());
     EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_voice.cpp b/radio/1.0/vts/functional/radio_hidl_hal_voice.cpp
index 3638ccb..fa2871d 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_voice.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_voice.cpp
@@ -28,8 +28,7 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE
-                || radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS);
+        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE);
     }
 }
 
@@ -87,8 +86,7 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS
-                || radioRsp->rspInfo.error == RadioError::INVALID_STATE
+        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::INVALID_STATE
                 || radioRsp->rspInfo.error == RadioError::MODEM_ERR
                 || radioRsp->rspInfo.error == RadioError::INTERNAL_ERR);
     }
@@ -106,8 +104,7 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS
-                || radioRsp->rspInfo.error == RadioError::INVALID_STATE
+        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::INVALID_STATE
                 || radioRsp->rspInfo.error == RadioError::MODEM_ERR
                 || radioRsp->rspInfo.error == RadioError::INTERNAL_ERR);
     }
@@ -125,8 +122,7 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS
-                || radioRsp->rspInfo.error == RadioError::INVALID_STATE
+        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::INVALID_STATE
                 || radioRsp->rspInfo.error == RadioError::MODEM_ERR
                 || radioRsp->rspInfo.error == RadioError::INTERNAL_ERR);
     }
@@ -144,8 +140,7 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS
-                || radioRsp->rspInfo.error == RadioError::INVALID_STATE
+        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::INVALID_STATE
                 || radioRsp->rspInfo.error == RadioError::MODEM_ERR
                 || radioRsp->rspInfo.error == RadioError::INTERNAL_ERR);
     }
@@ -163,8 +158,7 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS
-                || radioRsp->rspInfo.error == RadioError::INVALID_STATE
+        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::INVALID_STATE
                 || radioRsp->rspInfo.error == RadioError::MODEM_ERR
                 || radioRsp->rspInfo.error == RadioError::INTERNAL_ERR);
     }
@@ -182,8 +176,7 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS
-                || radioRsp->rspInfo.error == RadioError::NONE);
+        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE);
     }
 }
 
@@ -218,8 +211,7 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS
-                || radioRsp->rspInfo.error == RadioError::INVALID_STATE
+        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::INVALID_STATE
                 || radioRsp->rspInfo.error == RadioError::MODEM_ERR
                 || radioRsp->rspInfo.error == RadioError::INTERNAL_ERR);
     }
@@ -319,8 +311,7 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS
-                || radioRsp->rspInfo.error == RadioError::INVALID_STATE
+        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::INVALID_STATE
                 || radioRsp->rspInfo.error == RadioError::MODEM_ERR
                 || radioRsp->rspInfo.error == RadioError::INTERNAL_ERR);
     }
@@ -358,10 +349,29 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
+        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::INVALID_STATE
+                || radioRsp->rspInfo.error == RadioError::MODEM_ERR
+                || radioRsp->rspInfo.error == RadioError::INTERNAL_ERR);
+    }
+}
+
+/*
+ * Test IRadio.sendCDMAFeatureCode() for the response returned.
+ */
+TEST_F(RadioHidlTest, sendCDMAFeatureCode) {
+    int serial = 1;
+
+    radio->sendCDMAFeatureCode(serial, hidl_string());
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp->rspInfo.serial);
+
+    if (cardStatus.cardState == CardState::ABSENT) {
         ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS
                 || radioRsp->rspInfo.error == RadioError::INVALID_STATE
                 || radioRsp->rspInfo.error == RadioError::MODEM_ERR
-                || radioRsp->rspInfo.error == RadioError::INTERNAL_ERR);
+                || radioRsp->rspInfo.error == RadioError::INTERNAL_ERR
+                || radioRsp->rspInfo.error == RadioError::SYSTEM_ERR);
     }
 }
 
@@ -414,8 +424,7 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS
-                || radioRsp->rspInfo.error == RadioError::SYSTEM_ERR
+        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::SYSTEM_ERR
                 || radioRsp->rspInfo.error == RadioError::MODEM_ERR
                 || radioRsp->rspInfo.error == RadioError::INTERNAL_ERR);
     }
@@ -450,8 +459,7 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS
-                || radioRsp->rspInfo.error == RadioError::NONE);
+        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE);
     }
 }
 
diff --git a/radio/1.0/vts/functional/radio_response.cpp b/radio/1.0/vts/functional/radio_response.cpp
index 8759003..c889a18 100644
--- a/radio/1.0/vts/functional/radio_response.cpp
+++ b/radio/1.0/vts/functional/radio_response.cpp
@@ -496,7 +496,9 @@
     return Void();
 }
 
-Return<void> RadioResponse::setCdmaSubscriptionSourceResponse(const RadioResponseInfo& /*info*/) {
+Return<void> RadioResponse::setCdmaSubscriptionSourceResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent.notify();
     return Void();
 }
 
@@ -539,7 +541,9 @@
     return Void();
 }
 
-Return<void> RadioResponse::sendCDMAFeatureCodeResponse(const RadioResponseInfo& /*info*/) {
+Return<void> RadioResponse::sendCDMAFeatureCodeResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent.notify();
     return Void();
 }
 
diff --git a/sensors/1.0/default/Sensors.cpp b/sensors/1.0/default/Sensors.cpp
index 2457310..1100dd6 100644
--- a/sensors/1.0/default/Sensors.cpp
+++ b/sensors/1.0/default/Sensors.cpp
@@ -97,6 +97,15 @@
     // is considered optional.
     CHECK_GE(getHalDeviceVersion(), SENSORS_DEVICE_API_VERSION_1_3);
 
+    if (getHalDeviceVersion() == SENSORS_DEVICE_API_VERSION_1_4) {
+        if (mSensorDevice->inject_sensor_data == nullptr) {
+            LOG(ERROR) << "HAL specifies version 1.4, but does not implement inject_sensor_data()";
+        }
+        if (mSensorModule->set_operation_mode == nullptr) {
+            LOG(ERROR) << "HAL specifies version 1.4, but does not implement set_operation_mode()";
+        }
+    }
+
     mInitCheck = OK;
 }
 
@@ -132,6 +141,10 @@
 }
 
 Return<Result> Sensors::setOperationMode(OperationMode mode) {
+    if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_4
+            || mSensorModule->set_operation_mode == nullptr) {
+        return Result::INVALID_OPERATION;
+    }
     return ResultFromStatus(mSensorModule->set_operation_mode((uint32_t)mode));
 }
 
@@ -236,7 +249,8 @@
 }
 
 Return<Result> Sensors::injectSensorData(const Event& event) {
-    if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_4) {
+    if (getHalDeviceVersion() < SENSORS_DEVICE_API_VERSION_1_4
+            || mSensorDevice->inject_sensor_data == nullptr) {
         return Result::INVALID_OPERATION;
     }
 
diff --git a/tests/Android.bp b/tests/Android.bp
index 6606d94..31dc75e 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -23,4 +23,5 @@
     "versioning/1.0",
     "versioning/2.2",
     "versioning/2.3",
+    "versioning/2.4",
 ]
diff --git a/tests/baz/1.0/default/Baz.cpp b/tests/baz/1.0/default/Baz.cpp
index 6252fbe..875fe65 100644
--- a/tests/baz/1.0/default/Baz.cpp
+++ b/tests/baz/1.0/default/Baz.cpp
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 #include "Baz.h"
 #include <android-base/logging.h>
 
@@ -26,150 +42,6 @@
     return Void();
 }
 
-// TODO(b/35703683) : replace usage of below methods with toString()
-
-static std::string to_string(const IBaz::Foo::Bar &bar);
-static std::string to_string(const IBaz::Foo &foo);
-static std::string to_string(const hidl_string &s);
-static std::string to_string(bool x);
-static std::string to_string(const IBaz::StringMatrix5x3 &M);
-
-template<typename T, size_t SIZE>
-static std::string to_string(const hidl_array<T, SIZE> &array);
-
-template<size_t SIZE>
-static std::string to_string(const hidl_array<uint8_t, SIZE> &array);
-
-template<typename T>
-static std::string to_string(const hidl_vec<T> &vec) {
-    std::string out;
-    out = "[";
-    for (size_t i = 0; i < vec.size(); ++i) {
-        if (i > 0) {
-            out += ", ";
-        }
-        out += to_string(vec[i]);
-    }
-    out += "]";
-
-    return out;
-}
-
-template<typename T, size_t SIZE>
-static std::string to_string(const hidl_array<T, SIZE> &array) {
-    std::string out;
-    out = "[";
-    for (size_t i = 0; i < SIZE; ++i) {
-        if (i > 0) {
-            out += ", ";
-        }
-        out += to_string(array[i]);
-    }
-    out += "]";
-
-    return out;
-}
-
-template<size_t SIZE>
-static std::string to_string(const hidl_array<uint8_t, SIZE> &array) {
-    std::string out;
-    for (size_t i = 0; i < SIZE; ++i) {
-        if (i > 0) {
-            out += ":";
-        }
-
-        char tmp[3];
-        sprintf(tmp, "%02x", array[i]);
-
-        out += tmp;
-    }
-
-    return out;
-}
-
-template<typename T, size_t SIZE1, size_t SIZE2>
-static std::string to_string(const hidl_array<T, SIZE1, SIZE2> &array) {
-    std::string out;
-    out = "[";
-    for (size_t i = 0; i < SIZE1; ++i) {
-        if (i > 0) {
-            out += ", ";
-        }
-
-        out += "[";
-        for (size_t j = 0; j < SIZE2; ++j) {
-            if (j > 0) {
-                out += ", ";
-            }
-
-            out += to_string(array[i][j]);
-        }
-        out += "]";
-    }
-    out += "]";
-
-    return out;
-}
-
-static std::string to_string(bool x) {
-    return x ? "true" : "false";
-}
-
-static std::string to_string(const hidl_string &s) {
-    return std::string("'") + s.c_str() + "'";
-}
-
-static std::string to_string(const IBaz::Foo::Bar &bar) {
-    std::string out;
-    out = "Bar(";
-    out += "z = " + to_string(bar.z) + ", ";
-    out += "s = '" + std::string(bar.s.c_str()) + "'";
-    out += ")";
-
-    return out;
-}
-
-static std::string to_string(const IBaz::Foo &foo) {
-    std::string out;
-    out = "Foo(";
-    out += "x = " + to_string(foo.x) + ", ";
-    out += "y = " + to_string(foo.y) + ", ";
-    out += "aaa = " + to_string(foo.aaa);
-    out += ")";
-
-    return out;
-}
-
-static std::string to_string(const IBaz::StringMatrix5x3 &M) {
-    return to_string(M.s);
-}
-
-static std::string VectorOfArray_to_string(const IBaz::VectorOfArray &in) {
-    std::string out;
-    out += "VectorOfArray(";
-
-    for (size_t i = 0; i < in.addresses.size(); ++i) {
-        if (i > 0) {
-            out += ", ";
-        }
-
-        for (size_t j = 0; j < 6; ++j) {
-            if (j > 0) {
-                out += ":";
-            }
-
-            char tmp[3];
-            sprintf(tmp, "%02x", in.addresses[i][j]);
-
-            out += tmp;
-        }
-    }
-
-    out += ")";
-
-    return out;
-}
-
 // Methods from ::android::hardware::tests::baz::V1_0::IBase follow.
 Return<void> Baz::someBaseMethod() {
     LOG(INFO) << "Baz::someBaseMethod";
@@ -178,20 +50,14 @@
 }
 
 Return<bool> Baz::someBoolMethod(bool x) {
-    LOG(INFO) << "Baz::someBoolMethod(" << to_string(x) << ")";
+    LOG(INFO) << "Baz::someBoolMethod(" << std::to_string(x) << ")";
 
     return !x;
 }
 
 Return<void> Baz::someBoolArrayMethod(const hidl_array<bool, 3>& x,
                                       someBoolArrayMethod_cb _hidl_cb) {
-    LOG(INFO) << "Baz::someBoolArrayMethod("
-        << to_string(x[0])
-        << ", "
-        << to_string(x[1])
-        << ", "
-        << to_string(x[2])
-        << ")";
+    LOG(INFO) << "Baz::someBoolArrayMethod(" << toString(x) << ")";
 
     hidl_array<bool, 4> out;
     out[0] = !x[0];
@@ -205,7 +71,7 @@
 }
 
 Return<void> Baz::someBoolVectorMethod(const hidl_vec<bool>& x, someBoolVectorMethod_cb _hidl_cb) {
-    LOG(INFO) << "Baz::someBoolVectorMethod(" << to_string(x) << ")";
+    LOG(INFO) << "Baz::someBoolVectorMethod(" << toString(x) << ")";
 
     hidl_vec<bool> out;
     out.resize(x.size());
@@ -220,7 +86,7 @@
 
 Return<void> Baz::someOtherBaseMethod(const IBase::Foo& foo, someOtherBaseMethod_cb _hidl_cb) {
     LOG(INFO) << "Baz::someOtherBaseMethod "
-              << to_string(foo);
+              << toString(foo);
 
     _hidl_cb(foo);
 
@@ -230,7 +96,7 @@
 Return<void> Baz::someMethodWithFooArrays(const hidl_array<IBase::Foo, 2>& fooInput,
                                           someMethodWithFooArrays_cb _hidl_cb) {
     LOG(INFO) << "Baz::someMethodWithFooArrays "
-              << to_string(fooInput);
+              << toString(fooInput);
 
     hidl_array<IBaz::Foo, 2> fooOutput;
     fooOutput[0] = fooInput[1];
@@ -244,7 +110,7 @@
 Return<void> Baz::someMethodWithFooVectors(const hidl_vec<IBase::Foo>& fooInput,
                                            someMethodWithFooVectors_cb _hidl_cb) {
     LOG(INFO) << "Baz::someMethodWithFooVectors "
-              << to_string(fooInput);
+              << toString(fooInput);
 
     hidl_vec<IBaz::Foo> fooOutput;
     fooOutput.resize(2);
@@ -259,7 +125,7 @@
 Return<void> Baz::someMethodWithVectorOfArray(const IBase::VectorOfArray& in,
                                               someMethodWithVectorOfArray_cb _hidl_cb) {
     LOG(INFO) << "Baz::someMethodWithVectorOfArray "
-              << VectorOfArray_to_string(in);
+              << toString(in);
 
     IBase::VectorOfArray out;
 
@@ -278,7 +144,7 @@
 Return<void> Baz::someMethodTakingAVectorOfArray(const hidl_vec<hidl_array<uint8_t, 6>>& in,
                                                  someMethodTakingAVectorOfArray_cb _hidl_cb) {
     LOG(INFO) << "Baz::someMethodTakingAVectorOfArray "
-              << to_string(in);
+              << toString(in);
 
     const size_t n = in.size();
 
@@ -295,7 +161,7 @@
 }
 
 Return<void> Baz::transpose(const IBase::StringMatrix5x3& in, transpose_cb _hidl_cb) {
-    LOG(INFO) << "Baz::transpose " << to_string(in);
+    LOG(INFO) << "Baz::transpose " << toString(in);
 
     IBase::StringMatrix3x5 out;
     for (size_t i = 0; i < 3; ++i) {
@@ -310,7 +176,7 @@
 }
 
 Return<void> Baz::transpose2(const hidl_array<hidl_string, 5, 3>& in, transpose2_cb _hidl_cb) {
-    LOG(INFO) << "Baz::transpose2 " << to_string(in);
+    LOG(INFO) << "Baz::transpose2 " << toString(in);
 
     hidl_array<hidl_string, 3, 5> out;
     for (size_t i = 0; i < 3; ++i) {
@@ -443,7 +309,7 @@
 Return<void> Baz::haveSomeStrings(const hidl_array<hidl_string, 3>& array,
                                   haveSomeStrings_cb _hidl_cb) {
     LOG(INFO) << "haveSomeStrings("
-              << to_string(array)
+              << toString(array)
               << ")";
 
     hidl_array<hidl_string, 2> result;
@@ -457,7 +323,7 @@
 
 Return<void> Baz::haveAStringVec(const hidl_vec<hidl_string>& vector,
                                  haveAStringVec_cb _hidl_cb) {
-    LOG(INFO) << "haveAStringVec(" << to_string(vector) << ")";
+    LOG(INFO) << "haveAStringVec(" << toString(vector) << ")";
 
     hidl_vec<hidl_string> result;
     result.resize(2);
diff --git a/tests/extension/light/2.0/Android.bp b/tests/extension/light/2.0/Android.bp
index 5203da6..123bea1 100644
--- a/tests/extension/light/2.0/Android.bp
+++ b/tests/extension/light/2.0/Android.bp
@@ -51,6 +51,7 @@
         "libutils",
         "libcutils",
         "android.hardware.light@2.0",
+        "android.hidl.base@1.0",
     ],
     export_shared_lib_headers: [
         "libhidlbase",
@@ -58,5 +59,6 @@
         "libhwbinder",
         "libutils",
         "android.hardware.light@2.0",
+        "android.hidl.base@1.0",
     ],
 }
diff --git a/tests/versioning/2.3/Android.bp b/tests/versioning/2.3/Android.bp
index 122c484..3cc2076 100644
--- a/tests/versioning/2.3/Android.bp
+++ b/tests/versioning/2.3/Android.bp
@@ -63,6 +63,7 @@
         "libcutils",
         "android.hardware.tests.versioning@1.0",
         "android.hardware.tests.versioning@2.2",
+        "android.hidl.base@1.0",
     ],
     export_shared_lib_headers: [
         "libhidlbase",
@@ -71,5 +72,6 @@
         "libutils",
         "android.hardware.tests.versioning@1.0",
         "android.hardware.tests.versioning@2.2",
+        "android.hidl.base@1.0",
     ],
 }
diff --git a/tests/versioning/2.4/Android.bp b/tests/versioning/2.4/Android.bp
new file mode 100644
index 0000000..9d8303c
--- /dev/null
+++ b/tests/versioning/2.4/Android.bp
@@ -0,0 +1,63 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+filegroup {
+    name: "android.hardware.tests.versioning@2.4_hal",
+    srcs: [
+        "IFoo.hal",
+    ],
+}
+
+genrule {
+    name: "android.hardware.tests.versioning@2.4_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tests.versioning@2.4",
+    srcs: [
+        ":android.hardware.tests.versioning@2.4_hal",
+    ],
+    out: [
+        "android/hardware/tests/versioning/2.4/FooAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.tests.versioning@2.4_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++ -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tests.versioning@2.4",
+    srcs: [
+        ":android.hardware.tests.versioning@2.4_hal",
+    ],
+    out: [
+        "android/hardware/tests/versioning/2.4/IFoo.h",
+        "android/hardware/tests/versioning/2.4/IHwFoo.h",
+        "android/hardware/tests/versioning/2.4/BnHwFoo.h",
+        "android/hardware/tests/versioning/2.4/BpHwFoo.h",
+        "android/hardware/tests/versioning/2.4/BsFoo.h",
+    ],
+}
+
+cc_library_shared {
+    name: "android.hardware.tests.versioning@2.4",
+    generated_sources: ["android.hardware.tests.versioning@2.4_genc++"],
+    generated_headers: ["android.hardware.tests.versioning@2.4_genc++_headers"],
+    export_generated_headers: ["android.hardware.tests.versioning@2.4_genc++_headers"],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hardware.tests.versioning@2.2",
+        "android.hardware.tests.versioning@2.3",
+        "android.hidl.base@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hardware.tests.versioning@2.2",
+        "android.hardware.tests.versioning@2.3",
+        "android.hidl.base@1.0",
+    ],
+}
diff --git a/tests/versioning/2.4/Android.mk b/tests/versioning/2.4/Android.mk
new file mode 100644
index 0000000..e41397f
--- /dev/null
+++ b/tests/versioning/2.4/Android.mk
@@ -0,0 +1,80 @@
+# This file is autogenerated by hidl-gen. Do not edit manually.
+
+LOCAL_PATH := $(call my-dir)
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.tests.versioning@2.4-java
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(call local-generated-sources-dir, COMMON)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_JAVA_LIBRARIES := \
+    android.hardware.tests.versioning@2.2-java \
+    android.hardware.tests.versioning@2.3-java \
+    android.hidl.base@1.0-java \
+
+
+#
+# Build IFoo.hal
+#
+GEN := $(intermediates)/android/hardware/tests/versioning/V2_4/IFoo.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IFoo.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tests.versioning@2.4::IFoo
+
+$(GEN): $(LOCAL_PATH)/IFoo.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_JAVA_LIBRARY)
+
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.tests.versioning@2.4-java-static
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(call local-generated-sources-dir, COMMON)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android.hardware.tests.versioning@2.2-java-static \
+    android.hardware.tests.versioning@2.3-java-static \
+    android.hidl.base@1.0-java-static \
+
+
+#
+# Build IFoo.hal
+#
+GEN := $(intermediates)/android/hardware/tests/versioning/V2_4/IFoo.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IFoo.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tests.versioning@2.4::IFoo
+
+$(GEN): $(LOCAL_PATH)/IFoo.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/versioning/2.4/IFoo.hal b/tests/versioning/2.4/IFoo.hal
new file mode 100644
index 0000000..358b56f
--- /dev/null
+++ b/tests/versioning/2.4/IFoo.hal
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2017 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.tests.versioning@2.4;
+
+import @2.3::IFoo;
+
+// Must extend @2.3::IFoo.
+interface IFoo extends @2.3::IFoo {
+
+};
diff --git a/update-makefiles.sh b/update-makefiles.sh
index d0cb91c..88cc97b 100755
--- a/update-makefiles.sh
+++ b/update-makefiles.sh
@@ -1,52 +1,8 @@
 #!/bin/bash
 
-if [ ! -d hardware/interfaces ] ; then
-  echo "Where is hardware/interfaces?";
-  exit 1;
-fi
+source system/tools/hidl/update-makefiles-helper.sh
 
-if [ ! -d system/libhidl/transport ] ; then
-  echo "Where is system/libhidl/transport?";
-  exit 1;
-fi
+do_makefiles_update \
+  "android.hardware:hardware/interfaces" \
+  "android.hidl:system/libhidl/transport"
 
-packages=$(pushd hardware/interfaces > /dev/null; \
-           find . -type f -name \*.hal -exec dirname {} \; | sort -u | \
-           cut -c3- | \
-           awk -F'/' \
-                '{printf("android.hardware"); for(i=1;i<NF;i++){printf(".%s", $i);}; printf("@%s\n", $NF);}'; \
-           popd > /dev/null)
-
-for p in $packages; do
-  echo "Updating $p";
-  hidl-gen -Lmakefile -r android.hardware:hardware/interfaces -r android.hidl:system/libhidl/transport $p;
-  rc=$?; if [[ $rc != 0 ]]; then exit $rc; fi
-  hidl-gen -Landroidbp -r android.hardware:hardware/interfaces -r android.hidl:system/libhidl/transport $p;
-  rc=$?; if [[ $rc != 0 ]]; then exit $rc; fi
-done
-
-# subdirectories of hardware/interfaces which contain an Android.bp file
-android_dirs=$(find hardware/interfaces/*/     \
-              -name "Android.bp"               \
-              -printf "%h\n"                   \
-              | cut -d "/" -f1-3               \
-              | sort | uniq)
-
-echo "Updating Android.bp files."
-
-for bp_dir in $android_dirs; do
-  bp="$bp_dir/Android.bp"
-  # locations of Android.bp files in specific subdirectory of hardware/interfaces
-  android_bps=$(find $bp_dir                   \
-                -name "Android.bp"             \
-                ! -path $bp_dir/Android.bp     \
-                -printf "%h\n"                 \
-                | sort)
-
-  echo "// This is an autogenerated file, do not edit." > "$bp";
-  echo "subdirs = [" >> "$bp";
-  for a in $android_bps; do
-    echo "    \"${a#$bp_dir/}\"," >> "$bp";
-  done
-  echo "]" >> "$bp";
-done
diff --git a/usb/1.0/default/service.cpp b/usb/1.0/default/service.cpp
index b4db241..4605a4c 100644
--- a/usb/1.0/default/service.cpp
+++ b/usb/1.0/default/service.cpp
@@ -28,12 +28,11 @@
 using android::hardware::usb::V1_0::implementation::Usb;
 
 int main() {
-    const char instance[] = "usb_hal";
 
     android::sp<IUsb> service = new Usb();
 
     configureRpcThreadpool(1, true /*callerWillJoin*/);
-    service->registerAsService(instance);
+    service->registerAsService();
 
     ALOGI("USB HAL Ready.");
     joinRpcThreadpool();
diff --git a/usb/1.0/vts/functional/VtsHalUsbV1_0TargetTest.cpp b/usb/1.0/vts/functional/VtsHalUsbV1_0TargetTest.cpp
index 54db8c2..ea6d4a9 100644
--- a/usb/1.0/vts/functional/VtsHalUsbV1_0TargetTest.cpp
+++ b/usb/1.0/vts/functional/VtsHalUsbV1_0TargetTest.cpp
@@ -47,8 +47,6 @@
 using ::android::hardware::Void;
 using ::android::sp;
 
-#define USB_SERVICE_NAME "usb_hal"
-
 // The main test class for the USB hidl HAL
 class UsbHidlTest : public ::testing::VtsHalHidlTargetTestBase {
  public:
@@ -97,7 +95,7 @@
 
   virtual void SetUp() override {
     ALOGI("Setup");
-    usb = ::testing::VtsHalHidlTargetTestBase::getService<IUsb>(USB_SERVICE_NAME);
+    usb = ::testing::VtsHalHidlTargetTestBase::getService<IUsb>();
     ASSERT_NE(usb, nullptr);
 
     usb_cb_2 = new UsbCallback(*this, 2);
diff --git a/vibrator/1.0/Android.mk b/vibrator/1.0/Android.mk
index 4e1ba6a..d921a7e 100644
--- a/vibrator/1.0/Android.mk
+++ b/vibrator/1.0/Android.mk
@@ -17,6 +17,25 @@
 
 
 #
+# Build types.hal (Effect)
+#
+GEN := $(intermediates)/android/hardware/vibrator/V1_0/Effect.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vibrator@1.0::types.Effect
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
 # Build types.hal (Status)
 #
 GEN := $(intermediates)/android/hardware/vibrator/V1_0/Status.java
@@ -73,6 +92,25 @@
 
 
 #
+# Build types.hal (Effect)
+#
+GEN := $(intermediates)/android/hardware/vibrator/V1_0/Effect.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vibrator@1.0::types.Effect
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
 # Build types.hal (Status)
 #
 GEN := $(intermediates)/android/hardware/vibrator/V1_0/Status.java
@@ -114,5 +152,39 @@
 include $(BUILD_STATIC_JAVA_LIBRARY)
 
 
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.vibrator@1.0-java-constants
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(local-generated-sources-dir)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+#
+GEN := $(intermediates)/android/hardware/vibrator/V1_0/Constants.java
+$(GEN): $(HIDL)
+$(GEN): $(LOCAL_PATH)/types.hal
+$(GEN): $(LOCAL_PATH)/IVibrator.hal
+
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava-constants \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.vibrator@1.0
+
+$(GEN):
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+# Avoid dependency cycle of framework.jar -> this-library -> framework.jar
+LOCAL_NO_STANDARD_LIBRARIES := true
+LOCAL_JAVA_LIBRARIES := core-oj
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
 
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/vibrator/1.0/IVibrator.hal b/vibrator/1.0/IVibrator.hal
index 0a4ffca..757ad0d 100644
--- a/vibrator/1.0/IVibrator.hal
+++ b/vibrator/1.0/IVibrator.hal
@@ -17,7 +17,8 @@
 package android.hardware.vibrator@1.0;
 
 interface IVibrator {
-  /** Turn on vibrator
+  /**
+   * Turn on vibrator
    *
    * This function must only be called after the previous timeout has expired or
    * was canceled (through off()).
@@ -26,10 +27,46 @@
    */
   on(uint32_t timeoutMs) generates (Status vibratorOnRet);
 
-  /** Turn off vibrator
+  /**
+   * Turn off vibrator
    *
    * Cancel a previously-started vibration, if any.
    * @return vibratorOffRet whether vibrator command was successful or not.
    */
   off() generates (Status vibratorOffRet);
+
+  /**
+   * Returns whether the vibrator supports changes to its vibrational amplitude.
+   */
+  supportsAmplitudeControl() generates (bool supports);
+
+  /**
+   * Sets the motor's vibrational amplitude.
+   *
+   * Changes the force being produced by the underlying motor.
+   *
+   * @param amplitude The unitless force setting. Note that this number must
+   *                  be between 1 and 255, inclusive. If the motor does not
+   *                  have exactly 255 steps, it must do it's best to map it
+   *                  onto the number of steps it does have.
+   * @return status Whether the command was successful or not. Must return
+   *                Status::UNSUPPORTED_OPERATION if setting the amplitude is
+   *                not supported by the device.
+   */
+  setAmplitude(uint8_t amplitude) generates (Status status);
+
+  /**
+   * Fire off a predefined haptic event.
+   *
+   * @param event The type of haptic event to trigger.
+   * @return status Whether the effect was successfully performed or not. Must
+   *                return Status::UNSUPPORTED_OPERATION is the effect is not
+   *                supported.
+   * @return lengthMs The length of time the event is expected to take in
+   *                  milliseconds. This doesn't need to be perfectly accurate,
+   *                  but should be a reasonable approximation. Should be a
+   *                  positive, non-zero value if the returned status is
+   *                  Status::OK, and set to 0 otherwise.
+   */
+  perform(Effect effect, EffectStrength strength) generates (Status status, uint32_t lengthMs);
 };
diff --git a/vibrator/1.0/default/Vibrator.cpp b/vibrator/1.0/default/Vibrator.cpp
index 8c82bcd..19cf3dc 100644
--- a/vibrator/1.0/default/Vibrator.cpp
+++ b/vibrator/1.0/default/Vibrator.cpp
@@ -16,6 +16,8 @@
 
 #define LOG_TAG "VibratorService"
 
+#include <inttypes.h>
+
 #include <log/log.h>
 
 #include <hardware/hardware.h>
@@ -36,7 +38,7 @@
     int32_t ret = mDevice->vibrator_on(mDevice, timeout_ms);
     if (ret != 0) {
         ALOGE("on command failed : %s", strerror(-ret));
-        return Status::ERR;
+        return Status::UNKNOWN_ERROR;
     }
     return Status::OK;
 }
@@ -45,11 +47,24 @@
     int32_t ret = mDevice->vibrator_off(mDevice);
     if (ret != 0) {
         ALOGE("off command failed : %s", strerror(-ret));
-        return Status::ERR;
+        return Status::UNKNOWN_ERROR;
     }
     return Status::OK;
 }
 
+Return<bool> Vibrator::supportsAmplitudeControl()  {
+    return false;
+}
+
+Return<Status> Vibrator::setAmplitude(uint8_t) {
+    return Status::UNSUPPORTED_OPERATION;
+}
+
+Return<void> Vibrator::perform(Effect, EffectStrength, perform_cb _hidl_cb) {
+    _hidl_cb(Status::UNSUPPORTED_OPERATION, 0);
+    return Void();
+}
+
 IVibrator* HIDL_FETCH_IVibrator(const char * /*hal*/) {
     vibrator_device_t *vib_device;
     const hw_module_t *hw_module = nullptr;
diff --git a/vibrator/1.0/default/Vibrator.h b/vibrator/1.0/default/Vibrator.h
index 061b364..bea6ea8 100644
--- a/vibrator/1.0/default/Vibrator.h
+++ b/vibrator/1.0/default/Vibrator.h
@@ -26,23 +26,18 @@
 namespace V1_0 {
 namespace implementation {
 
-using ::android::hardware::vibrator::V1_0::IVibrator;
-using ::android::hardware::vibrator::V1_0::Status;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::hidl_string;
-using ::android::sp;
-
 struct Vibrator : public IVibrator {
   Vibrator(vibrator_device_t *device);
 
   // Methods from ::android::hardware::vibrator::V1_0::IVibrator follow.
   Return<Status> on(uint32_t timeoutMs)  override;
   Return<Status> off()  override;
+  Return<bool> supportsAmplitudeControl() override;
+  Return<Status> setAmplitude(uint8_t amplitude) override;
+  Return<void> perform(Effect effect, EffectStrength strength, perform_cb _hidl_cb) override;
 
-  private:
-    vibrator_device_t    *mDevice;
+private:
+  vibrator_device_t    *mDevice;
 };
 
 extern "C" IVibrator* HIDL_FETCH_IVibrator(const char* name);
diff --git a/vibrator/1.0/types.hal b/vibrator/1.0/types.hal
index 8fc5683..a080c07 100644
--- a/vibrator/1.0/types.hal
+++ b/vibrator/1.0/types.hal
@@ -16,7 +16,33 @@
 
 package android.hardware.vibrator@1.0;
 
-enum Status: uint32_t {
-    OK             = 0,
-    ERR            = 1
+enum Status : uint32_t {
+    OK,
+    UNKNOWN_ERROR,
+    BAD_VALUE,
+    UNSUPPORTED_OPERATION
+};
+
+@export
+enum Effect : uint32_t {
+    /**
+     * A single click effect.
+     *
+     * This effect should produce a sharp, crisp click sensation.
+     */
+    CLICK,
+    /**
+     * A double click effect.
+     *
+     * This effect should produce two sequential sharp, crisp click sensations with a minimal
+     * amount of time between them.
+     */
+    DOUBLE_CLICK
+};
+
+@export
+enum EffectStrength : uint8_t {
+    LIGHT,
+    MEDIUM,
+    STRONG
 };
diff --git a/vibrator/1.0/vts/functional/VtsHalVibratorV1_0TargetTest.cpp b/vibrator/1.0/vts/functional/VtsHalVibratorV1_0TargetTest.cpp
index a978f2c..f415ad5 100644
--- a/vibrator/1.0/vts/functional/VtsHalVibratorV1_0TargetTest.cpp
+++ b/vibrator/1.0/vts/functional/VtsHalVibratorV1_0TargetTest.cpp
@@ -22,6 +22,8 @@
 #include <VtsHalHidlTargetTestBase.h>
 #include <unistd.h>
 
+using ::android::hardware::vibrator::V1_0::Effect;
+using ::android::hardware::vibrator::V1_0::EffectStrength;
 using ::android::hardware::vibrator::V1_0::IVibrator;
 using ::android::hardware::vibrator::V1_0::Status;
 using ::android::hardware::Return;
@@ -50,12 +52,49 @@
  private:
 };
 
+static void validatePerformEffect(Status status, uint32_t lengthMs) {
+  ASSERT_TRUE(status == Status::OK || status == Status::UNSUPPORTED_OPERATION);
+  if (status == Status::OK) {
+      ASSERT_GT(lengthMs, static_cast<uint32_t>(0));
+  } else {
+      ASSERT_EQ(lengthMs, static_cast<uint32_t>(0));
+  }
+}
+
 TEST_F(VibratorHidlTest, OnThenOffBeforeTimeout) {
   EXPECT_EQ(Status::OK, vibrator->on(2000));
   sleep(1);
   EXPECT_EQ(Status::OK, vibrator->off());
 }
 
+TEST_F(VibratorHidlTest, PerformEffect) {
+  vibrator->perform(Effect::CLICK, EffectStrength::MEDIUM, validatePerformEffect);
+  vibrator->perform(Effect::DOUBLE_CLICK, EffectStrength::LIGHT, validatePerformEffect);
+}
+
+TEST_F(VibratorHidlTest, ChangeVibrationalAmplitude) {
+  if (vibrator->supportsAmplitudeControl()) {
+    EXPECT_EQ(Status::OK, vibrator->setAmplitude(1));
+    EXPECT_EQ(Status::OK, vibrator->on(2000));
+    EXPECT_EQ(Status::OK, vibrator->setAmplitude(128));
+    sleep(1);
+    EXPECT_EQ(Status::OK, vibrator->setAmplitude(255));
+    sleep(1);
+  }
+}
+
+TEST_F(VibratorHidlTest, AmplitudeOutsideRangeFails) {
+  if (vibrator->supportsAmplitudeControl()) {
+    EXPECT_EQ(Status::BAD_VALUE, vibrator->setAmplitude(0));
+  }
+}
+
+TEST_F(VibratorHidlTest, SetAmplitudeReturnUnsupportedOperationIfNotSupported) {
+  if (!vibrator->supportsAmplitudeControl()) {
+    EXPECT_EQ(Status::UNSUPPORTED_OPERATION, vibrator->setAmplitude(1));
+  }
+}
+
 int main(int argc, char **argv) {
   ::testing::AddGlobalTestEnvironment(new VibratorHidlEnvironment);
   ::testing::InitGoogleTest(&argc, argv);
diff --git a/wifi/1.0/Android.mk b/wifi/1.0/Android.mk
index eabc63d..82409de 100644
--- a/wifi/1.0/Android.mk
+++ b/wifi/1.0/Android.mk
@@ -226,6 +226,44 @@
 LOCAL_GENERATED_SOURCES += $(GEN)
 
 #
+# Build types.hal (NanDataPathSecurityConfig)
+#
+GEN := $(intermediates)/android/hardware/wifi/V1_0/NanDataPathSecurityConfig.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.wifi@1.0::types.NanDataPathSecurityConfig
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (NanDataPathSecurityType)
+#
+GEN := $(intermediates)/android/hardware/wifi/V1_0/NanDataPathSecurityType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.wifi@1.0::types.NanDataPathSecurityType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
 # Build types.hal (NanDebugConfig)
 #
 GEN := $(intermediates)/android/hardware/wifi/V1_0/NanDebugConfig.java
@@ -359,6 +397,25 @@
 LOCAL_GENERATED_SOURCES += $(GEN)
 
 #
+# Build types.hal (NanParamSizeLimits)
+#
+GEN := $(intermediates)/android/hardware/wifi/V1_0/NanParamSizeLimits.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.wifi@1.0::types.NanParamSizeLimits
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
 # Build types.hal (NanPublishRequest)
 #
 GEN := $(intermediates)/android/hardware/wifi/V1_0/NanPublishRequest.java
@@ -2048,6 +2105,44 @@
 LOCAL_GENERATED_SOURCES += $(GEN)
 
 #
+# Build types.hal (NanDataPathSecurityConfig)
+#
+GEN := $(intermediates)/android/hardware/wifi/V1_0/NanDataPathSecurityConfig.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.wifi@1.0::types.NanDataPathSecurityConfig
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (NanDataPathSecurityType)
+#
+GEN := $(intermediates)/android/hardware/wifi/V1_0/NanDataPathSecurityType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.wifi@1.0::types.NanDataPathSecurityType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
 # Build types.hal (NanDebugConfig)
 #
 GEN := $(intermediates)/android/hardware/wifi/V1_0/NanDebugConfig.java
@@ -2181,6 +2276,25 @@
 LOCAL_GENERATED_SOURCES += $(GEN)
 
 #
+# Build types.hal (NanParamSizeLimits)
+#
+GEN := $(intermediates)/android/hardware/wifi/V1_0/NanParamSizeLimits.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.wifi@1.0::types.NanParamSizeLimits
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
 # Build types.hal (NanPublishRequest)
 #
 GEN := $(intermediates)/android/hardware/wifi/V1_0/NanPublishRequest.java
diff --git a/wifi/1.0/default/hidl_struct_util.cpp b/wifi/1.0/default/hidl_struct_util.cpp
index fb93c5a..c005213 100644
--- a/wifi/1.0/default/hidl_struct_util.cpp
+++ b/wifi/1.0/default/hidl_struct_util.cpp
@@ -973,17 +973,41 @@
         hidl_request.baseConfigs.disableMatchExpirationIndication ? 0x2 : 0x0;
   legacy_request->recv_indication_cfg |=
         hidl_request.baseConfigs.disableFollowupReceivedIndication ? 0x4 : 0x0;
-  legacy_request->cipher_type = (unsigned int) hidl_request.baseConfigs.cipherType;
-  legacy_request->pmk_len = hidl_request.baseConfigs.pmk.size();
-  if (legacy_request->pmk_len > NAN_PMK_INFO_LEN) {
-    LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: pmk_len too large";
-    return false;
+  legacy_request->cipher_type = (unsigned int) hidl_request.baseConfigs.securityConfig.cipherType;
+  if (hidl_request.baseConfigs.securityConfig.securityType == NanDataPathSecurityType::PMK) {
+    legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PMK;
+    legacy_request->key_info.body.pmk_info.pmk_len =
+        hidl_request.baseConfigs.securityConfig.pmk.size();
+    if (legacy_request->key_info.body.pmk_info.pmk_len > NAN_PMK_INFO_LEN) {
+      LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: pmk_len too large";
+      return false;
+    }
+    memcpy(legacy_request->key_info.body.pmk_info.pmk,
+          hidl_request.baseConfigs.securityConfig.pmk.data(),
+          legacy_request->key_info.body.pmk_info.pmk_len);
   }
-  memcpy(legacy_request->pmk,
-        hidl_request.baseConfigs.pmk.data(),
-        legacy_request->pmk_len);
-  legacy_request->sdea_params.security_cfg = hidl_request.baseConfigs.securityEnabledInNdp ?
-        legacy_hal::NAN_DP_CONFIG_SECURITY : legacy_hal::NAN_DP_CONFIG_NO_SECURITY;
+  if (hidl_request.baseConfigs.securityConfig.securityType
+        == NanDataPathSecurityType::PASSPHRASE) {
+    legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
+    legacy_request->key_info.body.passphrase_info.passphrase_len =
+        hidl_request.baseConfigs.securityConfig.passphrase.size();
+    if (legacy_request->key_info.body.passphrase_info.passphrase_len
+            < NAN_SECURITY_MIN_PASSPHRASE_LEN) {
+      LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: passphrase_len too small";
+      return false;
+    }
+    if (legacy_request->key_info.body.passphrase_info.passphrase_len
+            > NAN_SECURITY_MIN_PASSPHRASE_LEN) {
+      LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: passphrase_len too large";
+      return false;
+    }
+    memcpy(legacy_request->key_info.body.passphrase_info.passphrase,
+          hidl_request.baseConfigs.securityConfig.passphrase.data(),
+          legacy_request->key_info.body.passphrase_info.passphrase_len);
+  }
+  legacy_request->sdea_params.security_cfg = (hidl_request.baseConfigs.securityConfig.securityType
+        != NanDataPathSecurityType::OPEN) ? legacy_hal::NAN_DP_CONFIG_SECURITY
+            : legacy_hal::NAN_DP_CONFIG_NO_SECURITY;
   legacy_request->sdea_params.ranging_state = hidl_request.baseConfigs.rangingRequired ?
         legacy_hal::NAN_RANGING_ENABLE : legacy_hal::NAN_RANGING_DISABLE;
   legacy_request->ranging_cfg.ranging_interval_msec = hidl_request.baseConfigs.rangingIntervalMsec;
@@ -1066,17 +1090,40 @@
         hidl_request.baseConfigs.disableMatchExpirationIndication ? 0x2 : 0x0;
   legacy_request->recv_indication_cfg |=
         hidl_request.baseConfigs.disableFollowupReceivedIndication ? 0x4 : 0x0;
-  legacy_request->cipher_type = (unsigned int) hidl_request.baseConfigs.cipherType;
-  legacy_request->pmk_len = hidl_request.baseConfigs.pmk.size();
-  if (legacy_request->pmk_len > NAN_PMK_INFO_LEN) {
-    LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: pmk_len too large";
-    return false;
+  legacy_request->cipher_type = (unsigned int) hidl_request.baseConfigs.securityConfig.cipherType;
+  if (hidl_request.baseConfigs.securityConfig.securityType == NanDataPathSecurityType::PMK) {
+    legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PMK;
+    legacy_request->key_info.body.pmk_info.pmk_len =
+        hidl_request.baseConfigs.securityConfig.pmk.size();
+    if (legacy_request->key_info.body.pmk_info.pmk_len > NAN_PMK_INFO_LEN) {
+      LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: pmk_len too large";
+      return false;
+    }
+    memcpy(legacy_request->key_info.body.pmk_info.pmk,
+          hidl_request.baseConfigs.securityConfig.pmk.data(),
+          legacy_request->key_info.body.pmk_info.pmk_len);
   }
-  memcpy(legacy_request->pmk,
-        hidl_request.baseConfigs.pmk.data(),
-        legacy_request->pmk_len);
-  legacy_request->sdea_params.security_cfg = hidl_request.baseConfigs.securityEnabledInNdp ?
-        legacy_hal::NAN_DP_CONFIG_SECURITY : legacy_hal::NAN_DP_CONFIG_NO_SECURITY;
+  if (hidl_request.baseConfigs.securityConfig.securityType == NanDataPathSecurityType::PASSPHRASE) {
+    legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
+    legacy_request->key_info.body.passphrase_info.passphrase_len =
+        hidl_request.baseConfigs.securityConfig.passphrase.size();
+    if (legacy_request->key_info.body.passphrase_info.passphrase_len
+            < NAN_SECURITY_MIN_PASSPHRASE_LEN) {
+      LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: passphrase_len too small";
+      return false;
+    }
+    if (legacy_request->key_info.body.passphrase_info.passphrase_len
+            > NAN_SECURITY_MIN_PASSPHRASE_LEN) {
+      LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: passphrase_len too large";
+      return false;
+    }
+    memcpy(legacy_request->key_info.body.passphrase_info.passphrase,
+          hidl_request.baseConfigs.securityConfig.passphrase.data(),
+          legacy_request->key_info.body.passphrase_info.passphrase_len);
+  }
+  legacy_request->sdea_params.security_cfg = (hidl_request.baseConfigs.securityConfig.securityType
+          != NanDataPathSecurityType::OPEN) ? legacy_hal::NAN_DP_CONFIG_SECURITY
+              : legacy_hal::NAN_DP_CONFIG_NO_SECURITY;
   legacy_request->sdea_params.ranging_state = hidl_request.baseConfigs.rangingRequired ?
         legacy_hal::NAN_RANGING_ENABLE : legacy_hal::NAN_RANGING_DISABLE;
   legacy_request->ranging_cfg.ranging_interval_msec = hidl_request.baseConfigs.rangingIntervalMsec;
@@ -1251,8 +1298,9 @@
         (legacy_hal::NanDataPathChannelCfg) hidl_request.channelRequestType;
   legacy_request->channel = hidl_request.channel;
   strcpy(legacy_request->ndp_iface, hidl_request.ifaceName.c_str());
-  legacy_request->ndp_cfg.security_cfg = hidl_request.securityRequired ?
-        legacy_hal::NAN_DP_CONFIG_SECURITY : legacy_hal::NAN_DP_CONFIG_NO_SECURITY;
+  legacy_request->ndp_cfg.security_cfg = (hidl_request.securityConfig.securityType
+        != NanDataPathSecurityType::OPEN) ? legacy_hal::NAN_DP_CONFIG_SECURITY
+            : legacy_hal::NAN_DP_CONFIG_NO_SECURITY;
   legacy_request->app_info.ndp_app_info_len = hidl_request.appInfo.size();
   if (legacy_request->app_info.ndp_app_info_len > NAN_DP_MAX_APP_INFO_LEN) {
     LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: ndp_app_info_len too large";
@@ -1260,13 +1308,43 @@
   }
   memcpy(legacy_request->app_info.ndp_app_info, hidl_request.appInfo.data(),
         legacy_request->app_info.ndp_app_info_len);
-  legacy_request->cipher_type = (unsigned int) hidl_request.cipherType;
-  legacy_request->pmk_len = hidl_request.pmk.size();
-  if (legacy_request->pmk_len > NAN_PMK_INFO_LEN) {
-    LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: pmk_len too large";
+  legacy_request->cipher_type = (unsigned int) hidl_request.securityConfig.cipherType;
+  if (hidl_request.securityConfig.securityType == NanDataPathSecurityType::PMK) {
+    legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PMK;
+    legacy_request->key_info.body.pmk_info.pmk_len = hidl_request.securityConfig.pmk.size();
+    if (legacy_request->key_info.body.pmk_info.pmk_len > NAN_PMK_INFO_LEN) {
+      LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: pmk_len too large";
+      return false;
+    }
+    memcpy(legacy_request->key_info.body.pmk_info.pmk,
+          hidl_request.securityConfig.pmk.data(),
+          legacy_request->key_info.body.pmk_info.pmk_len);
+  }
+  if (hidl_request.securityConfig.securityType == NanDataPathSecurityType::PASSPHRASE) {
+    legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
+    legacy_request->key_info.body.passphrase_info.passphrase_len =
+        hidl_request.securityConfig.passphrase.size();
+    if (legacy_request->key_info.body.passphrase_info.passphrase_len
+            < NAN_SECURITY_MIN_PASSPHRASE_LEN) {
+      LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: passphrase_len too small";
+      return false;
+    }
+    if (legacy_request->key_info.body.passphrase_info.passphrase_len
+            > NAN_SECURITY_MIN_PASSPHRASE_LEN) {
+      LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: passphrase_len too large";
+      return false;
+    }
+    memcpy(legacy_request->key_info.body.passphrase_info.passphrase,
+          hidl_request.securityConfig.passphrase.data(),
+          legacy_request->key_info.body.passphrase_info.passphrase_len);
+  }
+  legacy_request->service_name_len = hidl_request.serviceNameOutOfBand.size();
+  if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) {
+    LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: service_name_len too large";
     return false;
   }
-  memcpy(legacy_request->pmk, hidl_request.pmk.data(), legacy_request->pmk_len);
+  memcpy(legacy_request->service_name, hidl_request.serviceNameOutOfBand.data(),
+        legacy_request->service_name_len);
 
   return true;
 }
@@ -1284,8 +1362,9 @@
         legacy_hal::NAN_DP_REQUEST_ACCEPT : legacy_hal::NAN_DP_REQUEST_REJECT;
   legacy_request->ndp_instance_id = hidl_request.ndpInstanceId;
   strcpy(legacy_request->ndp_iface, hidl_request.ifaceName.c_str());
-  legacy_request->ndp_cfg.security_cfg = hidl_request.securityRequired ?
-        legacy_hal::NAN_DP_CONFIG_SECURITY : legacy_hal::NAN_DP_CONFIG_NO_SECURITY;
+  legacy_request->ndp_cfg.security_cfg = (hidl_request.securityConfig.securityType
+        != NanDataPathSecurityType::OPEN) ? legacy_hal::NAN_DP_CONFIG_SECURITY
+            : legacy_hal::NAN_DP_CONFIG_NO_SECURITY;
   legacy_request->app_info.ndp_app_info_len = hidl_request.appInfo.size();
   if (legacy_request->app_info.ndp_app_info_len > NAN_DP_MAX_APP_INFO_LEN) {
     LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: ndp_app_info_len too large";
@@ -1293,13 +1372,43 @@
   }
   memcpy(legacy_request->app_info.ndp_app_info, hidl_request.appInfo.data(),
         legacy_request->app_info.ndp_app_info_len);
-  legacy_request->cipher_type = (unsigned int) hidl_request.cipherType;
-  legacy_request->pmk_len = hidl_request.pmk.size();
-  if (legacy_request->pmk_len > NAN_PMK_INFO_LEN) {
-    LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: pmk_len too large";
+  legacy_request->cipher_type = (unsigned int) hidl_request.securityConfig.cipherType;
+  if (hidl_request.securityConfig.securityType == NanDataPathSecurityType::PMK) {
+    legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PMK;
+    legacy_request->key_info.body.pmk_info.pmk_len = hidl_request.securityConfig.pmk.size();
+    if (legacy_request->key_info.body.pmk_info.pmk_len > NAN_PMK_INFO_LEN) {
+      LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: pmk_len too large";
+      return false;
+    }
+    memcpy(legacy_request->key_info.body.pmk_info.pmk,
+          hidl_request.securityConfig.pmk.data(),
+          legacy_request->key_info.body.pmk_info.pmk_len);
+  }
+  if (hidl_request.securityConfig.securityType == NanDataPathSecurityType::PASSPHRASE) {
+    legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
+    legacy_request->key_info.body.passphrase_info.passphrase_len =
+        hidl_request.securityConfig.passphrase.size();
+    if (legacy_request->key_info.body.passphrase_info.passphrase_len
+            < NAN_SECURITY_MIN_PASSPHRASE_LEN) {
+      LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: passphrase_len too small";
+      return false;
+    }
+    if (legacy_request->key_info.body.passphrase_info.passphrase_len
+            > NAN_SECURITY_MIN_PASSPHRASE_LEN) {
+      LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: passphrase_len too large";
+      return false;
+    }
+    memcpy(legacy_request->key_info.body.passphrase_info.passphrase,
+          hidl_request.securityConfig.passphrase.data(),
+          legacy_request->key_info.body.passphrase_info.passphrase_len);
+  }
+  legacy_request->service_name_len = hidl_request.serviceNameOutOfBand.size();
+  if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) {
+    LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: service_name_len too large";
     return false;
   }
-  memcpy(legacy_request->pmk, hidl_request.pmk.data(), legacy_request->pmk_len);
+  memcpy(legacy_request->service_name, hidl_request.serviceNameOutOfBand.data(),
+        legacy_request->service_name_len);
 
   return true;
 }
diff --git a/wifi/1.0/default/wifi_legacy_hal.cpp b/wifi/1.0/default/wifi_legacy_hal.cpp
index 5fc0228..ba57ba7 100644
--- a/wifi/1.0/default/wifi_legacy_hal.cpp
+++ b/wifi/1.0/default/wifi_legacy_hal.cpp
@@ -328,9 +328,8 @@
   wifi_error status = init_wifi_vendor_hal_func_table(&global_func_table_);
   if (status != WIFI_SUCCESS) {
     LOG(ERROR) << "Failed to initialize legacy hal function table";
-    return WIFI_ERROR_UNKNOWN;
   }
-  return WIFI_SUCCESS;
+  return status;
 }
 
 wifi_error WifiLegacyHal::start() {
diff --git a/wifi/1.0/types.hal b/wifi/1.0/types.hal
index d3845c9..17aadee 100644
--- a/wifi/1.0/types.hal
+++ b/wifi/1.0/types.hal
@@ -586,6 +586,17 @@
  */
 
 /**
+ * Size limits for parameters used in the NAN interface.
+ */
+enum NanParamSizeLimits : uint32_t {
+  /* Minimum length of Passphrase argument for data-path configuration */
+  MIN_PASSPHRASE_LENGTH = 8,
+
+  /* Maximum length of Passphrase argument for data-path configuration */
+  MAX_PASSPHRASE_LENGTH = 63,
+};
+
+/**
  * A unique short handle provided by the client to identify individual invocations of
  * certain API's like |IWifiNanIface.*|.
  */
@@ -701,6 +712,15 @@
 };
 
 /**
+ * NAN DP (data-path) security configuration options.
+ */
+enum NanDataPathSecurityType : uint32_t {
+  OPEN,       // no security
+  PMK,        // security: PMK
+  PASSPHRASE, // security: passphrase
+};
+
+/**
  * NAN band-specific configuration.
  */
 struct NanBandSpecificConfig {
@@ -910,6 +930,38 @@
 };
 
 /**
+ * Configuration of NAN data-path security.
+ */
+struct NanDataPathSecurityConfig {
+  /**
+   * Security configuration of the data-path (NDP). Security is required if not equal to
+   * |NanDataPathSecurityType.OPEN|.
+   * NAN Spec: Service Discovery Extension Attribute (SDEA) / Control / Security Required
+   */
+  NanDataPathSecurityType securityType;
+  /**
+   * Cipher type for data-paths. If |securityType| is |NanDataPathSecurityType.OPEN| then must
+   * be set to |NanCipherSuiteType.NONE|, otherwise a non-|NanCipherSuiteType.NONE| cipher suite
+   * must be specified.
+   */
+  NanCipherSuiteType cipherType;
+  /**
+   * Optional Pairwise Master Key (PMK). Must be specified (and is only used) if |securityType| is
+   * set to |NanDataPathSecurityType.PMK|.
+   * Ref: IEEE 802.11i
+   */
+  uint8_t[32] pmk;
+  /**
+   * Optional Passphrase. Must be specified (and is only used) if |securityType| is set to
+   * |NanDataPathSecurityType.PASSPHRASE|.
+   * Min length: |MIN_PASSPHRASE_LENGTH|
+   * Max length: |MAX_PASSPHRASE_LENGTH|
+   * NAN Spec: Appendix: Mapping pass-phrase to PMK for NCS-SK Cipher Suites
+   */
+  vec<uint8_t> passphrase;
+};
+
+/**
  * Configurations of NAN discovery sessions: common to publish and subscribe discovery.
  */
 struct NanDiscoveryCommonConfig {
@@ -1009,25 +1061,11 @@
    */
   bool disableFollowupReceivedIndication;
   /**
-   * Cipher type for data-paths constructed in the context of this discovery session. Must be
-   * specified as |NanCipherSuiteType.NONE| if no |pmk| is provided.
+   * Security configuration of data-paths created in the context of this discovery session. Security
+   * parameters can be overridden during the actual construction of the data-path - allowing
+   * individual data-paths to have unique PMKs or Passphrases.
    */
-  NanCipherSuiteType cipherType;
-  /**
-   * Optional Pairwise Master Key (PMK) for data-paths constructed in the context of this discovery
-   * session. A PMK can also be provided during the actual construction of the data-path (which
-   * allows for unique PMKs for each data-path). The |cipherType| must be specified if a PMK is
-   * provided.
-   * Max length: 32
-   * Ref: IEEE 802.11i
-   */
-  vec<uint8_t> pmk;
-  /**
-   * Specifies whether or not security is enabled in any data-path (NDP) constructed in the context
-   * of this discovery session.
-   * NAN Spec: Service Discovery Extension Attribute (SDEA) / Control / Security Required
-   */
-  bool securityEnabledInNdp;
+  NanDataPathSecurityConfig securityConfig;
   /**
    * Specifies whether or not there is a ranging requirement in this discovery session.
    * Ranging is only performed if all other match criteria with the peer are met. Ranging must
@@ -1213,10 +1251,9 @@
    */
   string ifaceName;
   /**
-   * Specifies whether or not security is required for the data-path being created.
-   * NAN Spec: Data Path Attributes / NDP Attribute / NDP Control / Security Present
+   * Security configuration of the requested data-path.
    */
-  bool securityRequired;
+  NanDataPathSecurityConfig securityConfig;
   /**
    * Arbitrary information communicated to the peer as part of the data-path setup process - there
    * is no semantic meaning to these bytes. They are passed-through from sender to receiver as-is
@@ -1226,17 +1263,13 @@
    */
   vec<uint8_t> appInfo;
   /**
-   * Cipher type for the data-path being requested. Must be specified as |NanCipherSuiteType.NONE|
-   * if no |pmk| is provided.
+   * A service name to be used with |passphrase| to construct a Pairwise Master Key (PMK) for the
+   * data-path. Only relevant when a data-path is requested which is not associated with a NAN
+   * discovery session - e.g. using out-of-band discovery.
+   * Constraints: same as |NanDiscoveryCommonConfig.serviceName|
+   * NAN Spec: Appendix: Mapping pass-phrase to PMK for NCS-SK Cipher Suites
    */
-  NanCipherSuiteType cipherType;
-  /**
-   * Pairwise Master Key (PMK) for the data-path being requested (if |securityRequired| is true).
-   * The |cipherType| must be specified if a PMK is provided.
-   * Max length: 32
-   * Ref: IEEE 802.11i
-   */
-  vec<uint8_t> pmk;
+  vec<uint8_t> serviceNameOutOfBand;
 };
 
 /**
@@ -1259,10 +1292,9 @@
    */
   string ifaceName;
   /**
-   * Specifies whether or not security is required for the data-path being created.
-   * NAN Spec: Data Path Attributes / NDP Attribute / NDP Control / Security Present
+   * Security configuration of the requested data-path.
    */
-  bool securityRequired;
+  NanDataPathSecurityConfig securityConfig;
   /**
    * Arbitrary information communicated to the peer as part of the data-path setup process - there
    * is no semantic meaning to these bytes. They are passed-through from sender to receiver as-is
@@ -1272,16 +1304,13 @@
    */
   vec<uint8_t> appInfo;
   /**
-   * Cipher type for the data-path being negotiated. Must be specified as |NanCipherSuiteType.NONE|
-   * if no |pmk| is provided.
+   * A service name to be used with |passphrase| to construct a Pairwise Master Key (PMK) for the
+   * data-path. Only relevant when a data-path is requested which is not associated with a NAN
+   * discovery session - e.g. using out-of-band discovery.
+   * Constraints: same as |NanDiscoveryCommonConfig.serviceName|
+   * NAN Spec: Appendix: Mapping pass-phrase to PMK for NCS-SK Cipher Suites
    */
-  NanCipherSuiteType cipherType;
-  /**
-   * Pairwise Master Key (PMK) for the data-path being negotiated (if |securityRequired| is true).
-   * The |cipherType| must be specified if a PMK is provided.
-   * Max length: 32
-   */
-  vec<uint8_t> pmk;
+  vec<uint8_t> serviceNameOutOfBand;
 };
 
 /**
diff --git a/wifi/supplicant/1.0/ISupplicantP2pIface.hal b/wifi/supplicant/1.0/ISupplicantP2pIface.hal
index dc1388a..fb4323c 100644
--- a/wifi/supplicant/1.0/ISupplicantP2pIface.hal
+++ b/wifi/supplicant/1.0/ISupplicantP2pIface.hal
@@ -611,7 +611,7 @@
    *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
    *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
    */
-  setWfdDeviceInfo(uint8_t[8] info) generates (SupplicantStatus status);
+  setWfdDeviceInfo(uint8_t[6] info) generates (SupplicantStatus status);
 
   /**
    * Creates a NFC handover request message.
@@ -672,4 +672,15 @@
    */
   reportNfcHandoverInitiation(vec<uint8_t> select)
       generates (SupplicantStatus status);
+
+  /**
+   * Persist the current configuration to disk.
+   *
+   * @return status Status of the operation.
+   *         Possible status codes:
+   *         |SupplicantStatusCode.SUCCESS|,
+   *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+   *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+   */
+  saveConfig() generates (SupplicantStatus status);
 };
diff --git a/wifi/supplicant/1.0/ISupplicantP2pIfaceCallback.hal b/wifi/supplicant/1.0/ISupplicantP2pIfaceCallback.hal
index b6ee57f..8a54bf4 100644
--- a/wifi/supplicant/1.0/ISupplicantP2pIfaceCallback.hal
+++ b/wifi/supplicant/1.0/ISupplicantP2pIfaceCallback.hal
@@ -105,7 +105,7 @@
       MacAddress srcAddress, MacAddress p2pDeviceAddress,
       uint8_t[8] primaryDeviceType, string deviceName,
       bitfield<WpsConfigMethods> configMethods, uint8_t deviceCapabilities,
-      bitfield<P2pGroupCapabilityMask> groupCapabilities, uint8_t[8] wfdDeviceInfo);
+      bitfield<P2pGroupCapabilityMask> groupCapabilities, uint8_t[6] wfdDeviceInfo);
 
   /**
    * Used to indicate that a P2P device has been lost.
diff --git a/wifi/supplicant/1.0/ISupplicantP2pNetwork.hal b/wifi/supplicant/1.0/ISupplicantP2pNetwork.hal
index d32b47e..6ec7143 100644
--- a/wifi/supplicant/1.0/ISupplicantP2pNetwork.hal
+++ b/wifi/supplicant/1.0/ISupplicantP2pNetwork.hal
@@ -100,4 +100,34 @@
    * @return isGo true if group owner, false otherwise.
    */
   isGo() generates (SupplicantStatus status, bool isGo);
+
+  /**
+   * Set the list of P2P Clients in a persistent group (GO).
+   * This is a list of P2P Clients (P2P Device Address) that have joined
+   * the persistent group. This is maintained on the GO for persistent
+   * group entries (disabled == 2).
+   *
+   * @param clients MAC address of the clients.
+   * @return status Status of the operation.
+   *         Possible status codes:
+   *         |SupplicantStatusCode.SUCCESS|,
+   *         |SupplicantP2ptusCode.FAILURE_UNKNOWN|,
+   *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+   */
+  setClientList(vec<MacAddress> clients) generates (SupplicantStatus status);
+
+  /**
+   * Get the list of P2P Clients in a persistent group (GO).
+   * This is a list of P2P Clients (P2P Device Address) that have joined
+   * the persistent group. This is maintained on the GO for persistent
+   * group entries (disabled == 2).
+   *
+   * @return status Status of the operation.
+   *         Possible status codes:
+   *         |SupplicantStatusCode.SUCCESS|,
+   *         |SupplicantP2ptusCode.FAILURE_UNKNOWN|,
+   *         |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+   * @return clients MAC address of the clients.
+   */
+  getClientList() generates (SupplicantStatus status, vec<MacAddress> clients);
 };
diff --git a/wifi/supplicant/1.0/ISupplicantStaIfaceCallback.hal b/wifi/supplicant/1.0/ISupplicantStaIfaceCallback.hal
index 166ad96..173cce9 100644
--- a/wifi/supplicant/1.0/ISupplicantStaIfaceCallback.hal
+++ b/wifi/supplicant/1.0/ISupplicantStaIfaceCallback.hal
@@ -346,6 +346,24 @@
   };
 
   /**
+   * BSSID change Reasons.
+   */
+  enum BssidChangeReason : uint8_t {
+    /**
+     * Started association with new bssid.
+     */
+    ASSOC_START = 0,
+    /**
+     * Completed association with new bssid.
+     */
+    ASSOC_COMPLETE = 1,
+    /**
+     * Dis-association with current bssid.
+     */
+    DISASSOC = 2
+  };
+
+  /**
    * Used to indicate that a new network has been added.
    *
    * @param id Network ID allocated to the corresponding network.
@@ -466,6 +484,16 @@
   oneway onEapFailure();
 
   /**
+   * Used to indicate the change of active bssid.
+   * This is useful to figure out when the driver/firmware roams to a bssid
+   * on its own.
+   *
+   * @param reason Reason why the bssid changed.
+   * @param bssid BSSID of the corresponding AP.
+   */
+  oneway onBssidChanged(BssidChangeReason reason, Bssid bssid);
+
+  /**
    * Used to indicate the success of a WPS connection attempt.
    */
   oneway onWpsEventSuccess();
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp
index c6cf01f..72a3c42 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_p2p_iface_hidl_test.cpp
@@ -81,7 +81,7 @@
         const hidl_array<uint8_t, 8>& /* primaryDeviceType */,
         const hidl_string& /* deviceName */, uint16_t /* configMethods */,
         uint8_t /* deviceCapabilities */, uint32_t /* groupCapabilities */,
-        const hidl_array<uint8_t, 8>& /* wfdDeviceInfo */) override {
+        const hidl_array<uint8_t, 6>& /* wfdDeviceInfo */) override {
         return Void();
     }
     Return<void> onDeviceLost(