Merge "Fix program info call over-saturation."
diff --git a/Android.bp b/Android.bp
index 1c6e1b2..927e227 100644
--- a/Android.bp
+++ b/Android.bp
@@ -14,7 +14,10 @@
 // VTS tests must link to HAL definition libraries statically.
 cc_defaults {
     name: "VtsHalTargetTestDefaults",
-    defaults: ["hidl_defaults"],
+    defaults: [
+        "vts_target_tests_defaults",
+        "hidl_defaults",
+    ],
 
     // Lists all dependencies that can *not* be expected on the device.
     static_libs: [
diff --git a/audio/4.0/config/audio_policy_configuration.xsd b/audio/4.0/config/audio_policy_configuration.xsd
index ee17fc9..58bab22 100644
--- a/audio/4.0/config/audio_policy_configuration.xsd
+++ b/audio/4.0/config/audio_policy_configuration.xsd
@@ -280,6 +280,19 @@
             <xs:enumeration value="AUDIO_DEVICE_IN_STUB"/>
         </xs:restriction>
     </xs:simpleType>
+    <xs:simpleType name="vendorExtension">
+        <!-- Vendor extension names must be prefixed by "VX_" to distinguish them from AOSP values.
+             Vendor are encouraged to namespace their module names to avoid conflicts.
+             Example for an hypothetical Google virtual reality device:
+                <devicePort tagName="VR" type="VX_GOOGLE_VR" role="sink">
+        -->
+        <xs:restriction base="xs:string">
+            <xs:pattern value="VX_[_a-zA-Z0-9]+"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="extendableAudioDevice">
+        <xs:union memberTypes="audioDevice vendorExtension"/>
+    </xs:simpleType>
     <!-- Enum values of audio_format_t in audio.h
          TODO: generate from hidl to avoid manual sync. -->
     <xs:simpleType name="audioFormat">
@@ -346,6 +359,9 @@
             <xs:enumeration value="AUDIO_FORMAT_LDAC"/>
         </xs:restriction>
     </xs:simpleType>
+    <xs:simpleType name="extendableAudioFormat">
+        <xs:union memberTypes="audioFormat vendorExtension"/>
+    </xs:simpleType>
     <!-- Enum values of audio::common::4_0::AudioUsage
          TODO: generate from HIDL to avoid manual sync. -->
     <xs:simpleType name="audioUsage">
@@ -388,7 +404,7 @@
     </xs:simpleType>
     <xs:complexType name="profile">
         <xs:attribute name="name" type="xs:token" use="optional"/>
-        <xs:attribute name="format" type="audioFormat" use="optional"/>
+        <xs:attribute name="format" type="extendableAudioFormat" use="optional"/>
         <xs:attribute name="samplingRates" type="samplingRates" use="optional"/>
         <xs:attribute name="channelMasks" type="channelMask" use="optional"/>
     </xs:complexType>
@@ -425,7 +441,7 @@
                         <xs:element name="gains" type="gains" minOccurs="0"/>
                     </xs:sequence>
                     <xs:attribute name="tagName" type="xs:token" use="required"/>
-                    <xs:attribute name="type" type="audioDevice" use="required"/>
+                    <xs:attribute name="type" type="extendableAudioDevice" use="required"/>
                     <xs:attribute name="role" type="role" use="required"/>
                     <xs:attribute name="address" type="xs:string" use="optional" default=""/>
                     <!-- Note that XSD 1.0 can not check that a type only has one default. -->
diff --git a/biometrics/fingerprint/2.1/default/android.hardware.biometrics.fingerprint@2.1-service.rc b/biometrics/fingerprint/2.1/default/android.hardware.biometrics.fingerprint@2.1-service.rc
index 9bfd3ba..1667677 100644
--- a/biometrics/fingerprint/2.1/default/android.hardware.biometrics.fingerprint@2.1-service.rc
+++ b/biometrics/fingerprint/2.1/default/android.hardware.biometrics.fingerprint@2.1-service.rc
@@ -4,5 +4,5 @@
     # /data is mounted.
     class late_start
     user system
-    group system input
-    writepid /dev/cpuset/system-background/tasks
\ No newline at end of file
+    group system input uhid
+    writepid /dev/cpuset/system-background/tasks
diff --git a/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp b/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
index 90fbb3f..beb9a3e 100644
--- a/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
+++ b/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
@@ -105,6 +105,9 @@
   (ACL_PACKET_BOUNDARY_FLAG_FIRST_AUTO_FLUSHABLE \
    << ACL_PACKET_BOUNDARY_FLAG_OFFSET)
 
+// To be removed in VTS release builds
+#define ACL_HANDLE_QCA_DEBUG_MESSAGE 0xedc
+
 constexpr char kCallbackNameAclEventReceived[] = "aclDataReceived";
 constexpr char kCallbackNameHciEventReceived[] = "hciEventReceived";
 constexpr char kCallbackNameInitializationComplete[] = "initializationComplete";
@@ -318,6 +321,19 @@
       break;
     }
   }
+  // To be removed in VTS release builds
+  while (acl_queue.size() > 0) {
+    hidl_vec<uint8_t> acl_packet = acl_queue.front();
+    uint16_t connection_handle = acl_packet[1] & 0xF;
+    connection_handle <<= 8;
+    connection_handle |= acl_packet[0];
+    bool packet_is_no_op = connection_handle == ACL_HANDLE_QCA_DEBUG_MESSAGE;
+    if (packet_is_no_op) {
+      acl_queue.pop();
+    } else {
+      break;
+    }
+  }
 }
 
 // Receive an event, discarding NO-OPs.
diff --git a/camera/common/1.0/default/CameraModule.cpp b/camera/common/1.0/default/CameraModule.cpp
index 9c2b02b..08354b3 100644
--- a/camera/common/1.0/default/CameraModule.cpp
+++ b/camera/common/1.0/default/CameraModule.cpp
@@ -452,6 +452,16 @@
     return res;
 }
 
+int CameraModule::isStreamCombinationSupported(int cameraId, camera_stream_combination_t *streams) {
+    int res = INVALID_OPERATION;
+    if (mModule->is_stream_combination_supported != NULL) {
+        ATRACE_BEGIN("camera_module->is_stream_combination_supported");
+        res = mModule->is_stream_combination_supported(cameraId, streams);
+        ATRACE_END();
+    }
+    return res;
+}
+
 status_t CameraModule::filterOpenErrorCode(status_t err) {
     switch(err) {
         case NO_ERROR:
diff --git a/camera/common/1.0/default/include/CameraModule.h b/camera/common/1.0/default/include/CameraModule.h
index aee9654..ee75e72 100644
--- a/camera/common/1.0/default/include/CameraModule.h
+++ b/camera/common/1.0/default/include/CameraModule.h
@@ -66,6 +66,7 @@
     // Only used by CameraProvider
     void removeCamera(int cameraId);
     int getPhysicalCameraInfo(int physicalCameraId, camera_metadata_t **physicalInfo);
+    int isStreamCombinationSupported(int cameraId, camera_stream_combination_t *streams);
 
 private:
     // Derive camera characteristics keys defined after HAL device version
diff --git a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
index 4ef5fc9..66b17db 100644
--- a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
+++ b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
@@ -2163,7 +2163,8 @@
     }
 }
 
-bool ExternalCameraDeviceSession::isSupported(const Stream& stream) {
+bool ExternalCameraDeviceSession::isSupported(const Stream& stream,
+        const std::vector<SupportedV4L2Format>& supportedFormats) {
     int32_t ds = static_cast<int32_t>(stream.dataSpace);
     PixelFormat fmt = stream.format;
     uint32_t width = stream.width;
@@ -2206,7 +2207,7 @@
     // Assume we can convert any V4L2 format to any of supported output format for now, i.e,
     // ignoring v4l2Fmt.fourcc for now. Might need more subtle check if we support more v4l format
     // in the futrue.
-    for (const auto& v4l2Fmt : mSupportedFormats) {
+    for (const auto& v4l2Fmt : supportedFormats) {
         if (width == v4l2Fmt.width && height == v4l2Fmt.height) {
             return true;
         }
@@ -2541,11 +2542,9 @@
     mV4L2BufferReturned.notify_one();
 }
 
-Status ExternalCameraDeviceSession::configureStreams(
+Status ExternalCameraDeviceSession::isStreamCombinationSupported(
         const V3_2::StreamConfiguration& config,
-        V3_3::HalStreamConfiguration* out,
-        uint32_t blobBufferSize) {
-    ATRACE_CALL();
+        const std::vector<SupportedV4L2Format>& supportedFormats) {
     if (config.operationMode != StreamConfigurationMode::NORMAL_MODE) {
         ALOGE("%s: unsupported operation mode: %d", __FUNCTION__, config.operationMode);
         return Status::ILLEGAL_ARGUMENT;
@@ -2560,7 +2559,7 @@
     int numStallStream = 0;
     for (const auto& stream : config.streams) {
         // Check if the format/width/height combo is supported
-        if (!isSupported(stream)) {
+        if (!isSupported(stream, supportedFormats)) {
             return Status::ILLEGAL_ARGUMENT;
         }
         if (stream.format == PixelFormat::BLOB) {
@@ -2582,7 +2581,21 @@
         return Status::ILLEGAL_ARGUMENT;
     }
 
-    Status status = initStatus();
+    return Status::OK;
+}
+
+Status ExternalCameraDeviceSession::configureStreams(
+        const V3_2::StreamConfiguration& config,
+        V3_3::HalStreamConfiguration* out,
+        uint32_t blobBufferSize) {
+    ATRACE_CALL();
+
+    Status status = isStreamCombinationSupported(config, mSupportedFormats);
+    if (status != Status::OK) {
+        return status;
+    }
+
+    status = initStatus();
     if (status != Status::OK) {
         return status;
     }
diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h
index cabeaa4..9cc55cb 100644
--- a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h
+++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDeviceSession.h
@@ -193,13 +193,16 @@
     int configureV4l2StreamLocked(const SupportedV4L2Format& fmt, double fps = 0.0);
     int v4l2StreamOffLocked();
     int setV4l2FpsLocked(double fps);
+    static Status isStreamCombinationSupported(const V3_2::StreamConfiguration& config,
+            const std::vector<SupportedV4L2Format>& supportedFormats);
 
     // TODO: change to unique_ptr for better tracking
     sp<V4L2Frame> dequeueV4l2FrameLocked(/*out*/nsecs_t* shutterTs); // Called with mLock hold
     void enqueueV4l2Frame(const sp<V4L2Frame>&);
 
     // Check if input Stream is one of supported stream setting on this device
-    bool isSupported(const Stream&);
+    static bool isSupported(const Stream& stream,
+            const std::vector<SupportedV4L2Format>& supportedFormats);
 
     // Validate and import request's output buffers and acquire fence
     virtual Status importRequestLocked(
diff --git a/camera/device/3.5/ICameraDevice.hal b/camera/device/3.5/ICameraDevice.hal
index a77380f..d9f2837 100644
--- a/camera/device/3.5/ICameraDevice.hal
+++ b/camera/device/3.5/ICameraDevice.hal
@@ -19,6 +19,7 @@
 import android.hardware.camera.common@1.0::Status;
 import @3.2::CameraMetadata;
 import @3.2::ICameraDevice;
+import @3.4::StreamConfiguration;
 
 /**
  * Camera device interface
@@ -75,4 +76,41 @@
     getPhysicalCameraCharacteristics(string physicalCameraId)
             generates (Status status, CameraMetadata cameraCharacteristics);
 
+
+    /**
+     * isStreamCombinationSupported:
+     *
+     * Check for device support of specific camera stream combination.
+     *
+     * The streamList must contain at least one output-capable stream, and may
+     * not contain more than one input-capable stream.
+     *
+     * ------------------------------------------------------------------------
+     *
+     * Preconditions:
+     *
+     * The framework can call this method at any time before, during and
+     * after active session configuration. This means that calls must not
+     * impact the performance of pending camera requests in any way. In
+     * particular there must not be any glitches or delays during normal
+     * camera streaming.
+     *
+     * Performance requirements:
+     * This call is expected to be significantly faster than stream
+     * configuration. In general HW and SW camera settings must not be
+     * changed and there must not be a user-visible impact on camera performance.
+     *
+     * @return Status Status code for the operation, one of:
+     *     OK:
+     *          On successful stream combination query.
+     *     METHOD_NOT_SUPPORTED:
+     *          The camera device does not support stream combination query.
+     *     INTERNAL_ERROR:
+     *          The stream combination query cannot complete due to internal
+     *          error.
+     * @return true in case the stream combination is supported, false otherwise.
+     *
+     */
+    isStreamCombinationSupported(@3.4::StreamConfiguration streams)
+            generates (Status status, bool queryStatus);
 };
diff --git a/camera/device/3.5/default/CameraDevice.cpp b/camera/device/3.5/default/CameraDevice.cpp
index a6969af..cffda4e 100644
--- a/camera/device/3.5/default/CameraDevice.cpp
+++ b/camera/device/3.5/default/CameraDevice.cpp
@@ -95,6 +95,57 @@
     return Void();
 }
 
+Return<void> CameraDevice::isStreamCombinationSupported(const V3_4::StreamConfiguration& streams,
+        V3_5::ICameraDevice::isStreamCombinationSupported_cb _hidl_cb) {
+    Status status;
+    bool streamsSupported = false;
+
+    // Require module 2.5+ version.
+    if (mModule->getModuleApiVersion() < CAMERA_MODULE_API_VERSION_2_5) {
+        ALOGE("%s: is_stream_combination_supported must be called on camera module 2.5 or "\
+                "newer", __FUNCTION__);
+        status = Status::INTERNAL_ERROR;
+    } else {
+        camera_stream_combination_t streamComb{};
+        streamComb.operation_mode = static_cast<uint32_t> (streams.operationMode);
+        streamComb.num_streams = streams.streams.size();
+        camera_stream_t *streamBuffer  = new camera_stream_t[streamComb.num_streams];
+
+        size_t i = 0;
+        for (const auto &it : streams.streams) {
+            streamBuffer[i].stream_type = static_cast<int> (it.v3_2.streamType);
+            streamBuffer[i].width = it.v3_2.width;
+            streamBuffer[i].height = it.v3_2.height;
+            streamBuffer[i].format = static_cast<int> (it.v3_2.format);
+            streamBuffer[i].data_space = static_cast<android_dataspace_t> (it.v3_2.dataSpace);
+            streamBuffer[i].usage = static_cast<uint32_t> (it.v3_2.usage);
+            streamBuffer[i].physical_camera_id = it.physicalCameraId.c_str();
+            streamBuffer[i++].rotation = static_cast<int> (it.v3_2.rotation);
+        }
+        streamComb.streams = streamBuffer;
+        auto res = mModule->isStreamCombinationSupported(mCameraIdInt, &streamComb);
+        switch (res) {
+            case NO_ERROR:
+                streamsSupported = true;
+                status = Status::OK;
+                break;
+            case BAD_VALUE:
+                status = Status::OK;
+                break;
+            case INVALID_OPERATION:
+                status = Status::METHOD_NOT_SUPPORTED;
+                break;
+            default:
+                ALOGE("%s: Unexpected error: %d", __FUNCTION__, res);
+                status = Status::INTERNAL_ERROR;
+        };
+        delete [] streamBuffer;
+    }
+
+    _hidl_cb(status, streamsSupported);
+    return Void();
+}
+
 // End of methods from ::android::hardware::camera::device::V3_2::ICameraDevice.
 
 } // namespace implementation
diff --git a/camera/device/3.5/default/ExternalCameraDevice.cpp b/camera/device/3.5/default/ExternalCameraDevice.cpp
index e8d14b5..6a0b51e 100644
--- a/camera/device/3.5/default/ExternalCameraDevice.cpp
+++ b/camera/device/3.5/default/ExternalCameraDevice.cpp
@@ -86,6 +86,27 @@
     return OK;
 }
 
+Return<void> ExternalCameraDevice::isStreamCombinationSupported(
+        const V3_4::StreamConfiguration& streams,
+        V3_5::ICameraDevice::isStreamCombinationSupported_cb _hidl_cb) {
+
+    if (isInitFailed()) {
+        ALOGE("%s: camera %s. camera init failed!", __FUNCTION__, mCameraId.c_str());
+        _hidl_cb(Status::INTERNAL_ERROR, false);
+        return Void();
+    }
+
+    hidl_vec<V3_2::Stream> streamsV3_2(streams.streams.size());
+    size_t i = 0;
+    for (const auto& it : streams.streams) {
+        streamsV3_2[i++] = it.v3_2;
+    }
+    V3_2::StreamConfiguration streamConfig = {streamsV3_2, streams.operationMode};
+    auto status = ExternalCameraDeviceSession::isStreamCombinationSupported(streamConfig,
+            mSupportedFormats);
+    _hidl_cb(Status::OK, Status::OK == status);
+    return Void();
+}
 #undef UPDATE
 
 }  // namespace implementation
diff --git a/camera/device/3.5/default/include/device_v3_5_impl/CameraDevice_3_5.h b/camera/device/3.5/default/include/device_v3_5_impl/CameraDevice_3_5.h
index 6bdc60f..76c8cf8 100644
--- a/camera/device/3.5/default/include/device_v3_5_impl/CameraDevice_3_5.h
+++ b/camera/device/3.5/default/include/device_v3_5_impl/CameraDevice_3_5.h
@@ -64,6 +64,10 @@
     Return<void> getPhysicalCameraCharacteristics(const hidl_string& physicalCameraId,
             V3_5::ICameraDevice::getPhysicalCameraCharacteristics_cb _hidl_cb);
 
+    Return<void> isStreamCombinationSupported(
+            const V3_4::StreamConfiguration& streams,
+            V3_5::ICameraDevice::isStreamCombinationSupported_cb _hidl_cb);
+
 private:
     struct TrampolineDeviceInterface_3_5 : public ICameraDevice {
         TrampolineDeviceInterface_3_5(sp<CameraDevice> parent) :
@@ -96,6 +100,13 @@
                 V3_5::ICameraDevice::getPhysicalCameraCharacteristics_cb _hidl_cb) override {
             return mParent->getPhysicalCameraCharacteristics(physicalCameraId, _hidl_cb);
         }
+
+        virtual Return<void> isStreamCombinationSupported(
+                const V3_4::StreamConfiguration& streams,
+                V3_5::ICameraDevice::isStreamCombinationSupported_cb _hidl_cb) override {
+            return mParent->isStreamCombinationSupported(streams, _hidl_cb);
+        }
+
     private:
         sp<CameraDevice> mParent;
     };
diff --git a/camera/device/3.5/default/include/ext_device_v3_5_impl/ExternalCameraDeviceSession.h b/camera/device/3.5/default/include/ext_device_v3_5_impl/ExternalCameraDeviceSession.h
index 4d2d6b7..aa119fc 100644
--- a/camera/device/3.5/default/include/ext_device_v3_5_impl/ExternalCameraDeviceSession.h
+++ b/camera/device/3.5/default/include/ext_device_v3_5_impl/ExternalCameraDeviceSession.h
@@ -90,6 +90,12 @@
         return new TrampolineSessionInterface_3_5(this);
     }
 
+    static Status isStreamCombinationSupported(const V3_2::StreamConfiguration& config,
+            const std::vector<SupportedV4L2Format>& supportedFormats) {
+        return V3_4::implementation::ExternalCameraDeviceSession::isStreamCombinationSupported(
+                config, supportedFormats);
+    }
+
 protected:
     // Methods from v3.4 and earlier will trampoline to inherited implementation
     Return<void> configureStreams_3_5(
diff --git a/camera/device/3.5/default/include/ext_device_v3_5_impl/ExternalCameraDevice_3_5.h b/camera/device/3.5/default/include/ext_device_v3_5_impl/ExternalCameraDevice_3_5.h
index 7db86dc..b73490c 100644
--- a/camera/device/3.5/default/include/ext_device_v3_5_impl/ExternalCameraDevice_3_5.h
+++ b/camera/device/3.5/default/include/ext_device_v3_5_impl/ExternalCameraDevice_3_5.h
@@ -67,6 +67,10 @@
     Return<void> getPhysicalCameraCharacteristics(const hidl_string& physicalCameraId,
             V3_5::ICameraDevice::getPhysicalCameraCharacteristics_cb _hidl_cb);
 
+    Return<void> isStreamCombinationSupported(
+            const V3_4::StreamConfiguration& streams,
+            V3_5::ICameraDevice::isStreamCombinationSupported_cb _hidl_cb);
+
 protected:
     virtual sp<V3_4::implementation::ExternalCameraDeviceSession> createSession(
             const sp<V3_2::ICameraDeviceCallback>&,
@@ -116,6 +120,13 @@
                 V3_5::ICameraDevice::getPhysicalCameraCharacteristics_cb _hidl_cb) override {
             return mParent->getPhysicalCameraCharacteristics(physicalCameraId, _hidl_cb);
         }
+
+        virtual Return<void> isStreamCombinationSupported(
+                const V3_4::StreamConfiguration& streams,
+                V3_5::ICameraDevice::isStreamCombinationSupported_cb _hidl_cb) override {
+            return mParent->isStreamCombinationSupported(streams, _hidl_cb);
+        }
+
     private:
         sp<ExternalCameraDevice> mParent;
     };
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index bb03d91..e376551 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -703,11 +703,14 @@
     void openEmptyDeviceSession(const std::string &name,
             sp<ICameraProvider> provider,
             sp<ICameraDeviceSession> *session /*out*/,
-            camera_metadata_t **staticMeta /*out*/);
+            camera_metadata_t **staticMeta /*out*/,
+            ::android::sp<ICameraDevice> *device = nullptr/*out*/);
     void castSession(const sp<ICameraDeviceSession> &session, int32_t deviceVersion,
             sp<device::V3_3::ICameraDeviceSession> *session3_3 /*out*/,
             sp<device::V3_4::ICameraDeviceSession> *session3_4 /*out*/,
             sp<device::V3_5::ICameraDeviceSession> *session3_5 /*out*/);
+    void castDevice(const sp<device::V3_2::ICameraDevice> &device, int32_t deviceVersion,
+            sp<device::V3_5::ICameraDevice> *device3_5/*out*/);
     void createStreamConfiguration(const ::android::hardware::hidl_vec<V3_2::Stream>& streams3_2,
             StreamConfigurationMode configMode,
             ::android::hardware::camera::device::V3_2::StreamConfiguration *config3_2,
@@ -748,6 +751,9 @@
     void verifyMonochromeCharacteristics(const CameraMetadata& chars, int deviceVersion);
     void verifyMonochromeCameraResult(
             const ::android::hardware::camera::common::V1_0::helper::CameraMetadata& metadata);
+    void verifyStreamCombination(sp<device::V3_5::ICameraDevice> cameraDevice3_5,
+            const ::android::hardware::camera::device::V3_4::StreamConfiguration &config3_4,
+            bool expectedStatus);
 
     void verifyBuffersReturned(sp<device::V3_2::ICameraDeviceSession> session,
             int deviceVerison, int32_t streamId, sp<DeviceCb> cb,
@@ -2769,9 +2775,12 @@
         sp<device::V3_3::ICameraDeviceSession> session3_3;
         sp<device::V3_4::ICameraDeviceSession> session3_4;
         sp<device::V3_5::ICameraDeviceSession> session3_5;
+        sp<device::V3_2::ICameraDevice> cameraDevice;
+        sp<device::V3_5::ICameraDevice> cameraDevice3_5;
         openEmptyDeviceSession(name, mProvider,
-                &session /*out*/, &staticMeta /*out*/);
+                &session /*out*/, &staticMeta /*out*/, &cameraDevice /*out*/);
         castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5);
+        castDevice(cameraDevice, deviceVersion, &cameraDevice3_5);
 
         outputStreams.clear();
         ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, outputStreams));
@@ -2797,6 +2806,8 @@
             createStreamConfiguration(streams3_2, StreamConfigurationMode::NORMAL_MODE,
                                       &config3_2, &config3_4, &config3_5);
             if (session3_5 != nullptr) {
+                verifyStreamCombination(cameraDevice3_5, config3_4,
+                        /*expectedStatus*/ true);
                 config3_5.streamConfigCounter = streamConfigCounter++;
                 ret = session3_5->configureStreams_3_5(config3_5,
                         [streamId](Status s, device::V3_4::HalStreamConfiguration halConfig) {
@@ -2857,8 +2868,12 @@
         sp<device::V3_3::ICameraDeviceSession> session3_3;
         sp<device::V3_4::ICameraDeviceSession> session3_4;
         sp<device::V3_5::ICameraDeviceSession> session3_5;
-        openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/);
+        sp<device::V3_2::ICameraDevice> cameraDevice;
+        sp<device::V3_5::ICameraDevice> cameraDevice3_5;
+        openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/,
+                &cameraDevice /*out*/);
         castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5);
+        castDevice(cameraDevice, deviceVersion, &cameraDevice3_5);
 
         outputStreams.clear();
         ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, outputStreams));
@@ -2881,6 +2896,7 @@
         createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE,
                                   &config3_2, &config3_4, &config3_5);
         if (session3_5 != nullptr) {
+            verifyStreamCombination(cameraDevice3_5, config3_4, /*expectedStatus*/ false);
             config3_5.streamConfigCounter = streamConfigCounter++;
             ret = session3_5->configureStreams_3_5(config3_5,
                     [](Status s, device::V3_4::HalStreamConfiguration) {
@@ -3044,8 +3060,12 @@
         sp<device::V3_3::ICameraDeviceSession> session3_3;
         sp<device::V3_4::ICameraDeviceSession> session3_4;
         sp<device::V3_5::ICameraDeviceSession> session3_5;
-        openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/);
+        sp<device::V3_2::ICameraDevice> cameraDevice;
+        sp<device::V3_5::ICameraDevice> cameraDevice3_5;
+        openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/,
+                &cameraDevice /*out*/);
         castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5);
+        castDevice(cameraDevice, deviceVersion, &cameraDevice3_5);
 
         Status rc = isZSLModeAvailable(staticMeta);
         if (Status::METHOD_NOT_SUPPORTED == rc) {
@@ -3132,6 +3152,8 @@
                 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE,
                                           &config3_2, &config3_4, &config3_5);
                 if (session3_5 != nullptr) {
+                    verifyStreamCombination(cameraDevice3_5, config3_4,
+                            /*expectedStatus*/ true);
                     config3_5.streamConfigCounter = streamConfigCounter++;
                     ret = session3_5->configureStreams_3_5(config3_5,
                             [](Status s, device::V3_4::HalStreamConfiguration halConfig) {
@@ -3304,8 +3326,12 @@
         sp<device::V3_3::ICameraDeviceSession> session3_3;
         sp<device::V3_4::ICameraDeviceSession> session3_4;
         sp<device::V3_5::ICameraDeviceSession> session3_5;
-        openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/);
+        sp<device::V3_2::ICameraDevice> cameraDevice;
+        sp<device::V3_5::ICameraDevice> cameraDevice3_5;
+        openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/,
+                &cameraDevice /*out*/);
         castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5);
+        castDevice(cameraDevice, deviceVersion, &cameraDevice3_5);
 
         outputBlobStreams.clear();
         ASSERT_EQ(Status::OK,
@@ -3346,6 +3372,8 @@
                 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE,
                                           &config3_2, &config3_4, &config3_5);
                 if (session3_5 != nullptr) {
+                    verifyStreamCombination(cameraDevice3_5, config3_4,
+                            /*expectedStatus*/ true);
                     config3_5.streamConfigCounter = streamConfigCounter++;
                     ret = session3_5->configureStreams_3_5(config3_5,
                             [](Status s, device::V3_4::HalStreamConfiguration halConfig) {
@@ -3403,8 +3431,12 @@
         sp<device::V3_3::ICameraDeviceSession> session3_3;
         sp<device::V3_4::ICameraDeviceSession> session3_4;
         sp<device::V3_5::ICameraDeviceSession> session3_5;
-        openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/);
+        sp<device::V3_2::ICameraDevice> cameraDevice;
+        sp<device::V3_5::ICameraDevice> cameraDevice3_5;
+        openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/,
+                &cameraDevice /*out*/);
         castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5);
+        castDevice(cameraDevice, deviceVersion, &cameraDevice3_5);
 
         Status rc = isConstrainedModeAvailable(staticMeta);
         if (Status::METHOD_NOT_SUPPORTED == rc) {
@@ -3435,6 +3467,8 @@
         createStreamConfiguration(streams, StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE,
                                   &config3_2, &config3_4, &config3_5);
         if (session3_5 != nullptr) {
+            verifyStreamCombination(cameraDevice3_5, config3_4,
+                    /*expectedStatus*/ true);
             config3_5.streamConfigCounter = streamConfigCounter++;
             ret = session3_5->configureStreams_3_5(config3_5,
                     [streamId](Status s, device::V3_4::HalStreamConfiguration halConfig) {
@@ -3608,8 +3642,12 @@
         sp<device::V3_3::ICameraDeviceSession> session3_3;
         sp<device::V3_4::ICameraDeviceSession> session3_4;
         sp<device::V3_5::ICameraDeviceSession> session3_5;
-        openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/);
+        sp<device::V3_2::ICameraDevice> cameraDevice;
+        sp<device::V3_5::ICameraDevice> cameraDevice3_5;
+        openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/,
+                &cameraDevice /*out*/);
         castSession(session, deviceVersion, &session3_3, &session3_4, &session3_5);
+        castDevice(cameraDevice, deviceVersion, &cameraDevice3_5);
 
         outputBlobStreams.clear();
         ASSERT_EQ(Status::OK,
@@ -3650,6 +3688,8 @@
                 createStreamConfiguration(streams, StreamConfigurationMode::NORMAL_MODE,
                                           &config3_2, &config3_4, &config3_5);
                 if (session3_5 != nullptr) {
+                    verifyStreamCombination(cameraDevice3_5, config3_4,
+                            /*expectedStatus*/ true);
                     config3_5.streamConfigCounter = streamConfigCounter++;
                     ret = session3_5->configureStreams_3_5(config3_5,
                             [](Status s, device::V3_4::HalStreamConfiguration halConfig) {
@@ -5228,6 +5268,16 @@
     ASSERT_TRUE(ret.isOk());
 }
 
+void CameraHidlTest::castDevice(const sp<device::V3_2::ICameraDevice> &device,
+        int32_t deviceVersion, sp<device::V3_5::ICameraDevice> *device3_5/*out*/) {
+    ASSERT_NE(nullptr, device3_5);
+    if (deviceVersion == CAMERA_DEVICE_API_VERSION_3_5) {
+        auto castResult = device::V3_5::ICameraDevice::castFrom(device);
+        ASSERT_TRUE(castResult.isOk());
+        *device3_5 = castResult;
+    }
+}
+
 //Cast camera device session to corresponding version
 void CameraHidlTest::castSession(const sp<ICameraDeviceSession> &session, int32_t deviceVersion,
         sp<device::V3_3::ICameraDeviceSession> *session3_3 /*out*/,
@@ -5262,6 +5312,21 @@
     }
 }
 
+void CameraHidlTest::verifyStreamCombination(sp<device::V3_5::ICameraDevice> cameraDevice3_5,
+        const ::android::hardware::camera::device::V3_4::StreamConfiguration &config3_4,
+        bool expectedStatus) {
+    if (cameraDevice3_5.get() != nullptr) {
+        auto ret = cameraDevice3_5->isStreamCombinationSupported(config3_4,
+                [expectedStatus] (Status s, bool combStatus) {
+                    ASSERT_TRUE((Status::OK == s) || (Status::METHOD_NOT_SUPPORTED == s));
+                    if (Status::OK == s) {
+                        ASSERT_TRUE(combStatus == expectedStatus);
+                    }
+                });
+        ASSERT_TRUE(ret.isOk());
+    }
+}
+
 // Verify logical camera static metadata
 void CameraHidlTest::verifyLogicalCameraMetadata(const std::string& cameraName,
         const ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice>& device,
@@ -5531,10 +5596,9 @@
 }
 
 // Open a device session with empty callbacks and return static metadata.
-void CameraHidlTest::openEmptyDeviceSession(const std::string &name,
-        sp<ICameraProvider> provider,
-        sp<ICameraDeviceSession> *session /*out*/,
-        camera_metadata_t **staticMeta /*out*/) {
+void CameraHidlTest::openEmptyDeviceSession(const std::string &name, sp<ICameraProvider> provider,
+        sp<ICameraDeviceSession> *session /*out*/, camera_metadata_t **staticMeta /*out*/,
+        ::android::sp<ICameraDevice> *cameraDevice /*out*/) {
     ASSERT_NE(nullptr, session);
     ASSERT_NE(nullptr, staticMeta);
 
@@ -5551,6 +5615,9 @@
             device3_x = device;
         });
     ASSERT_TRUE(ret.isOk());
+    if (cameraDevice != nullptr) {
+        *cameraDevice = device3_x;
+    }
 
     sp<EmptyDeviceCb> cb = new EmptyDeviceCb();
     ret = device3_x->open(cb, [&](auto status, const auto& newSession) {
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
index 0a3e88b..4018aea 100644
--- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
+++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
@@ -577,14 +577,6 @@
     }
 
     modes.clear();
-
-    modes.push_back(IComposerClient::PowerMode::ON);
-    modes.push_back(IComposerClient::PowerMode::ON);
-    for (auto mode : modes) {
-        ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode(mPrimaryDisplay, mode));
-    }
-
-    modes.clear();
     if (mComposerClient->getDozeSupport(mPrimaryDisplay)) {
         modes.push_back(IComposerClient::PowerMode::DOZE);
         modes.push_back(IComposerClient::PowerMode::DOZE);
@@ -602,6 +594,14 @@
             ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode(mPrimaryDisplay, mode));
         }
     }
+
+    modes.clear();
+
+    modes.push_back(IComposerClient::PowerMode::ON);
+    modes.push_back(IComposerClient::PowerMode::ON);
+    for (auto mode : modes) {
+        ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode(mPrimaryDisplay, mode));
+    }
 }
 
 /**
diff --git a/graphics/composer/2.3/IComposerClient.hal b/graphics/composer/2.3/IComposerClient.hal
index 87002ec..e5ee3c5 100644
--- a/graphics/composer/2.3/IComposerClient.hal
+++ b/graphics/composer/2.3/IComposerClient.hal
@@ -37,7 +37,7 @@
         INVALID = 0,
 
         /**
-         * Specifies that the display must a color transform even when
+         * Indicates that the display must apply a color transform even when
          * either the client or the device has chosen that all layers should
          * be composed by the client. This prevents the client from applying
          * the color transform during its composition step.
@@ -51,7 +51,7 @@
         SKIP_CLIENT_COLOR_TRANSFORM = 1,
 
         /**
-         * Specifies that the display supports PowerMode::DOZE and
+         * Indicates that the display supports PowerMode::DOZE and
          * PowerMode::DOZE_SUSPEND. DOZE_SUSPEND may not provide any benefit
          * over DOZE (see the definition of PowerMode for more information),
          * but if both DOZE and DOZE_SUSPEND are no different from
diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal
index f196792..45476ee 100644
--- a/neuralnetworks/1.2/types.hal
+++ b/neuralnetworks/1.2/types.hal
@@ -126,6 +126,8 @@
     ROTATED_BBOX_TRANSFORM = 87,
     ABS = 88,
     ROI_POOLING = 89,
+    EQUAL = 90,
+    NOT_EQUAL = 91,
     /* ADDING A NEW FUNDAMENTAL OPERATION REQUIRES UPDATING THE VALUE OF
      * OperationTypeRange::OPERATION_FUNDAMENTAL_MAX.
      */
@@ -139,7 +141,7 @@
  */
 enum OperationTypeRange : uint32_t {
     OPERATION_FUNDAMENTAL_MIN = 0,
-    OPERATION_FUNDAMENTAL_MAX = 89,
+    OPERATION_FUNDAMENTAL_MAX = 91,
     OPERATION_OEM_MIN = 10000,
     OPERATION_OEM_MAX = 10000,
 };
diff --git a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
index 294415b..562ac33 100644
--- a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
@@ -304,6 +304,7 @@
         // - ARGMIN and ARGMAX's first argument can be any of
         // TENSOR_(FLOAT16|FLOAT32|INT32|QUANT8_ASYMM).
         // - CAST's argument can be any of TENSOR_(FLOAT16|FLOAT32|INT32|QUANT8_ASYMM).
+        // - RANDOM_MULTINOMIAL's argument can be either TENSOR_FLOAT16 or TENSOR_FLOAT32.
         switch (operation.type) {
             case OperationType::LSH_PROJECTION: {
                 if (operand == operation.inputs[1]) {
@@ -318,6 +319,11 @@
                     return true;
                 }
             } break;
+            case OperationType::RANDOM_MULTINOMIAL: {
+                if (type == OperandType::TENSOR_FLOAT16 || type == OperandType::TENSOR_FLOAT32) {
+                    return true;
+                }
+            } break;
             default:
                 break;
         }
diff --git a/radio/1.3/IRadio.hal b/radio/1.3/IRadio.hal
index d582c71..2d64381 100644
--- a/radio/1.3/IRadio.hal
+++ b/radio/1.3/IRadio.hal
@@ -17,8 +17,12 @@
 package android.hardware.radio@1.3;
 
 import @1.2::IRadio;
+import @1.1::RadioAccessSpecifier;
 
 /**
+ * Note: IRadio 1.3 is an intermediate layer between Android P and Android Q. It's specifically
+ * designed for CBRS related interfaces. All other interfaces for Q are added in IRadio 1.4.
+ *
  * This interface is used by telephony and telecom to talk to cellular radio.
  * All the functions have minimum one parameter:
  * serial: which corresponds to serial no. of request. Serial numbers must only be memorized for the
@@ -27,4 +31,33 @@
  * setResponseFunctions must work with @1.1::IRadioResponse and @1.1::IRadioIndication.
  */
 interface IRadio extends @1.2::IRadio {
+    /**
+     * Specify which bands modem's background scan must act on.
+     * If specifyChannels is true, it only scans bands specified in specifiers.
+     * If specifyChannels is false, it scans all bands.
+     *
+     * For example, CBRS is only on LTE band 48. By specifying this band,
+     * modem saves more power.
+     *
+     * @param serial Serial number of request.
+     * @param specifyChannels whether to scan bands defined in specifiers.
+     * @param specifiers which bands to scan. Only used if specifyChannels is true.
+     *
+     * Response callback is IRadioResponse.setSystemSelectionChannelsResponse()
+     */
+    oneway setSystemSelectionChannels(int32_t serial, bool specifyChannels,
+            vec<RadioAccessSpecifier> specifiers);
+
+   /**
+    * Toggle logical modem on and off. It should put the logical modem in low power
+    * mode without any activity, while the SIM card remains visible. The difference
+    * with setRadioPower is, setRadioPower affects all logical modem while this controls
+    * just one.
+    *
+    * @param serial Serial number of request.
+    * @param on True to turn on the logical modem, otherwise turn it off.
+    *
+    * Response function is IRadioResponse.enableModemResponse()
+    */
+    oneway enableModem(int32_t serial, bool on);
 };
diff --git a/radio/1.3/IRadioResponse.hal b/radio/1.3/IRadioResponse.hal
index 2bcdd02..abdf2ee 100644
--- a/radio/1.3/IRadioResponse.hal
+++ b/radio/1.3/IRadioResponse.hal
@@ -17,9 +17,33 @@
 package android.hardware.radio@1.3;
 
 import @1.2::IRadioResponse;
+import @1.0::RadioResponseInfo;
 
 /**
+ * Note: IRadio 1.3 is an intermediate layer between Android P and Android Q. It's specifically
+ * designed for CBRS related interfaces. All other interfaces for Q are added in IRadio 1.4.
+ *
  * Interface declaring response functions to solicited radio requests.
  */
 interface IRadioResponse extends @1.2::IRadioResponse {
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     */
+    oneway setSystemSelectionChannelsResponse(RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     */
+    oneway enableModemResponse(RadioResponseInfo info);
 };
diff --git a/radio/1.4/Android.bp b/radio/1.4/Android.bp
index a450f20..c2ba47e 100644
--- a/radio/1.4/Android.bp
+++ b/radio/1.4/Android.bp
@@ -37,6 +37,7 @@
         "PhysicalChannelConfig",
         "RadioFrequencyInfo",
         "RadioTechnology",
+        "NrIndicators",
     ],
     gen_java: true,
 }
diff --git a/radio/1.4/IRadio.hal b/radio/1.4/IRadio.hal
index 1b6d9a6..8854453 100644
--- a/radio/1.4/IRadio.hal
+++ b/radio/1.4/IRadio.hal
@@ -16,11 +16,11 @@
 
 package android.hardware.radio@1.4;
 
-import @1.4::DataProfileInfo;
 import @1.0::Dial;
 import @1.2::DataRequestReason;
 import @1.3::IRadio;
 import @1.4::AccessNetwork;
+import @1.4::DataProfileInfo;
 import @1.4::EmergencyServiceCategory;
 
 /**
diff --git a/radio/1.4/types.hal b/radio/1.4/types.hal
index ea3c53f..4e5b288 100644
--- a/radio/1.4/types.hal
+++ b/radio/1.4/types.hal
@@ -228,18 +228,18 @@
     bool isEmcBearerSupported;
 };
 
-struct DataRegStateResult {
-    @1.2::DataRegStateResult base;
+/** The parameters of NR 5G Non-Standalone. */
+struct NrIndicators {
     /**
-     * Network capabilities for voice over PS services. This info is valid only
-     * on LTE network and must be present when device is camped on LTE. vopsInfo
-     * will be empty when device is camped only on 2G/3G .
+     * Indicates that if E-UTRA-NR Dual Connectivity (EN-DC) is supported by the primary serving
+     * cell.
+     *
+     * True the primary serving cell is LTE cell and the plmn-InfoList-r15 is present in SIB2 and
+     * at least one bit in this list is true, otherwise this value should be false.
+     *
+     * Reference: 3GPP TS 36.331 v15.2.2 6.3.1 System information blocks.
      */
-    safe_union VopsInfo {
-        Monostate noinit;
-
-        LteVopsInfo lteVopsInfo; // LTE network capability
-    } vopsInfo;
+    bool isEndcAvailable;
 
     /**
      * True if use of dual connectivity with NR is restricted.
@@ -256,6 +256,27 @@
     bool isNrAvailable;
 };
 
+struct DataRegStateResult {
+    @1.2::DataRegStateResult base;
+
+    /**
+     * Network capabilities for voice over PS services. This info is valid only on LTE network and
+     * must be present when device is camped on LTE. vopsInfo must be empty when device is camped
+     * only on 2G/3G.
+     */
+    safe_union VopsInfo {
+        Monostate noinit;
+
+        LteVopsInfo lteVopsInfo; // LTE network capability
+    } vopsInfo;
+
+    /**
+     * The parameters of NR 5G Non-Standalone. This value is only valid on E-UTRAN, otherwise
+     * must be empty.
+     */
+    NrIndicators nrIndicators;
+};
+
 /** Contains the configuration of the LTE cell tower. */
 struct CellConfigLte {
     /**
diff --git a/radio/config/1.1/Android.bp b/radio/config/1.1/Android.bp
index 10c4c98..056510c 100644
--- a/radio/config/1.1/Android.bp
+++ b/radio/config/1.1/Android.bp
@@ -7,14 +7,20 @@
         enabled: true,
     },
     srcs: [
+        "IRadioConfig.hal",
         "IRadioConfigIndication.hal",
         "IRadioConfigResponse.hal",
+        "types.hal",
     ],
     interfaces: [
         "android.hardware.radio.config@1.0",
         "android.hardware.radio@1.0",
         "android.hidl.base@1.0",
     ],
+    types: [
+        "ModemInfo",
+        "PhoneCapability",
+    ],
     gen_java: true,
 }
 
diff --git a/radio/config/1.1/IRadioConfig.hal b/radio/config/1.1/IRadioConfig.hal
new file mode 100644
index 0000000..bc63339
--- /dev/null
+++ b/radio/config/1.1/IRadioConfig.hal
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.config@1.1;
+
+import @1.0::IRadioConfig;
+import @1.1::IRadioConfigResponse;
+import @1.1::PhoneCapability;
+
+/**
+ * Note: IRadioConfig 1.1 is an intermediate layer between Android P and Android Q.
+ * It's specifically designed for CBRS related interfaces. All other interfaces
+ * for Q are added in IRadioConfig 1.2.
+ *
+ * This interface is used by telephony and telecom to talk to cellular radio for the purpose of
+ * radio configuration, and it is not associated with any specific modem or slot.
+ * All the functions have minimum one parameter:
+ * serial: which corresponds to serial no. of request. Serial numbers must only be memorized for the
+ * duration of a method call. If clients provide colliding serials (including passing the same
+ * serial to different methods), multiple responses (one for each method call) must still be served.
+ */
+interface IRadioConfig extends @1.0::IRadioConfig {
+   /**
+     * Request current phone capability.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response callback is IRadioResponse.getPhoneCapabilityResponse() which
+     * will return <@1.1::PhoneCapability>.
+     */
+    oneway getPhoneCapability(int32_t serial);
+
+   /**
+     * Set preferred data modem Id.
+     * In a multi-SIM device, notify modem layer which logical modem will be used primarily
+     * for data. It helps modem with resource optimization and decisions of what data connections
+     * should be satisfied.
+     *
+     * @param serial Serial number of request.
+     * @param modem Id the logical modem ID, which should match one of modem IDs returned
+     * from getPhoneCapability().
+     *
+     * Response callback is IRadioConfigResponse.setPreferredDataModemResponse()
+     */
+    oneway setPreferredDataModem(int32_t serial, uint8_t modemId);
+};
diff --git a/radio/config/1.1/IRadioConfigResponse.hal b/radio/config/1.1/IRadioConfigResponse.hal
index 5d75600..42a31b1 100644
--- a/radio/config/1.1/IRadioConfigResponse.hal
+++ b/radio/config/1.1/IRadioConfigResponse.hal
@@ -17,9 +17,37 @@
 package android.hardware.radio.config@1.1;
 
 import @1.0::IRadioConfigResponse;
+import @1.1::PhoneCapability;
+import android.hardware.radio@1.0::RadioResponseInfo;
 
 /**
+ * Note: IRadioConfig 1.1 is an intermediate layer between Android P and Android Q.
+ * It's specifically designed for CBRS related interfaces. All other interfaces
+ * for Q are be added in IRadioConfig 1.2.
+ *
  * Interface declaring response functions to solicited radio config requests.
  */
 interface IRadioConfigResponse extends @1.0::IRadioConfigResponse {
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param phoneCapability <@1.1::PhoneCapability> it defines modem's capability for example
+     *        how many logical modems it has, how many data connections it supports.
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     */
+    oneway getPhoneCapabilityResponse(RadioResponseInfo info, PhoneCapability phoneCapability);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:INVALID_ARGUMENTS
+     */
+    oneway setPreferredDataModemResponse(RadioResponseInfo info);
 };
diff --git a/radio/config/1.1/types.hal b/radio/config/1.1/types.hal
new file mode 100644
index 0000000..a7b9f86
--- /dev/null
+++ b/radio/config/1.1/types.hal
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio.config@1.1;
+
+/**
+ * Note: IRadioConfig 1.1 is an intermediate layer between Android P and Android Q.
+ * It's specifically designed for CBRS related interfaces. All other interfaces
+ * for Q are be added in IRadioConfig 1.2.
+ */
+
+/**
+ * A field in PhoneCapability that has information of each logical modem.
+ */
+struct ModemInfo {
+    /**
+     * Logical modem ID.
+     */
+    uint8_t modemId;
+};
+
+/**
+ * Phone capability which describes the data connection capability of modem.
+ * It's used to evaluate possible phone config change, for example from single
+ * SIM device to multi-SIM device.
+ */
+struct PhoneCapability {
+    /**
+     * maxActiveData defines how many logical modems can have
+     * PS attached simultaneously. For example, for L+L modem it
+     * should be 2.
+     */
+    uint8_t maxActiveData;
+    /**
+     * maxActiveData defines how many logical modems can have
+     * internet PDN connections simultaneously. For example, for L+L
+     * DSDS modem it’s 1, and for DSDA modem it’s 2.
+     */
+    uint8_t maxActiveInternetData;
+    /**
+     * Whether modem supports both internet PDN up so
+     * that we can do ping test before tearing down the
+     * other one.
+     */
+    bool isInternetLingeringSupported;
+    /**
+     * List of logical modem information.
+     */
+    vec<ModemInfo> logicalModemList;
+};
diff --git a/renderscript/1.0/default/Context.cpp b/renderscript/1.0/default/Context.cpp
index f5b70c9..bb2a40e 100644
--- a/renderscript/1.0/default/Context.cpp
+++ b/renderscript/1.0/default/Context.cpp
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 #include "Context.h"
 #include "Device.h"
 
diff --git a/renderscript/1.0/default/Context.h b/renderscript/1.0/default/Context.h
index d8bfe4f..4ed2d9a 100644
--- a/renderscript/1.0/default/Context.h
+++ b/renderscript/1.0/default/Context.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 #ifndef ANDROID_HARDWARE_RENDERSCRIPT_V1_0_CONTEXT_H
 #define ANDROID_HARDWARE_RENDERSCRIPT_V1_0_CONTEXT_H
 
diff --git a/renderscript/1.0/default/Device.cpp b/renderscript/1.0/default/Device.cpp
index 8fda3ff..d603a12 100644
--- a/renderscript/1.0/default/Device.cpp
+++ b/renderscript/1.0/default/Device.cpp
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 #include "Context.h"
 #include "Device.h"
 
diff --git a/renderscript/1.0/default/Device.h b/renderscript/1.0/default/Device.h
index f5bda37..74e1907 100644
--- a/renderscript/1.0/default/Device.h
+++ b/renderscript/1.0/default/Device.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 #ifndef ANDROID_HARDWARE_RENDERSCRIPT_V1_0_DEVICE_H
 #define ANDROID_HARDWARE_RENDERSCRIPT_V1_0_DEVICE_H
 
diff --git a/thermal/2.0/types.hal b/thermal/2.0/types.hal
index ad11849..a1c0325 100644
--- a/thermal/2.0/types.hal
+++ b/thermal/2.0/types.hal
@@ -71,9 +71,10 @@
     CRITICAL,
 
     /**
-     * User should be warned before shutdown.
+     * Key components in platform are shutting down due to thermal condition.
+     * Device functionalities will be limited.
      */
-    WARNING,
+    EMERGENCY,
 
     /**
      * Need shutdown immediately.
diff --git a/wifi/1.3/default/hidl_struct_util.cpp b/wifi/1.3/default/hidl_struct_util.cpp
index c88ddaa..b3d612f 100644
--- a/wifi/1.3/default/hidl_struct_util.cpp
+++ b/wifi/1.3/default/hidl_struct_util.cpp
@@ -69,9 +69,9 @@
     return {};
 }
 
-V1_2::IWifiChip::ChipCapabilityMask convertLegacyFeatureToHidlChipCapability(
+V1_3::IWifiChip::ChipCapabilityMask convertLegacyFeatureToHidlChipCapability(
     uint32_t feature) {
-    using HidlChipCaps = V1_2::IWifiChip::ChipCapabilityMask;
+    using HidlChipCaps = V1_3::IWifiChip::ChipCapabilityMask;
     switch (feature) {
         case WIFI_FEATURE_SET_TX_POWER_LIMIT:
             return HidlChipCaps::SET_TX_POWER_LIMIT;
@@ -81,6 +81,8 @@
             return HidlChipCaps::D2D_RTT;
         case WIFI_FEATURE_D2AP_RTT:
             return HidlChipCaps::D2AP_RTT;
+        case WIFI_FEATURE_SET_LATENCY_MODE:
+            return HidlChipCaps::SET_LATENCY_MODE;
     };
     CHECK(false) << "Unknown legacy feature: " << feature;
     return {};
@@ -141,7 +143,8 @@
     }
     for (const auto feature :
          {WIFI_FEATURE_SET_TX_POWER_LIMIT, WIFI_FEATURE_USE_BODY_HEAD_SAR,
-          WIFI_FEATURE_D2D_RTT, WIFI_FEATURE_D2AP_RTT}) {
+          WIFI_FEATURE_D2D_RTT, WIFI_FEATURE_D2AP_RTT,
+          WIFI_FEATURE_SET_LATENCY_MODE}) {
         if (feature & legacy_feature_set) {
             *hidl_caps |= convertLegacyFeatureToHidlChipCapability(feature);
         }
@@ -292,6 +295,17 @@
     CHECK(false);
 }
 
+legacy_hal::wifi_latency_mode convertHidlLatencyModeToLegacy(
+    IWifiChip::LatencyMode hidl_latency_mode) {
+    switch (hidl_latency_mode) {
+        case IWifiChip::LatencyMode::NORMAL:
+            return legacy_hal::WIFI_LATENCY_MODE_NORMAL;
+        case IWifiChip::LatencyMode::LOW:
+            return legacy_hal::WIFI_LATENCY_MODE_LOW;
+    }
+    CHECK(false);
+}
+
 bool convertLegacyWifiMacInfoToHidl(
     const legacy_hal::WifiMacInfo& legacy_mac_info,
     V1_2::IWifiChipEventCallback::RadioModeInfo* hidl_radio_mode_info) {
diff --git a/wifi/1.3/default/hidl_struct_util.h b/wifi/1.3/default/hidl_struct_util.h
index 8df484d..3eefd95 100644
--- a/wifi/1.3/default/hidl_struct_util.h
+++ b/wifi/1.3/default/hidl_struct_util.h
@@ -21,9 +21,9 @@
 
 #include <android/hardware/wifi/1.0/IWifiChip.h>
 #include <android/hardware/wifi/1.0/types.h>
-#include <android/hardware/wifi/1.2/IWifiChip.h>
 #include <android/hardware/wifi/1.2/IWifiChipEventCallback.h>
 #include <android/hardware/wifi/1.2/types.h>
+#include <android/hardware/wifi/1.3/IWifiChip.h>
 #include <android/hardware/wifi/1.3/types.h>
 
 #include "wifi_legacy_hal.h"
@@ -57,6 +57,8 @@
     WifiDebugHostWakeReasonStats* hidl_stats);
 legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy(
     V1_1::IWifiChip::TxPowerScenario hidl_scenario);
+legacy_hal::wifi_latency_mode convertHidlLatencyModeToLegacy(
+    V1_3::IWifiChip::LatencyMode hidl_latency_mode);
 legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy_1_2(
     V1_2::IWifiChip::TxPowerScenario hidl_scenario);
 bool convertLegacyWifiMacInfosToHidl(
diff --git a/wifi/1.3/default/tests/hidl_struct_util_unit_tests.cpp b/wifi/1.3/default/tests/hidl_struct_util_unit_tests.cpp
index d600a2b..7056759 100644
--- a/wifi/1.3/default/tests/hidl_struct_util_unit_tests.cpp
+++ b/wifi/1.3/default/tests/hidl_struct_util_unit_tests.cpp
@@ -238,6 +238,27 @@
                   converted.radios[i].onTimeInMsForHs20Scan);
     }
 }
+
+TEST_F(HidlStructUtilTest, CanConvertLegacyFeaturesToHidl) {
+    using HidlChipCaps = V1_3::IWifiChip::ChipCapabilityMask;
+
+    uint32_t hidle_caps;
+
+    uint32_t legacy_feature_set =
+            WIFI_FEATURE_D2D_RTT | WIFI_FEATURE_SET_LATENCY_MODE;
+    uint32_t legacy_logger_feature_set =
+            legacy_hal::WIFI_LOGGER_DRIVER_DUMP_SUPPORTED;
+
+    ASSERT_TRUE(hidl_struct_util::convertLegacyFeaturesToHidlChipCapabilities(
+        legacy_feature_set, legacy_logger_feature_set, &hidle_caps));
+
+    EXPECT_EQ(HidlChipCaps::DEBUG_RING_BUFFER_VENDOR_DATA |
+                  HidlChipCaps::DEBUG_HOST_WAKE_REASON_STATS |
+                  HidlChipCaps::DEBUG_ERROR_ALERTS | HidlChipCaps::D2D_RTT |
+                  HidlChipCaps::SET_LATENCY_MODE |
+                  HidlChipCaps::DEBUG_MEMORY_DRIVER_DUMP,
+              hidle_caps);
+}
 }  // namespace implementation
 }  // namespace V1_3
 }  // namespace wifi
diff --git a/wifi/1.3/default/wifi_chip.cpp b/wifi/1.3/default/wifi_chip.cpp
index faf1862..a80116a 100644
--- a/wifi/1.3/default/wifi_chip.cpp
+++ b/wifi/1.3/default/wifi_chip.cpp
@@ -561,6 +561,13 @@
                            hidl_status_cb);
 }
 
+Return<void> WifiChip::setLatencyMode(LatencyMode mode,
+                                      setLatencyMode_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::setLatencyModeInternal, hidl_status_cb,
+                           mode);
+}
+
 Return<void> WifiChip::registerEventCallback_1_2(
     const sp<V1_2::IWifiChipEventCallback>& event_callback,
     registerEventCallback_cb hidl_status_cb) {
@@ -576,6 +583,12 @@
                            hidl_status_cb, scenario);
 }
 
+Return<void> WifiChip::getCapabilities_1_3(getCapabilities_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::getCapabilitiesInternal_1_3,
+                           hidl_status_cb);
+}
+
 Return<void> WifiChip::debug(const hidl_handle& handle,
                              const hidl_vec<hidl_string>&) {
     if (handle != nullptr && handle->numFds >= 1) {
@@ -618,6 +631,11 @@
 }
 
 std::pair<WifiStatus, uint32_t> WifiChip::getCapabilitiesInternal() {
+    // Deprecated support for this callback.
+    return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), 0};
+}
+
+std::pair<WifiStatus, uint32_t> WifiChip::getCapabilitiesInternal_1_3() {
     legacy_hal::wifi_error legacy_status;
     uint32_t legacy_feature_set;
     uint32_t legacy_logger_feature_set;
@@ -1058,6 +1076,13 @@
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
+WifiStatus WifiChip::setLatencyModeInternal(LatencyMode mode) {
+    auto legacy_status = legacy_hal_.lock()->setLatencyMode(
+        getWlan0IfaceName(),
+        hidl_struct_util::convertHidlLatencyModeToLegacy(mode));
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
 WifiStatus WifiChip::registerEventCallbackInternal_1_2(
     const sp<V1_2::IWifiChipEventCallback>& event_callback) {
     if (!event_cb_handler_.addCallback(event_callback)) {
diff --git a/wifi/1.3/default/wifi_chip.h b/wifi/1.3/default/wifi_chip.h
index ba60a8e..11200f9 100644
--- a/wifi/1.3/default/wifi_chip.h
+++ b/wifi/1.3/default/wifi_chip.h
@@ -21,7 +21,7 @@
 #include <map>
 
 #include <android-base/macros.h>
-#include <android/hardware/wifi/1.2/IWifiChip.h>
+#include <android/hardware/wifi/1.3/IWifiChip.h>
 
 #include "hidl_callback_util.h"
 #include "ringbuffer.h"
@@ -46,7 +46,7 @@
  * Since there is only a single chip instance used today, there is no
  * identifying handle information stored here.
  */
-class WifiChip : public V1_2::IWifiChip {
+class WifiChip : public V1_3::IWifiChip {
    public:
     WifiChip(
         ChipId chip_id,
@@ -137,12 +137,16 @@
         selectTxPowerScenario_cb hidl_status_cb) override;
     Return<void> resetTxPowerScenario(
         resetTxPowerScenario_cb hidl_status_cb) override;
+    Return<void> setLatencyMode(LatencyMode mode,
+                                setLatencyMode_cb hidl_status_cb) override;
     Return<void> registerEventCallback_1_2(
         const sp<V1_2::IWifiChipEventCallback>& event_callback,
         registerEventCallback_1_2_cb hidl_status_cb) override;
     Return<void> selectTxPowerScenario_1_2(
         TxPowerScenario scenario,
         selectTxPowerScenario_cb hidl_status_cb) override;
+    Return<void> getCapabilities_1_3(
+        getCapabilities_cb hidl_status_cb) override;
     Return<void> debug(const hidl_handle& handle,
                        const hidl_vec<hidl_string>& options) override;
 
@@ -201,9 +205,11 @@
     WifiStatus selectTxPowerScenarioInternal(
         V1_1::IWifiChip::TxPowerScenario scenario);
     WifiStatus resetTxPowerScenarioInternal();
+    WifiStatus setLatencyModeInternal(LatencyMode mode);
     WifiStatus registerEventCallbackInternal_1_2(
         const sp<V1_2::IWifiChipEventCallback>& event_callback);
     WifiStatus selectTxPowerScenarioInternal_1_2(TxPowerScenario scenario);
+    std::pair<WifiStatus, uint32_t> getCapabilitiesInternal_1_3();
     WifiStatus handleChipConfiguration(
         std::unique_lock<std::recursive_mutex>* lock, ChipModeId mode_id);
     WifiStatus registerDebugRingBufferCallback();
diff --git a/wifi/1.3/default/wifi_legacy_hal.cpp b/wifi/1.3/default/wifi_legacy_hal.cpp
index 817c860..2cd7c2a 100644
--- a/wifi/1.3/default/wifi_legacy_hal.cpp
+++ b/wifi/1.3/default/wifi_legacy_hal.cpp
@@ -796,6 +796,12 @@
         getIfaceHandle(iface_name));
 }
 
+wifi_error WifiLegacyHal::setLatencyMode(const std::string& iface_name,
+                                         wifi_latency_mode mode) {
+    return global_func_table_.wifi_set_latency_mode(getIfaceHandle(iface_name),
+                                                    mode);
+}
+
 std::pair<wifi_error, uint32_t> WifiLegacyHal::getLoggerSupportedFeatureSet(
     const std::string& iface_name) {
     uint32_t supported_feature_flags;
diff --git a/wifi/1.3/default/wifi_legacy_hal.h b/wifi/1.3/default/wifi_legacy_hal.h
index af654fa..2f513c4 100644
--- a/wifi/1.3/default/wifi_legacy_hal.h
+++ b/wifi/1.3/default/wifi_legacy_hal.h
@@ -254,6 +254,8 @@
     wifi_error selectTxPowerScenario(const std::string& iface_name,
                                      wifi_power_scenario scenario);
     wifi_error resetTxPowerScenario(const std::string& iface_name);
+    wifi_error setLatencyMode(const std::string& iface_name,
+                              wifi_latency_mode mode);
     // Logger/debug functions.
     std::pair<wifi_error, uint32_t> getLoggerSupportedFeatureSet(
         const std::string& iface_name);
diff --git a/wifi/1.3/default/wifi_legacy_hal_stubs.cpp b/wifi/1.3/default/wifi_legacy_hal_stubs.cpp
index 942df2a..dedd2d4 100644
--- a/wifi/1.3/default/wifi_legacy_hal_stubs.cpp
+++ b/wifi/1.3/default/wifi_legacy_hal_stubs.cpp
@@ -137,6 +137,7 @@
     populateStubFor(&hal_fn->wifi_select_tx_power_scenario);
     populateStubFor(&hal_fn->wifi_reset_tx_power_scenario);
     populateStubFor(&hal_fn->wifi_set_radio_mode_change_handler);
+    populateStubFor(&hal_fn->wifi_set_latency_mode);
     return true;
 }
 }  // namespace legacy_hal
diff --git a/wifi/1.3/vts/functional/Android.bp b/wifi/1.3/vts/functional/Android.bp
index dbe77bd..f5a0999 100644
--- a/wifi/1.3/vts/functional/Android.bp
+++ b/wifi/1.3/vts/functional/Android.bp
@@ -19,6 +19,7 @@
     defaults: ["VtsHalTargetTestDefaults"],
     srcs: [
         "VtsHalWifiV1_3TargetTest.cpp",
+        "wifi_chip_hidl_test.cpp",
     ],
     static_libs: [
         "VtsHalWifiV1_0TargetTestUtil",
diff --git a/wifi/1.3/vts/functional/wifi_chip_hidl_test.cpp b/wifi/1.3/vts/functional/wifi_chip_hidl_test.cpp
new file mode 100644
index 0000000..d980fcb
--- /dev/null
+++ b/wifi/1.3/vts/functional/wifi_chip_hidl_test.cpp
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+
+#include <android/hardware/wifi/1.3/IWifiChip.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+
+#include "wifi_hidl_call_util.h"
+#include "wifi_hidl_test_utils.h"
+
+using ::android::sp;
+using ::android::hardware::wifi::V1_0::ChipModeId;
+using ::android::hardware::wifi::V1_0::IfaceType;
+using ::android::hardware::wifi::V1_0::WifiStatusCode;
+using ::android::hardware::wifi::V1_3::IWifiChip;
+
+namespace {
+constexpr IWifiChip::LatencyMode kLatencyModeNormal =
+    IWifiChip::LatencyMode::NORMAL;
+
+constexpr IWifiChip::LatencyMode kLatencyModeLow = IWifiChip::LatencyMode::LOW;
+};  // namespace
+
+/**
+ * Fixture to use for all Wifi chip HIDL interface tests.
+ */
+class WifiChipHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+   public:
+    virtual void SetUp() override {
+        wifi_chip_ = IWifiChip::castFrom(getWifiChip());
+        ASSERT_NE(nullptr, wifi_chip_.get());
+    }
+
+    virtual void TearDown() override { stopWifi(); }
+
+   protected:
+    // Helper function to configure the Chip in one of the supported modes.
+    // Most of the non-mode-configuration-related methods require chip
+    // to be first configured.
+    ChipModeId configureChipForIfaceType(IfaceType type, bool expectSuccess) {
+        ChipModeId mode_id;
+        EXPECT_EQ(expectSuccess,
+                  configureChipToSupportIfaceType(wifi_chip_, type, &mode_id));
+        return mode_id;
+    }
+
+    uint32_t configureChipForStaIfaceAndGetCapabilities() {
+        ChipModeId mode_id;
+        EXPECT_TRUE(configureChipToSupportIfaceType(wifi_chip_, IfaceType::STA,
+                                                    &mode_id));
+        const auto& status_and_caps =
+            HIDL_INVOKE(wifi_chip_, getCapabilities_1_3);
+        EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_caps.first.code);
+        return status_and_caps.second;
+    }
+
+    sp<IWifiChip> wifi_chip_;
+};
+
+/*
+ * SetLatencyMode_normal
+ * This test case tests the setLatencyMode() API with
+ * Latency mode NORMAL
+ */
+TEST_F(WifiChipHidlTest, SetLatencyMode_normal) {
+    uint32_t caps = configureChipForStaIfaceAndGetCapabilities();
+    const auto& status =
+        HIDL_INVOKE(wifi_chip_, setLatencyMode, kLatencyModeNormal);
+    if (caps & (IWifiChip::ChipCapabilityMask::SET_LATENCY_MODE)) {
+        EXPECT_EQ(WifiStatusCode::SUCCESS, status.code);
+    } else {
+        EXPECT_EQ(WifiStatusCode::ERROR_NOT_SUPPORTED, status.code);
+    }
+}
+
+/*
+ * SetLatencyMode_low
+ * This test case tests the setLatencyMode() API with Latency mode LOW
+ */
+TEST_F(WifiChipHidlTest, SetLatencyMode_low) {
+    uint32_t caps = configureChipForStaIfaceAndGetCapabilities();
+    const auto& status =
+        HIDL_INVOKE(wifi_chip_, setLatencyMode, kLatencyModeLow);
+    if (caps & (IWifiChip::ChipCapabilityMask::SET_LATENCY_MODE)) {
+        EXPECT_EQ(WifiStatusCode::SUCCESS, status.code);
+    } else {
+        EXPECT_EQ(WifiStatusCode::ERROR_NOT_SUPPORTED, status.code);
+    }
+}
+
+/*
+ * GetCapabilities_1_3
+ */
+TEST_F(WifiChipHidlTest, GetCapabilities_1_3) {
+    configureChipForIfaceType(IfaceType::STA, true);
+    const auto& status_and_caps = HIDL_INVOKE(wifi_chip_, getCapabilities_1_3);
+    if (status_and_caps.first.code != WifiStatusCode::SUCCESS) {
+        EXPECT_EQ(WifiStatusCode::ERROR_NOT_SUPPORTED,
+                  status_and_caps.first.code);
+        return;
+    }
+    EXPECT_NE(0u, status_and_caps.second);
+}