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();
+}