Merge "Add drm hal/vts owners"
diff --git a/audio/common/all-versions/copyHAL.sh b/audio/common/all-versions/copyHAL.sh
index d07012f..56559d1 100755
--- a/audio/common/all-versions/copyHAL.sh
+++ b/audio/common/all-versions/copyHAL.sh
@@ -26,6 +26,7 @@
 readonly VTS_DIRECTORY=test/vts-testcase/hal/audio
 readonly VTS_LIST=test/vts/tools/build/tasks/list/vts_test_lib_hidl_package_list.mk
 readonly WATCHDOG=frameworks/base/services/core/java/com/android/server/Watchdog.cpp
+readonly DUMP_UTILS=frameworks/native/libs/dumputils/dump_utils.cpp
 readonly GSI_CURRENT=build/make/target/product/gsi/current.txt
 
 readonly BASE_VERSION=${1:-$(ls $ANDROID_BUILD_TOP/$HAL_DIRECTORY | grep -E '[0-9]+\.[0-9]+' |
@@ -171,6 +172,9 @@
 echo "Now update watchdog"
 runIfNeeded $(dirname $WATCHDOG) updateAudioVersion -v original_before=1 $(basename $WATCHDOG)
 
+echo "Now update dumputils"
+runIfNeeded $(dirname $DUMP_UTILS) updateAudioVersion -v original_before=1 $(basename $DUMP_UTILS)
+
 echo "Now update GSI current.txt"
 runIfNeeded $(dirname $GSI_CURRENT) update-vndk-list.sh
 
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index fb6ae0e..395848c 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -469,14 +469,6 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
-        <name>android.hardware.vibrator</name>
-        <version>1.0-3</version>
-        <interface>
-            <name>IVibrator</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    <hal format="hidl" optional="true">
         <name>android.hardware.vr</name>
         <version>1.0</version>
         <interface>
diff --git a/current.txt b/current.txt
index edfaf65..205e013 100644
--- a/current.txt
+++ b/current.txt
@@ -622,10 +622,11 @@
 27ae3724053940462114228872b3ffaf0b8e6177d5ba97f5a76339d12b8a99dd android.hardware.keymaster@4.1::IKeymasterDevice
 adb0efdf1462e9b2e742c0dcadd598666aac551f178be06e755bfcdf5797abd0 android.hardware.keymaster@4.1::IOperation
 ac429fca0da4ce91218768ec31b64ded88251f8a26d8c4f27c06abdc5b1926d9 android.hardware.keymaster@4.1::types
-9e59fffceed0dd72a9799e04505db5f777bbbea1af0695ba4107ef6d967c6fda android.hardware.neuralnetworks@1.3::IDevice
-258825966435b3ed08832055bb736d81516013e405f161d9ccde9a90cfcdde83 android.hardware.neuralnetworks@1.3::IPreparedModel
+4b5c8546533db9412fec6d32c0ef42b22e5e68dbf390c775ec3c22bb2d501102 android.hardware.neuralnetworks@1.3::IBuffer
+5a6b75f13f0e010a4268defa4f627b862ab2899fb04f9d985194a25bd8f9fe0d android.hardware.neuralnetworks@1.3::IDevice
+058b48f0e2e725bb2b3fa2b7917b0f0a696383d03a4c57afe26f0eadb6a7af28 android.hardware.neuralnetworks@1.3::IPreparedModel
 94e803236398bed1febb11cc21051bc42ec003700139b099d6c479e02a7ca3c3 android.hardware.neuralnetworks@1.3::IPreparedModelCallback
-f3c1e7298da628a755b452cd3325e8d0fe867a2debb873069baab6a27434a72d android.hardware.neuralnetworks@1.3::types
+12c51f9d04a52324510419aeee3e37bb3607e6900556cdde79774d80ed989855 android.hardware.neuralnetworks@1.3::types
 3e01d4446cd69fd1c48f8572efd97487bc179564b32bd795800b97bbe10be37b android.hardware.wifi@1.4::IWifi
 a64467bae843569f0d465c5be7f0c7a5b987985b55a3ef4794dd5afc68538650 android.hardware.wifi.supplicant@1.3::ISupplicant
 44445b8a03d7b9e68b2fbd954672c18a8fce9e32851b0692f4f4ab3407f86ecb android.hardware.wifi.supplicant@1.3::ISupplicantStaIface
@@ -635,14 +636,14 @@
 ##
 # BEGIN Radio HAL Merge Conflict Avoidance Buffer - STOPSHIP if present
 ##
-275a01e456f3c988ac9736d26ceaf3e95fb7b3c333a8a7fe983de6bae39df58a android.hardware.radio@1.5::types
-7a0a3382cca78d13a55e856b14b7fb025987f52c2adeab5747cd584391cd3cc7 android.hardware.radio@1.5::IRadio
+bbed8ec4b3e9bb419b61d3fe53ec2d7def943378d1de8eaa02d79b17b0838136 android.hardware.radio@1.5::types
+603851ca0f5360778049902fc7486d0ff60065b16e83b99f076487667aba1928 android.hardware.radio@1.5::IRadio
 20d52e66fd548f89bcb98cda42749a591ce8f439a2a7148617adac0c967ad937 android.hardware.radio@1.5::IRadioIndication
-c7b4a0debd3bb8815a463d11194487c7eef81bca584f558d7ba74c34b18d7e3f android.hardware.radio@1.5::IRadioResponse
-55f0a15642869ec98a55ea0a5ac049d3e1a6245ff7750deb6bcb7182057eee83 android.hardware.radio.config@1.3::types
-b27ab0cd40b0b078cdcd024bfe1061c4c4c065f3519eeb9347fa359a3268a5ae android.hardware.radio.config@1.3::IRadioConfig
+afa9ba21fbf130e5cd6463b01ee34175a60220cdc8b657443e683494e6deca8d android.hardware.radio@1.5::IRadioResponse
+5971a891d7d8843e9fb9f44583a9a0a265ec42fd5e4e1c95c9803454d21fabf7 android.hardware.radio.config@1.3::types
+a2977755bc5f1ef47f04b7f2400632efda6218e1515dba847da487145cfabc4f android.hardware.radio.config@1.3::IRadioConfig
 742360c775313438b0f82256eac62fb5bbc76a6ae6f388573f3aa142fb2c1eea android.hardware.radio.config@1.3::IRadioConfigIndication
-7683fed9d253956071f18b152e6be657719536f98d9b534433d5e411bcde5061 android.hardware.radio.config@1.3::IRadioConfigResponse
+0006ab8e8b0910cbd3bbb08d5f17d5fac7d65a2bdad5f2334e4851db9d1e6fa8 android.hardware.radio.config@1.3::IRadioConfigResponse
 ##
 # END Radio HAL Merge Conflict Avoidance Buffer - STOPSHIP if present
 ##
diff --git a/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp b/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp
index 49891b7..352a990 100644
--- a/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp
+++ b/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp
@@ -315,9 +315,7 @@
 TEST_P(HealthHidlTest, getChargeStatus) {
     SKIP_IF_SKIPPED();
     EXPECT_OK(mHealth->getChargeStatus([](auto result, auto value) {
-        EXPECT_VALID_OR_UNSUPPORTED_PROP(
-            result, toString(value),
-            value != BatteryStatus::UNKNOWN && verifyEnum<BatteryStatus>(value));
+        EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), verifyEnum<BatteryStatus>(value));
     }));
 }
 
diff --git a/health/2.1/vts/functional/Android.bp b/health/2.1/vts/functional/Android.bp
index 5aa873a..17472fa 100644
--- a/health/2.1/vts/functional/Android.bp
+++ b/health/2.1/vts/functional/Android.bp
@@ -25,5 +25,8 @@
         "android.hardware.health@2.0",
         "android.hardware.health@2.1",
     ],
-    test_suites: ["general-tests"],
+    test_suites: [
+        "general-tests",
+        "vts-core",
+    ],
 }
diff --git a/neuralnetworks/1.3/Android.bp b/neuralnetworks/1.3/Android.bp
index 0b07a58..08e824d 100644
--- a/neuralnetworks/1.3/Android.bp
+++ b/neuralnetworks/1.3/Android.bp
@@ -8,6 +8,7 @@
     },
     srcs: [
         "types.hal",
+        "IBuffer.hal",
         "IDevice.hal",
         "IPreparedModel.hal",
         "IPreparedModelCallback.hal",
diff --git a/neuralnetworks/1.3/IBuffer.hal b/neuralnetworks/1.3/IBuffer.hal
new file mode 100644
index 0000000..84241c5
--- /dev/null
+++ b/neuralnetworks/1.3/IBuffer.hal
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.neuralnetworks@1.3;
+
+import @1.0::ErrorStatus;
+
+/**
+ * This interface represents a device memory buffer.
+ */
+interface IBuffer {
+    /**
+     * Retrieves the content of this buffer to a shared memory region.
+     *
+     * The IBuffer object must have been initialized before the call to IBuffer::copyTo.
+     * For more information on the state of the IBuffer object, refer to IDevice::allocate.
+     *
+     * @param dst The destination shared memory region.
+     * @return status Error status of the call, must be:
+     *     - NONE if successful
+     *     - DEVICE_UNAVAILABLE if driver is offline or busy
+     *     - GENERAL_FAILURE if the IBuffer object is uninitialized, or there is an unspecified
+     *       error
+     *     - INVALID_ARGUMENT if provided memory is invalid
+     */
+    copyTo(memory dst) generates (ErrorStatus status);
+
+    /**
+     * Sets the content of this buffer from a shared memory region.
+     *
+     * @param src The source shared memory region.
+     * @param dimensions Updated dimensional information. If the dimensions of the IBuffer object
+     *     are not fully specified, then the dimensions must be fully specified here. If the
+     *     dimensions of the IBuffer object are fully specified, then the dimensions may be empty
+     *     here. If dimensions.size() > 0, then all dimensions must be specified here, and any
+     *     dimension that was specified in the IBuffer object must have the same value here.
+     * @return status Error status of the call, must be:
+     *     - NONE if successful
+     *     - DEVICE_UNAVAILABLE if driver is offline or busy
+     *     - GENERAL_FAILURE if there is an unspecified error
+     *     - INVALID_ARGUMENT if provided memory is invalid, or if the dimensions is invalid
+     */
+    copyFrom(memory src, vec<uint32_t> dimensions) generates (ErrorStatus status);
+};
diff --git a/neuralnetworks/1.3/IDevice.hal b/neuralnetworks/1.3/IDevice.hal
index 1295d6a..8dc41f7 100644
--- a/neuralnetworks/1.3/IDevice.hal
+++ b/neuralnetworks/1.3/IDevice.hal
@@ -22,6 +22,12 @@
 import @1.2::DeviceType;
 import @1.2::Extension;
 import @1.2::IDevice;
+import BufferDesc;
+import BufferRole;
+import Capabilities;
+import Model;
+import IBuffer;
+import IPreparedModel;
 import IPreparedModelCallback;
 
 /**
@@ -42,9 +48,14 @@
     /**
      * Gets the supported operations in a model.
      *
-     * getSupportedOperations indicates which operations of a model are fully
-     * supported by the vendor driver. If an operation may not be supported for
-     * any reason, getSupportedOperations must return false for that operation.
+     * getSupportedOperations indicates which operations of the top-level
+     * subgraph are fully supported by the vendor driver. If an operation may
+     * not be supported for any reason, getSupportedOperations must return
+     * false for that operation.
+     *
+     * The {@link OperationType::IF} and {@link OperationType::WHILE}
+     * operations may only be fully supported if the vendor driver fully
+     * supports all operations in the referenced subgraphs.
      *
      * @param model A model whose operations--and their corresponding operands--
      *     are to be verified by the driver.
@@ -247,4 +258,61 @@
                               uint8_t[Constant:BYTE_SIZE_OF_CACHE_TOKEN] token,
                               IPreparedModelCallback callback)
             generates (ErrorStatus status);
+
+    /**
+     * Allocates a driver-managed buffer with the properties specified by the buffer descriptor
+     * as well as the input and output roles.
+     *
+     * The allocate function must verify its inputs are correct. If there is an error, or if a
+     * certain role or property is not supported by the driver, the allocate
+     * function must return with an appropriate ErrorStatus, a nullptr as the IBuffer, and 0 as the
+     * buffer token. If the allocation is successful, this method must return with ErrorStatus::NONE
+     * and the produced IBuffer with a positive token identifying the allocated buffer. A successful
+     * allocation must accommodate all of the specified roles and buffer properties.
+     *
+     * The buffer is allocated to an uninitialized state. An uninitialized buffer may only be used
+     * in ways that are specified by outputRoles. A buffer is initialized after it is used as an
+     * output in a successful execution, or after a successful invocation of IBuffer::copyFrom on
+     * the buffer. An initialized buffer may be used according to all roles specified in inputRoles
+     * and outputRoles. A buffer will return to the uninitialized state if it is used as an output
+     * in a failed execution, or after a failed invocation of IBuffer::copyFrom on the buffer.
+     *
+     * The dimensions of the buffer can be deduced from the buffer descriptor as well as the
+     * dimensions of the corresponding model operands of the input and output roles. The dimensions
+     * or rank of the buffer may be unknown at this stage. As such, some driver services may only
+     * create a placeholder and defer the actual allocation until execution time. Note that the
+     * same buffer may be used for different shapes of outputs on different executions. When the
+     * buffer is used as an input, the input shape must be the same as the output shape from the
+     * last execution using this buffer as an output.
+     *
+     * The driver must apply proper validatation upon every usage of the buffer, and must fail the
+     * execution immediately if the usage is illegal.
+     *
+     * @param desc A buffer descriptor specifying the properties of the buffer to allocate.
+     * @param preparedModels A vector of IPreparedModel objects. Must only contain IPreparedModel
+     *     objects from the same IDevice as this method is being invoked on.
+     * @param inputRoles A vector of roles with each specifying an input to a prepared model.
+     * @param outputRoles A vector of roles with each specifying an output to a prepared model.
+     *     Each role specified in inputRoles and outputRoles must be unique. The corresponding
+     *     model operands of the roles must have the same OperandType, scale, zero point, and
+     *     ExtraParams. The dimensions of the operands and the dimensions specified in the buffer
+     *     descriptor must be compatible with each other. Two dimensions are incompatible if there
+     *     is at least one axis that is fully specified in both but has different values.
+     * @return status Error status of the buffer allocation. Must be:
+     *     - NONE if successful
+     *     - DEVICE_UNAVAILABLE if driver is offline or busy
+     *     - GENERAL_FAILURE if a certain buffer property or a certain role is not supported,
+     *       or if there is an unspecified error
+     *     - INVALID_ARGUMENT if one of the input arguments is invalid
+     * @return buffer The allocated IBuffer object. If the buffer was unable to be allocated
+     *     due to an error, nullptr must be returned.
+     * @return token A positive token identifying the allocated buffer. The same token will be
+     *     provided when referencing the buffer as one of the memory pools in the request of an
+     *     execution. The token must not collide with the tokens of other IBuffer objects that are
+     *     currently alive in the same driver service. If the buffer was unable to be allocated
+     *     due to an error, the token must be 0.
+     */
+    allocate(BufferDesc desc, vec<IPreparedModel> preparedModels, vec<BufferRole> inputRoles,
+             vec<BufferRole> outputRoles)
+            generates (ErrorStatus status, IBuffer buffer, int32_t token);
 };
diff --git a/neuralnetworks/1.3/IPreparedModel.hal b/neuralnetworks/1.3/IPreparedModel.hal
index 7aea416..00adc1f 100644
--- a/neuralnetworks/1.3/IPreparedModel.hal
+++ b/neuralnetworks/1.3/IPreparedModel.hal
@@ -17,12 +17,12 @@
 package android.hardware.neuralnetworks@1.3;
 
 import @1.0::ErrorStatus;
-import @1.0::Request;
 import @1.2::IExecutionCallback;
 import @1.2::IPreparedModel;
 import @1.2::MeasureTiming;
 import @1.2::OutputShape;
 import @1.2::Timing;
+import Request;
 
 /**
  * IPreparedModel describes a model that has been prepared for execution and
@@ -33,7 +33,8 @@
      * Launches an asynchronous execution on a prepared model.
      *
      * The execution is performed asynchronously with respect to the caller.
-     * execute_1_3 must verify the inputs to the function are correct. If there is
+     * execute_1_3 must verify the inputs to the function are correct, and the usages
+     * of memory pools allocated by IDevice::allocate are valid. If there is
      * an error, execute_1_3 must immediately invoke the callback with the
      * appropriate ErrorStatus value, then return with the same ErrorStatus. If
      * the inputs to the function are valid and there is no error, execute_1_3 must
@@ -95,7 +96,8 @@
      *
      * The execution is performed synchronously with respect to the caller.
      * executeSynchronously_1_3 must verify the inputs to the function are
-     * correct. If there is an error, executeSynchronously_1_3 must immediately
+     * correct, and the usages of memory pools allocated by IDevice::allocate
+     * are valid. If there is an error, executeSynchronously_1_3 must immediately
      * return with the appropriate ErrorStatus value. If the inputs to the
      * function are valid and there is no error, executeSynchronously_1_3 must
      * perform the execution, and must not return until the execution is
diff --git a/neuralnetworks/1.3/types.hal b/neuralnetworks/1.3/types.hal
index 62c5833..a6d274a 100644
--- a/neuralnetworks/1.3/types.hal
+++ b/neuralnetworks/1.3/types.hal
@@ -17,8 +17,10 @@
 package android.hardware.neuralnetworks@1.3;
 
 import @1.0::DataLocation;
-import @1.0::OperandLifeTime;
 import @1.0::PerformanceInfo;
+import @1.0::RequestArgument;
+import @1.2::Model.ExtensionNameAndPrefix;
+import @1.2::Model.ExtensionTypeEncoding;
 import @1.2::OperandType;
 import @1.2::OperationType;
 import @1.2::SymmPerChannelQuantParams;
@@ -39,6 +41,13 @@
      */
     TENSOR_QUANT8_ASYMM_SIGNED = 14,
 
+    /**
+     * A reference to a subgraph.
+     *
+     * Must have the lifetime {@link OperandLifeTime::SUBGRAPH}.
+     */
+    SUBGRAPH = 15,
+
     /*
      * DEPRECATED. Since HAL version 1.2, extensions are the preferred
      * alternative to OEM operation and data types.
@@ -67,7 +76,7 @@
 enum OperandTypeRange : uint32_t {
     BASE_MIN        = 0,
     FUNDAMENTAL_MIN = 0,
-    FUNDAMENTAL_MAX = 14,
+    FUNDAMENTAL_MAX = 15,
     OEM_MIN         = 10000,
     OEM_MAX         = 10001,
     BASE_MAX        = 0xFFFF,
@@ -4876,6 +4885,92 @@
     QUANTIZED_LSTM = 95,
 
     /**
+     * Executes one of the two referenced subgraphs as determined by a boolean
+     * value.
+     *
+     * The inputs and outputs of the two referenced subgraphs must agree with the
+     * signature of this operation. That is, if the operation has (3 + n) inputs
+     * and m outputs, both subgraphs must have n inputs and m outputs with the same
+     * types as the corresponding operation inputs and outputs.
+     *
+     * Inputs:
+     * * 0: A value of type {@link OperandType::TENSOR_BOOL8} and shape [1]
+     *      that determines which of the two referenced subgraphs to execute.
+     * * 1: A {@link OperandType::SUBGRAPH} reference to the subgraph to be
+     *      executed if the condition is true.
+     * * 2: A {@link OperandType::SUBGRAPH} reference to the subgraph to be
+     *      executed if the condition is false.
+     * * 3 ~ (n + 2): Inputs to be passed to the subgraph selected for execution.
+     *
+     * Outputs:
+     * * 0 ~ (m - 1): Outputs produced by the selected subgraph.
+     */
+    IF = 96,
+
+    /**
+     * Executes the body subgraph until the condition subgraph outputs false.
+     *
+     * The inputs to this operation are the condition subgraph, the body subgraph,
+     * and operand values for the first iteration of the loop. The values are
+     * implicitly split into three groups of input-output, state-only, and
+     * input-only values, as described below.
+     *
+     * The outputs of this operation are the final values of input-output
+     * operands.
+     *
+     * Both the condition and body subgraph receive (m + k + n) inputs.
+     * * The first m (m >= 1) inputs are input-output operands. For the first
+     *   iteration, these are initialized from the corresponding inputs of the
+     *   WHILE operation. In subsequent iterations, their values come from the
+     *   corresponding outputs of the body subgraph produced during the previous
+     *   iteration.
+     * * The next k (k >= 0) inputs are state-only operands. They are similar to
+     *   the input-output operands, except that their values are no longer
+     *   available after the loop terminates.
+     * * The last n (n >= 0) inputs are input-only operands. Their values come
+     *   from the corresponding inputs of the WHILE operation.
+     *
+     * The body subgraph produces (m + k) outputs.
+     * * The first m outputs are input-output operands. They become the outputs
+     *   of the WHILE operation when a termination condition is reached.
+     * * The last k outputs are state-only operands. Their values are no longer
+     *   available after the loop terminates.
+     *
+     * The numbers m, k, and n are inferred by the driver as follows:
+     *     m = (WHILE operation output count)
+     *     k = (body subgraph output count) - m
+     *     n = (body subgraph input count) - m - k
+     *
+     * The pseudo-code below illustrates the flow of a WHILE operation with
+     * inputs condition, body, initial_input_output, initial_state, input_only
+     * (m = 1, k = 1, n = 1):
+     *
+     *     input_output = initial_input_output
+     *     state = initial_state
+     *     while condition(input_output, state, input_only):
+     *         input_output, state = body(input_output, state, input_only)
+     *     return input_output
+     *
+     * Inputs:
+     * * 0: A {@link OperandType::SUBGRAPH} reference to the condition
+     *      subgraph. The subgraph must have (m + k + n) inputs with
+     *      the same types as the corresponding inputs of the WHILE operation
+     *      and exactly one output of {@link OperandType::TENSOR_BOOL8}
+     *      and shape [1].
+     * * 1: A {@link OperandType::SUBGRAPH} reference to the body subgraph.
+     *      The subgraph must have (m + k + n) inputs and (m + k) outputs with
+     *      the same types as the corresponding inputs and outputs of the WHILE
+     *      operation.
+     * * (m inputs): Initial values for input-output operands.
+     * * (k inputs): Initial values for state-only operands.
+     * * (n inputs): Values for input-only operands.
+     *
+     * Outputs:
+     * * 0 ~ (m - 1): Outputs produced by the loop.
+     */
+    WHILE = 97,
+
+    /**
      * DEPRECATED. Since NNAPI 1.2, extensions are the preferred alternative to
      * OEM operation and data types.
      *
@@ -4897,13 +4992,12 @@
 enum OperationTypeRange : uint32_t {
     BASE_MIN        = 0,
     FUNDAMENTAL_MIN = 0,
-    FUNDAMENTAL_MAX = 95,
+    FUNDAMENTAL_MAX = 97,
     OEM_MIN         = 10000,
     OEM_MAX         = 10000,
     BASE_MAX        = 0xFFFF,
 };
 
-
 /**
  * The capabilities of a driver.
  *
@@ -4965,6 +5059,59 @@
 };
 
 /**
+ * How an operand is used.
+ */
+enum OperandLifeTime : int32_t {
+    /**
+     * The operand is internal to the model. It's created by an operation and
+     * consumed by other operations. It must be an output operand of
+     * exactly one operation.
+     */
+    TEMPORARY_VARIABLE,
+
+    /**
+     * The operand is an input of a subgraph. It must not be an output
+     * operand of any operation.
+     *
+     * An operand can't be both input and output of a subgraph.
+     */
+    SUBGRAPH_INPUT,
+
+    /**
+     * The operand is an output of a subgraph. It must be an output
+     * operand of exactly one operation.
+     *
+     * An operand can't be both input and output of a subgraph.
+     */
+    SUBGRAPH_OUTPUT,
+
+    /**
+     * The operand is a constant found in Model.operandValues. It must
+     * not be an output operand of any operation.
+     */
+    CONSTANT_COPY,
+
+    /**
+     * The operand is a constant that was specified via a Memory
+     * object. It must not be an output operand of any operation.
+     */
+    CONSTANT_REFERENCE,
+
+    /**
+     * The operand does not have a value. This is valid only for optional
+     * arguments of operations.
+     */
+    NO_VALUE,
+
+    /**
+     * The operand is a reference to a subgraph. It must be an input to one
+     * or more {@link OperationType::IF} or {@link OperationType::WHILE}
+     * operations.
+     */
+    SUBGRAPH,
+};
+
+/**
  * Describes one operand of the model's graph.
  */
 struct Operand {
@@ -5000,7 +5147,7 @@
      *     . The operand has lifetime CONSTANT_COPY or
      *       CONSTANT_REFERENCE.
      *
-     *     . The operand has lifetime MODEL_INPUT. Fully
+     *     . The operand has lifetime SUBGRAPH_INPUT. Fully
      *       specified dimensions must either be present in the
      *       Operand or they must be provided in the corresponding
      *       RequestArgument.
@@ -5048,8 +5195,8 @@
 
     /**
      * Where to find the data for this operand.
-     * If the lifetime is TEMPORARY_VARIABLE, MODEL_INPUT, MODEL_OUTPUT, or
-     * NO_VALUE:
+     * If the lifetime is TEMPORARY_VARIABLE, SUBGRAPH_INPUT, SUBGRAPH_OUTPUT,
+     * or NO_VALUE:
      * - All the fields must be 0.
      * If the lifetime is CONSTANT_COPY:
      * - location.poolIndex is 0.
@@ -5059,6 +5206,11 @@
      * - location.poolIndex is set.
      * - location.offset is the offset in bytes into the specified pool.
      * - location.length is set.
+     * If the lifetime is SUBGRAPH:
+     * - location.poolIndex is 0.
+     * - location.offset is the index of the referenced subgraph in
+     *   {@link Model::referenced}.
+     * - location.length is 0.
      */
     DataLocation location;
 
@@ -5097,32 +5249,19 @@
  */
 struct Model {
     /**
-     * All operands included in the model.
+     * The top-level subgraph.
      */
-    vec<Operand> operands;
+    Subgraph main;
 
     /**
-     * All operations included in the model.
+     * Referenced subgraphs.
      *
-     * The operations are sorted into execution order. Every operand
-     * with lifetime MODEL_OUTPUT or TEMPORARY_VARIABLE must be
-     * written before it is read.
-     */
-    vec<Operation> operations;
-
-    /**
-     * Input indexes of the model. There must be at least one.
+     * Each subgraph is referenced by the main subgraph or at least one other
+     * referenced subgraph.
      *
-     * Each value corresponds to the index of the operand in "operands".
+     * There must be no reference cycles.
      */
-    vec<uint32_t> inputIndexes;
-
-    /**
-     * Output indexes of the model. There must be at least one.
-     *
-     * Each value corresponds to the index of the operand in "operands".
-     */
-    vec<uint32_t> outputIndexes;
+    vec<Subgraph> referenced;
 
     /**
      * A byte buffer containing operand data that were copied into the model.
@@ -5156,9 +5295,9 @@
      * {@link OperandTypeRange::BASE_MAX} or
      * {@link OperationTypeRange::BASE_MAX} respectively should be interpreted
      * as an extension operand. The low
-     * {@link Model::ExtensionTypeEncoding::LOW_BITS_TYPE} bits of the value
-     * correspond to the type ID within the extension and the high
-     * {@link Model::ExtensionTypeEncoding::HIGH_BITS_PREFIX} bits encode
+     * {@link @1.2::Model::ExtensionTypeEncoding::LOW_BITS_TYPE} bits of the
+     * value correspond to the type ID within the extension and the high
+     * {@link @1.2::Model::ExtensionTypeEncoding::HIGH_BITS_PREFIX} bits encode
      * the "prefix", which maps uniquely to the extension name.
      *
      * For example, if a model contains an operation whose value is
@@ -5171,37 +5310,127 @@
      * prefix corresponding to each extension name and at most one extension
      * name corresponding to each prefix.
      */
-    vec<ExtensionNameAndPrefix> extensionNameToPrefix;
+    vec<@1.2::Model.ExtensionNameAndPrefix> extensionNameToPrefix;
+};
+
+/**
+ * An excerpt of the execution graph.
+ */
+struct Subgraph {
+    /**
+     * All operands included in the subgraph.
+     */
+    vec<Operand> operands;
 
     /**
-     * A correspondence between an extension name and a prefix of operand and
-     * operation type values.
+     * All operations included in the subgraph.
+     *
+     * The operations are sorted into execution order. Every operand
+     * with lifetime SUBGRAPH_OUTPUT or TEMPORARY_VARIABLE must be
+     * written before it is read.
      */
-    struct ExtensionNameAndPrefix {
+    vec<Operation> operations;
+
+    /**
+     * Input indexes of the subgraph. There must be at least one.
+     *
+     * Each value corresponds to the index of the operand in "operands".
+     */
+    vec<uint32_t> inputIndexes;
+
+    /**
+     * Output indexes of the subgraph. There must be at least one.
+     *
+     * Each value corresponds to the index of the operand in "operands".
+     */
+    vec<uint32_t> outputIndexes;
+};
+
+/**
+ * A buffer descriptor. Describes the properties of a buffer.
+ */
+struct BufferDesc {
+    /**
+     * Dimensions of the buffer. May have unknown dimensions or rank. A buffer with some number
+     * of unspecified dimensions is represented by setting each unspecified dimension to 0. A
+     * buffer with unspecified rank is represented by providing an empty dimensions vector.
+     */
+    vec<uint32_t> dimensions;
+};
+
+/**
+ * Describes a role of an input or output to a prepared model.
+ */
+struct BufferRole {
+    /**
+     * The index of the IPreparedModel within the "preparedModel" argument passed in
+     * IDevice::allocate.
+     */
+    uint32_t modelIndex;
+
+    /**
+     * The index of the input or output operand.
+     */
+    uint32_t ioIndex;
+
+    /**
+     * A floating-point value within the range (0.0, 1.0]. Describes how likely the
+     * buffer is to be used in the specified role. This is provided as a hint to
+     * optimize the case when multiple roles prefer different buffer locations or data
+     * layouts.
+     */
+    float frequency;
+};
+
+/**
+ * Inputs to be sent to and outputs to be retrieved from a prepared model.
+ *
+ * A Request serves two primary tasks:
+ * 1) Provides the input and output data to be used when executing the model.
+ * 2) Specifies any updates to the input operand metadata that were left
+ *    unspecified at model preparation time.
+ *
+ * An output must not overlap with any other output, with an input, or
+ * with an operand of lifetime CONSTANT_REFERENCE.
+ */
+struct Request {
+    /**
+     * Input data and information to be used in the execution of a prepared
+     * model.
+     *
+     * The index of the input corresponds to the index in Model.inputIndexes.
+     *   E.g., input[i] corresponds to Model.inputIndexes[i].
+     */
+    vec<RequestArgument> inputs;
+
+    /**
+     * Output data and information to be used in the execution of a prepared
+     * model.
+     *
+     * The index of the output corresponds to the index in Model.outputIndexes.
+     *   E.g., output[i] corresponds to Model.outputIndexes[i].
+     */
+    vec<RequestArgument> outputs;
+
+    /**
+     * A memory pool.
+     */
+    safe_union MemoryPool {
         /**
-         * The extension name.
-         *
-         * See {@link Extension::name} for the format specification.
+         * Specifies a client-managed shared memory pool.
          */
-        string name;
+        memory hidlMemory;
 
         /**
-         * The unique extension identifier within the model.
-         *
-         * See {@link Model::extensionNameToPrefix}.
+         * Specifies a driver-managed buffer. It is the token returned from IDevice::allocate,
+         * and is specific to the IDevice object.
          */
-        uint16_t prefix;
+        int32_t token;
     };
 
     /**
-     * Numeric values of extension operand and operation types have the
-     * following structure:
-     * - 16 high bits represent the "prefix", which corresponds uniquely to the
-     *   extension name.
-     * - 16 low bits represent the type ID within the extension.
+     * A collection of memory pools containing operand data for both the
+     * inputs and the outputs to a model.
      */
-    enum ExtensionTypeEncoding : uint8_t {
-        HIGH_BITS_PREFIX = 16,
-        LOW_BITS_TYPE = 16,
-    };
+    vec<MemoryPool> pools;
 };
diff --git a/neuralnetworks/1.3/types.t b/neuralnetworks/1.3/types.t
index 0d20d06..f3319e5 100644
--- a/neuralnetworks/1.3/types.t
+++ b/neuralnetworks/1.3/types.t
@@ -19,8 +19,10 @@
 package android.hardware.neuralnetworks@1.3;
 
 import @1.0::DataLocation;
-import @1.0::OperandLifeTime;
 import @1.0::PerformanceInfo;
+import @1.0::RequestArgument;
+import @1.2::Model.ExtensionNameAndPrefix;
+import @1.2::Model.ExtensionTypeEncoding;
 import @1.2::OperandType;
 import @1.2::OperationType;
 import @1.2::SymmPerChannelQuantParams;
@@ -87,7 +89,6 @@
     BASE_MAX        = 0xFFFF,
 };
 
-
 /**
  * The capabilities of a driver.
  *
@@ -149,6 +150,59 @@
 };
 
 /**
+ * How an operand is used.
+ */
+enum OperandLifeTime : int32_t {
+    /**
+     * The operand is internal to the model. It's created by an operation and
+     * consumed by other operations. It must be an output operand of
+     * exactly one operation.
+     */
+    TEMPORARY_VARIABLE,
+
+    /**
+     * The operand is an input of a subgraph. It must not be an output
+     * operand of any operation.
+     *
+     * An operand can't be both input and output of a subgraph.
+     */
+    SUBGRAPH_INPUT,
+
+    /**
+     * The operand is an output of a subgraph. It must be an output
+     * operand of exactly one operation.
+     *
+     * An operand can't be both input and output of a subgraph.
+     */
+    SUBGRAPH_OUTPUT,
+
+    /**
+     * The operand is a constant found in Model.operandValues. It must
+     * not be an output operand of any operation.
+     */
+    CONSTANT_COPY,
+
+    /**
+     * The operand is a constant that was specified via a Memory
+     * object. It must not be an output operand of any operation.
+     */
+    CONSTANT_REFERENCE,
+
+    /**
+     * The operand does not have a value. This is valid only for optional
+     * arguments of operations.
+     */
+    NO_VALUE,
+
+    /**
+     * The operand is a reference to a subgraph. It must be an input to one
+     * or more {@link OperationType::IF} or {@link OperationType::WHILE}
+     * operations.
+     */
+    SUBGRAPH,
+};
+
+/**
  * Describes one operand of the model's graph.
  */
 struct Operand {
@@ -184,7 +238,7 @@
      *     . The operand has lifetime CONSTANT_COPY or
      *       CONSTANT_REFERENCE.
      *
-     *     . The operand has lifetime MODEL_INPUT. Fully
+     *     . The operand has lifetime SUBGRAPH_INPUT. Fully
      *       specified dimensions must either be present in the
      *       Operand or they must be provided in the corresponding
      *       RequestArgument.
@@ -232,8 +286,8 @@
 
     /**
      * Where to find the data for this operand.
-     * If the lifetime is TEMPORARY_VARIABLE, MODEL_INPUT, MODEL_OUTPUT, or
-     * NO_VALUE:
+     * If the lifetime is TEMPORARY_VARIABLE, SUBGRAPH_INPUT, SUBGRAPH_OUTPUT,
+     * or NO_VALUE:
      * - All the fields must be 0.
      * If the lifetime is CONSTANT_COPY:
      * - location.poolIndex is 0.
@@ -243,6 +297,11 @@
      * - location.poolIndex is set.
      * - location.offset is the offset in bytes into the specified pool.
      * - location.length is set.
+     * If the lifetime is SUBGRAPH:
+     * - location.poolIndex is 0.
+     * - location.offset is the index of the referenced subgraph in
+     *   {@link Model::referenced}.
+     * - location.length is 0.
      */
     DataLocation location;
 
@@ -281,32 +340,19 @@
  */
 struct Model {
     /**
-     * All operands included in the model.
+     * The top-level subgraph.
      */
-    vec<Operand> operands;
+    Subgraph main;
 
     /**
-     * All operations included in the model.
+     * Referenced subgraphs.
      *
-     * The operations are sorted into execution order. Every operand
-     * with lifetime MODEL_OUTPUT or TEMPORARY_VARIABLE must be
-     * written before it is read.
-     */
-    vec<Operation> operations;
-
-    /**
-     * Input indexes of the model. There must be at least one.
+     * Each subgraph is referenced by the main subgraph or at least one other
+     * referenced subgraph.
      *
-     * Each value corresponds to the index of the operand in "operands".
+     * There must be no reference cycles.
      */
-    vec<uint32_t> inputIndexes;
-
-    /**
-     * Output indexes of the model. There must be at least one.
-     *
-     * Each value corresponds to the index of the operand in "operands".
-     */
-    vec<uint32_t> outputIndexes;
+    vec<Subgraph> referenced;
 
     /**
      * A byte buffer containing operand data that were copied into the model.
@@ -340,9 +386,9 @@
      * {@link OperandTypeRange::BASE_MAX} or
      * {@link OperationTypeRange::BASE_MAX} respectively should be interpreted
      * as an extension operand. The low
-     * {@link Model::ExtensionTypeEncoding::LOW_BITS_TYPE} bits of the value
-     * correspond to the type ID within the extension and the high
-     * {@link Model::ExtensionTypeEncoding::HIGH_BITS_PREFIX} bits encode
+     * {@link @1.2::Model::ExtensionTypeEncoding::LOW_BITS_TYPE} bits of the
+     * value correspond to the type ID within the extension and the high
+     * {@link @1.2::Model::ExtensionTypeEncoding::HIGH_BITS_PREFIX} bits encode
      * the "prefix", which maps uniquely to the extension name.
      *
      * For example, if a model contains an operation whose value is
@@ -355,37 +401,127 @@
      * prefix corresponding to each extension name and at most one extension
      * name corresponding to each prefix.
      */
-    vec<ExtensionNameAndPrefix> extensionNameToPrefix;
+    vec<@1.2::Model.ExtensionNameAndPrefix> extensionNameToPrefix;
+};
+
+/**
+ * An excerpt of the execution graph.
+ */
+struct Subgraph {
+    /**
+     * All operands included in the subgraph.
+     */
+    vec<Operand> operands;
 
     /**
-     * A correspondence between an extension name and a prefix of operand and
-     * operation type values.
+     * All operations included in the subgraph.
+     *
+     * The operations are sorted into execution order. Every operand
+     * with lifetime SUBGRAPH_OUTPUT or TEMPORARY_VARIABLE must be
+     * written before it is read.
      */
-    struct ExtensionNameAndPrefix {
+    vec<Operation> operations;
+
+    /**
+     * Input indexes of the subgraph. There must be at least one.
+     *
+     * Each value corresponds to the index of the operand in "operands".
+     */
+    vec<uint32_t> inputIndexes;
+
+    /**
+     * Output indexes of the subgraph. There must be at least one.
+     *
+     * Each value corresponds to the index of the operand in "operands".
+     */
+    vec<uint32_t> outputIndexes;
+};
+
+/**
+ * A buffer descriptor. Describes the properties of a buffer.
+ */
+struct BufferDesc {
+    /**
+     * Dimensions of the buffer. May have unknown dimensions or rank. A buffer with some number
+     * of unspecified dimensions is represented by setting each unspecified dimension to 0. A
+     * buffer with unspecified rank is represented by providing an empty dimensions vector.
+     */
+    vec<uint32_t> dimensions;
+};
+
+/**
+ * Describes a role of an input or output to a prepared model.
+ */
+struct BufferRole {
+    /**
+     * The index of the IPreparedModel within the "preparedModel" argument passed in
+     * IDevice::allocate.
+     */
+    uint32_t modelIndex;
+
+    /**
+     * The index of the input or output operand.
+     */
+    uint32_t ioIndex;
+
+    /**
+     * A floating-point value within the range (0.0, 1.0]. Describes how likely the
+     * buffer is to be used in the specified role. This is provided as a hint to
+     * optimize the case when multiple roles prefer different buffer locations or data
+     * layouts.
+     */
+    float frequency;
+};
+
+/**
+ * Inputs to be sent to and outputs to be retrieved from a prepared model.
+ *
+ * A Request serves two primary tasks:
+ * 1) Provides the input and output data to be used when executing the model.
+ * 2) Specifies any updates to the input operand metadata that were left
+ *    unspecified at model preparation time.
+ *
+ * An output must not overlap with any other output, with an input, or
+ * with an operand of lifetime CONSTANT_REFERENCE.
+ */
+struct Request {
+    /**
+     * Input data and information to be used in the execution of a prepared
+     * model.
+     *
+     * The index of the input corresponds to the index in Model.inputIndexes.
+     *   E.g., input[i] corresponds to Model.inputIndexes[i].
+     */
+    vec<RequestArgument> inputs;
+
+    /**
+     * Output data and information to be used in the execution of a prepared
+     * model.
+     *
+     * The index of the output corresponds to the index in Model.outputIndexes.
+     *   E.g., output[i] corresponds to Model.outputIndexes[i].
+     */
+    vec<RequestArgument> outputs;
+
+    /**
+     * A memory pool.
+     */
+    safe_union MemoryPool {
         /**
-         * The extension name.
-         *
-         * See {@link Extension::name} for the format specification.
+         * Specifies a client-managed shared memory pool.
          */
-        string name;
+        memory hidlMemory;
 
         /**
-         * The unique extension identifier within the model.
-         *
-         * See {@link Model::extensionNameToPrefix}.
+         * Specifies a driver-managed buffer. It is the token returned from IDevice::allocate,
+         * and is specific to the IDevice object.
          */
-        uint16_t prefix;
+        int32_t token;
     };
 
     /**
-     * Numeric values of extension operand and operation types have the
-     * following structure:
-     * - 16 high bits represent the "prefix", which corresponds uniquely to the
-     *   extension name.
-     * - 16 low bits represent the type ID within the extension.
+     * A collection of memory pools containing operand data for both the
+     * inputs and the outputs to a model.
      */
-    enum ExtensionTypeEncoding : uint8_t {
-        HIGH_BITS_PREFIX = 16,
-        LOW_BITS_TYPE = 16,
-    };
+    vec<MemoryPool> pools;
 };
diff --git a/neuralnetworks/1.3/vts/functional/CompilationCachingTests.cpp b/neuralnetworks/1.3/vts/functional/CompilationCachingTests.cpp
index 60992d5..5cb466f 100644
--- a/neuralnetworks/1.3/vts/functional/CompilationCachingTests.cpp
+++ b/neuralnetworks/1.3/vts/functional/CompilationCachingTests.cpp
@@ -308,7 +308,7 @@
                 model,
                 [&fullySupportsModel, &model](ErrorStatus status, const hidl_vec<bool>& supported) {
                     ASSERT_EQ(ErrorStatus::NONE, status);
-                    ASSERT_EQ(supported.size(), model.operations.size());
+                    ASSERT_EQ(supported.size(), model.main.operations.size());
                     fullySupportsModel = std::all_of(supported.begin(), supported.end(),
                                                      [](bool valid) { return valid; });
                 });
@@ -456,7 +456,7 @@
     }
 
     // Execute and verify results.
-    EvaluatePreparedModel(preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
+    EvaluatePreparedModel(kDevice, preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
 }
 
 TEST_P(CompilationCachingTest, CacheSavingAndRetrievalNonZeroOffset) {
@@ -518,7 +518,7 @@
     }
 
     // Execute and verify results.
-    EvaluatePreparedModel(preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
+    EvaluatePreparedModel(kDevice, preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
 }
 
 TEST_P(CompilationCachingTest, SaveToCacheInvalidNumCache) {
@@ -539,7 +539,7 @@
         saveModelToCache(model, modelCache, dataCache, &preparedModel);
         ASSERT_NE(preparedModel, nullptr);
         // Execute and verify results.
-        EvaluatePreparedModel(preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
+        EvaluatePreparedModel(kDevice, preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
         // Check if prepareModelFromCache fails.
         preparedModel = nullptr;
         ErrorStatus status;
@@ -563,7 +563,7 @@
         saveModelToCache(model, modelCache, dataCache, &preparedModel);
         ASSERT_NE(preparedModel, nullptr);
         // Execute and verify results.
-        EvaluatePreparedModel(preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
+        EvaluatePreparedModel(kDevice, preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
         // Check if prepareModelFromCache fails.
         preparedModel = nullptr;
         ErrorStatus status;
@@ -586,7 +586,7 @@
         saveModelToCache(model, modelCache, dataCache, &preparedModel);
         ASSERT_NE(preparedModel, nullptr);
         // Execute and verify results.
-        EvaluatePreparedModel(preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
+        EvaluatePreparedModel(kDevice, preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
         // Check if prepareModelFromCache fails.
         preparedModel = nullptr;
         ErrorStatus status;
@@ -610,7 +610,7 @@
         saveModelToCache(model, modelCache, dataCache, &preparedModel);
         ASSERT_NE(preparedModel, nullptr);
         // Execute and verify results.
-        EvaluatePreparedModel(preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
+        EvaluatePreparedModel(kDevice, preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
         // Check if prepareModelFromCache fails.
         preparedModel = nullptr;
         ErrorStatus status;
@@ -721,7 +721,7 @@
         saveModelToCache(model, modelCache, dataCache, &preparedModel);
         ASSERT_NE(preparedModel, nullptr);
         // Execute and verify results.
-        EvaluatePreparedModel(preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
+        EvaluatePreparedModel(kDevice, preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
         // Check if prepareModelFromCache fails.
         preparedModel = nullptr;
         ErrorStatus status;
@@ -745,7 +745,7 @@
         saveModelToCache(model, modelCache, dataCache, &preparedModel);
         ASSERT_NE(preparedModel, nullptr);
         // Execute and verify results.
-        EvaluatePreparedModel(preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
+        EvaluatePreparedModel(kDevice, preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
         // Check if prepareModelFromCache fails.
         preparedModel = nullptr;
         ErrorStatus status;
@@ -768,7 +768,7 @@
         saveModelToCache(model, modelCache, dataCache, &preparedModel);
         ASSERT_NE(preparedModel, nullptr);
         // Execute and verify results.
-        EvaluatePreparedModel(preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
+        EvaluatePreparedModel(kDevice, preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
         // Check if prepareModelFromCache fails.
         preparedModel = nullptr;
         ErrorStatus status;
@@ -792,7 +792,7 @@
         saveModelToCache(model, modelCache, dataCache, &preparedModel);
         ASSERT_NE(preparedModel, nullptr);
         // Execute and verify results.
-        EvaluatePreparedModel(preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
+        EvaluatePreparedModel(kDevice, preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
         // Check if prepareModelFromCache fails.
         preparedModel = nullptr;
         ErrorStatus status;
@@ -904,7 +904,7 @@
         saveModelToCache(model, modelCache, dataCache, &preparedModel);
         ASSERT_NE(preparedModel, nullptr);
         // Execute and verify results.
-        EvaluatePreparedModel(preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
+        EvaluatePreparedModel(kDevice, preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
         // Check if prepareModelFromCache fails.
         preparedModel = nullptr;
         ErrorStatus status;
@@ -926,7 +926,7 @@
         saveModelToCache(model, modelCache, dataCache, &preparedModel);
         ASSERT_NE(preparedModel, nullptr);
         // Execute and verify results.
-        EvaluatePreparedModel(preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
+        EvaluatePreparedModel(kDevice, preparedModel, testModel, /*testKind=*/TestKind::GENERAL);
         // Check if prepareModelFromCache fails.
         preparedModel = nullptr;
         ErrorStatus status;
@@ -1070,7 +1070,8 @@
                 ASSERT_EQ(preparedModel, nullptr);
             } else {
                 ASSERT_NE(preparedModel, nullptr);
-                EvaluatePreparedModel(preparedModel, testModelAdd, /*testKind=*/TestKind::GENERAL);
+                EvaluatePreparedModel(kDevice, preparedModel, testModelAdd,
+                                      /*testKind=*/TestKind::GENERAL);
             }
         }
     }
@@ -1131,7 +1132,8 @@
                 ASSERT_EQ(preparedModel, nullptr);
             } else {
                 ASSERT_NE(preparedModel, nullptr);
-                EvaluatePreparedModel(preparedModel, testModelAdd, /*testKind=*/TestKind::GENERAL);
+                EvaluatePreparedModel(kDevice, preparedModel, testModelAdd,
+                                      /*testKind=*/TestKind::GENERAL);
             }
         }
     }
diff --git a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp
index eced063..805d5b5 100644
--- a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp
@@ -59,8 +59,7 @@
 using implementation::PreparedModelCallback;
 using V1_0::DataLocation;
 using V1_0::ErrorStatus;
-using V1_0::OperandLifeTime;
-using V1_0::Request;
+using V1_0::RequestArgument;
 using V1_1::ExecutionPreference;
 using V1_2::Constant;
 using V1_2::MeasureTiming;
@@ -76,27 +75,118 @@
 
 enum class OutputType { FULLY_SPECIFIED, UNSPECIFIED, INSUFFICIENT };
 
+enum class MemoryType { SHARED, DEVICE };
+
+enum class IOType { INPUT, OUTPUT };
+
 struct TestConfig {
     Executor executor;
     MeasureTiming measureTiming;
     OutputType outputType;
+    MemoryType memoryType;
     // `reportSkipping` indicates if a test should print an info message in case
     // it is skipped. The field is set to true by default and is set to false in
     // quantization coupling tests to suppress skipping a test
     bool reportSkipping;
-    TestConfig(Executor executor, MeasureTiming measureTiming, OutputType outputType)
+    TestConfig(Executor executor, MeasureTiming measureTiming, OutputType outputType,
+               MemoryType memoryType)
         : executor(executor),
           measureTiming(measureTiming),
           outputType(outputType),
+          memoryType(memoryType),
           reportSkipping(true) {}
     TestConfig(Executor executor, MeasureTiming measureTiming, OutputType outputType,
-               bool reportSkipping)
+               MemoryType memoryType, bool reportSkipping)
         : executor(executor),
           measureTiming(measureTiming),
           outputType(outputType),
+          memoryType(memoryType),
           reportSkipping(reportSkipping) {}
 };
 
+class DeviceMemoryAllocator {
+  public:
+    DeviceMemoryAllocator(const sp<IDevice>& device, const sp<IPreparedModel>& preparedModel,
+                          const TestModel& testModel)
+        : kDevice(device), kPreparedModel(preparedModel), kTestModel(testModel) {}
+
+    // Allocate device memory for a target input/output operand.
+    // Return {IBuffer object, token} if successful.
+    // Return {nullptr, 0} if device memory is not supported.
+    template <IOType ioType>
+    std::pair<sp<IBuffer>, int32_t> allocate(uint32_t index) {
+        std::pair<sp<IBuffer>, int32_t> buffer;
+        allocateInternal<ioType>(index, &buffer);
+        return buffer;
+    }
+
+  private:
+    template <IOType ioType>
+    void allocateInternal(uint32_t index, std::pair<sp<IBuffer>, int32_t>* result) {
+        ASSERT_NE(result, nullptr);
+
+        // Prepare arguments.
+        BufferRole role = {.modelIndex = 0, .ioIndex = index, .frequency = 1.0f};
+        hidl_vec<BufferRole> inputRoles, outputRoles;
+        if constexpr (ioType == IOType::INPUT) {
+            inputRoles = {role};
+        } else {
+            outputRoles = {role};
+        }
+
+        // Allocate device memory.
+        ErrorStatus status;
+        sp<IBuffer> buffer;
+        int32_t token;
+        const auto ret = kDevice->allocate(
+                {}, {kPreparedModel}, inputRoles, outputRoles,
+                [&status, &buffer, &token](ErrorStatus error, const sp<IBuffer>& buf, int32_t tok) {
+                    status = error;
+                    buffer = buf;
+                    token = tok;
+                });
+
+        // Check allocation results.
+        ASSERT_TRUE(ret.isOk());
+        if (status == ErrorStatus::NONE) {
+            ASSERT_NE(buffer, nullptr);
+            ASSERT_GT(token, 0);
+        } else {
+            ASSERT_EQ(status, ErrorStatus::GENERAL_FAILURE);
+            ASSERT_EQ(buffer, nullptr);
+            ASSERT_EQ(token, 0);
+        }
+
+        // Initialize input data from TestBuffer.
+        if constexpr (ioType == IOType::INPUT) {
+            if (buffer != nullptr) {
+                // TestBuffer -> Shared memory.
+                const auto& testBuffer = kTestModel.operands[kTestModel.inputIndexes[index]].data;
+                ASSERT_GT(testBuffer.size(), 0);
+                hidl_memory tmp = nn::allocateSharedMemory(testBuffer.size());
+                sp<IMemory> inputMemory = mapMemory(tmp);
+                ASSERT_NE(inputMemory.get(), nullptr);
+                uint8_t* inputPtr =
+                        static_cast<uint8_t*>(static_cast<void*>(inputMemory->getPointer()));
+                ASSERT_NE(inputPtr, nullptr);
+                const uint8_t* begin = testBuffer.get<uint8_t>();
+                const uint8_t* end = begin + testBuffer.size();
+                std::copy(begin, end, inputPtr);
+
+                // Shared memory -> IBuffer.
+                auto ret = buffer->copyFrom(tmp, {});
+                ASSERT_TRUE(ret.isOk());
+                ASSERT_EQ(static_cast<ErrorStatus>(ret), ErrorStatus::NONE);
+            }
+        }
+        *result = {std::move(buffer), token};
+    }
+
+    const sp<IDevice> kDevice;
+    const sp<IPreparedModel> kPreparedModel;
+    const TestModel& kTestModel;
+};
+
 }  // namespace
 
 Model createModel(const TestModel& testModel) {
@@ -178,10 +268,10 @@
         }
     }
 
-    return {.operands = std::move(operands),
-            .operations = std::move(operations),
-            .inputIndexes = testModel.inputIndexes,
-            .outputIndexes = testModel.outputIndexes,
+    return {.main = {.operands = std::move(operands),
+                     .operations = std::move(operations),
+                     .inputIndexes = testModel.inputIndexes,
+                     .outputIndexes = testModel.outputIndexes},
             .operandValues = std::move(operandValues),
             .pools = std::move(pools),
             .relaxComputationFloat32toFloat16 = testModel.isRelaxed};
@@ -199,12 +289,167 @@
 }
 
 static void makeOutputDimensionsUnspecified(Model* model) {
-    for (auto i : model->outputIndexes) {
-        auto& dims = model->operands[i].dimensions;
+    for (auto i : model->main.outputIndexes) {
+        auto& dims = model->main.operands[i].dimensions;
         std::fill(dims.begin(), dims.end(), 0);
     }
 }
 
+constexpr uint32_t kInputPoolIndex = 0;
+constexpr uint32_t kOutputPoolIndex = 1;
+constexpr uint32_t kDeviceMemoryBeginIndex = 2;
+
+static std::pair<Request, std::vector<sp<IBuffer>>> createRequest(
+        const sp<IDevice>& device, const sp<IPreparedModel>& preparedModel,
+        const TestModel& testModel, bool preferDeviceMemory) {
+    // Memory pools are organized as:
+    // - 0: Input shared memory pool
+    // - 1: Output shared memory pool
+    // - [2, 2+i): Input device memories
+    // - [2+i, 2+i+o): Output device memories
+    DeviceMemoryAllocator allocator(device, preparedModel, testModel);
+    std::vector<sp<IBuffer>> buffers;
+    std::vector<int32_t> tokens;
+
+    // Model inputs.
+    hidl_vec<RequestArgument> inputs(testModel.inputIndexes.size());
+    size_t inputSize = 0;
+    for (uint32_t i = 0; i < testModel.inputIndexes.size(); i++) {
+        const auto& op = testModel.operands[testModel.inputIndexes[i]];
+        if (op.data.size() == 0) {
+            // Omitted input.
+            inputs[i] = {.hasNoValue = true};
+            continue;
+        } else if (preferDeviceMemory) {
+            SCOPED_TRACE("Input index = " + std::to_string(i));
+            auto [buffer, token] = allocator.allocate<IOType::INPUT>(i);
+            if (buffer != nullptr) {
+                DataLocation loc = {.poolIndex = static_cast<uint32_t>(buffers.size() +
+                                                                       kDeviceMemoryBeginIndex)};
+                buffers.push_back(std::move(buffer));
+                tokens.push_back(token);
+                inputs[i] = {.hasNoValue = false, .location = loc, .dimensions = {}};
+                continue;
+            }
+        }
+
+        // Reserve shared memory for input.
+        DataLocation loc = {.poolIndex = kInputPoolIndex,
+                            .offset = static_cast<uint32_t>(inputSize),
+                            .length = static_cast<uint32_t>(op.data.size())};
+        inputSize += op.data.alignedSize();
+        inputs[i] = {.hasNoValue = false, .location = loc, .dimensions = {}};
+    }
+
+    // Model outputs.
+    hidl_vec<RequestArgument> outputs(testModel.outputIndexes.size());
+    size_t outputSize = 0;
+    for (uint32_t i = 0; i < testModel.outputIndexes.size(); i++) {
+        const auto& op = testModel.operands[testModel.outputIndexes[i]];
+        if (preferDeviceMemory) {
+            SCOPED_TRACE("Output index = " + std::to_string(i));
+            auto [buffer, token] = allocator.allocate<IOType::OUTPUT>(i);
+            if (buffer != nullptr) {
+                DataLocation loc = {.poolIndex = static_cast<uint32_t>(buffers.size() +
+                                                                       kDeviceMemoryBeginIndex)};
+                buffers.push_back(std::move(buffer));
+                tokens.push_back(token);
+                outputs[i] = {.hasNoValue = false, .location = loc, .dimensions = {}};
+                continue;
+            }
+        }
+
+        // In the case of zero-sized output, we should at least provide a one-byte buffer.
+        // This is because zero-sized tensors are only supported internally to the driver, or
+        // reported in output shapes. It is illegal for the client to pre-specify a zero-sized
+        // tensor as model output. Otherwise, we will have two semantic conflicts:
+        // - "Zero dimension" conflicts with "unspecified dimension".
+        // - "Omitted operand buffer" conflicts with "zero-sized operand buffer".
+        size_t bufferSize = std::max<size_t>(op.data.size(), 1);
+
+        // Reserve shared memory for output.
+        DataLocation loc = {.poolIndex = kOutputPoolIndex,
+                            .offset = static_cast<uint32_t>(outputSize),
+                            .length = static_cast<uint32_t>(bufferSize)};
+        outputSize += op.data.size() == 0 ? TestBuffer::kAlignment : op.data.alignedSize();
+        outputs[i] = {.hasNoValue = false, .location = loc, .dimensions = {}};
+    }
+
+    // Memory pools.
+    hidl_vec<Request::MemoryPool> pools(kDeviceMemoryBeginIndex + buffers.size());
+    pools[kInputPoolIndex].hidlMemory(nn::allocateSharedMemory(std::max<size_t>(inputSize, 1)));
+    pools[kOutputPoolIndex].hidlMemory(nn::allocateSharedMemory(std::max<size_t>(outputSize, 1)));
+    CHECK_NE(pools[kInputPoolIndex].hidlMemory().size(), 0u);
+    CHECK_NE(pools[kOutputPoolIndex].hidlMemory().size(), 0u);
+    for (uint32_t i = 0; i < buffers.size(); i++) {
+        pools[kDeviceMemoryBeginIndex + i].token(tokens[i]);
+    }
+
+    // Copy input data to the input shared memory pool.
+    sp<IMemory> inputMemory = mapMemory(pools[kInputPoolIndex].hidlMemory());
+    CHECK(inputMemory.get() != nullptr);
+    uint8_t* inputPtr = static_cast<uint8_t*>(static_cast<void*>(inputMemory->getPointer()));
+    CHECK(inputPtr != nullptr);
+    for (uint32_t i = 0; i < testModel.inputIndexes.size(); i++) {
+        if (!inputs[i].hasNoValue && inputs[i].location.poolIndex == kInputPoolIndex) {
+            const auto& op = testModel.operands[testModel.inputIndexes[i]];
+            const uint8_t* begin = op.data.get<uint8_t>();
+            const uint8_t* end = begin + op.data.size();
+            std::copy(begin, end, inputPtr + inputs[i].location.offset);
+        }
+    }
+
+    Request request = {
+            .inputs = std::move(inputs), .outputs = std::move(outputs), .pools = std::move(pools)};
+    return {std::move(request), std::move(buffers)};
+}
+
+// Get a TestBuffer with data copied from an IBuffer object.
+static void getBuffer(const sp<IBuffer>& buffer, size_t size, TestBuffer* testBuffer) {
+    // IBuffer -> Shared memory.
+    hidl_memory tmp = nn::allocateSharedMemory(size);
+    const auto ret = buffer->copyTo(tmp);
+    ASSERT_TRUE(ret.isOk());
+    ASSERT_EQ(static_cast<ErrorStatus>(ret), ErrorStatus::NONE);
+
+    // Shared memory -> TestBuffer.
+    sp<IMemory> outputMemory = mapMemory(tmp);
+    ASSERT_NE(outputMemory.get(), nullptr);
+    uint8_t* outputPtr = static_cast<uint8_t*>(static_cast<void*>(outputMemory->getPointer()));
+    ASSERT_NE(outputPtr, nullptr);
+    ASSERT_NE(testBuffer, nullptr);
+    *testBuffer = TestBuffer(size, outputPtr);
+}
+
+static std::vector<TestBuffer> getOutputBuffers(const TestModel& testModel, const Request& request,
+                                                const std::vector<sp<IBuffer>>& buffers) {
+    sp<IMemory> outputMemory = mapMemory(request.pools[kOutputPoolIndex].hidlMemory());
+    CHECK(outputMemory.get() != nullptr);
+    uint8_t* outputPtr = static_cast<uint8_t*>(static_cast<void*>(outputMemory->getPointer()));
+    CHECK(outputPtr != nullptr);
+
+    // Copy out output results.
+    std::vector<TestBuffer> outputBuffers;
+    for (uint32_t i = 0; i < request.outputs.size(); i++) {
+        const auto& outputLoc = request.outputs[i].location;
+        if (outputLoc.poolIndex == kOutputPoolIndex) {
+            outputBuffers.emplace_back(outputLoc.length, outputPtr + outputLoc.offset);
+        } else {
+            const auto& op = testModel.operands[testModel.outputIndexes[i]];
+            if (op.data.size() == 0) {
+                outputBuffers.emplace_back();
+            } else {
+                SCOPED_TRACE("Output index = " + std::to_string(i));
+                const uint32_t bufferIndex = outputLoc.poolIndex - kDeviceMemoryBeginIndex;
+                TestBuffer buffer;
+                getBuffer(buffers[bufferIndex], op.data.size(), &buffer);
+                outputBuffers.push_back(std::move(buffer));
+            }
+        }
+    }
+    return outputBuffers;
+}
+
 static Return<ErrorStatus> ExecutePreparedModel(const sp<IPreparedModel>& preparedModel,
                                                 const Request& request, MeasureTiming measure,
                                                 sp<ExecutionCallback>& callback) {
@@ -234,8 +479,9 @@
                                                          std::chrono::microseconds{0});
 }
 
-void EvaluatePreparedModel(const sp<IPreparedModel>& preparedModel, const TestModel& testModel,
-                           const TestConfig& testConfig, bool* skipped = nullptr) {
+void EvaluatePreparedModel(const sp<IDevice>& device, const sp<IPreparedModel>& preparedModel,
+                           const TestModel& testModel, const TestConfig& testConfig,
+                           bool* skipped = nullptr) {
     if (skipped != nullptr) {
         *skipped = false;
     }
@@ -245,7 +491,13 @@
         return;
     }
 
-    Request request = createRequest(testModel);
+    auto [request, buffers] =
+            createRequest(device, preparedModel, testModel,
+                          /*preferDeviceMemory=*/testConfig.memoryType == MemoryType::DEVICE);
+    // Skip if testing memory domain but no device memory has been allocated.
+    if (testConfig.memoryType == MemoryType::DEVICE && buffers.empty()) {
+        return;
+    }
     if (testConfig.outputType == OutputType::INSUFFICIENT) {
         makeOutputInsufficientSize(/*outputIndex=*/0, &request);
     }
@@ -284,23 +536,29 @@
             break;
         }
         case Executor::BURST: {
+            // TODO(butlermichael): Check if we need to test burst in V1_3 if the interface remains
+            //                      V1_2.
             SCOPED_TRACE("burst");
 
+            // check compliance
+            ASSERT_TRUE(nn::compliantWithV1_0(request));
+            V1_0::Request request10 = nn::convertToV1_0(request);
+
             // create burst
             const std::shared_ptr<::android::nn::ExecutionBurstController> controller =
                     CreateBurst(preparedModel);
             ASSERT_NE(nullptr, controller.get());
 
             // create memory keys
-            std::vector<intptr_t> keys(request.pools.size());
+            std::vector<intptr_t> keys(request10.pools.size());
             for (size_t i = 0; i < keys.size(); ++i) {
-                keys[i] = reinterpret_cast<intptr_t>(&request.pools[i]);
+                keys[i] = reinterpret_cast<intptr_t>(&request10.pools[i]);
             }
 
             // execute burst
             int n;
             std::tie(n, outputShapes, timing, std::ignore) =
-                    controller->compute(request, testConfig.measureTiming, keys);
+                    controller->compute(request10, testConfig.measureTiming, keys);
             executionStatus = nn::convertResultCodeToErrorStatus(n);
 
             break;
@@ -361,17 +619,18 @@
     }
 
     // Retrieve execution results.
-    const std::vector<TestBuffer> outputs = getOutputBuffers(request);
+    const std::vector<TestBuffer> outputs = getOutputBuffers(testModel, request, buffers);
 
     // We want "close-enough" results.
     checkResults(testModel, outputs);
 }
 
-void EvaluatePreparedModel(const sp<IPreparedModel>& preparedModel, const TestModel& testModel,
-                           TestKind testKind) {
+void EvaluatePreparedModel(const sp<IDevice>& device, const sp<IPreparedModel>& preparedModel,
+                           const TestModel& testModel, TestKind testKind) {
     std::vector<OutputType> outputTypesList;
     std::vector<MeasureTiming> measureTimingList;
     std::vector<Executor> executorList;
+    MemoryType memoryType = MemoryType::SHARED;
 
     switch (testKind) {
         case TestKind::GENERAL: {
@@ -384,6 +643,12 @@
             measureTimingList = {MeasureTiming::NO, MeasureTiming::YES};
             executorList = {Executor::ASYNC, Executor::SYNC, Executor::BURST};
         } break;
+        case TestKind::MEMORY_DOMAIN: {
+            outputTypesList = {OutputType::FULLY_SPECIFIED};
+            measureTimingList = {MeasureTiming::NO};
+            executorList = {Executor::ASYNC, Executor::SYNC};
+            memoryType = MemoryType::DEVICE;
+        } break;
         case TestKind::QUANTIZATION_COUPLING: {
             LOG(FATAL) << "Wrong TestKind for EvaluatePreparedModel";
             return;
@@ -393,14 +658,15 @@
     for (const OutputType outputType : outputTypesList) {
         for (const MeasureTiming measureTiming : measureTimingList) {
             for (const Executor executor : executorList) {
-                const TestConfig testConfig(executor, measureTiming, outputType);
-                EvaluatePreparedModel(preparedModel, testModel, testConfig);
+                const TestConfig testConfig(executor, measureTiming, outputType, memoryType);
+                EvaluatePreparedModel(device, preparedModel, testModel, testConfig);
             }
         }
     }
 }
 
-void EvaluatePreparedCoupledModels(const sp<IPreparedModel>& preparedModel,
+void EvaluatePreparedCoupledModels(const sp<IDevice>& device,
+                                   const sp<IPreparedModel>& preparedModel,
                                    const TestModel& testModel,
                                    const sp<IPreparedModel>& preparedCoupledModel,
                                    const TestModel& coupledModel) {
@@ -411,12 +677,12 @@
     for (const OutputType outputType : outputTypesList) {
         for (const MeasureTiming measureTiming : measureTimingList) {
             for (const Executor executor : executorList) {
-                const TestConfig testConfig(executor, measureTiming, outputType,
+                const TestConfig testConfig(executor, measureTiming, outputType, MemoryType::SHARED,
                                             /*reportSkipping=*/false);
                 bool baseSkipped = false;
-                EvaluatePreparedModel(preparedModel, testModel, testConfig, &baseSkipped);
+                EvaluatePreparedModel(device, preparedModel, testModel, testConfig, &baseSkipped);
                 bool coupledSkipped = false;
-                EvaluatePreparedModel(preparedCoupledModel, coupledModel, testConfig,
+                EvaluatePreparedModel(device, preparedCoupledModel, coupledModel, testConfig,
                                       &coupledSkipped);
                 ASSERT_EQ(baseSkipped, coupledSkipped);
                 if (baseSkipped) {
@@ -441,15 +707,12 @@
 
     sp<IPreparedModel> preparedModel;
     switch (testKind) {
-        case TestKind::GENERAL: {
+        case TestKind::GENERAL:
+        case TestKind::DYNAMIC_SHAPE:
+        case TestKind::MEMORY_DOMAIN: {
             createPreparedModel(device, model, &preparedModel);
             if (preparedModel == nullptr) return;
-            EvaluatePreparedModel(preparedModel, testModel, TestKind::GENERAL);
-        } break;
-        case TestKind::DYNAMIC_SHAPE: {
-            createPreparedModel(device, model, &preparedModel);
-            if (preparedModel == nullptr) return;
-            EvaluatePreparedModel(preparedModel, testModel, TestKind::DYNAMIC_SHAPE);
+            EvaluatePreparedModel(device, preparedModel, testModel, testKind);
         } break;
         case TestKind::QUANTIZATION_COUPLING: {
             ASSERT_TRUE(testModel.hasQuant8CoupledOperands());
@@ -473,7 +736,7 @@
                 GTEST_SKIP();
             }
             ASSERT_NE(preparedCoupledModel, nullptr);
-            EvaluatePreparedCoupledModels(preparedModel, testModel, preparedCoupledModel,
+            EvaluatePreparedCoupledModels(device, preparedModel, testModel, preparedCoupledModel,
                                           signedQuantizedModel);
         } break;
     }
@@ -499,6 +762,9 @@
 // Tag for the dynamic output shape tests
 class DynamicOutputShapeTest : public GeneratedTest {};
 
+// Tag for the memory domain tests
+class MemoryDomainTest : public GeneratedTest {};
+
 // Tag for the dynamic output shape tests
 class QuantizationCouplingTest : public GeneratedTest {};
 
@@ -510,6 +776,10 @@
     Execute(kDevice, kTestModel, /*testKind=*/TestKind::DYNAMIC_SHAPE);
 }
 
+TEST_P(MemoryDomainTest, Test) {
+    Execute(kDevice, kTestModel, /*testKind=*/TestKind::MEMORY_DOMAIN);
+}
+
 TEST_P(QuantizationCouplingTest, Test) {
     Execute(kDevice, kTestModel, /*testKind=*/TestKind::QUANTIZATION_COUPLING);
 }
@@ -520,6 +790,9 @@
 INSTANTIATE_GENERATED_TEST(DynamicOutputShapeTest,
                            [](const TestModel& testModel) { return !testModel.expectFailure; });
 
+INSTANTIATE_GENERATED_TEST(MemoryDomainTest,
+                           [](const TestModel& testModel) { return !testModel.expectFailure; });
+
 INSTANTIATE_GENERATED_TEST(QuantizationCouplingTest, [](const TestModel& testModel) {
     return testModel.hasQuant8CoupledOperands() && testModel.operations.size() == 1;
 });
diff --git a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.h b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.h
index ad6323f..2273e3b 100644
--- a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.h
+++ b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.h
@@ -62,13 +62,15 @@
     GENERAL,
     // Same as GENERAL but sets dimensions for the output tensors to zeros
     DYNAMIC_SHAPE,
+    // Same as GENERAL but use device memories for inputs and outputs
+    MEMORY_DOMAIN,
     // Tests if quantized model with TENSOR_QUANT8_ASYMM produces the same result
     // (OK/SKIPPED/FAILED) as the model with all such tensors converted to
     // TENSOR_QUANT8_ASYMM_SIGNED.
     QUANTIZATION_COUPLING
 };
 
-void EvaluatePreparedModel(const sp<IPreparedModel>& preparedModel,
+void EvaluatePreparedModel(const sp<IDevice>& device, const sp<IPreparedModel>& preparedModel,
                            const test_helper::TestModel& testModel, TestKind testKind);
 
 }  // namespace android::hardware::neuralnetworks::V1_3::vts::functional
diff --git a/neuralnetworks/1.3/vts/functional/ValidateModel.cpp b/neuralnetworks/1.3/vts/functional/ValidateModel.cpp
index 8395111..cc86264 100644
--- a/neuralnetworks/1.3/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.3/vts/functional/ValidateModel.cpp
@@ -25,7 +25,6 @@
 
 using implementation::PreparedModelCallback;
 using V1_0::ErrorStatus;
-using V1_0::OperandLifeTime;
 using V1_1::ExecutionPreference;
 using V1_2::SymmPerChannelQuantParams;
 using HidlToken =
@@ -83,22 +82,22 @@
 }
 
 static uint32_t addOperand(Model* model) {
-    return hidl_vec_push_back(&model->operands,
+    return hidl_vec_push_back(&model->main.operands,
                               {
                                       .type = OperandType::INT32,
                                       .dimensions = {},
                                       .numberOfConsumers = 0,
                                       .scale = 0.0f,
                                       .zeroPoint = 0,
-                                      .lifetime = OperandLifeTime::MODEL_INPUT,
+                                      .lifetime = OperandLifeTime::SUBGRAPH_INPUT,
                                       .location = {.poolIndex = 0, .offset = 0, .length = 0},
                               });
 }
 
 static uint32_t addOperand(Model* model, OperandLifeTime lifetime) {
     uint32_t index = addOperand(model);
-    model->operands[index].numberOfConsumers = 1;
-    model->operands[index].lifetime = lifetime;
+    model->main.operands[index].numberOfConsumers = 1;
+    model->main.operands[index].lifetime = lifetime;
     return index;
 }
 
@@ -112,13 +111,13 @@
 };
 
 static void mutateOperandTypeTest(const sp<IDevice>& device, const Model& model) {
-    for (size_t operand = 0; operand < model.operands.size(); ++operand) {
+    for (size_t operand = 0; operand < model.main.operands.size(); ++operand) {
         for (uint32_t invalidOperandType : invalidOperandTypes) {
             const std::string message = "mutateOperandTypeTest: operand " +
                                         std::to_string(operand) + " set to value " +
                                         std::to_string(invalidOperandType);
             validate(device, message, model, [operand, invalidOperandType](Model* model) {
-                model->operands[operand].type = static_cast<OperandType>(invalidOperandType);
+                model->main.operands[operand].type = static_cast<OperandType>(invalidOperandType);
             });
         }
     }
@@ -150,15 +149,15 @@
 }
 
 static void mutateOperandRankTest(const sp<IDevice>& device, const Model& model) {
-    for (size_t operand = 0; operand < model.operands.size(); ++operand) {
-        const uint32_t invalidRank = getInvalidRank(model.operands[operand].type);
+    for (size_t operand = 0; operand < model.main.operands.size(); ++operand) {
+        const uint32_t invalidRank = getInvalidRank(model.main.operands[operand].type);
         if (invalidRank == 0) {
             continue;
         }
         const std::string message = "mutateOperandRankTest: operand " + std::to_string(operand) +
                                     " has rank of " + std::to_string(invalidRank);
         validate(device, message, model, [operand, invalidRank](Model* model) {
-            model->operands[operand].dimensions = std::vector<uint32_t>(invalidRank, 0);
+            model->main.operands[operand].dimensions = std::vector<uint32_t>(invalidRank, 0);
         });
     }
 }
@@ -190,12 +189,12 @@
 }
 
 static void mutateOperandScaleTest(const sp<IDevice>& device, const Model& model) {
-    for (size_t operand = 0; operand < model.operands.size(); ++operand) {
-        const float invalidScale = getInvalidScale(model.operands[operand].type);
+    for (size_t operand = 0; operand < model.main.operands.size(); ++operand) {
+        const float invalidScale = getInvalidScale(model.main.operands[operand].type);
         const std::string message = "mutateOperandScaleTest: operand " + std::to_string(operand) +
                                     " has scale of " + std::to_string(invalidScale);
         validate(device, message, model, [operand, invalidScale](Model* model) {
-            model->operands[operand].scale = invalidScale;
+            model->main.operands[operand].scale = invalidScale;
         });
     }
 }
@@ -229,15 +228,15 @@
 }
 
 static void mutateOperandZeroPointTest(const sp<IDevice>& device, const Model& model) {
-    for (size_t operand = 0; operand < model.operands.size(); ++operand) {
+    for (size_t operand = 0; operand < model.main.operands.size(); ++operand) {
         const std::vector<int32_t> invalidZeroPoints =
-                getInvalidZeroPoints(model.operands[operand].type);
+                getInvalidZeroPoints(model.main.operands[operand].type);
         for (int32_t invalidZeroPoint : invalidZeroPoints) {
             const std::string message = "mutateOperandZeroPointTest: operand " +
                                         std::to_string(operand) + " has zero point of " +
                                         std::to_string(invalidZeroPoint);
             validate(device, message, model, [operand, invalidZeroPoint](Model* model) {
-                model->operands[operand].zeroPoint = invalidZeroPoint;
+                model->main.operands[operand].zeroPoint = invalidZeroPoint;
             });
         }
     }
@@ -310,11 +309,11 @@
 
 static bool mutateOperationOperandTypeSkip(size_t operand, OperandType type, const Model& model) {
     // Do not test OEM types
-    if (type == model.operands[operand].type || type == OperandType::OEM ||
+    if (type == model.main.operands[operand].type || type == OperandType::OEM ||
         type == OperandType::TENSOR_OEM_BYTE) {
         return true;
     }
-    for (const Operation& operation : model.operations) {
+    for (const Operation& operation : model.main.operations) {
         // Skip mutateOperationOperandTypeTest for the following operations.
         // - LSH_PROJECTION's second argument is allowed to have any type.
         // - ARGMIN and ARGMAX's first argument can be any of
@@ -401,7 +400,7 @@
 }
 
 static void mutateOperationOperandTypeTest(const sp<IDevice>& device, const Model& model) {
-    for (size_t operand = 0; operand < model.operands.size(); ++operand) {
+    for (size_t operand = 0; operand < model.main.operands.size(); ++operand) {
         for (OperandType invalidOperandType : hidl_enum_range<OperandType>{}) {
             if (mutateOperationOperandTypeSkip(operand, invalidOperandType, model)) {
                 continue;
@@ -410,7 +409,7 @@
                                         std::to_string(operand) + " set to type " +
                                         toString(invalidOperandType);
             validate(device, message, model, [operand, invalidOperandType](Model* model) {
-                mutateOperand(&model->operands[operand], invalidOperandType);
+                mutateOperand(&model->main.operands[operand], invalidOperandType);
             });
         }
     }
@@ -425,13 +424,13 @@
 };
 
 static void mutateOperationTypeTest(const sp<IDevice>& device, const Model& model) {
-    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+    for (size_t operation = 0; operation < model.main.operations.size(); ++operation) {
         for (uint32_t invalidOperationType : invalidOperationTypes) {
             const std::string message = "mutateOperationTypeTest: operation " +
                                         std::to_string(operation) + " set to value " +
                                         std::to_string(invalidOperationType);
             validate(device, message, model, [operation, invalidOperationType](Model* model) {
-                model->operations[operation].type =
+                model->main.operations[operation].type =
                         static_cast<OperationType>(invalidOperationType);
             });
         }
@@ -441,14 +440,14 @@
 ///////////////////////// VALIDATE MODEL OPERATION INPUT OPERAND INDEX /////////////////////////
 
 static void mutateOperationInputOperandIndexTest(const sp<IDevice>& device, const Model& model) {
-    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
-        const uint32_t invalidOperand = model.operands.size();
-        for (size_t input = 0; input < model.operations[operation].inputs.size(); ++input) {
+    for (size_t operation = 0; operation < model.main.operations.size(); ++operation) {
+        const uint32_t invalidOperand = model.main.operands.size();
+        for (size_t input = 0; input < model.main.operations[operation].inputs.size(); ++input) {
             const std::string message = "mutateOperationInputOperandIndexTest: operation " +
                                         std::to_string(operation) + " input " +
                                         std::to_string(input);
             validate(device, message, model, [operation, input, invalidOperand](Model* model) {
-                model->operations[operation].inputs[input] = invalidOperand;
+                model->main.operations[operation].inputs[input] = invalidOperand;
             });
         }
     }
@@ -457,14 +456,15 @@
 ///////////////////////// VALIDATE MODEL OPERATION OUTPUT OPERAND INDEX /////////////////////////
 
 static void mutateOperationOutputOperandIndexTest(const sp<IDevice>& device, const Model& model) {
-    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
-        const uint32_t invalidOperand = model.operands.size();
-        for (size_t output = 0; output < model.operations[operation].outputs.size(); ++output) {
+    for (size_t operation = 0; operation < model.main.operations.size(); ++operation) {
+        const uint32_t invalidOperand = model.main.operands.size();
+        for (size_t output = 0; output < model.main.operations[operation].outputs.size();
+             ++output) {
             const std::string message = "mutateOperationOutputOperandIndexTest: operation " +
                                         std::to_string(operation) + " output " +
                                         std::to_string(output);
             validate(device, message, model, [operation, output, invalidOperand](Model* model) {
-                model->operations[operation].outputs[output] = invalidOperand;
+                model->main.operations[operation].outputs[output] = invalidOperand;
             });
         }
     }
@@ -485,17 +485,17 @@
 }
 
 static void removeOperand(Model* model, uint32_t index) {
-    hidl_vec_removeAt(&model->operands, index);
-    for (Operation& operation : model->operations) {
+    hidl_vec_removeAt(&model->main.operands, index);
+    for (Operation& operation : model->main.operations) {
         removeValueAndDecrementGreaterValues(&operation.inputs, index);
         removeValueAndDecrementGreaterValues(&operation.outputs, index);
     }
-    removeValueAndDecrementGreaterValues(&model->inputIndexes, index);
-    removeValueAndDecrementGreaterValues(&model->outputIndexes, index);
+    removeValueAndDecrementGreaterValues(&model->main.inputIndexes, index);
+    removeValueAndDecrementGreaterValues(&model->main.outputIndexes, index);
 }
 
 static bool removeOperandSkip(size_t operand, const Model& model) {
-    for (const Operation& operation : model.operations) {
+    for (const Operation& operation : model.main.operations) {
         // Skip removeOperandTest for the following operations.
         // - SPLIT's outputs are not checked during prepareModel.
         if (operation.type == OperationType::SPLIT) {
@@ -520,7 +520,7 @@
 }
 
 static void removeOperandTest(const sp<IDevice>& device, const Model& model) {
-    for (size_t operand = 0; operand < model.operands.size(); ++operand) {
+    for (size_t operand = 0; operand < model.main.operands.size(); ++operand) {
         if (removeOperandSkip(operand, model)) {
             continue;
         }
@@ -533,14 +533,14 @@
 ///////////////////////// REMOVE OPERATION /////////////////////////
 
 static void removeOperation(Model* model, uint32_t index) {
-    for (uint32_t operand : model->operations[index].inputs) {
-        model->operands[operand].numberOfConsumers--;
+    for (uint32_t operand : model->main.operations[index].inputs) {
+        model->main.operands[operand].numberOfConsumers--;
     }
-    hidl_vec_removeAt(&model->operations, index);
+    hidl_vec_removeAt(&model->main.operations, index);
 }
 
 static void removeOperationTest(const sp<IDevice>& device, const Model& model) {
-    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+    for (size_t operation = 0; operation < model.main.operations.size(); ++operation) {
         const std::string message = "removeOperationTest: operation " + std::to_string(operation);
         validate(device, message, model,
                  [operation](Model* model) { removeOperation(model, operation); });
@@ -615,9 +615,9 @@
 }
 
 static void removeOperationInputTest(const sp<IDevice>& device, const Model& model) {
-    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
-        for (size_t input = 0; input < model.operations[operation].inputs.size(); ++input) {
-            const Operation& op = model.operations[operation];
+    for (size_t operation = 0; operation < model.main.operations.size(); ++operation) {
+        for (size_t input = 0; input < model.main.operations[operation].inputs.size(); ++input) {
+            const Operation& op = model.main.operations[operation];
             if (removeOperationInputSkip(op, input)) {
                 continue;
             }
@@ -625,9 +625,9 @@
                                         std::to_string(operation) + ", input " +
                                         std::to_string(input);
             validate(device, message, model, [operation, input](Model* model) {
-                uint32_t operand = model->operations[operation].inputs[input];
-                model->operands[operand].numberOfConsumers--;
-                hidl_vec_removeAt(&model->operations[operation].inputs, input);
+                uint32_t operand = model->main.operations[operation].inputs[input];
+                model->main.operands[operand].numberOfConsumers--;
+                hidl_vec_removeAt(&model->main.operations[operation].inputs, input);
             });
         }
     }
@@ -636,13 +636,14 @@
 ///////////////////////// REMOVE OPERATION OUTPUT /////////////////////////
 
 static void removeOperationOutputTest(const sp<IDevice>& device, const Model& model) {
-    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
-        for (size_t output = 0; output < model.operations[operation].outputs.size(); ++output) {
+    for (size_t operation = 0; operation < model.main.operations.size(); ++operation) {
+        for (size_t output = 0; output < model.main.operations[operation].outputs.size();
+             ++output) {
             const std::string message = "removeOperationOutputTest: operation " +
                                         std::to_string(operation) + ", output " +
                                         std::to_string(output);
             validate(device, message, model, [operation, output](Model* model) {
-                hidl_vec_removeAt(&model->operations[operation].outputs, output);
+                hidl_vec_removeAt(&model->main.operations[operation].outputs, output);
             });
         }
     }
@@ -669,15 +670,15 @@
 }
 
 static void addOperationInputTest(const sp<IDevice>& device, const Model& model) {
-    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
-        if (addOperationInputSkip(model.operations[operation])) {
+    for (size_t operation = 0; operation < model.main.operations.size(); ++operation) {
+        if (addOperationInputSkip(model.main.operations[operation])) {
             continue;
         }
         const std::string message = "addOperationInputTest: operation " + std::to_string(operation);
         validate(device, message, model, [operation](Model* model) {
-            uint32_t index = addOperand(model, OperandLifeTime::MODEL_INPUT);
-            hidl_vec_push_back(&model->operations[operation].inputs, index);
-            hidl_vec_push_back(&model->inputIndexes, index);
+            uint32_t index = addOperand(model, OperandLifeTime::SUBGRAPH_INPUT);
+            hidl_vec_push_back(&model->main.operations[operation].inputs, index);
+            hidl_vec_push_back(&model->main.inputIndexes, index);
         });
     }
 }
@@ -685,13 +686,13 @@
 ///////////////////////// ADD OPERATION OUTPUT /////////////////////////
 
 static void addOperationOutputTest(const sp<IDevice>& device, const Model& model) {
-    for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+    for (size_t operation = 0; operation < model.main.operations.size(); ++operation) {
         const std::string message =
                 "addOperationOutputTest: operation " + std::to_string(operation);
         validate(device, message, model, [operation](Model* model) {
-            uint32_t index = addOperand(model, OperandLifeTime::MODEL_OUTPUT);
-            hidl_vec_push_back(&model->operations[operation].outputs, index);
-            hidl_vec_push_back(&model->outputIndexes, index);
+            uint32_t index = addOperand(model, OperandLifeTime::SUBGRAPH_OUTPUT);
+            hidl_vec_push_back(&model->main.operations[operation].outputs, index);
+            hidl_vec_push_back(&model->main.outputIndexes, index);
         });
     }
 }
diff --git a/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp
index 8092d04..96dc589 100644
--- a/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp
@@ -28,7 +28,6 @@
 namespace android::hardware::neuralnetworks::V1_3::vts::functional {
 
 using V1_0::ErrorStatus;
-using V1_0::Request;
 using V1_2::MeasureTiming;
 using V1_2::OutputShape;
 using V1_2::Timing;
@@ -93,9 +92,13 @@
     }
 
     // burst
+    // TODO(butlermichael): Check if we need to test burst in V1_3 if the interface remains V1_2.
     {
         SCOPED_TRACE(message + " [burst]");
 
+        ASSERT_TRUE(nn::compliantWithV1_0(request));
+        V1_0::Request request10 = nn::convertToV1_0(request);
+
         // create burst
         std::shared_ptr<::android::nn::ExecutionBurstController> burst =
                 android::nn::ExecutionBurstController::create(preparedModel,
@@ -103,13 +106,13 @@
         ASSERT_NE(nullptr, burst.get());
 
         // create memory keys
-        std::vector<intptr_t> keys(request.pools.size());
+        std::vector<intptr_t> keys(request10.pools.size());
         for (size_t i = 0; i < keys.size(); ++i) {
-            keys[i] = reinterpret_cast<intptr_t>(&request.pools[i]);
+            keys[i] = reinterpret_cast<intptr_t>(&request10.pools[i]);
         }
 
         // execute and verify
-        const auto [n, outputShapes, timing, fallback] = burst->compute(request, measure, keys);
+        const auto [n, outputShapes, timing, fallback] = burst->compute(request10, measure, keys);
         const ErrorStatus status = nn::convertResultCodeToErrorStatus(n);
         EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status);
         EXPECT_EQ(outputShapes.size(), 0);
@@ -117,7 +120,7 @@
         EXPECT_FALSE(fallback);
 
         // additional burst testing
-        if (request.pools.size() > 0) {
+        if (request10.pools.size() > 0) {
             // valid free
             burst->freeMemory(keys.front());
 
diff --git a/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.cpp
index 92d8fa7..1140b68 100644
--- a/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.cpp
+++ b/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.cpp
@@ -25,6 +25,7 @@
 #include "1.3/Callbacks.h"
 #include "GeneratedTestHarness.h"
 #include "TestHarness.h"
+#include "Utils.h"
 
 namespace android::hardware::neuralnetworks::V1_3::vts::functional {
 
@@ -32,7 +33,6 @@
         hidl_array<uint8_t, static_cast<uint32_t>(V1_2::Constant::BYTE_SIZE_OF_CACHE_TOKEN)>;
 using implementation::PreparedModelCallback;
 using V1_0::ErrorStatus;
-using V1_0::Request;
 using V1_1::ExecutionPreference;
 
 // internal helper function
@@ -124,9 +124,9 @@
 // Forward declaration from ValidateModel.cpp
 void validateModel(const sp<IDevice>& device, const Model& model);
 // Forward declaration from ValidateRequest.cpp
-void validateRequest(const sp<IPreparedModel>& preparedModel, const V1_0::Request& request);
+void validateRequest(const sp<IPreparedModel>& preparedModel, const Request& request);
 // Forward declaration from ValidateRequest.cpp
-void validateRequestFailure(const sp<IPreparedModel>& preparedModel, const V1_0::Request& request);
+void validateRequestFailure(const sp<IPreparedModel>& preparedModel, const Request& request);
 // Forward declaration from ValidateBurst.cpp
 void validateBurst(const sp<IPreparedModel>& preparedModel, const V1_0::Request& request);
 
@@ -139,7 +139,11 @@
     if (preparedModel == nullptr) return;
 
     validateRequest(preparedModel, request);
-    validateBurst(preparedModel, request);
+
+    // TODO(butlermichael): Check if we need to test burst in V1_3 if the interface remains V1_2.
+    ASSERT_TRUE(nn::compliantWithV1_0(request));
+    V1_0::Request request10 = nn::convertToV1_0(request);
+    validateBurst(preparedModel, request10);
 }
 
 void validateFailure(const sp<IDevice>& device, const Model& model, const Request& request) {
@@ -157,7 +161,7 @@
 
 TEST_P(ValidationTest, Test) {
     const Model model = createModel(kTestModel);
-    const Request request = createRequest(kTestModel);
+    const Request request = nn::convertToV1_3(createRequest(kTestModel));
     if (kTestModel.expectFailure) {
         validateFailure(kDevice, model, request);
     } else {
diff --git a/radio/1.5/IRadio.hal b/radio/1.5/IRadio.hal
index 22cc4e1..be6a727 100644
--- a/radio/1.5/IRadio.hal
+++ b/radio/1.5/IRadio.hal
@@ -249,6 +249,24 @@
     oneway getBarringInfo(int32_t serial);
 
     /**
+     * Request current voice registration state
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioResponse.getVoiceRegistrationStateResponse_1_5()
+     */
+    oneway getVoiceRegistrationState_1_5(int32_t serial);
+
+    /**
+     * Request current data registration state
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioResponse.getDataRegistrationStateResponse_1_5()
+     */
+    oneway getDataRegistrationState_1_5(int32_t serial);
+
+    /**
      * Requests that deactivates one category of the device personalization.
      *
      * @param serial Serial number of request.
diff --git a/radio/1.5/IRadioResponse.hal b/radio/1.5/IRadioResponse.hal
index 88f3134..f65c075 100644
--- a/radio/1.5/IRadioResponse.hal
+++ b/radio/1.5/IRadioResponse.hal
@@ -20,9 +20,9 @@
 import @1.0::SendSmsResult;
 import @1.4::IRadioResponse;
 import @1.5::BarringInfo;
-import @1.5::SetupDataCallResult;
-import @1.4::SetupDataCallResult;
 import @1.5::PersoSubstate;
+import @1.5::RegStateResult;
+import @1.5::SetupDataCallResult;
 
 /**
  * Interface declaring response functions to solicited radio requests.
@@ -176,6 +176,33 @@
 
     /**
      * @param info Response info struct containing response type, serial no. and error
+     * @param voiceRegResponse Current Voice registration response as defined by RegStateResult
+     *        in types.hal
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     */
+    oneway getVoiceRegistrationStateResponse_1_5(RadioResponseInfo info,
+            RegStateResult voiceRegResponse);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param dataRegResponse Current Data registration response as defined by RegStateResult in
+     *        types.hal
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NOT_PROVISIONED
+     */
+    oneway getDataRegistrationStateResponse_1_5(RadioResponseInfo info,
+            RegStateResult dataRegResponse);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
      * @param persoType SIM Personalisation type
      * @param remainingRetries Positive values indicates number of retries remaining,
      * must be equal to -1 if number of retries are infinite.
diff --git a/radio/1.5/types.hal b/radio/1.5/types.hal
index b056408..48796be 100644
--- a/radio/1.5/types.hal
+++ b/radio/1.5/types.hal
@@ -16,7 +16,12 @@
 
 package android.hardware.radio@1.5;
 
+import @1.0::ApnAuthType;
+import @1.0::DataProfileId;
+import @1.0::DataProfileInfoType;
 import @1.0::PersoSubstate;
+import @1.0::RadioAccessFamily;
+import @1.0::RegState;
 import @1.1::EutranBands;
 import @1.1::GeranBands;
 import @1.1::RadioAccessNetworks;
@@ -36,7 +41,10 @@
 import @1.4::DataCallFailCause;
 import @1.4::DataConnActiveStatus;
 import @1.4::DataProfileInfo;
+import @1.4::LteVopsInfo;
+import @1.4::NrIndicators;
 import @1.4::PdpProtocolType;
+import @1.4::RadioTechnology;
 
 import android.hidl.safe_union@1.0::Monostate;
 
@@ -229,6 +237,16 @@
     BAND_261 = 261,
 };
 
+enum UtranBands : @1.1::UtranBands {
+    /** TD-SCDMA bands. 3GPP TS 25.102, Table 5.2: Frequency bands */
+    BAND_A = 101,
+    BAND_B = 102,
+    BAND_C = 103,
+    BAND_D = 104,
+    BAND_E = 105,
+    BAND_F = 106,
+};
+
 /**
  * Overwritten from @1.2::NetworkScanRequest to update
  * RadioAccessSpecifier to 1.5 version
@@ -556,6 +574,192 @@
 };
 
 /**
+ * Call fail causes for Circuit-switched service enumerated in 3GPP TS 24.008, 10.5.3.6 and
+ * 10.5.147. Additional detail is available in 3GPP TS 24.008 Annex G.
+ */
+enum RegistrationFailCause : int32_t {
+    /** 0 - None */
+    NONE = 0,
+    /** 2 - IMSI unknown in HLR */
+    IMSI_UNKNOWN_IN_HLR = 2,
+    /** 3 - Illegal MS */
+    ILLEGAL_MS = 3,
+    /** 4 - Illegal ME */
+    IMSI_UNKNOWN_IN_VLR = 4,
+    /** 5 - PLMN not allowed */
+    IMEI_NOT_ACCEPTED = 5,
+    /** 6 - Location area not allowed */
+    ILLEGAL_ME = 6,
+    /** 7 - Roaming not allowed */
+    GPRS_SERVICES_NOT_ALLOWED = 7,
+    /** 8 - No Suitable Cells in this Location Area */
+    GPRS_AND_NON_GPRS_SERVICES_NOT_ALLOWED = 8,
+    /** 9 - Network failure */
+    MS_IDENTITY_CANNOT_BE_DERIVED_BY_NETWORK = 9,
+    /** 10 - Persistent location update reject */
+    IMPLICITLY_DETACHED = 10,
+    /** 11 - PLMN not allowed */
+    PLMN_NOT_ALLOWED = 11,
+    /** 12 - Location area not allowed */
+    LOCATION_AREA_NOT_ALLOWED = 12,
+    /** 13 - Roaming not allowed in this Location Area */
+    ROAMING_NOT_ALLOWED = 13,
+    /** 14 - GPRS Services not allowed in this PLMN */
+    GPRS_SERVICES_NOT_ALLOWED_IN_PLMN = 14,
+    /** 15 - No Suitable Cells in this Location Area */
+    NO_SUITABLE_CELLS = 15,
+    /** 16 - MSC temporarily not reachable */
+    MSC_TEMPORARILY_NOT_REACHABLE = 15,
+    /** 17 - Network Failure */
+    NETWORK_FAILURE = 17,
+    /** 20 - MAC Failure */
+    MAC_FAILURE = 20,
+    /** 21 - Sync Failure */
+    SYNC_FAILURE = 21,
+    /** 22 - Congestion */
+    CONGESTION = 22,
+    /** 23 - GSM Authentication unacceptable */
+    GSM_AUTHENTICATION_UNACCEPTABLE = 23,
+    /** 25 - Not Authorized for this CSG */
+    NOT_AUTHORIZED_FOR_THIS_CSG = 25,
+    /** 28 SMS provided via GPRS in this routing area */
+    SMS_PROVIDED_BY_GPRS_IN_ROUTING_AREA,
+    /** 32 - Service option not supported */
+    SERVICE_OPTION_NOT_SUPPORTED = 32,
+    /** 33 - Requested service option not subscribed */
+    SERVICE_OPTION_NOT_SUBSCRIBED = 33,
+    /** 34 - Service option temporarily out of order */
+    SERVICE_OPTION_TEMPORARILY_OUT_OF_ORDER = 34,
+    /** 38 - Call cannot be identified */
+    CALL_CANNOT_BE_IDENTIFIED = 38,
+    /** 40 No PDP context activated */
+    NO_PDP_CONTEXT_ACTIVATED = 40,
+    /** 48-63 - Retry upon entry into a new cell */
+    RETRY_UPON_ENTRY_INTO_NEW_CELL_1 = 48,
+    RETRY_UPON_ENTRY_INTO_NEW_CELL_2 = 49,
+    RETRY_UPON_ENTRY_INTO_NEW_CELL_3 = 50,
+    RETRY_UPON_ENTRY_INTO_NEW_CELL_4 = 51,
+    RETRY_UPON_ENTRY_INTO_NEW_CELL_5 = 52,
+    RETRY_UPON_ENTRY_INTO_NEW_CELL_6 = 53,
+    RETRY_UPON_ENTRY_INTO_NEW_CELL_7 = 54,
+    RETRY_UPON_ENTRY_INTO_NEW_CELL_8 = 55,
+    RETRY_UPON_ENTRY_INTO_NEW_CELL_9 = 56,
+    RETRY_UPON_ENTRY_INTO_NEW_CELL_10 = 57,
+    RETRY_UPON_ENTRY_INTO_NEW_CELL_11 = 58,
+    RETRY_UPON_ENTRY_INTO_NEW_CELL_12 = 59,
+    RETRY_UPON_ENTRY_INTO_NEW_CELL_13 = 60,
+    RETRY_UPON_ENTRY_INTO_NEW_CELL_14 = 61,
+    RETRY_UPON_ENTRY_INTO_NEW_CELL_15 = 62,
+    RETRY_UPON_ENTRY_INTO_NEW_CELL_16 = 63,
+    /** 95 - Semantically incorrect message */
+    SEMANTICALLY_INCORRECT_MESSAGE = 95,
+    /** 96 - Invalid mandatory information */
+    INVALID_MANDATORY_INFORMATION = 96,
+    /** 97 - Message type non-existent or not implemented */
+    MESSAGE_TYPE_NON_EXISTENT_OR_NOT_IMPLEMENTED = 97,
+    /** 98 - Message type not compatible with protocol state */
+    MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 98,
+    /** 99 - Information element non-existent or not implemented */
+    INFORMATION_ELEMENT_NON_EXISTENT_OR_NOT_IMPLEMENTED = 99,
+    /** 100 - Conditional IE error */
+    CONDITIONAL_IE_ERROR = 100,
+    /** 101 - Message not compatible with protocol state */
+    MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE = 101,
+    /** 111 - Protocol error, unspecified */
+    PROTOCOL_ERROR_UNSPECIFIED = 111,
+};
+
+enum PrlIndicator : int32_t {
+    NOT_REGISTERED = -1,
+    NOT_IN_PRL = 0,
+    IN_PRL = 1,
+};
+
+struct RegStateResult {
+    /**
+     * Registration state
+     *
+     * If the RAT is indicated as a GERAN, UTRAN, or CDMA2000 technology, this value reports
+     * registration in the Circuit-switched domain.
+     * If the RAT is indicated as an EUTRAN, NGRAN, or another technology that does not support
+     * circuit-switched services, this value reports registration in the Packet-switched domain.
+     */
+    RegState regState;
+
+    /**
+     * Indicates the available voice radio technology, valid values as
+     * defined by RadioTechnology.
+     */
+    RadioTechnology rat;
+
+    /**
+     * Cause code reported by the network in case registration fails. This will be a mobility
+     * management cause code defined for MM, GMM, MME or equivalent as appropriate for the RAT.
+     */
+    RegistrationFailCause reasonForDenial;
+
+    /** CellIdentity */
+    CellIdentity cellIdentity;
+
+    /**
+     * The most-recent PLMN-ID upon which the UE registered (or attempted to register if a failure
+     * is reported in the reasonForDenial field). This PLMN shall be in standard format consisting
+     * of a 3 digit MCC concatenated with a 2 or 3 digit MNC.
+     */
+    string registeredPlmn;
+
+    /**
+     * Access-technology-specific registration information, such as for Cdma2000.
+     */
+    safe_union AccessTechnologySpecificInfo {
+        Monostate noinit;
+
+        struct Cdma2000RegistrationInfo {
+            /**
+             * concurrent services support indicator. if registered on a CDMA system.
+             * false - Concurrent services not supported,
+             * true - Concurrent services supported
+             */
+            bool cssSupported;
+
+            /**
+             * TSB-58 Roaming Indicator if registered on a CDMA or EVDO system or -1 if not.
+             * Valid values are 0-255.
+             */
+            int32_t roamingIndicator;
+
+            /**
+             * Indicates whether the current system is in the PRL if registered on a CDMA or EVDO
+             * system or -1 if not. 0=not in the PRL, 1=in the PRL.
+             */
+            PrlIndicator systemIsInPrl;
+
+            /**
+             * Default Roaming Indicator from the PRL if registered on a CDMA or EVDO system or -1
+             * if not.
+             * Valid values are 0-255.
+             */
+            int32_t defaultRoamingIndicator;
+        } cdmaInfo;
+
+        struct EutranRegistrationInfo {
+            /**
+             * 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.
+             */
+            LteVopsInfo lteVopsInfo; // LTE network capability
+
+            /**
+             * The parameters of NR 5G Non-Standalone. This value is only valid on E-UTRAN,
+             * otherwise must be empty.
+             */
+            NrIndicators nrIndicators;
+        } eutranInfo;
+    } accessTechnologySpecificInfo;
+};
+
+/**
  * Additional personalization categories in addition to those specified in 3GPP TS 22.022 and 3GPP2 C.S0068-0.
  */
 enum PersoSubstate : @1.0::PersoSubstate {
diff --git a/radio/1.5/vts/functional/Android.bp b/radio/1.5/vts/functional/Android.bp
index 85c4f99..182985e 100644
--- a/radio/1.5/vts/functional/Android.bp
+++ b/radio/1.5/vts/functional/Android.bp
@@ -34,6 +34,7 @@
         "android.hardware.radio@1.0",
         "android.hardware.radio.config@1.0",
         "android.hardware.radio.config@1.1",
+        "android.hardware.radio.config@1.3",
     ],
     header_libs: ["radio.util.header@1.0"],
     test_suites: ["general-tests"]
diff --git a/radio/1.5/vts/functional/radio_hidl_hal_test.cpp b/radio/1.5/vts/functional/radio_hidl_hal_test.cpp
index a5d236d..c29ebf9 100644
--- a/radio/1.5/vts/functional/radio_hidl_hal_test.cpp
+++ b/radio/1.5/vts/functional/radio_hidl_hal_test.cpp
@@ -47,9 +47,9 @@
     EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
     EXPECT_EQ(RadioError::NONE, radioRsp_v1_5->rspInfo.error);
 
-    sp<::android::hardware::radio::config::V1_1::IRadioConfig> radioConfig =
+    sp<::android::hardware::radio::config::V1_3::IRadioConfig> radioConfig =
             ::testing::VtsHalHidlTargetTestBase::getService<
-                    ::android::hardware::radio::config::V1_1::IRadioConfig>();
+                    ::android::hardware::radio::config::V1_3::IRadioConfig>();
 
     /* Enforce Vts tesing with RadioConfig is existed. */
     ASSERT_NE(nullptr, radioConfig.get());
diff --git a/radio/1.5/vts/functional/radio_hidl_hal_utils_v1_5.h b/radio/1.5/vts/functional/radio_hidl_hal_utils_v1_5.h
index 1c4ec9f..db7cf41 100644
--- a/radio/1.5/vts/functional/radio_hidl_hal_utils_v1_5.h
+++ b/radio/1.5/vts/functional/radio_hidl_hal_utils_v1_5.h
@@ -22,7 +22,7 @@
 #include <condition_variable>
 #include <mutex>
 
-#include <android/hardware/radio/config/1.1/IRadioConfig.h>
+#include <android/hardware/radio/config/1.3/IRadioConfig.h>
 
 #include <android/hardware/radio/1.5/IRadio.h>
 #include <android/hardware/radio/1.5/IRadioIndication.h>
@@ -563,6 +563,14 @@
             const RadioResponseInfo& info,
             const ::android::hardware::hidl_vec<::android::hardware::radio::V1_5::BarringInfo>&
                     barringInfos);
+
+    Return<void> getVoiceRegistrationStateResponse_1_5(
+            const RadioResponseInfo& info,
+            const ::android::hardware::radio::V1_5::RegStateResult& regResponse);
+
+    Return<void> getDataRegistrationStateResponse_1_5(
+            const RadioResponseInfo& info,
+            const ::android::hardware::radio::V1_5::RegStateResult& regResponse);
 };
 
 /* Callback class for radio indication */
diff --git a/radio/1.5/vts/functional/radio_response.cpp b/radio/1.5/vts/functional/radio_response.cpp
index c56087c..859db3f 100644
--- a/radio/1.5/vts/functional/radio_response.cpp
+++ b/radio/1.5/vts/functional/radio_response.cpp
@@ -981,3 +981,19 @@
     parent_v1_5.notify(info.serial);
     return Void();
 }
+
+Return<void> RadioResponse_v1_5::getVoiceRegistrationStateResponse_1_5(
+        const RadioResponseInfo& info,
+        const ::android::hardware::radio::V1_5::RegStateResult& /*regResponse*/) {
+    rspInfo = info;
+    parent_v1_5.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_5::getDataRegistrationStateResponse_1_5(
+        const RadioResponseInfo& info,
+        const ::android::hardware::radio::V1_5::RegStateResult& /*regResponse*/) {
+    rspInfo = info;
+    parent_v1_5.notify(info.serial);
+    return Void();
+}
diff --git a/radio/config/1.3/Android.bp b/radio/config/1.3/Android.bp
index 88de666..7360270 100644
--- a/radio/config/1.3/Android.bp
+++ b/radio/config/1.3/Android.bp
@@ -17,6 +17,9 @@
         "android.hardware.radio.config@1.1",
         "android.hardware.radio.config@1.2",
         "android.hardware.radio@1.0",
+        "android.hardware.radio@1.1",
+        "android.hardware.radio@1.4",
+        "android.hardware.radio@1.5",
         "android.hidl.base@1.0",
     ],
     gen_java: true,
diff --git a/radio/config/1.3/IRadioConfig.hal b/radio/config/1.3/IRadioConfig.hal
index a0ce6e0..d01f54b 100644
--- a/radio/config/1.3/IRadioConfig.hal
+++ b/radio/config/1.3/IRadioConfig.hal
@@ -27,5 +27,13 @@
  * serial to different methods), multiple responses (one for each method call) must still be served.
  */
 interface IRadioConfig extends @1.1::IRadioConfig {
-
+    /**
+     * Request current phone capability.
+     *
+     * @param serial Serial number of request.
+     *
+     * Response callback is IRadioResponse.getPhoneCapabilityResponse_1_3() which
+     * will return <@1.3::PhoneCapability>.
+     */
+    oneway getPhoneCapability_1_3(int32_t serial);
 };
diff --git a/radio/config/1.3/IRadioConfigResponse.hal b/radio/config/1.3/IRadioConfigResponse.hal
index 9c4c971..e13aa1e 100644
--- a/radio/config/1.3/IRadioConfigResponse.hal
+++ b/radio/config/1.3/IRadioConfigResponse.hal
@@ -16,11 +16,22 @@
 
 package android.hardware.radio.config@1.3;
 
+import android.hardware.radio@1.0::RadioResponseInfo;
 import @1.2::IRadioConfigResponse;
+import @1.3::PhoneCapability;
 
 /**
  * Interface declaring response functions to solicited radio config requests.
  */
 interface IRadioConfigResponse extends @1.2::IRadioConfigResponse {
-
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param phoneCapability <@1.3::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
+     */
+    oneway getPhoneCapabilityResponse_1_3(RadioResponseInfo info, PhoneCapability phoneCapability);
 };
diff --git a/radio/config/1.3/default/RadioConfig.cpp b/radio/config/1.3/default/RadioConfig.cpp
index c28119c..01e98f1 100644
--- a/radio/config/1.3/default/RadioConfig.cpp
+++ b/radio/config/1.3/default/RadioConfig.cpp
@@ -24,7 +24,6 @@
 namespace implementation {
 
 using namespace ::android::hardware::radio::V1_0;
-using namespace ::android::hardware::radio::config;
 
 // Methods from ::android::hardware::radio::config::V1_0::IRadioConfig follow.
 Return<void> RadioConfig::setResponseFunctions(
@@ -105,6 +104,14 @@
     return Void();
 }
 
+// Methods from ::android::hardware::radio::config::V1_3::IRadioConfig follow.
+Return<void> RadioConfig::getPhoneCapability_1_3(int32_t /* serial */) {
+    V1_3::PhoneCapability phoneCapability;
+    RadioResponseInfo info;
+    mRadioConfigResponseV1_3->getPhoneCapabilityResponse_1_3(info, phoneCapability);
+    return Void();
+}
+
 }  // namespace implementation
 }  // namespace V1_3
 }  // namespace config
diff --git a/radio/config/1.3/default/RadioConfig.h b/radio/config/1.3/default/RadioConfig.h
index 00585e6..57ff368 100644
--- a/radio/config/1.3/default/RadioConfig.h
+++ b/radio/config/1.3/default/RadioConfig.h
@@ -62,6 +62,9 @@
     Return<void> setPreferredDataModem(int32_t serial, uint8_t modemId);
     Return<void> setModemsConfig(int32_t serial, const V1_1::ModemsConfig& modemsConfig);
     Return<void> getModemsConfig(int32_t serial);
+
+    // Methods from ::android::hardware::radio::config::V1_3::IRadioConfig follow.
+    Return<void> getPhoneCapability_1_3(int32_t serial);
 };
 
 }  // namespace implementation
diff --git a/radio/config/1.3/default/RadioConfigIndication.cpp b/radio/config/1.3/default/RadioConfigIndication.cpp
index eb77a48..608fa1c 100644
--- a/radio/config/1.3/default/RadioConfigIndication.cpp
+++ b/radio/config/1.3/default/RadioConfigIndication.cpp
@@ -23,10 +23,6 @@
 namespace V1_3 {
 namespace implementation {
 
-using namespace ::android::hardware::radio::V1_0;
-using namespace ::android::hardware::radio::config::V1_0;
-using namespace ::android::hardware::radio::config::V1_2;
-
 // Methods from ::android::hardware::radio::config::V1_0::IRadioConfigIndication follow.
 Return<void> RadioConfigIndication::simSlotsStatusChanged(
         RadioIndicationType /* type */, const hidl_vec<V1_0::SimSlotStatus>& /* slotStatus */) {
diff --git a/radio/config/1.3/default/RadioConfigIndication.h b/radio/config/1.3/default/RadioConfigIndication.h
index 3697492..c92446c 100644
--- a/radio/config/1.3/default/RadioConfigIndication.h
+++ b/radio/config/1.3/default/RadioConfigIndication.h
@@ -31,10 +31,6 @@
 using namespace ::android::hardware::radio::V1_0;
 using namespace ::android::hardware::radio::config;
 
-using ::android::sp;
-using ::android::hardware::hidl_array;
-using ::android::hardware::hidl_memory;
-using ::android::hardware::hidl_string;
 using ::android::hardware::hidl_vec;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
diff --git a/radio/config/1.3/default/RadioConfigResponse.cpp b/radio/config/1.3/default/RadioConfigResponse.cpp
index 48e81da..1d48a13 100644
--- a/radio/config/1.3/default/RadioConfigResponse.cpp
+++ b/radio/config/1.3/default/RadioConfigResponse.cpp
@@ -23,11 +23,6 @@
 namespace V1_3 {
 namespace implementation {
 
-using namespace ::android::hardware::radio::V1_0;
-using namespace ::android::hardware::radio::config::V1_0;
-using namespace ::android::hardware::radio::config::V1_1;
-using namespace ::android::hardware::radio::config::V1_2;
-
 // Methods from ::android::hardware::radio::config::V1_0::IRadioConfigResponse follow.
 Return<void> RadioConfigResponse::getSimSlotsStatusResponse(
         const RadioResponseInfo& /* info */,
@@ -73,6 +68,13 @@
     return Void();
 }
 
+// Methods from ::android::hardware::radio::config::V1_3::IRadioConfigResponse follow.
+Return<void> RadioConfigResponse::getPhoneCapabilityResponse_1_3(
+        const RadioResponseInfo& /* info */, const V1_3::PhoneCapability& /* phoneCapability */) {
+    // TODO implement
+    return Void();
+}
+
 }  // namespace implementation
 }  // namespace V1_3
 }  // namespace config
diff --git a/radio/config/1.3/default/RadioConfigResponse.h b/radio/config/1.3/default/RadioConfigResponse.h
index 0f0033f..dc169bb 100644
--- a/radio/config/1.3/default/RadioConfigResponse.h
+++ b/radio/config/1.3/default/RadioConfigResponse.h
@@ -28,43 +28,36 @@
 namespace V1_3 {
 namespace implementation {
 
-using ::android::sp;
-using ::android::hardware::hidl_array;
-using ::android::hardware::hidl_memory;
-using ::android::hardware::hidl_string;
+using namespace ::android::hardware::radio::config;
+
 using ::android::hardware::hidl_vec;
 using ::android::hardware::Return;
-using ::android::hardware::Void;
+
+using ::android::hardware::radio::V1_0::RadioResponseInfo;
 
 struct RadioConfigResponse : public IRadioConfigResponse {
     // Methods from ::android::hardware::radio::config::V1_0::IRadioConfigResponse follow.
     Return<void> getSimSlotsStatusResponse(
-            const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
-            const hidl_vec<::android::hardware::radio::config::V1_0::SimSlotStatus>& slotStatus)
-            override;
-    Return<void> setSimSlotsMappingResponse(
-            const ::android::hardware::radio::V1_0::RadioResponseInfo& info) override;
+            const RadioResponseInfo& info,
+            const hidl_vec<V1_0::SimSlotStatus>& slotStatus) override;
+    Return<void> setSimSlotsMappingResponse(const RadioResponseInfo& info) override;
 
     // Methods from ::android::hardware::radio::config::V1_1::IRadioConfigResponse follow.
-    Return<void> getPhoneCapabilityResponse(
-            const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
-            const ::android::hardware::radio::config::V1_1::PhoneCapability& phoneCapability)
-            override;
-    Return<void> setPreferredDataModemResponse(
-            const ::android::hardware::radio::V1_0::RadioResponseInfo& info) override;
-    Return<void> setModemsConfigResponse(
-            const ::android::hardware::radio::V1_0::RadioResponseInfo& info) override;
-    Return<void> getModemsConfigResponse(
-            const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
-            const ::android::hardware::radio::config::V1_1::ModemsConfig& modemsConfig) override;
+    Return<void> getPhoneCapabilityResponse(const RadioResponseInfo& info,
+                                            const V1_1::PhoneCapability& phoneCapability) override;
+    Return<void> setPreferredDataModemResponse(const RadioResponseInfo& info) override;
+    Return<void> setModemsConfigResponse(const RadioResponseInfo& info) override;
+    Return<void> getModemsConfigResponse(const RadioResponseInfo& info,
+                                         const V1_1::ModemsConfig& modemsConfig) override;
 
     // Methods from ::android::hardware::radio::config::V1_2::IRadioConfigResponse follow.
     Return<void> getSimSlotsStatusResponse_1_2(
-            const ::android::hardware::radio::V1_0::RadioResponseInfo& info,
-            const hidl_vec<::android::hardware::radio::config::V1_2::SimSlotStatus>& slotStatus)
-            override;
+            const RadioResponseInfo& info,
+            const hidl_vec<V1_2::SimSlotStatus>& slotStatus) override;
 
-    // Methods from ::android::hidl::base::V1_0::IBase follow.
+    // Methods from ::android::hardware::radio::config::V1_3::IRadioConfigResponse follow.
+    Return<void> getPhoneCapabilityResponse_1_3(
+            const RadioResponseInfo& info, const V1_3::PhoneCapability& phoneCapability) override;
 };
 
 }  // namespace implementation
diff --git a/radio/config/1.3/types.hal b/radio/config/1.3/types.hal
index 866002a..3414534 100644
--- a/radio/config/1.3/types.hal
+++ b/radio/config/1.3/types.hal
@@ -15,3 +15,181 @@
  */
 
 package android.hardware.radio.config@1.3;
+
+import android.hardware.radio@1.1::GeranBands;
+import android.hardware.radio@1.1::UtranBands;
+import android.hardware.radio@1.1::EutranBands;
+import android.hardware.radio@1.4::RadioAccessFamily;
+import android.hardware.radio@1.5::NgranBands;
+
+/** Type for the SIM slot. */
+enum SlotType : int32_t {
+    /** Slot type for UICC/pSIM (physical SIM). */
+    UICC       = 1,
+    /** Slot type for iUICC/iSIM (integrated SIM). */
+    IUICC      = 2,
+    /** Slot type for eUICC/eSIM (embedded SIM). */
+    EUICC      = 3,
+    /** Slot type for soft SIM (no physical SIM). */
+    SOFT_SIM   = 4,
+};
+
+/** A field in PhoneCapability that holds information about the SIM slot. */
+struct SimSlotCapability {
+    /** Corresponds to physicalSlotId in Radio@1.2::CardStatus. */
+    uint32_t physicalSlotId;
+
+    /** Type of slot. */
+    SlotType slotType;
+};
+
+/** Bitmask of features that can be supported by a single modem. */
+enum ModemFeatures : int32_t {
+    /** 3GPP2 capability. */
+    THREE_GPP2_REG            = 1 << 0,
+    /** 3GPP capability. */
+    THREE_GPP_REG             = 1 << 1,
+    /** CDMA 2000 with EHRPD capability. */
+    CDMA2000_EHRPD_REG        = 1 << 2,
+    /** GSM capability. */
+    GERAN_REG                 = 1 << 3,
+    /** UMTS capability. */
+    UTRAN_REG                 = 1 << 4,
+    /** LTE capability. */
+    EUTRAN_REG                = 1 << 5,
+    /** 5G capability. */
+    NGRAN_REG                 = 1 << 6,
+    /** Dual Connectivity capability. */
+    EN_DC_REG                 = 1 << 7,
+    /** VoLTE capability (IMS registered). */
+    PS_VOICE_REG              = 1 << 8,
+    /** CS voice call capability. */
+    CS_VOICE_SESSION          = 1 << 9,
+    /** Internet connection capability. */
+    INTERACTIVE_DATA_SESSION  = 1 << 10,
+    /** Dedicated bearer capability. */
+    DEDICATED_BEARER          = 1 << 11,
+    /** Network scanning capability. */
+    NETWORK_SCAN              = 1 << 12,
+    /** CDMA capability for SIM associated with modem. */
+    CSIM                      = 1 << 13,
+};
+
+struct ConcurrentModemFeatures {
+    /**
+     * A vector of concurrently supportable modem features across all modems.
+     * Each entry in the vector is a bitfield of ModemFeatures that can be used
+     * concurrently with the other ModemFeatures in that list.
+     * Each bitfield must be the full set of features for a single modem.
+     *
+     * On a Dual-SIM device, each entry will be a vector of length 2.
+     * The examples below depict the modemFeatures for four Dual-SIM setups:
+     * 1. Only one modem can PS attach (IMS registered).
+     *    {
+     *        (GERAN_REG | UTRAN_REG | EUTRAN_REG | PS_VOICE_REG |
+     *            CS_VOICE_SESSION | INTERACTIVE_DATA_SESSION | DEDICATED_BEARER),
+     *        (GERAN_REG | UTRAN_REG)
+     *    }
+     *    or
+     *    {
+     *        (GERAN_REG | UTRAN_REG | EUTRAN_REG | PS_VOICE_REG |
+     *            INTERACTIVE_DATA_SESSION),
+     *        (GERAN_REG | UTRAN_REG | CS_VOICE_SESSION)
+     *    }
+     * 2. Both modems can PS attach (dual VoLTE).
+     *    {
+     *        (GERAN_REG | UTRAN_REG | EUTRAN_REG | PS_VOICE_REG |
+     *            CS_VOICE_SESSION | INTERACTIVE_DATA_SESSION | DEDICATED_BEARER),
+     *        (GERAN_REG | UTRAN_REG | EUTRAN_REG | PS_VOICE_REG)
+     *    }
+     * 3. Both modems can maintain an Internet connection, but they share
+     *    one RF hardware.
+     *    {
+     *        (GERAN_REG | UTRAN_REG | EUTRAN_REG | PS_VOICE_REG |
+     *            CS_VOICE_SESSION | INTERACTIVE_DATA_SESSION | DEDICATED_BEARER),
+     *        (GERAN_REG | UTRAN_REG | EUTRAN_REG | PS_VOICE_REG |
+     *            INTERACTIVE_DATA_SESSION)
+     *    }
+     * 4. Both modems can maintain an Internet connection, and they have
+     *    their own RF hardware.
+     *    {
+     *        (GERAN_REG | UTRAN_REG | EUTRAN_REG | PS_VOICE_REG |
+     *            CS_VOICE_SESSION | INTERACTIVE_DATA_SESSION | DEDICATED_BEARER),
+     *        (GERAN_REG | UTRAN_REG | EUTRAN_REG | PS_VOICE_REG |
+     *            INTERACTIVE_DATA_SESSION | DEDICATED_BEARER)
+     *    }
+     */
+    vec<bitfield<ModemFeatures>> modemFeatures;
+};
+
+/**
+ * Overwritten from @1.1::PhoneCapability to add new capabilities and deprecate
+ * maxActiveData, maxActiveInternetData, isInternetLingeringSupported, logicalModemList.
+ * Replaces RadioConfig@1.1::ModemInfo and should replace Radio@1.4::RadioCapabilities
+ * in the next major version upgrade. In the future, this should be extended instead of overwritten.
+ */
+struct PhoneCapability {
+    /**
+     * 3GPP UE category for UTRAN downlink direction.
+     * 25.306 Table 5.1a
+     */
+    uint8_t utranUeCategoryDl;
+    /**
+     * 3GPP UE category for UTRAN uplink direction.
+     * 25.306 Table 5.1g
+     */
+    uint8_t utranUeCategoryUl;
+    /**
+     * 3GPP UE category for EUTRAN downlink direction.
+     * 25.306 Table 4.1a
+     */
+    uint8_t eutranUeCategoryDl;
+    /**
+     * 3GPP UE category for EUTRAN uplink direction.
+     * 25.306 Table 4.1a-2
+     */
+    uint8_t eutranUeCategoryUl;
+
+    /**
+     * Length of grace period for switching between logical modems, in milliseconds.
+     * Used only when the number of logical modems is greater than the number of
+     * Internet connections the device can support, otherwise must be 0.
+     */
+    uint64_t psDataConnectionLingerTimeMillis;
+
+    vec<GeranBands> geranBands;
+    vec<UtranBands> utranBands;
+    vec<EutranBands> eutranBands;
+    vec<NgranBands> ngranBands;
+
+    /**
+     * 32-bit bitmap of supported Radio@1.4::RadioAccessFamily types.
+     * Note that RadioAccessFamily is actually the radio access technologies, so it should be
+     * renamed in the next major version upgrade.
+     */
+    bitfield<RadioAccessFamily> supportedRats;
+
+    /**
+     * List of unique logical modem UUIDs from Radio@1.4::RadioCapabilities.
+     * A UUID is typically "com.xxxx.lmX" where X is the logical modem ID.
+     * Must be equal to the number of logical modems in the device.
+     * Radio@1.2::RadioConst::MAX_UUID_LENGTH is the max length of each UUID.
+     */
+    vec<string> logicalModemUuids;
+
+    /**
+     * List of SIM slot capabilities. The order of physical slot IDs must correspond to
+     * the order of modems in logicalModemUuids.
+     */
+    vec<SimSlotCapability> simSlotCapabilities;
+
+    /**
+     * A vector of all sets of concurrently supportable modem feature sets. The order of modems
+     * in modemFeatures must correspond to the order of modems in logicalModemUuids.
+     * Each entry in concurrentFeatureSupport is independent of others in the list
+     * and represents a set of concurrently supportable features across all modems.
+     * Each entry in ConcurrentModemFeatures::modemFeatures is a bitfield of
+     * concurrently supported ModemFeatures for one modem.
+     */
+    vec<ConcurrentModemFeatures> concurrentFeatureSupport;
+};
diff --git a/radio/config/1.3/vts/functional/radio_config_hidl_hal_api.cpp b/radio/config/1.3/vts/functional/radio_config_hidl_hal_api.cpp
index 07e9ede..7f90023 100644
--- a/radio/config/1.3/vts/functional/radio_config_hidl_hal_api.cpp
+++ b/radio/config/1.3/vts/functional/radio_config_hidl_hal_api.cpp
@@ -17,3 +17,34 @@
 #include <radio_config_hidl_hal_utils.h>
 
 #define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
+
+/*
+ * Test IRadioConfig.getPhoneCapability_1_3()
+ */
+TEST_P(RadioConfigHidlTest, getPhoneCapability_1_3) {
+    serial = GetRandomSerialNumber();
+    Return<void> res = radioConfig->getPhoneCapability_1_3(serial);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioConfigRsp->rspInfo.type);
+    EXPECT_EQ(serial, radioConfigRsp->rspInfo.serial);
+    ALOGI("getPhoneCapability_1_3, rspInfo.error = %s\n",
+          toString(radioConfigRsp->rspInfo.error).c_str());
+
+    ASSERT_TRUE(CheckAnyOfErrors(
+            radioConfigRsp->rspInfo.error,
+            {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::INTERNAL_ERR}));
+
+    if (radioConfigRsp->rspInfo.error == RadioError ::NONE) {
+        int numModems = radioConfigRsp->phoneCap_1_3.logicalModemUuids.size();
+        EXPECT_GE(numModems, 0);
+        // length of simSlotCapabilities should be equal to length of logicalModemUuids.
+        EXPECT_EQ(numModems, radioConfigRsp->phoneCap_1_3.simSlotCapabilities.size());
+        // length of modemFeatures in each ConcurrentModemFeatures should be
+        // equal to length of logicalModemUuids.
+        for (V1_3::ConcurrentModemFeatures cmf :
+             radioConfigRsp->phoneCap_1_3.concurrentFeatureSupport) {
+            EXPECT_EQ(numModems, cmf.modemFeatures.size());
+        }
+    }
+}
diff --git a/radio/config/1.3/vts/functional/radio_config_hidl_hal_test.cpp b/radio/config/1.3/vts/functional/radio_config_hidl_hal_test.cpp
index dbb4bf4..cd48b25 100644
--- a/radio/config/1.3/vts/functional/radio_config_hidl_hal_test.cpp
+++ b/radio/config/1.3/vts/functional/radio_config_hidl_hal_test.cpp
@@ -17,7 +17,7 @@
 #include <radio_config_hidl_hal_utils.h>
 
 void RadioConfigHidlTest::SetUp() {
-    radioConfig = ::android::hardware::radio::config::V1_3::IRadioConfig::getService(GetParam());
+    radioConfig = V1_3::IRadioConfig::getService(GetParam());
     ASSERT_NE(nullptr, radioConfig.get());
 
     radioConfigRsp = new (std::nothrow) RadioConfigResponse(*this);
diff --git a/radio/config/1.3/vts/functional/radio_config_hidl_hal_utils.h b/radio/config/1.3/vts/functional/radio_config_hidl_hal_utils.h
index 9b78c04..b21c7c0 100644
--- a/radio/config/1.3/vts/functional/radio_config_hidl_hal_utils.h
+++ b/radio/config/1.3/vts/functional/radio_config_hidl_hal_utils.h
@@ -28,19 +28,18 @@
 #include <gtest/gtest.h>
 #include <hidl/GtestPrinter.h>
 #include <hidl/ServiceManagement.h>
+#include <log/log.h>
 
 #include "vts_test_util.h"
 
-using namespace ::android::hardware::radio::config::V1_1;
-using namespace ::android::hardware::radio::config::V1_2;
-using namespace ::android::hardware::radio::config::V1_3;
+using namespace ::android::hardware::radio::config;
 
 using ::android::sp;
-using ::android::hardware::hidl_string;
 using ::android::hardware::hidl_vec;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
 
+using ::android::hardware::radio::V1_0::RadioIndicationType;
 using ::android::hardware::radio::V1_0::RadioResponseInfo;
 using ::android::hardware::radio::V1_0::RadioResponseType;
 
@@ -49,43 +48,46 @@
 class RadioConfigHidlTest;
 
 /* Callback class for radio config response */
-class RadioConfigResponse : public ::android::hardware::radio::config::V1_3::IRadioConfigResponse {
+class RadioConfigResponse : public V1_3::IRadioConfigResponse {
   protected:
     RadioConfigHidlTest& parent;
 
   public:
     RadioResponseInfo rspInfo;
-    PhoneCapability phoneCap;
+    V1_1::PhoneCapability phoneCap_1_1;
+    V1_3::PhoneCapability phoneCap_1_3;
 
     RadioConfigResponse(RadioConfigHidlTest& parent);
     virtual ~RadioConfigResponse() = default;
 
     /* 1.0 Api */
-    Return<void> getSimSlotsStatusResponse(
-            const RadioResponseInfo& info,
-            const hidl_vec<::android::hardware::radio::config::V1_0::SimSlotStatus>& slotStatus);
+    Return<void> getSimSlotsStatusResponse(const RadioResponseInfo& info,
+                                           const hidl_vec<V1_0::SimSlotStatus>& slotStatus);
 
     Return<void> setSimSlotsMappingResponse(const RadioResponseInfo& info);
 
     /* 1.1 Api */
     Return<void> getPhoneCapabilityResponse(const RadioResponseInfo& info,
-                                            const PhoneCapability& phoneCapability);
+                                            const V1_1::PhoneCapability& phoneCapability);
 
     Return<void> setPreferredDataModemResponse(const RadioResponseInfo& info);
 
     Return<void> getModemsConfigResponse(const RadioResponseInfo& info,
-                                         const ModemsConfig& mConfig);
+                                         const V1_1::ModemsConfig& mConfig);
 
     Return<void> setModemsConfigResponse(const RadioResponseInfo& info);
 
     /* 1.2 Api */
     Return<void> getSimSlotsStatusResponse_1_2(const RadioResponseInfo& info,
-                                               const hidl_vec<SimSlotStatus>& slotStatus);
+                                               const hidl_vec<V1_2::SimSlotStatus>& slotStatus);
+
+    /* 1.3 Api */
+    Return<void> getPhoneCapabilityResponse_1_3(const RadioResponseInfo& info,
+                                                const V1_3::PhoneCapability& phoneCapability);
 };
 
 /* Callback class for radio config indication */
-class RadioConfigIndication
-    : public ::android::hardware::radio::config::V1_3::IRadioConfigIndication {
+class RadioConfigIndication : public V1_3::IRadioConfigIndication {
   protected:
     RadioConfigHidlTest& parent;
 
@@ -94,9 +96,8 @@
     virtual ~RadioConfigIndication() = default;
 
     /* 1.2 Api */
-    Return<void> simSlotsStatusChanged_1_2(
-            ::android::hardware::radio::V1_0::RadioIndicationType type,
-            const hidl_vec<SimSlotStatus>& slotStatus);
+    Return<void> simSlotsStatusChanged_1_2(RadioIndicationType type,
+                                           const hidl_vec<V1_2::SimSlotStatus>& slotStatus);
 };
 
 // The main test class for Radio config HIDL.
@@ -121,7 +122,7 @@
     int serial;
 
     /* radio config service handle */
-    sp<::android::hardware::radio::config::V1_3::IRadioConfig> radioConfig;
+    sp<V1_3::IRadioConfig> radioConfig;
 
     /* radio config response handle */
     sp<RadioConfigResponse> radioConfigRsp;
diff --git a/radio/config/1.3/vts/functional/radio_config_response.cpp b/radio/config/1.3/vts/functional/radio_config_response.cpp
index 1ca960e..22098d3 100644
--- a/radio/config/1.3/vts/functional/radio_config_response.cpp
+++ b/radio/config/1.3/vts/functional/radio_config_response.cpp
@@ -16,17 +16,18 @@
 
 #include <radio_config_hidl_hal_utils.h>
 
-using ::android::hardware::radio::V1_0::RadioResponseInfo;
+using namespace ::android::hardware::radio::config;
 
-// SimSlotStatus slotStatus;
+using ::android::hardware::hidl_vec;
+
+using ::android::hardware::radio::V1_0::RadioResponseInfo;
 
 RadioConfigResponse::RadioConfigResponse(RadioConfigHidlTest& parent) : parent(parent) {}
 
 /* 1.0 Apis */
 Return<void> RadioConfigResponse::getSimSlotsStatusResponse(
         const RadioResponseInfo& /* info */,
-        const ::android::hardware::hidl_vec<
-                ::android::hardware::radio::config::V1_0::SimSlotStatus>& /* slotStatus */) {
+        const hidl_vec<V1_0::SimSlotStatus>& /* slotStatus */) {
     return Void();
 }
 
@@ -36,9 +37,9 @@
 
 /* 1.1 Apis */
 Return<void> RadioConfigResponse::getPhoneCapabilityResponse(
-        const RadioResponseInfo& info, const PhoneCapability& phoneCapability) {
+        const RadioResponseInfo& info, const V1_1::PhoneCapability& phoneCapability) {
     rspInfo = info;
-    phoneCap = phoneCapability;
+    phoneCap_1_1 = phoneCapability;
     parent.notify(info.serial);
     return Void();
 }
@@ -49,7 +50,7 @@
 }
 
 Return<void> RadioConfigResponse::getModemsConfigResponse(const RadioResponseInfo& /* info */,
-                                                          const ModemsConfig& /* mConfig */) {
+                                                          const V1_1::ModemsConfig& /* mConfig */) {
     return Void();
 }
 
@@ -60,6 +61,15 @@
 /* 1.2 Apis */
 Return<void> RadioConfigResponse::getSimSlotsStatusResponse_1_2(
         const RadioResponseInfo& /* info */,
-        const ::android::hardware::hidl_vec<SimSlotStatus>& /* slotStatus */) {
+        const hidl_vec<V1_2::SimSlotStatus>& /* slotStatus */) {
     return Void();
-}
\ No newline at end of file
+}
+
+/* 1.3 Apis */
+Return<void> RadioConfigResponse::getPhoneCapabilityResponse_1_3(
+        const RadioResponseInfo& info, const V1_3::PhoneCapability& phoneCapability) {
+    rspInfo = info;
+    phoneCap_1_3 = phoneCapability;
+    parent.notify(info.serial);
+    return Void();
+}