Merge "Fix the conditions for the tests based on comments on ag/15968818. Check EXPECT_TRUE with status ok and Error none for valid display. and EXPECT_FALSE with status ok. If service exists then we can proceed with test otherwise tests will be skipped."
diff --git a/audio/common/6.0/Android.bp b/audio/common/6.0/Android.bp
index fc54caf..91721fc 100644
--- a/audio/common/6.0/Android.bp
+++ b/audio/common/6.0/Android.bp
@@ -20,4 +20,8 @@
],
gen_java: true,
gen_java_constants: true,
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.car.framework",
+ ],
}
diff --git a/authsecret/1.0/vts/functional/OWNERS b/authsecret/1.0/vts/functional/OWNERS
new file mode 100644
index 0000000..ec8c304
--- /dev/null
+++ b/authsecret/1.0/vts/functional/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 186411
+chengyouho@google.com
+frankwoo@google.com
diff --git a/automotive/audiocontrol/1.0/Android.bp b/automotive/audiocontrol/1.0/Android.bp
index 628793b..53ed78b 100644
--- a/automotive/audiocontrol/1.0/Android.bp
+++ b/automotive/audiocontrol/1.0/Android.bp
@@ -20,4 +20,8 @@
"android.hidl.base@1.0",
],
gen_java: true,
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.car.framework",
+ ],
}
diff --git a/automotive/audiocontrol/1.0/vts/functional/OWNERS b/automotive/audiocontrol/1.0/vts/functional/OWNERS
new file mode 100644
index 0000000..fb422db
--- /dev/null
+++ b/automotive/audiocontrol/1.0/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 162915
+zhaomingyin@google.com
diff --git a/automotive/audiocontrol/2.0/Android.bp b/automotive/audiocontrol/2.0/Android.bp
index 4d1fdbc..413cf48 100644
--- a/automotive/audiocontrol/2.0/Android.bp
+++ b/automotive/audiocontrol/2.0/Android.bp
@@ -24,4 +24,8 @@
"android.hidl.safe_union@1.0",
],
gen_java: true,
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.car.framework",
+ ],
}
diff --git a/automotive/audiocontrol/2.0/vts/functional/OWNERS b/automotive/audiocontrol/2.0/vts/functional/OWNERS
new file mode 100644
index 0000000..fb422db
--- /dev/null
+++ b/automotive/audiocontrol/2.0/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 162915
+zhaomingyin@google.com
diff --git a/automotive/evs/common/utils/default/test/fuzz/FormatConvertFuzzer.cpp b/automotive/evs/common/utils/default/test/fuzz/FormatConvertFuzzer.cpp
index 583a455..58423c8 100644
--- a/automotive/evs/common/utils/default/test/fuzz/FormatConvertFuzzer.cpp
+++ b/automotive/evs/common/utils/default/test/fuzz/FormatConvertFuzzer.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <fuzzer/FuzzedDataProvider.h>
#include <cmath>
#include <cstdlib>
#include <cstring>
@@ -21,36 +22,43 @@
#include "FormatConvert.h"
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, std::size_t size) {
- if (size < 256) {
+ // 1 random value (4bytes) + min imagesize = 16*2 times bytes per pixel (worse case 2)
+ if (size < (4 + 16 * 2 * 2)) {
return 0;
}
+ FuzzedDataProvider fdp(data, size);
+ std::size_t image_pixel_size = size - 4;
+ image_pixel_size = (image_pixel_size & INT_MAX) / 2;
- std::srand(std::time(nullptr)); // use current time as seed for random generator
- int random_variable = std::rand() % 10;
- int width = (int)sqrt(size);
- int height = width * ((float)random_variable / 10.0);
+ // API have a requirement that width must be divied by 16 except yuyvtorgb
+ int min_height = 2;
+ int max_height = (image_pixel_size / 16) & ~(1); // must be even number
+ int height = fdp.ConsumeIntegralInRange<uint32_t>(min_height, max_height);
+ int width = (image_pixel_size / height) & ~(16); // must be divisible by 16
- uint8_t* src = (uint8_t*)malloc(sizeof(uint8_t) * size);
- memcpy(src, data, sizeof(uint8_t) * (size));
- uint32_t* tgt = (uint32_t*)malloc(sizeof(uint32_t) * size);
+ uint8_t* src = (uint8_t*)(data + 4);
+ uint32_t* tgt = (uint32_t*)malloc(sizeof(uint32_t) * image_pixel_size);
#ifdef COPY_NV21_TO_RGB32
- android::hardware::automotive::evs::common::Utils::copyNV21toRGB32(width, height, src, tgt, 0);
+ android::hardware::automotive::evs::common::Utils::copyNV21toRGB32(width, height, src, tgt,
+ width);
#elif COPY_NV21_TO_BGR32
- android::hardware::automotive::evs::common::Utils::copyNV21toBGR32(width, height, src, tgt, 0);
+ android::hardware::automotive::evs::common::Utils::copyNV21toBGR32(width, height, src, tgt,
+ width);
#elif COPY_YV12_TO_RGB32
- android::hardware::automotive::evs::common::Utils::copyYV12toRGB32(width, height, src, tgt, 0);
+ android::hardware::automotive::evs::common::Utils::copyYV12toRGB32(width, height, src, tgt,
+ width);
#elif COPY_YV12_TO_BGR32
- android::hardware::automotive::evs::common::Utils::copyYV12toBGR32(width, height, src, tgt, 0);
+ android::hardware::automotive::evs::common::Utils::copyYV12toBGR32(width, height, src, tgt,
+ width);
#elif COPY_YUYV_TO_RGB32
- android::hardware::automotive::evs::common::Utils::copyYUYVtoRGB32(width, height, src, 0, tgt,
- 0);
+ android::hardware::automotive::evs::common::Utils::copyYUYVtoRGB32(width, height, src, width,
+ tgt, width);
#elif COPY_YUYV_TO_BGR32
- android::hardware::automotive::evs::common::Utils::copyYUYVtoBGR32(width, height, src, 0, tgt,
- 0);
+ android::hardware::automotive::evs::common::Utils::copyYUYVtoBGR32(width, height, src, width,
+ tgt, width);
#endif
- free(src);
free(tgt);
return 0;
diff --git a/automotive/sv/1.0/vts/functional/OWNERS b/automotive/sv/1.0/vts/functional/OWNERS
new file mode 100644
index 0000000..2ba00a3
--- /dev/null
+++ b/automotive/sv/1.0/vts/functional/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 821659
+tanmayp@google.com
+ankitarora@google.com
diff --git a/automotive/vehicle/2.0/Android.bp b/automotive/vehicle/2.0/Android.bp
index e2164b1..5c2e0ea 100644
--- a/automotive/vehicle/2.0/Android.bp
+++ b/automotive/vehicle/2.0/Android.bp
@@ -21,4 +21,8 @@
"android.hidl.base@1.0",
],
gen_java: true,
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.car.framework",
+ ],
}
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index e025d1e..cfbbbd3 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -1036,7 +1036,7 @@
.access = VehiclePropertyAccess::READ,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
},
- .initialValue = {.int32Values = {0 /* ClusterHome */, -1 /* ClusterNone */}},
+ .initialValue = {.int32Values = {0 /* ClusterHome */}},
},
{
.config =
diff --git a/automotive/vehicle/2.0/vts/functional/OWNERS b/automotive/vehicle/2.0/vts/functional/OWNERS
new file mode 100644
index 0000000..8a0f2af
--- /dev/null
+++ b/automotive/vehicle/2.0/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 533426
+kwangsudo@google.com
diff --git a/automotive/vehicle/aidl/impl/Android.bp b/automotive/vehicle/aidl/impl/Android.bp
index a97d544..94f590d 100644
--- a/automotive/vehicle/aidl/impl/Android.bp
+++ b/automotive/vehicle/aidl/impl/Android.bp
@@ -21,7 +21,8 @@
cc_defaults {
name: "VehicleHalDefaults",
static_libs: [
- "android.hardware.automotive.vehicle-V1-ndk_platform",
+ "android.hardware.automotive.vehicle-V1-ndk",
+ "libmath",
],
shared_libs: [
"libbase",
diff --git a/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h b/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h
index ebcb77a..12a5691 100644
--- a/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h
+++ b/automotive/vehicle/aidl/impl/default_config/include/DefaultConfig.h
@@ -1052,7 +1052,7 @@
.access = VehiclePropertyAccess::READ,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
},
- .initialValue = {.int32Values = {0 /* ClusterHome */, -1 /* ClusterNone */}},
+ .initialValue = {.int32Values = {0 /* ClusterHome */}},
},
{
.config =
diff --git a/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/Android.bp b/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/Android.bp
index 2b0b11f..7670c25 100644
--- a/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/Android.bp
+++ b/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/Android.bp
@@ -14,6 +14,15 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
cc_library {
name: "VehicleHalProtoMessageConverter",
srcs: [
diff --git a/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/test/proto_message_converter_test.cpp b/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/test/proto_message_converter_test.cpp
index d5f2373..c742db5 100644
--- a/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/test/proto_message_converter_test.cpp
+++ b/automotive/vehicle/aidl/impl/grpc/utils/proto_message_converter/test/proto_message_converter_test.cpp
@@ -45,7 +45,7 @@
std::vector<aidl_vehicle::VehiclePropValue> prepareTestValues() {
std::vector<aidl_vehicle::VehiclePropValue> values;
- long timestamp = 1;
+ int64_t timestamp = 1;
for (auto& property : defaultconfig::getDefaultConfigs()) {
values.push_back({
.timestamp = timestamp,
diff --git a/automotive/vehicle/aidl/impl/hardware/include/IVehicleHardware.h b/automotive/vehicle/aidl/impl/hardware/include/IVehicleHardware.h
index 981088a..58531b9 100644
--- a/automotive/vehicle/aidl/impl/hardware/include/IVehicleHardware.h
+++ b/automotive/vehicle/aidl/impl/hardware/include/IVehicleHardware.h
@@ -39,7 +39,7 @@
// A request type for 'setValues' or 'getValues' method.
struct VehiclePropValueRequest {
// A unique request ID set by the sender.
- int requestId;
+ int64_t requestId;
// The property to get/set.
::aidl::android::hardware::automotive::vehicle::VehiclePropValue value;
};
diff --git a/automotive/vehicle/aidl/impl/proto/Android.bp b/automotive/vehicle/aidl/impl/proto/Android.bp
index 80966df..709307d 100644
--- a/automotive/vehicle/aidl/impl/proto/Android.bp
+++ b/automotive/vehicle/aidl/impl/proto/Android.bp
@@ -14,6 +14,15 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
filegroup {
name: "VehicleHalProtoFiles",
srcs: ["**/*.proto"],
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehicleObjectPool.h b/automotive/vehicle/aidl/impl/utils/common/include/VehicleObjectPool.h
new file mode 100644
index 0000000..61e475a
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/utils/common/include/VehicleObjectPool.h
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef android_hardware_automotive_vehicle_utils_include_VehicleObjectPool_H_
+#define android_hardware_automotive_vehicle_utils_include_VehicleObjectPool_H_
+
+#include <deque>
+#include <map>
+#include <memory>
+#include <mutex>
+
+#include <VehicleHalTypes.h>
+
+#include <android-base/thread_annotations.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+// Handy metric mostly for unit tests and debug.
+#define INC_METRIC_IF_DEBUG(val) PoolStats::instance()->val++;
+
+struct PoolStats {
+ std::atomic<uint32_t> Obtained{0};
+ std::atomic<uint32_t> Created{0};
+ std::atomic<uint32_t> Recycled{0};
+ std::atomic<uint32_t> Deleted{0};
+
+ static PoolStats* instance() {
+ static PoolStats inst;
+ return &inst;
+ }
+};
+
+template <typename T>
+struct Deleter {
+ using OnDeleteFunc = std::function<void(T*)>;
+
+ explicit Deleter(const OnDeleteFunc& f) : mOnDelete(f){};
+
+ Deleter() = default;
+ Deleter(const Deleter&) = default;
+
+ void operator()(T* o) { mOnDelete(o); }
+
+ private:
+ OnDeleteFunc mOnDelete;
+};
+
+// This is std::unique_ptr<> with custom delete operation that typically moves the pointer it holds
+// back to ObjectPool.
+template <typename T>
+using recyclable_ptr = typename std::unique_ptr<T, Deleter<T>>;
+
+// Generic abstract object pool class. Users of this class must implement {@Code createObject}.
+//
+// This class is thread-safe. Concurrent calls to {@Code obtain} from multiple threads is OK, also
+// client can obtain an object in one thread and then move ownership to another thread.
+template <typename T>
+class ObjectPool {
+ public:
+ using GetSizeFunc = std::function<size_t(const T&)>;
+
+ ObjectPool(size_t maxPoolObjectsSize, GetSizeFunc getSizeFunc)
+ : mMaxPoolObjectsSize(maxPoolObjectsSize), mGetSizeFunc(getSizeFunc){};
+ virtual ~ObjectPool() = default;
+
+ virtual recyclable_ptr<T> obtain() {
+ std::lock_guard<std::mutex> lock(mLock);
+ INC_METRIC_IF_DEBUG(Obtained)
+ if (mObjects.empty()) {
+ INC_METRIC_IF_DEBUG(Created)
+ return wrap(createObject());
+ }
+
+ auto o = wrap(mObjects.front().release());
+ mObjects.pop_front();
+ mPoolObjectsSize -= mGetSizeFunc(*o);
+ return o;
+ }
+
+ ObjectPool& operator=(const ObjectPool&) = delete;
+ ObjectPool(const ObjectPool&) = delete;
+
+ protected:
+ virtual T* createObject() = 0;
+
+ virtual void recycle(T* o) {
+ std::lock_guard<std::mutex> lock(mLock);
+ size_t objectSize = mGetSizeFunc(*o);
+
+ if (objectSize > mMaxPoolObjectsSize ||
+ mPoolObjectsSize > mMaxPoolObjectsSize - objectSize) {
+ INC_METRIC_IF_DEBUG(Deleted)
+
+ // We have no space left in the pool.
+ delete o;
+ return;
+ }
+
+ INC_METRIC_IF_DEBUG(Recycled)
+
+ mObjects.push_back(std::unique_ptr<T>{o});
+ mPoolObjectsSize += objectSize;
+ }
+
+ const size_t mMaxPoolObjectsSize;
+
+ private:
+ const Deleter<T>& getDeleter() {
+ if (!mDeleter.get()) {
+ Deleter<T>* d =
+ new Deleter<T>(std::bind(&ObjectPool::recycle, this, std::placeholders::_1));
+ mDeleter.reset(d);
+ }
+ return *mDeleter.get();
+ }
+
+ recyclable_ptr<T> wrap(T* raw) { return recyclable_ptr<T>{raw, getDeleter()}; }
+
+ mutable std::mutex mLock;
+ std::deque<std::unique_ptr<T>> mObjects GUARDED_BY(mLock);
+ std::unique_ptr<Deleter<T>> mDeleter;
+ size_t mPoolObjectsSize GUARDED_BY(mLock);
+ GetSizeFunc mGetSizeFunc;
+};
+
+#undef INC_METRIC_IF_DEBUG
+
+// This class provides a pool of recyclable VehiclePropertyValue objects.
+//
+// It has only one overloaded public method - obtain(...), users must call this method when new
+// object is needed with given VehiclePropertyType and vector size (for vector properties). This
+// method returns a recyclable smart pointer to VehiclePropertyValue, essentially this is a
+// std::unique_ptr with custom delete function, so recyclable object has only one owner and
+// developers can safely pass it around. Once this object goes out of scope, it will be returned to
+// the object pool.
+//
+// Some objects are not recyclable: strings and vector data types with vector
+// length > maxRecyclableVectorSize (provided in the constructor). These objects will be deleted
+// immediately once the go out of scope. There's no synchronization penalty for these objects since
+// we do not store them in the pool.
+//
+// This class is thread-safe. Users can obtain an object in one thread and pass it to another.
+//
+// Sample usage:
+//
+// VehiclePropValuePool pool;
+// auto v = pool.obtain(VehiclePropertyType::INT32);
+// v->propId = VehicleProperty::HVAC_FAN_SPEED;
+// v->areaId = VehicleAreaSeat::ROW_1_LEFT;
+// v->timestamp = elapsedRealtimeNano();
+// v->value->int32Values[0] = 42;
+class VehiclePropValuePool {
+ public:
+ using RecyclableType =
+ recyclable_ptr<::aidl::android::hardware::automotive::vehicle::VehiclePropValue>;
+
+ // Creates VehiclePropValuePool
+ //
+ // @param maxRecyclableVectorSize - vector value types (e.g. VehiclePropertyType::INT32_VEC)
+ // with size equal or less to this value will be stored in the pool. If users tries to obtain
+ // value with vector size greater than maxRecyclableVectorSize, user will receive a regular
+ // unique pointer instead of a recyclable pointer. The object would not be recycled once it
+ // goes out of scope, but would be deleted.
+ // @param maxPoolObjectsSize - The approximate upper bound of memory each internal recycling
+ // pool could take. We have 4 different type pools, each with 4 different vector size, so
+ // approximately this pool would at-most take 4 * 4 * 10240 = 160k memory.
+ VehiclePropValuePool(size_t maxRecyclableVectorSize = 4, size_t maxPoolObjectsSize = 10240)
+ : mMaxRecyclableVectorSize(maxRecyclableVectorSize),
+ mMaxPoolObjectsSize(maxPoolObjectsSize){};
+
+ // Obtain a recyclable VehiclePropertyValue object from the pool for the given type. If the
+ // given type is not MIXED or STRING, the internal value vector size would be set to 1.
+ // If the given type is MIXED or STRING, all the internal vector sizes would be initialized to
+ // 0.
+ RecyclableType obtain(::aidl::android::hardware::automotive::vehicle::VehiclePropertyType type);
+
+ // Obtain a recyclable VehiclePropertyValue object from the pool for the given type. If the
+ // given type is *_VEC or BYTES, the internal value vector size would be set to vectorSize. If
+ // the given type is BOOLEAN, INT32, FLOAT, or INT64, the internal value vector size would be
+ // set to 1. If the given type is MIXED or STRING, all the internal value vector sizes would be
+ // set to 0. vectorSize must be larger than 0.
+ RecyclableType obtain(::aidl::android::hardware::automotive::vehicle::VehiclePropertyType type,
+ size_t vectorSize);
+ // Obtain a recyclable VehicePropertyValue object that is a copy of src. If src does not contain
+ // any value or the src property type is not valid, this function would return an empty
+ // VehiclePropValue.
+ RecyclableType obtain(
+ const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& src);
+ // Obtain a recyclable boolean object.
+ RecyclableType obtainBoolean(bool value);
+ // Obtain a recyclable int32 object.
+ RecyclableType obtainInt32(int32_t value);
+ // Obtain a recyclable int64 object.
+ RecyclableType obtainInt64(int64_t value);
+ // Obtain a recyclable float object.
+ RecyclableType obtainFloat(float value);
+ // Obtain a recyclable float object.
+ RecyclableType obtainString(const char* cstr);
+ // Obtain a recyclable mixed object.
+ RecyclableType obtainComplex();
+
+ VehiclePropValuePool(VehiclePropValuePool&) = delete;
+ VehiclePropValuePool& operator=(VehiclePropValuePool&) = delete;
+
+ private:
+ static inline bool isSingleValueType(
+ ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType type) {
+ return type == ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::
+ BOOLEAN ||
+ type == ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT32 ||
+ type == ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT64 ||
+ type == ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::FLOAT;
+ }
+
+ static inline bool isComplexType(
+ ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType type) {
+ return type == ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::MIXED ||
+ type == ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::STRING;
+ }
+
+ bool isDisposable(::aidl::android::hardware::automotive::vehicle::VehiclePropertyType type,
+ size_t vectorSize) const {
+ return vectorSize > mMaxRecyclableVectorSize || isComplexType(type);
+ }
+
+ RecyclableType obtainDisposable(
+ ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType valueType,
+ size_t vectorSize) const;
+ RecyclableType obtainRecyclable(
+ ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType type,
+ size_t vectorSize);
+
+ class InternalPool
+ : public ObjectPool<::aidl::android::hardware::automotive::vehicle::VehiclePropValue> {
+ public:
+ InternalPool(::aidl::android::hardware::automotive::vehicle::VehiclePropertyType type,
+ size_t vectorSize, size_t maxPoolObjectsSize,
+ ObjectPool::GetSizeFunc getSizeFunc)
+ : ObjectPool(maxPoolObjectsSize, getSizeFunc),
+ mPropType(type),
+ mVectorSize(vectorSize) {}
+
+ protected:
+ ::aidl::android::hardware::automotive::vehicle::VehiclePropValue* createObject() override;
+ void recycle(::aidl::android::hardware::automotive::vehicle::VehiclePropValue* o) override;
+
+ private:
+ bool check(::aidl::android::hardware::automotive::vehicle::RawPropValues* v);
+
+ template <typename VecType>
+ bool check(std::vector<VecType>* vec, bool isVectorType) {
+ return vec->size() == (isVectorType ? mVectorSize : 0);
+ }
+
+ private:
+ ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType mPropType;
+ size_t mVectorSize;
+ };
+ const Deleter<::aidl::android::hardware::automotive::vehicle::VehiclePropValue>
+ mDisposableDeleter{
+ [](::aidl::android::hardware::automotive::vehicle::VehiclePropValue* v) {
+ delete v;
+ }};
+
+ mutable std::mutex mLock;
+ const size_t mMaxRecyclableVectorSize;
+ const size_t mMaxPoolObjectsSize;
+ // A map with 'property_type' | 'value_vector_size' as key and a recyclable object pool as
+ // value. We would create a recyclable pool for each property type and vector size combination.
+ std::map<int32_t, std::unique_ptr<InternalPool>> mValueTypePools GUARDED_BY(mLock);
+};
+
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
+
+#endif // android_hardware_automotive_vehicle_utils_include_VehicleObjectPool_H_
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehiclePropertyStore.h b/automotive/vehicle/aidl/impl/utils/common/include/VehiclePropertyStore.h
index b19ab84..ababf5e 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/VehiclePropertyStore.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/VehiclePropertyStore.h
@@ -24,6 +24,7 @@
#include <unordered_map>
#include <VehicleHalTypes.h>
+#include <VehicleObjectPool.h>
#include <android-base/result.h>
#include <android-base/thread_annotations.h>
@@ -41,6 +42,9 @@
// This class is thread-safe, however it uses blocking synchronization across all methods.
class VehiclePropertyStore {
public:
+ explicit VehiclePropertyStore(std::shared_ptr<VehiclePropValuePool> valuePool)
+ : mValuePool(valuePool) {}
+
// Function that used to calculate unique token for given VehiclePropValue.
using TokenFunction = ::std::function<int64_t(
const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& value)>;
@@ -53,10 +57,13 @@
const ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig& config,
TokenFunction tokenFunc = nullptr);
- // Stores provided value. Returns true if value was written returns false if config wasn't
- // registered.
- ::android::base::Result<void> writeValue(
- const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue);
+ // Stores provided value. Returns error if config wasn't registered. If 'updateStatus' is
+ // true, the 'status' in 'propValue' would be stored. Otherwise, if this is a new value,
+ // 'status' would be initialized to {@code VehiclePropertyStatus::AVAILABLE}, if this is to
+ // override an existing value, the status for the existing value would be used for the
+ // overridden value.
+ ::android::base::Result<void> writeValue(VehiclePropValuePool::RecyclableType propValue,
+ bool updateStatus = false);
// Remove a given property value from the property store. The 'propValue' would be used to
// generate the key for the value to remove.
@@ -67,24 +74,19 @@
void removeValuesForProperty(int32_t propId);
// Read all the stored values.
- std::vector<::aidl::android::hardware::automotive::vehicle::VehiclePropValue> readAllValues()
- const;
+ std::vector<VehiclePropValuePool::RecyclableType> readAllValues() const;
// Read all the values for the property.
- ::android::base::Result<
- std::vector<::aidl::android::hardware::automotive::vehicle::VehiclePropValue>>
+ ::android::base::Result<std::vector<VehiclePropValuePool::RecyclableType>>
readValuesForProperty(int32_t propId) const;
// Read the value for the requested property.
- ::android::base::Result<
- std::unique_ptr<::aidl::android::hardware::automotive::vehicle::VehiclePropValue>>
- readValue(
+ ::android::base::Result<VehiclePropValuePool::RecyclableType> readValue(
const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& request) const;
// Read the value for the requested property.
- ::android::base::Result<
- std::unique_ptr<::aidl::android::hardware::automotive::vehicle::VehiclePropValue>>
- readValue(int32_t prop, int32_t area = 0, int64_t token = 0) const;
+ ::android::base::Result<VehiclePropValuePool::RecyclableType> readValue(
+ int32_t prop, int32_t area = 0, int64_t token = 0) const;
// Get all property configs.
std::vector<::aidl::android::hardware::automotive::vehicle::VehiclePropConfig> getAllConfigs()
@@ -100,20 +102,25 @@
int32_t area;
int64_t token;
- bool operator==(const RecordId& other) const;
- bool operator<(const RecordId& other) const;
-
std::string toString() const;
+
+ bool operator==(const RecordId& other) const;
+ };
+
+ struct RecordIdHash {
+ size_t operator()(RecordId const& recordId) const;
};
struct Record {
::aidl::android::hardware::automotive::vehicle::VehiclePropConfig propConfig;
TokenFunction tokenFunction;
- std::map<RecordId, ::aidl::android::hardware::automotive::vehicle::VehiclePropValue> values;
+ std::unordered_map<RecordId, VehiclePropValuePool::RecyclableType, RecordIdHash> values;
};
mutable std::mutex mLock;
std::unordered_map<int32_t, Record> mRecordsByPropId GUARDED_BY(mLock);
+ // {@code VehiclePropValuePool} is thread-safe.
+ std::shared_ptr<VehiclePropValuePool> mValuePool;
const Record* getRecordLocked(int32_t propId) const;
@@ -123,9 +130,8 @@
const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& propValue,
const Record& record) const;
- ::android::base::Result<
- std::unique_ptr<::aidl::android::hardware::automotive::vehicle::VehiclePropValue>>
- readValueLocked(const RecordId& recId, const Record& record) const;
+ ::android::base::Result<VehiclePropValuePool::RecyclableType> readValueLocked(
+ const RecordId& recId, const Record& record) const;
};
} // namespace vehicle
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h b/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
index c4bf1d3..b02aaf7 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h
@@ -18,6 +18,7 @@
#define android_hardware_automotive_vehicle_aidl_impl_utils_common_include_VehicleUtils_H_
#include <VehicleHalTypes.h>
+#include <utils/Log.h>
namespace android {
namespace hardware {
@@ -81,6 +82,104 @@
return nullptr;
}
+inline std::unique_ptr<::aidl::android::hardware::automotive::vehicle::VehiclePropValue>
+createVehiclePropValueVec(::aidl::android::hardware::automotive::vehicle::VehiclePropertyType type,
+ size_t vecSize) {
+ auto val = std::unique_ptr<::aidl::android::hardware::automotive::vehicle::VehiclePropValue>(
+ new ::aidl::android::hardware::automotive::vehicle::VehiclePropValue);
+ switch (type) {
+ case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT32:
+ [[fallthrough]];
+ case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::BOOLEAN:
+ vecSize = 1;
+ [[fallthrough]];
+ case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT32_VEC:
+ val->value.int32Values.resize(vecSize);
+ break;
+ case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::FLOAT:
+ vecSize = 1;
+ [[fallthrough]];
+ case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::FLOAT_VEC:
+ val->value.floatValues.resize(vecSize);
+ break;
+ case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT64:
+ vecSize = 1;
+ [[fallthrough]];
+ case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT64_VEC:
+ val->value.int64Values.resize(vecSize);
+ break;
+ case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::BYTES:
+ val->value.byteValues.resize(vecSize);
+ break;
+ case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::STRING:
+ case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::MIXED:
+ break; // Valid, but nothing to do.
+ default:
+ ALOGE("createVehiclePropValue: unknown type: %d", toInt(type));
+ val.reset(nullptr);
+ }
+ return val;
+}
+
+inline std::unique_ptr<::aidl::android::hardware::automotive::vehicle::VehiclePropValue>
+createVehiclePropValue(::aidl::android::hardware::automotive::vehicle::VehiclePropertyType type) {
+ return createVehiclePropValueVec(type, 1);
+}
+
+inline size_t getVehicleRawValueVectorSize(
+ const ::aidl::android::hardware::automotive::vehicle::RawPropValues& value,
+ ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType type) {
+ switch (type) {
+ case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT32: // fall
+ // through
+ case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::
+ BOOLEAN: // fall through
+ return std::min(value.int32Values.size(), static_cast<size_t>(1));
+ case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::FLOAT:
+ return std::min(value.floatValues.size(), static_cast<size_t>(1));
+ case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT64:
+ return std::min(value.int64Values.size(), static_cast<size_t>(1));
+ case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT32_VEC:
+ return value.int32Values.size();
+ case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::FLOAT_VEC:
+ return value.floatValues.size();
+ case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::INT64_VEC:
+ return value.int64Values.size();
+ case ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType::BYTES:
+ return value.byteValues.size();
+ default:
+ ALOGE("getVehicleRawValueVectorSize: unknown type: %d", toInt(type));
+ return 0;
+ }
+}
+
+inline void copyVehicleRawValue(
+ ::aidl::android::hardware::automotive::vehicle::RawPropValues* dest,
+ const ::aidl::android::hardware::automotive::vehicle::RawPropValues& src) {
+ dest->int32Values = src.int32Values;
+ dest->floatValues = src.floatValues;
+ dest->int64Values = src.int64Values;
+ dest->byteValues = src.byteValues;
+ dest->stringValue = src.stringValue;
+}
+
+// getVehiclePropValueSize returns approximately how much memory 'value' would take. This should
+// only be used in a limited-size memory pool to set an upper bound for memory consumption.
+inline size_t getVehiclePropValueSize(
+ const ::aidl::android::hardware::automotive::vehicle::VehiclePropValue& prop) {
+ size_t size = 0;
+ size += sizeof(prop.timestamp);
+ size += sizeof(prop.areaId);
+ size += sizeof(prop.prop);
+ size += sizeof(prop.status);
+ size += prop.value.int32Values.size() * sizeof(int32_t);
+ size += prop.value.int64Values.size() * sizeof(int64_t);
+ size += prop.value.floatValues.size() * sizeof(float);
+ size += prop.value.byteValues.size() * sizeof(uint8_t);
+ size += prop.value.stringValue.size();
+ return size;
+}
+
} // namespace vehicle
} // namespace automotive
} // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/utils/common/src/VehicleObjectPool.cpp b/automotive/vehicle/aidl/impl/utils/common/src/VehicleObjectPool.cpp
new file mode 100644
index 0000000..0ff58f7
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/utils/common/src/VehicleObjectPool.cpp
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "VehicleObjectPool"
+
+#include <VehicleObjectPool.h>
+
+#include <VehicleUtils.h>
+
+#include <assert.h>
+#include <utils/Log.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+using ::aidl::android::hardware::automotive::vehicle::RawPropValues;
+using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtain(VehiclePropertyType type) {
+ if (isComplexType(type)) {
+ return obtain(type, 0);
+ }
+ return obtain(type, 1);
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtain(VehiclePropertyType type,
+ size_t vectorSize) {
+ if (isSingleValueType(type)) {
+ vectorSize = 1;
+ } else if (isComplexType(type)) {
+ vectorSize = 0;
+ }
+ return isDisposable(type, vectorSize) ? obtainDisposable(type, vectorSize)
+ : obtainRecyclable(type, vectorSize);
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtain(const VehiclePropValue& src) {
+ VehiclePropertyType type = getPropType(src.prop);
+ size_t vectorSize = getVehicleRawValueVectorSize(src.value, type);
+ if (vectorSize == 0 && !isComplexType(type)) {
+ ALOGW("empty vehicle prop value, contains no content");
+ // Return any empty VehiclePropValue.
+ return RecyclableType{new VehiclePropValue, mDisposableDeleter};
+ }
+
+ auto dest = obtain(type, vectorSize);
+
+ dest->prop = src.prop;
+ dest->areaId = src.areaId;
+ dest->status = src.status;
+ dest->timestamp = src.timestamp;
+ copyVehicleRawValue(&dest->value, src.value);
+
+ return dest;
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainInt32(int32_t value) {
+ auto val = obtain(VehiclePropertyType::INT32);
+ val->value.int32Values[0] = value;
+ return val;
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainInt64(int64_t value) {
+ auto val = obtain(VehiclePropertyType::INT64);
+ val->value.int64Values[0] = value;
+ return val;
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainFloat(float value) {
+ auto val = obtain(VehiclePropertyType::FLOAT);
+ val->value.floatValues[0] = value;
+ return val;
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainString(const char* cstr) {
+ auto val = obtain(VehiclePropertyType::STRING);
+ val->value.stringValue = cstr;
+ return val;
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainComplex() {
+ return obtain(VehiclePropertyType::MIXED);
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainRecyclable(
+ VehiclePropertyType type, size_t vectorSize) {
+ std::lock_guard<std::mutex> lock(mLock);
+ assert(vectorSize > 0);
+
+ // VehiclePropertyType is not overlapping with vectorSize.
+ int32_t key = static_cast<int32_t>(type) | static_cast<int32_t>(vectorSize);
+ auto it = mValueTypePools.find(key);
+
+ if (it == mValueTypePools.end()) {
+ auto newPool(std::make_unique<InternalPool>(type, vectorSize, mMaxPoolObjectsSize,
+ getVehiclePropValueSize));
+ it = mValueTypePools.emplace(key, std::move(newPool)).first;
+ }
+ return it->second->obtain();
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainBoolean(bool value) {
+ return obtainInt32(value);
+}
+
+VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainDisposable(
+ VehiclePropertyType valueType, size_t vectorSize) const {
+ return RecyclableType{createVehiclePropValueVec(valueType, vectorSize).release(),
+ mDisposableDeleter};
+}
+
+void VehiclePropValuePool::InternalPool::recycle(VehiclePropValue* o) {
+ if (o == nullptr) {
+ ALOGE("Attempt to recycle nullptr");
+ return;
+ }
+
+ if (!check(&o->value)) {
+ ALOGE("Discarding value for prop 0x%x because it contains "
+ "data that is not consistent with this pool. "
+ "Expected type: %d, vector size: %zu",
+ o->prop, toInt(mPropType), mVectorSize);
+ delete o;
+ } else {
+ ObjectPool<VehiclePropValue>::recycle(o);
+ }
+}
+
+bool VehiclePropValuePool::InternalPool::check(RawPropValues* v) {
+ return check(&v->int32Values, (VehiclePropertyType::INT32 == mPropType ||
+ VehiclePropertyType::INT32_VEC == mPropType ||
+ VehiclePropertyType::BOOLEAN == mPropType)) &&
+ check(&v->floatValues, (VehiclePropertyType::FLOAT == mPropType ||
+ VehiclePropertyType::FLOAT_VEC == mPropType)) &&
+ check(&v->int64Values, (VehiclePropertyType::INT64 == mPropType ||
+ VehiclePropertyType::INT64_VEC == mPropType)) &&
+ check(&v->byteValues, VehiclePropertyType::BYTES == mPropType) &&
+ v->stringValue.size() == 0;
+}
+
+VehiclePropValue* VehiclePropValuePool::InternalPool::createObject() {
+ return createVehiclePropValueVec(mPropType, mVectorSize).release();
+}
+
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp b/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp
index b660f36..2869d1d 100644
--- a/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/src/VehiclePropertyStore.cpp
@@ -21,6 +21,7 @@
#include <VehicleUtils.h>
#include <android-base/format.h>
+#include <math/HashCombine.h>
namespace android {
namespace hardware {
@@ -29,6 +30,7 @@
using ::aidl::android::hardware::automotive::vehicle::VehicleAreaConfig;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
using ::android::base::Result;
@@ -36,14 +38,17 @@
return area == other.area && token == other.token;
}
-bool VehiclePropertyStore::RecordId::operator<(const VehiclePropertyStore::RecordId& other) const {
- return area < other.area || (area == other.area && token < other.token);
-}
-
std::string VehiclePropertyStore::RecordId::toString() const {
return ::fmt::format("RecordID{{.areaId={:d}, .token={:d}}}", area, token);
}
+size_t VehiclePropertyStore::RecordIdHash::operator()(RecordId const& recordId) const {
+ size_t res = 0;
+ hashCombine(res, recordId.area);
+ hashCombine(res, recordId.token);
+ return res;
+}
+
const VehiclePropertyStore::Record* VehiclePropertyStore::getRecordLocked(int32_t propId) const
REQUIRES(mLock) {
auto RecordIt = mRecordsByPropId.find(propId);
@@ -68,13 +73,13 @@
return recId;
}
-Result<std::unique_ptr<VehiclePropValue>> VehiclePropertyStore::readValueLocked(
+Result<VehiclePropValuePool::RecyclableType> VehiclePropertyStore::readValueLocked(
const RecordId& recId, const Record& record) const REQUIRES(mLock) {
auto it = record.values.find(recId);
if (it == record.values.end()) {
return Errorf("Record ID: {} is not found", recId.toString());
}
- return std::make_unique<VehiclePropValue>(it->second);
+ return mValuePool->obtain(*(it->second));
}
void VehiclePropertyStore::registerProperty(const VehiclePropConfig& config,
@@ -87,36 +92,42 @@
};
}
-Result<void> VehiclePropertyStore::writeValue(const VehiclePropValue& propValue) {
+Result<void> VehiclePropertyStore::writeValue(VehiclePropValuePool::RecyclableType propValue,
+ bool updateStatus) {
std::lock_guard<std::mutex> g(mLock);
- VehiclePropertyStore::Record* record = getRecordLocked(propValue.prop);
+ VehiclePropertyStore::Record* record = getRecordLocked(propValue->prop);
if (record == nullptr) {
- return Errorf("property: {:d} not registered", propValue.prop);
+ return Errorf("property: {:d} not registered", propValue->prop);
}
- if (!isGlobalProp(propValue.prop) && getAreaConfig(propValue, record->propConfig) == nullptr) {
- return Errorf("no config for property: {:d} area: {:d}", propValue.prop, propValue.areaId);
+ if (!isGlobalProp(propValue->prop) &&
+ getAreaConfig(*propValue, record->propConfig) == nullptr) {
+ return Errorf("no config for property: {:d} area: {:d}", propValue->prop,
+ propValue->areaId);
}
- VehiclePropertyStore::RecordId recId = getRecordIdLocked(propValue, *record);
+ VehiclePropertyStore::RecordId recId = getRecordIdLocked(*propValue, *record);
auto it = record->values.find(recId);
if (it == record->values.end()) {
- record->values[recId] = propValue;
+ record->values[recId] = std::move(propValue);
+ if (!updateStatus) {
+ record->values[recId]->status = VehiclePropertyStatus::AVAILABLE;
+ }
return {};
}
- VehiclePropValue* valueToUpdate = &(it->second);
-
+ const VehiclePropValue* valueToUpdate = it->second.get();
+ long oldTimestamp = valueToUpdate->timestamp;
+ VehiclePropertyStatus oldStatus = valueToUpdate->status;
// propValue is outdated and drops it.
- if (valueToUpdate->timestamp > propValue.timestamp) {
- return Errorf("outdated timestamp: {:d}", propValue.timestamp);
+ if (oldTimestamp > propValue->timestamp) {
+ return Errorf("outdated timestamp: {:d}", propValue->timestamp);
}
- // Update the propertyValue.
- // The timestamp in propertyStore should only be updated by the server side. It indicates
- // the time when the event is generated by the server.
- valueToUpdate->timestamp = propValue.timestamp;
- valueToUpdate->value = propValue.value;
- valueToUpdate->status = propValue.status;
+ record->values[recId] = std::move(propValue);
+ if (!updateStatus) {
+ record->values[recId]->status = oldStatus;
+ }
+
return {};
}
@@ -145,25 +156,25 @@
record->values.clear();
}
-std::vector<VehiclePropValue> VehiclePropertyStore::readAllValues() const {
+std::vector<VehiclePropValuePool::RecyclableType> VehiclePropertyStore::readAllValues() const {
std::lock_guard<std::mutex> g(mLock);
- std::vector<VehiclePropValue> allValues;
+ std::vector<VehiclePropValuePool::RecyclableType> allValues;
for (auto const& [_, record] : mRecordsByPropId) {
for (auto const& [_, value] : record.values) {
- allValues.push_back(value);
+ allValues.push_back(std::move(mValuePool->obtain(*value)));
}
}
return allValues;
}
-Result<std::vector<VehiclePropValue>> VehiclePropertyStore::readValuesForProperty(
- int32_t propId) const {
+Result<std::vector<VehiclePropValuePool::RecyclableType>>
+VehiclePropertyStore::readValuesForProperty(int32_t propId) const {
std::lock_guard<std::mutex> g(mLock);
- std::vector<VehiclePropValue> values;
+ std::vector<VehiclePropValuePool::RecyclableType> values;
const VehiclePropertyStore::Record* record = getRecordLocked(propId);
if (record == nullptr) {
@@ -171,12 +182,12 @@
}
for (auto const& [_, value] : record->values) {
- values.push_back(value);
+ values.push_back(std::move(mValuePool->obtain(*value)));
}
return values;
}
-Result<std::unique_ptr<VehiclePropValue>> VehiclePropertyStore::readValue(
+Result<VehiclePropValuePool::RecyclableType> VehiclePropertyStore::readValue(
const VehiclePropValue& propValue) const {
std::lock_guard<std::mutex> g(mLock);
@@ -189,9 +200,9 @@
return readValueLocked(recId, *record);
}
-Result<std::unique_ptr<VehiclePropValue>> VehiclePropertyStore::readValue(int32_t propId,
- int32_t areaId,
- int64_t token) const {
+Result<VehiclePropValuePool::RecyclableType> VehiclePropertyStore::readValue(int32_t propId,
+ int32_t areaId,
+ int64_t token) const {
std::lock_guard<std::mutex> g(mLock);
const VehiclePropertyStore::Record* record = getRecordLocked(propId);
diff --git a/automotive/vehicle/aidl/impl/utils/common/test/VehicleObjectPoolTest.cpp b/automotive/vehicle/aidl/impl/utils/common/test/VehicleObjectPoolTest.cpp
new file mode 100644
index 0000000..a62532c
--- /dev/null
+++ b/automotive/vehicle/aidl/impl/utils/common/test/VehicleObjectPoolTest.cpp
@@ -0,0 +1,381 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <thread>
+
+#include <gtest/gtest.h>
+
+#include <utils/SystemClock.h>
+
+#include <VehicleHalTypes.h>
+#include <VehicleObjectPool.h>
+#include <VehicleUtils.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+
+namespace {
+
+using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+
+struct TestPropertyTypeInfo {
+ VehiclePropertyType type;
+ bool recyclable;
+ size_t vecSize;
+};
+
+std::vector<TestPropertyTypeInfo> getAllPropertyTypes() {
+ return {
+ {
+ .type = VehiclePropertyType::INT32,
+ .recyclable = true,
+ .vecSize = 1,
+ },
+ {
+ .type = VehiclePropertyType::INT64,
+ .recyclable = true,
+ .vecSize = 1,
+ },
+ {
+ .type = VehiclePropertyType::FLOAT,
+ .recyclable = true,
+ .vecSize = 1,
+ },
+ {
+ .type = VehiclePropertyType::INT32_VEC,
+ .recyclable = true,
+ .vecSize = 4,
+ },
+ {
+ .type = VehiclePropertyType::INT64_VEC,
+ .recyclable = true,
+ .vecSize = 4,
+ },
+ {
+ .type = VehiclePropertyType::FLOAT_VEC,
+ .recyclable = true,
+ .vecSize = 4,
+ },
+ {
+ .type = VehiclePropertyType::BYTES,
+ .recyclable = true,
+ .vecSize = 4,
+ },
+ {
+ .type = VehiclePropertyType::INT32_VEC,
+ .recyclable = false,
+ .vecSize = 5,
+ },
+ {
+ .type = VehiclePropertyType::INT64_VEC,
+ .recyclable = false,
+ .vecSize = 5,
+ },
+ {
+ .type = VehiclePropertyType::FLOAT_VEC,
+ .recyclable = false,
+ .vecSize = 5,
+ },
+ {
+ .type = VehiclePropertyType::BYTES,
+ .recyclable = false,
+ .vecSize = 5,
+ },
+ {
+ .type = VehiclePropertyType::STRING,
+ .recyclable = false,
+ .vecSize = 0,
+ },
+ {
+ .type = VehiclePropertyType::MIXED,
+ .recyclable = false,
+ .vecSize = 0,
+ },
+ };
+}
+
+} // namespace
+
+class VehicleObjectPoolTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ mStats = PoolStats::instance();
+ resetStats();
+ mValuePool.reset(new VehiclePropValuePool);
+ }
+
+ void TearDown() override {
+ // At the end, all created objects should be either recycled or deleted.
+ ASSERT_EQ(mStats->Obtained, mStats->Recycled + mStats->Deleted);
+ // Some objects could be recycled multiple times.
+ ASSERT_LE(mStats->Created, mStats->Recycled + mStats->Deleted);
+ }
+
+ PoolStats* mStats;
+ std::unique_ptr<VehiclePropValuePool> mValuePool;
+
+ private:
+ void resetStats() {
+ mStats->Obtained = 0;
+ mStats->Created = 0;
+ mStats->Recycled = 0;
+ mStats->Deleted = 0;
+ }
+};
+
+class VehiclePropertyTypesTest : public VehicleObjectPoolTest,
+ public testing::WithParamInterface<TestPropertyTypeInfo> {};
+
+TEST_P(VehiclePropertyTypesTest, testRecycle) {
+ auto info = GetParam();
+ if (!info.recyclable) {
+ GTEST_SKIP();
+ }
+
+ auto value = mValuePool->obtain(info.type, info.vecSize);
+ void* raw = value.get();
+ value.reset();
+ // At this point, value should be recycled and the only object in the pool.
+ ASSERT_EQ(mValuePool->obtain(info.type, info.vecSize).get(), raw);
+
+ ASSERT_EQ(mStats->Obtained, 2u);
+ ASSERT_EQ(mStats->Created, 1u);
+}
+
+TEST_P(VehiclePropertyTypesTest, testNotRecyclable) {
+ auto info = GetParam();
+ if (info.recyclable) {
+ GTEST_SKIP();
+ }
+
+ auto value = mValuePool->obtain(info.type, info.vecSize);
+
+ ASSERT_EQ(mStats->Obtained, 0u) << "Non recyclable object should not be obtained from the pool";
+ ASSERT_EQ(mStats->Created, 0u) << "Non recyclable object should not be created from the pool";
+}
+
+INSTANTIATE_TEST_SUITE_P(AllPropertyTypes, VehiclePropertyTypesTest,
+ ::testing::ValuesIn(getAllPropertyTypes()));
+
+TEST_F(VehicleObjectPoolTest, testObtainNewObject) {
+ auto value = mValuePool->obtain(VehiclePropertyType::INT32);
+ void* raw = value.get();
+ value.reset();
+ // At this point, value should be recycled and the only object in the pool.
+ ASSERT_EQ(mValuePool->obtain(VehiclePropertyType::INT32).get(), raw);
+ // Obtaining value of another type - should return a new object
+ ASSERT_NE(mValuePool->obtain(VehiclePropertyType::FLOAT).get(), raw);
+
+ ASSERT_EQ(mStats->Obtained, 3u);
+ ASSERT_EQ(mStats->Created, 2u);
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainStrings) {
+ mValuePool->obtain(VehiclePropertyType::STRING);
+ auto stringProp = mValuePool->obtain(VehiclePropertyType::STRING);
+ stringProp->value.stringValue = "Hello";
+ void* raw = stringProp.get();
+ stringProp.reset(); // delete the pointer
+
+ auto newStringProp = mValuePool->obtain(VehiclePropertyType::STRING);
+
+ ASSERT_EQ(newStringProp->value.stringValue.size(), 0u);
+ ASSERT_NE(mValuePool->obtain(VehiclePropertyType::STRING).get(), raw);
+ ASSERT_EQ(mStats->Obtained, 0u);
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainBoolean) {
+ auto prop = mValuePool->obtainBoolean(true);
+
+ ASSERT_NE(prop, nullptr);
+ ASSERT_EQ(*prop, (VehiclePropValue{
+ .value = {.int32Values = {1}},
+ }));
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainInt32) {
+ auto prop = mValuePool->obtainInt32(1234);
+
+ ASSERT_NE(prop, nullptr);
+ ASSERT_EQ(*prop, (VehiclePropValue{
+ .value = {.int32Values = {1234}},
+ }));
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainInt64) {
+ auto prop = mValuePool->obtainInt64(1234);
+
+ ASSERT_NE(prop, nullptr);
+ ASSERT_EQ(*prop, (VehiclePropValue{
+ .value = {.int64Values = {1234}},
+ }));
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainFloat) {
+ auto prop = mValuePool->obtainFloat(1.234);
+
+ ASSERT_NE(prop, nullptr);
+ ASSERT_EQ(*prop, (VehiclePropValue{
+ .value = {.floatValues = {1.234}},
+ }));
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainString) {
+ auto prop = mValuePool->obtainString("test");
+
+ ASSERT_NE(prop, nullptr);
+ ASSERT_EQ(*prop, (VehiclePropValue{
+ .value = {.stringValue = "test"},
+ }));
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainComplex) {
+ auto prop = mValuePool->obtainComplex();
+
+ ASSERT_NE(prop, nullptr);
+ ASSERT_EQ(*prop, VehiclePropValue{});
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainCopyInt32Values) {
+ VehiclePropValue prop{
+ // INT32_VEC property.
+ .prop = toInt(VehicleProperty::INFO_FUEL_TYPE),
+ .areaId = 2,
+ .timestamp = 3,
+ .value = {.int32Values = {1, 2, 3, 4}},
+ };
+ auto gotValue = mValuePool->obtain(prop);
+
+ ASSERT_NE(gotValue, nullptr);
+ ASSERT_EQ(*gotValue, prop);
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainCopyInt64Values) {
+ VehiclePropValue prop{
+ // INT64_VEC property.
+ .prop = toInt(VehicleProperty::WHEEL_TICK),
+ .areaId = 2,
+ .timestamp = 3,
+ .value = {.int64Values = {1, 2, 3, 4}},
+ };
+ auto gotValue = mValuePool->obtain(prop);
+
+ ASSERT_NE(gotValue, nullptr);
+ ASSERT_EQ(*gotValue, prop);
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainCopyFloatValues) {
+ VehiclePropValue prop{
+ // FLOAT_VEC property.
+ .prop = toInt(VehicleProperty::HVAC_TEMPERATURE_VALUE_SUGGESTION),
+ .areaId = 2,
+ .timestamp = 3,
+ .value = {.floatValues = {1, 2, 3, 4}},
+ };
+ auto gotValue = mValuePool->obtain(prop);
+
+ ASSERT_NE(gotValue, nullptr);
+ ASSERT_EQ(*gotValue, prop);
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainCopyString) {
+ VehiclePropValue prop{
+ // STRING property.
+ .prop = toInt(VehicleProperty::INFO_VIN),
+ .areaId = 2,
+ .timestamp = 3,
+ .value = {.stringValue = "test"},
+ };
+ auto gotValue = mValuePool->obtain(prop);
+
+ ASSERT_NE(gotValue, nullptr);
+ ASSERT_EQ(*gotValue, prop);
+}
+
+TEST_F(VehicleObjectPoolTest, testObtainCopyMixed) {
+ VehiclePropValue prop{
+ // MIxed property.
+ .prop = toInt(VehicleProperty::VEHICLE_MAP_SERVICE),
+ .areaId = 2,
+ .timestamp = 3,
+ .value =
+ {
+ .int32Values = {1, 2, 3},
+ .floatValues = {4.0, 5.0},
+ .stringValue = "test",
+ },
+ };
+ auto gotValue = mValuePool->obtain(prop);
+
+ ASSERT_NE(gotValue, nullptr);
+ ASSERT_EQ(*gotValue, prop);
+}
+
+TEST_F(VehicleObjectPoolTest, testMultithreaded) {
+ // In this test we have T threads that concurrently in C cycles
+ // obtain and release O VehiclePropValue objects of FLOAT / INT32 types.
+
+ const int T = 2;
+ const int C = 500;
+ const int O = 100;
+
+ auto poolPtr = mValuePool.get();
+
+ std::vector<std::thread> threads;
+ for (int i = 0; i < T; i++) {
+ threads.push_back(std::thread([&poolPtr]() {
+ for (int j = 0; j < C; j++) {
+ std::vector<recyclable_ptr<VehiclePropValue>> vec;
+ for (int k = 0; k < O; k++) {
+ vec.push_back(poolPtr->obtain(k % 2 == 0 ? VehiclePropertyType::FLOAT
+ : VehiclePropertyType::INT32));
+ }
+ }
+ }));
+ }
+
+ for (auto& t : threads) {
+ t.join();
+ }
+
+ ASSERT_EQ(mStats->Obtained, static_cast<uint32_t>(T * C * O));
+ ASSERT_EQ(mStats->Recycled + mStats->Deleted, static_cast<uint32_t>(T * C * O));
+ // Created less than obtained in one cycle.
+ ASSERT_LE(mStats->Created, static_cast<uint32_t>(T * O));
+}
+
+TEST_F(VehicleObjectPoolTest, testMemoryLimitation) {
+ std::vector<recyclable_ptr<VehiclePropValue>> vec;
+ for (size_t i = 0; i < 10000; i++) {
+ vec.push_back(mValuePool->obtain(VehiclePropertyType::INT32));
+ }
+ // We have too many values, not all of them would be recycled, some of them will be deleted.
+ vec.clear();
+
+ ASSERT_EQ(mStats->Obtained, 10000u);
+ ASSERT_EQ(mStats->Created, 10000u);
+ ASSERT_GT(mStats->Deleted, 0u) << "expect some values to be deleted, not recycled if too many "
+ "values are in the pool";
+}
+
+} // namespace vehicle
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/vehicle/aidl/impl/utils/common/test/VehiclePropertyStoreTest.cpp b/automotive/vehicle/aidl/impl/utils/common/test/VehiclePropertyStoreTest.cpp
index 8c70fea..f1d218d 100644
--- a/automotive/vehicle/aidl/impl/utils/common/test/VehiclePropertyStoreTest.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/test/VehiclePropertyStoreTest.cpp
@@ -32,6 +32,8 @@
using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyChangeMode;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyStatus;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
using ::android::base::Result;
using ::testing::ElementsAre;
@@ -51,6 +53,17 @@
return value.timestamp;
}
+// A helper function to turn value pointer to value structure for easier comparison.
+std::vector<VehiclePropValue> convertValuePtrsToValues(
+ const std::vector<VehiclePropValuePool::RecyclableType>& values) {
+ std::vector<VehiclePropValue> returnValues;
+ returnValues.reserve(values.size());
+ for (auto& value : values) {
+ returnValues.push_back(*value);
+ }
+ return returnValues;
+}
+
} // namespace
class VehiclePropertyStoreTest : public ::testing::Test {
@@ -70,30 +83,33 @@
VehicleAreaConfig{.areaId = WHEEL_REAR_LEFT},
VehicleAreaConfig{.areaId = WHEEL_REAR_RIGHT}},
};
- mStore.registerProperty(mConfigFuelCapacity);
- mStore.registerProperty(configTirePressure);
+ mValuePool = std::make_shared<VehiclePropValuePool>();
+ mStore.reset(new VehiclePropertyStore(mValuePool));
+ mStore->registerProperty(mConfigFuelCapacity);
+ mStore->registerProperty(configTirePressure);
}
- VehiclePropertyStore mStore;
VehiclePropConfig mConfigFuelCapacity;
+ std::shared_ptr<VehiclePropValuePool> mValuePool;
+ std::unique_ptr<VehiclePropertyStore> mStore;
};
TEST_F(VehiclePropertyStoreTest, testGetAllConfigs) {
- std::vector<VehiclePropConfig> configs = mStore.getAllConfigs();
+ std::vector<VehiclePropConfig> configs = mStore->getAllConfigs();
ASSERT_EQ(configs.size(), static_cast<size_t>(2));
}
TEST_F(VehiclePropertyStoreTest, testGetConfig) {
Result<const VehiclePropConfig*> result =
- mStore.getConfig(toInt(VehicleProperty::INFO_FUEL_CAPACITY));
+ mStore->getConfig(toInt(VehicleProperty::INFO_FUEL_CAPACITY));
ASSERT_RESULT_OK(result);
ASSERT_EQ(*(result.value()), mConfigFuelCapacity);
}
TEST_F(VehiclePropertyStoreTest, testGetConfigWithInvalidPropId) {
- Result<const VehiclePropConfig*> result = mStore.getConfig(INVALID_PROP_ID);
+ Result<const VehiclePropConfig*> result = mStore->getConfig(INVALID_PROP_ID);
ASSERT_FALSE(result.ok()) << "expect error when getting a config for an invalid property ID";
}
@@ -122,46 +138,47 @@
TEST_F(VehiclePropertyStoreTest, testWriteValueOk) {
auto values = getTestPropValues();
- ASSERT_RESULT_OK(mStore.writeValue(values[0]));
+ ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(values[0])));
}
TEST_F(VehiclePropertyStoreTest, testReadAllValues) {
auto values = getTestPropValues();
for (const auto& value : values) {
- ASSERT_RESULT_OK(mStore.writeValue(value));
+ ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(value)));
}
- auto gotValues = mStore.readAllValues();
+ auto gotValues = mStore->readAllValues();
- ASSERT_THAT(gotValues, WhenSortedBy(propValueCmp, Eq(values)));
+ ASSERT_THAT(convertValuePtrsToValues(gotValues), WhenSortedBy(propValueCmp, Eq(values)));
}
TEST_F(VehiclePropertyStoreTest, testReadValuesForPropertyOneValue) {
auto values = getTestPropValues();
for (const auto& value : values) {
- ASSERT_RESULT_OK(mStore.writeValue(value));
+ ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(value)));
}
- auto result = mStore.readValuesForProperty(toInt(VehicleProperty::INFO_FUEL_CAPACITY));
+ auto result = mStore->readValuesForProperty(toInt(VehicleProperty::INFO_FUEL_CAPACITY));
ASSERT_RESULT_OK(result);
- ASSERT_THAT(result.value(), ElementsAre(values[0]));
+ ASSERT_THAT(convertValuePtrsToValues(result.value()), ElementsAre(values[0]));
}
TEST_F(VehiclePropertyStoreTest, testReadValuesForPropertyMultipleValues) {
auto values = getTestPropValues();
for (const auto& value : values) {
- ASSERT_RESULT_OK(mStore.writeValue(value));
+ ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(value)));
}
- auto result = mStore.readValuesForProperty(toInt(VehicleProperty::TIRE_PRESSURE));
+ auto result = mStore->readValuesForProperty(toInt(VehicleProperty::TIRE_PRESSURE));
ASSERT_RESULT_OK(result);
- ASSERT_THAT(result.value(), WhenSortedBy(propValueCmp, ElementsAre(values[1], values[2])));
+ ASSERT_THAT(convertValuePtrsToValues(result.value()),
+ WhenSortedBy(propValueCmp, ElementsAre(values[1], values[2])));
}
TEST_F(VehiclePropertyStoreTest, testReadValuesForPropertyError) {
- auto result = mStore.readValuesForProperty(INVALID_PROP_ID);
+ auto result = mStore->readValuesForProperty(INVALID_PROP_ID);
ASSERT_FALSE(result.ok()) << "expect error when reading values for an invalid property";
}
@@ -169,7 +186,7 @@
TEST_F(VehiclePropertyStoreTest, testReadValueOk) {
auto values = getTestPropValues();
for (const auto& value : values) {
- ASSERT_RESULT_OK(mStore.writeValue(value));
+ ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(value)));
}
VehiclePropValue requestValue = {
@@ -177,7 +194,7 @@
.areaId = WHEEL_FRONT_LEFT,
};
- auto result = mStore.readValue(requestValue);
+ auto result = mStore->readValue(requestValue);
ASSERT_RESULT_OK(result);
ASSERT_EQ(*(result.value()), values[1]);
@@ -186,10 +203,10 @@
TEST_F(VehiclePropertyStoreTest, testReadValueByPropIdOk) {
auto values = getTestPropValues();
for (const auto& value : values) {
- ASSERT_RESULT_OK(mStore.writeValue(value));
+ ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(value)));
}
- auto result = mStore.readValue(toInt(VehicleProperty::TIRE_PRESSURE), WHEEL_FRONT_RIGHT);
+ auto result = mStore->readValue(toInt(VehicleProperty::TIRE_PRESSURE), WHEEL_FRONT_RIGHT);
ASSERT_EQ(*(result.value()), values[2]);
}
@@ -197,50 +214,47 @@
TEST_F(VehiclePropertyStoreTest, testReadValueError) {
auto values = getTestPropValues();
for (const auto& value : values) {
- ASSERT_RESULT_OK(mStore.writeValue(value));
+ ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(value)));
}
- auto result = mStore.readValue(toInt(VehicleProperty::TIRE_PRESSURE), WHEEL_REAR_LEFT);
+ auto result = mStore->readValue(toInt(VehicleProperty::TIRE_PRESSURE), WHEEL_REAR_LEFT);
ASSERT_FALSE(result.ok()) << "expect error when reading a value that has not been written";
}
TEST_F(VehiclePropertyStoreTest, testWriteValueError) {
- ASSERT_FALSE(mStore.writeValue({
- .prop = INVALID_PROP_ID,
- .value = {.floatValues = {1.0}},
- })
- .ok())
+ auto v = mValuePool->obtain(VehiclePropertyType::FLOAT);
+ v->prop = INVALID_PROP_ID;
+ v->value.floatValues = {1.0};
+ ASSERT_FALSE(mStore->writeValue(std::move(v)).ok())
<< "expect error when writing value for an invalid property ID";
}
TEST_F(VehiclePropertyStoreTest, testWriteValueNoAreaConfig) {
- ASSERT_FALSE(mStore.writeValue({
- .prop = toInt(VehicleProperty::TIRE_PRESSURE),
- .value = {.floatValues = {180.0}},
- // There is no config for ALL_WHEELS.
- .areaId = ALL_WHEELS,
- })
- .ok())
+ auto v = mValuePool->obtain(VehiclePropertyType::FLOAT);
+ v->prop = toInt(VehicleProperty::TIRE_PRESSURE);
+ v->value.floatValues = {1.0};
+ // There is no config for ALL_WHEELS.
+ v->areaId = ALL_WHEELS;
+ ASSERT_FALSE(mStore->writeValue(std::move(v)).ok())
<< "expect error when writing value for an area without config";
}
TEST_F(VehiclePropertyStoreTest, testWriteOutdatedValue) {
- ASSERT_RESULT_OK(mStore.writeValue({
- .timestamp = 1,
- .prop = toInt(VehicleProperty::TIRE_PRESSURE),
- .value = {.floatValues = {180.0}},
- .areaId = WHEEL_FRONT_LEFT,
- }));
+ auto v = mValuePool->obtain(VehiclePropertyType::FLOAT);
+ v->timestamp = 1;
+ v->prop = toInt(VehicleProperty::TIRE_PRESSURE);
+ v->value.floatValues = {180.0};
+ v->areaId = WHEEL_FRONT_LEFT;
+ ASSERT_RESULT_OK(mStore->writeValue(std::move(v)));
// Write an older value.
- ASSERT_FALSE(mStore.writeValue({
- .timestamp = 0,
- .prop = toInt(VehicleProperty::TIRE_PRESSURE),
- .value = {.floatValues = {180.0}},
- .areaId = WHEEL_FRONT_LEFT,
- })
- .ok())
+ auto v2 = mValuePool->obtain(VehiclePropertyType::FLOAT);
+ v2->timestamp = 0;
+ v2->prop = toInt(VehicleProperty::TIRE_PRESSURE);
+ v2->value.floatValues = {180.0};
+ v2->areaId = WHEEL_FRONT_LEFT;
+ ASSERT_FALSE(mStore->writeValue(std::move(v2)).ok())
<< "expect error when writing an outdated value";
}
@@ -251,7 +265,7 @@
};
// Replace existing config.
- mStore.registerProperty(config, timestampToken);
+ mStore->registerProperty(config, timestampToken);
VehiclePropValue fuelCapacityValueToken1 = {
.timestamp = 1,
@@ -265,15 +279,15 @@
.value = {.floatValues = {2.0}},
};
- ASSERT_RESULT_OK(mStore.writeValue(fuelCapacityValueToken1));
- ASSERT_RESULT_OK(mStore.writeValue(fuelCapacityValueToken2));
+ ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacityValueToken1)));
+ ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacityValueToken2)));
- auto result = mStore.readValuesForProperty(propId);
+ auto result = mStore->readValuesForProperty(propId);
ASSERT_RESULT_OK(result);
ASSERT_EQ(result.value().size(), static_cast<size_t>(2));
- auto tokenResult = mStore.readValue(propId, /*areaId=*/0, /*token=*/2);
+ auto tokenResult = mStore->readValue(propId, /*areaId=*/0, /*token=*/2);
ASSERT_RESULT_OK(tokenResult);
ASSERT_EQ(*(tokenResult.value()), fuelCapacityValueToken2);
@@ -282,14 +296,14 @@
TEST_F(VehiclePropertyStoreTest, testRemoveValue) {
auto values = getTestPropValues();
for (const auto& value : values) {
- ASSERT_RESULT_OK(mStore.writeValue(value));
+ ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(value)));
}
- mStore.removeValue(values[0]);
+ mStore->removeValue(values[0]);
- ASSERT_FALSE(mStore.readValue(values[0]).ok()) << "expect error when reading a removed value";
+ ASSERT_FALSE(mStore->readValue(values[0]).ok()) << "expect error when reading a removed value";
- auto leftTirePressureResult = mStore.readValue(values[1]);
+ auto leftTirePressureResult = mStore->readValue(values[1]);
ASSERT_RESULT_OK(leftTirePressureResult);
ASSERT_EQ(*(leftTirePressureResult.value()), values[1]);
@@ -298,16 +312,76 @@
TEST_F(VehiclePropertyStoreTest, testRemoveValuesForProperty) {
auto values = getTestPropValues();
for (const auto& value : values) {
- ASSERT_RESULT_OK(mStore.writeValue(value));
+ ASSERT_RESULT_OK(mStore->writeValue(std::move(mValuePool->obtain(value))));
}
- mStore.removeValuesForProperty(toInt(VehicleProperty::INFO_FUEL_CAPACITY));
- mStore.removeValuesForProperty(toInt(VehicleProperty::TIRE_PRESSURE));
+ mStore->removeValuesForProperty(toInt(VehicleProperty::INFO_FUEL_CAPACITY));
+ mStore->removeValuesForProperty(toInt(VehicleProperty::TIRE_PRESSURE));
- auto gotValues = mStore.readAllValues();
+ auto gotValues = mStore->readAllValues();
ASSERT_TRUE(gotValues.empty());
}
+TEST_F(VehiclePropertyStoreTest, testWriteValueUpdateStatus) {
+ VehiclePropValue fuelCapacity = {
+ .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
+ .value = {.floatValues = {1.0}},
+ };
+ ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity), true));
+
+ fuelCapacity.status = VehiclePropertyStatus::UNAVAILABLE;
+
+ ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity), true));
+
+ VehiclePropValue requestValue = {
+ .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
+ };
+
+ auto result = mStore->readValue(requestValue);
+
+ ASSERT_RESULT_OK(result);
+ ASSERT_EQ(result.value()->status, VehiclePropertyStatus::UNAVAILABLE);
+}
+
+TEST_F(VehiclePropertyStoreTest, testWriteValueNoUpdateStatus) {
+ VehiclePropValue fuelCapacity = {
+ .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
+ .value = {.floatValues = {1.0}},
+ };
+ ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity), true));
+
+ fuelCapacity.status = VehiclePropertyStatus::UNAVAILABLE;
+
+ ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity), false));
+
+ VehiclePropValue requestValue = {
+ .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
+ };
+
+ auto result = mStore->readValue(requestValue);
+
+ ASSERT_RESULT_OK(result);
+ ASSERT_EQ(result.value()->status, VehiclePropertyStatus::AVAILABLE);
+}
+
+TEST_F(VehiclePropertyStoreTest, testWriteValueNoUpdateStatusForNewValue) {
+ VehiclePropValue fuelCapacity = {
+ .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
+ .value = {.floatValues = {1.0}},
+ .status = VehiclePropertyStatus::UNAVAILABLE,
+ };
+ ASSERT_RESULT_OK(mStore->writeValue(mValuePool->obtain(fuelCapacity), false));
+
+ VehiclePropValue requestValue = {
+ .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
+ };
+
+ auto result = mStore->readValue(requestValue);
+
+ ASSERT_RESULT_OK(result);
+ ASSERT_EQ(result.value()->status, VehiclePropertyStatus::AVAILABLE);
+}
+
} // namespace vehicle
} // namespace automotive
} // namespace hardware
diff --git a/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp b/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp
index c09b06d..7ad3d31 100644
--- a/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp
+++ b/automotive/vehicle/aidl/impl/utils/common/test/VehicleUtilsTest.cpp
@@ -16,7 +16,9 @@
#include <PropertyUtils.h>
#include <VehicleUtils.h>
+
#include <gtest/gtest.h>
+#include <vector>
namespace android {
namespace hardware {
@@ -122,6 +124,129 @@
ASSERT_EQ(gotConfig, nullptr);
}
+TEST(VehicleUtilsTest, testCreateVehiclePropValueInt32) {
+ std::unique_ptr<VehiclePropValue> value = createVehiclePropValue(VehiclePropertyType::INT32);
+
+ ASSERT_NE(value, nullptr);
+ ASSERT_EQ(1u, value->value.int32Values.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueInt32Vec) {
+ std::unique_ptr<VehiclePropValue> value =
+ createVehiclePropValue(VehiclePropertyType::INT32_VEC);
+
+ ASSERT_NE(value, nullptr);
+ ASSERT_EQ(1u, value->value.int32Values.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueInt64) {
+ std::unique_ptr<VehiclePropValue> value = createVehiclePropValue(VehiclePropertyType::INT64);
+
+ ASSERT_NE(value, nullptr);
+ ASSERT_EQ(1u, value->value.int64Values.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueInt64Vec) {
+ std::unique_ptr<VehiclePropValue> value =
+ createVehiclePropValue(VehiclePropertyType::INT64_VEC);
+
+ ASSERT_NE(value, nullptr);
+ ASSERT_EQ(1u, value->value.int64Values.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueFloat) {
+ std::unique_ptr<VehiclePropValue> value = createVehiclePropValue(VehiclePropertyType::FLOAT);
+
+ ASSERT_NE(value, nullptr);
+ ASSERT_EQ(1u, value->value.floatValues.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueFloatVec) {
+ std::unique_ptr<VehiclePropValue> value =
+ createVehiclePropValue(VehiclePropertyType::FLOAT_VEC);
+
+ ASSERT_NE(value, nullptr);
+ ASSERT_EQ(1u, value->value.floatValues.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueBytes) {
+ std::unique_ptr<VehiclePropValue> value = createVehiclePropValue(VehiclePropertyType::BYTES);
+
+ ASSERT_NE(value, nullptr);
+ ASSERT_EQ(1u, value->value.byteValues.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueString) {
+ std::unique_ptr<VehiclePropValue> value = createVehiclePropValue(VehiclePropertyType::STRING);
+
+ ASSERT_NE(value, nullptr);
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueMixed) {
+ std::unique_ptr<VehiclePropValue> value = createVehiclePropValue(VehiclePropertyType::MIXED);
+
+ ASSERT_NE(value, nullptr);
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueVecInt32) {
+ std::unique_ptr<VehiclePropValue> value =
+ createVehiclePropValueVec(VehiclePropertyType::INT32, /*vecSize=*/2);
+
+ ASSERT_NE(value, nullptr);
+ ASSERT_EQ(1u, value->value.int32Values.size())
+ << "vector size should always be 1 for single value type";
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueIntVec32Vec) {
+ std::unique_ptr<VehiclePropValue> value =
+ createVehiclePropValueVec(VehiclePropertyType::INT32_VEC, /*vecSize=*/2);
+
+ ASSERT_NE(value, nullptr);
+ ASSERT_EQ(2u, value->value.int32Values.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueVecInt64) {
+ std::unique_ptr<VehiclePropValue> value =
+ createVehiclePropValueVec(VehiclePropertyType::INT64, /*vecSize=*/2);
+
+ ASSERT_NE(value, nullptr);
+ ASSERT_EQ(1u, value->value.int64Values.size())
+ << "vector size should always be 1 for single value type";
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueIntVec64Vec) {
+ std::unique_ptr<VehiclePropValue> value =
+ createVehiclePropValueVec(VehiclePropertyType::INT64_VEC, /*vecSize=*/2);
+
+ ASSERT_NE(value, nullptr);
+ ASSERT_EQ(2u, value->value.int64Values.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueVecFloat) {
+ std::unique_ptr<VehiclePropValue> value =
+ createVehiclePropValueVec(VehiclePropertyType::FLOAT, /*vecSize=*/2);
+
+ ASSERT_NE(value, nullptr);
+ ASSERT_EQ(1u, value->value.floatValues.size())
+ << "vector size should always be 1 for single value type";
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueFloVecatVec) {
+ std::unique_ptr<VehiclePropValue> value =
+ createVehiclePropValueVec(VehiclePropertyType::FLOAT_VEC, /*vecSize=*/2);
+
+ ASSERT_NE(value, nullptr);
+ ASSERT_EQ(2u, value->value.floatValues.size());
+}
+
+TEST(VehicleUtilsTest, testCreateVehiclePropValueVecBytes) {
+ std::unique_ptr<VehiclePropValue> value =
+ createVehiclePropValueVec(VehiclePropertyType::BYTES, /*vecSize=*/2);
+
+ ASSERT_NE(value, nullptr);
+ ASSERT_EQ(2u, value->value.byteValues.size());
+}
+
} // namespace vehicle
} // namespace automotive
} // namespace hardware
diff --git a/bluetooth/a2dp/1.0/vts/OWNERS b/bluetooth/a2dp/1.0/vts/OWNERS
index 58d3a66..4e982a1 100644
--- a/bluetooth/a2dp/1.0/vts/OWNERS
+++ b/bluetooth/a2dp/1.0/vts/OWNERS
@@ -1,8 +1,4 @@
-zachoverflow@google.com
-siyuanh@google.com
-mylesgw@google.com
-jpawlowski@google.com
-apanicke@google.com
-stng@google.com
-hsz@google.com
+# Bug component: 27441
+include platform/system/bt:/OWNERS
+cheneyni@google.com
diff --git a/camera/metadata/3.7/types.hal b/camera/metadata/3.7/types.hal
new file mode 100644
index 0000000..a09bdf9
--- /dev/null
+++ b/camera/metadata/3.7/types.hal
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+/*
+ * Autogenerated from camera metadata definitions in
+ * /system/media/camera/docs/metadata_definitions.xml
+ * *** DO NOT EDIT BY HAND ***
+ */
+
+package android.hardware.camera.metadata@3.7;
+
+import android.hardware.camera.metadata@3.2;
+import android.hardware.camera.metadata@3.3;
+import android.hardware.camera.metadata@3.4;
+import android.hardware.camera.metadata@3.5;
+import android.hardware.camera.metadata@3.6;
+
+// No new metadata sections added in this revision
+
+/**
+ * Main enumeration for defining camera metadata tags added in this revision
+ *
+ * <p>Partial documentation is included for each tag; for complete documentation, reference
+ * '/system/media/camera/docs/docs.html' in the corresponding Android source tree.</p>
+ */
+enum CameraMetadataTag : @3.6::CameraMetadataTag {
+ /** android.info.deviceStateOrientations [static, int64[], ndk_public]
+ */
+ ANDROID_INFO_DEVICE_STATE_ORIENTATIONS = android.hardware.camera.metadata@3.4::CameraMetadataTag:ANDROID_INFO_END_3_4,
+
+ ANDROID_INFO_END_3_7,
+
+};
+
+/*
+ * Enumeration definitions for the various entries that need them
+ */
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 7727547..ad3da48 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -8161,6 +8161,20 @@
poseReference >= ANDROID_LENS_POSE_REFERENCE_PRIMARY_CAMERA);
}
+ retcode = find_camera_metadata_ro_entry(metadata,
+ ANDROID_INFO_DEVICE_STATE_ORIENTATIONS, &entry);
+ if (0 == retcode && entry.count > 0) {
+ ASSERT_TRUE((entry.count % 2) == 0);
+ uint64_t maxPublicState = ((uint64_t) provider::V2_5::DeviceState::FOLDED) << 1;
+ uint64_t vendorStateStart = 1UL << 31; // Reserved for vendor specific states
+ uint64_t stateMask = (1 << vendorStateStart) - 1;
+ stateMask &= ~((1 << maxPublicState) - 1);
+ for (int i = 0; i < entry.count; i += 2){
+ ASSERT_TRUE((entry.data.i64[i] & stateMask) == 0);
+ ASSERT_TRUE((entry.data.i64[i+1] % 90) == 0);
+ }
+ }
+
verifyExtendedSceneModeCharacteristics(metadata);
verifyZoomCharacteristics(metadata);
}
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index a1f1de9..92f9263 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -418,6 +418,7 @@
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.neuralnetworks</name>
+ <version>1-2</version>
<interface>
<name>IDevice</name>
<regex-instance>.*</regex-instance>
diff --git a/compatibility_matrices/exclude/fcm_exclude.cpp b/compatibility_matrices/exclude/fcm_exclude.cpp
index d8c9170..1def738 100644
--- a/compatibility_matrices/exclude/fcm_exclude.cpp
+++ b/compatibility_matrices/exclude/fcm_exclude.cpp
@@ -57,6 +57,7 @@
"android.hardware.graphics.common",
"android.hardware.keymaster",
"android.hardware.radio",
+ "android.hardware.uwb.fira_android",
// Fastboot HAL is only used by recovery. Recovery is owned by OEM. Framework
// does not depend on this HAL, hence it is not declared in any manifests or matrices.
diff --git a/current.txt b/current.txt
index 21ee123..1dbf5ab 100644
--- a/current.txt
+++ b/current.txt
@@ -901,8 +901,12 @@
4a087a308608d146b022ebc15633de989f5f4dfe1491a83fa41763290a82e40d android.hardware.automotive.vehicle@2.0::types
70eb14415391f835fb218b43a1e25f5d6495f098f96fa2acaea70985e98e1ce8 android.hardware.automotive.vehicle@2.0::types
+# HALs released in Android SCv2
+77f6fcf3fd0dd3e424d8a0292094ebd17e4c35454bb9abbd3a6cbed1aba70765 android.hardware.camera.metadata@3.7::types
+
# ABI preserving changes to HALs during Android T
62ace52d9c3ff1f60f94118557a2aaf0b953513e59dcd34d5f94ae28d4c7e780 android.hardware.fastboot@1.0::IFastboot
+f767a132ef28275294db15353f14f3876a4048770751931a77d038d4228f2cb7 android.hardware.graphics.composer@2.4::IComposerClient
ca62a2a95d173ed323309e5e00f653ad3cceec82a6e5e4976a249cb5aafe2515 android.hardware.neuralnetworks@1.2::types
fa76bced6b1b71c40fc706c508a9011284c57f57831cd0cf5f45653ed4ea463e android.hardware.neuralnetworks@1.3::types
diff --git a/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp b/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp
index fe59a9d..2d4cc7d 100644
--- a/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp
+++ b/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp
@@ -61,18 +61,18 @@
void TestRenderEngine::drawLayers() {
base::unique_fd bufferFence;
- std::vector<const renderengine::LayerSettings*> compositionLayerPointers;
- compositionLayerPointers.reserve(mCompositionLayers.size());
+ std::vector<renderengine::LayerSettings> compositionLayers;
+ compositionLayers.reserve(mCompositionLayers.size());
std::transform(mCompositionLayers.begin(), mCompositionLayers.end(),
- std::back_insert_iterator(compositionLayerPointers),
- [](renderengine::LayerSettings& settings) -> renderengine::LayerSettings* {
- return &settings;
+ std::back_insert_iterator(compositionLayers),
+ [](renderengine::LayerSettings& settings) -> renderengine::LayerSettings {
+ return settings;
});
auto texture = std::make_shared<renderengine::ExternalTexture>(
mGraphicBuffer, *mRenderEngine, renderengine::ExternalTexture::Usage::WRITEABLE);
auto [status, readyFence] = mRenderEngine
- ->drawLayers(mDisplaySettings, compositionLayerPointers,
- texture, true, std::move(bufferFence))
+ ->drawLayers(mDisplaySettings, compositionLayers, texture,
+ true, std::move(bufferFence))
.get();
int fd = readyFence.release();
if (fd != -1) {
diff --git a/graphics/composer/2.4/IComposerClient.hal b/graphics/composer/2.4/IComposerClient.hal
index 1a59bbd..476302f 100644
--- a/graphics/composer/2.4/IComposerClient.hal
+++ b/graphics/composer/2.4/IComposerClient.hal
@@ -34,9 +34,7 @@
/**
* The configuration group ID (as int32_t) this config is associated to.
* Switching between configurations within the same group may be done seamlessly
- * in some conditions via setActiveConfigWithConstraints. Configurations which
- * share the same config group are similar in all attributes except for the
- * vsync period.
+ * in some conditions via setActiveConfigWithConstraints.
*/
CONFIG_GROUP = 7,
};
@@ -307,9 +305,8 @@
* If the display is internally connected (not through HDMI), and such modes are available,
* this method should trigger them.
*
- * This function should only be called if the display reports support for the corresponding
- * content type (ContentType::{GRAPHICS, PHOTO, CINEMA, GAME}) from getSupportedContentTypes.
- * ContentType::NONE is supported by default and can always be set.
+ * This function can be called for a content type even if no support for it is
+ * reported from getSupportedContentTypes.
*
* @return error is NONE upon success. Otherwise,
* BAD_DISPLAY when an invalid display handle was passed in.
diff --git a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
index 5aceda7..b071f71 100644
--- a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
+++ b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
@@ -19,8 +19,6 @@
#include <algorithm>
#include <regex>
#include <thread>
-#include <unordered_map>
-#include <utility>
#include <android-base/logging.h>
#include <android-base/properties.h>
@@ -317,59 +315,6 @@
}
}
-TEST_P(GraphicsComposerHidlTest, GetDisplayAttribute_2_4_ConfigsInAGroupDifferOnlyByVsyncPeriod) {
- struct Resolution {
- int32_t width, height;
- };
- struct Dpi {
- int32_t x, y;
- };
- for (const auto& display : mDisplays) {
- std::vector<Config> configs = mComposerClient->getDisplayConfigs(display.get());
- std::unordered_map<int32_t, Resolution> configGroupToResolutionMap;
- std::unordered_map<int32_t, Dpi> configGroupToDpiMap;
- for (auto config : configs) {
- const auto configGroup = mComposerClient->getDisplayAttribute_2_4(
- display.get(), config, IComposerClient::Attribute::CONFIG_GROUP);
- const auto width = mComposerClient->getDisplayAttribute_2_4(
- display.get(), config, IComposerClient::Attribute::WIDTH);
- const auto height = mComposerClient->getDisplayAttribute_2_4(
- display.get(), config, IComposerClient::Attribute::HEIGHT);
- if (configGroupToResolutionMap.find(configGroup) == configGroupToResolutionMap.end()) {
- configGroupToResolutionMap[configGroup] = {width, height};
- }
- EXPECT_EQ(configGroupToResolutionMap[configGroup].width, width);
- EXPECT_EQ(configGroupToResolutionMap[configGroup].height, height);
-
- int32_t dpiX = -1;
- mComposerClient->getRaw()->getDisplayAttribute_2_4(
- display.get(), config, IComposerClient::Attribute::DPI_X,
- [&](const auto& tmpError, const auto& value) {
- if (tmpError == Error::NONE) {
- dpiX = value;
- }
- });
- int32_t dpiY = -1;
- mComposerClient->getRaw()->getDisplayAttribute_2_4(
- display.get(), config, IComposerClient::Attribute::DPI_Y,
- [&](const auto& tmpError, const auto& value) {
- if (tmpError == Error::NONE) {
- dpiY = value;
- }
- });
- if (dpiX == -1 && dpiY == -1) {
- continue;
- }
-
- if (configGroupToDpiMap.find(configGroup) == configGroupToDpiMap.end()) {
- configGroupToDpiMap[configGroup] = {dpiX, dpiY};
- }
- EXPECT_EQ(configGroupToDpiMap[configGroup].x, dpiX);
- EXPECT_EQ(configGroupToDpiMap[configGroup].y, dpiY);
- }
- }
-}
-
TEST_P(GraphicsComposerHidlTest, getDisplayVsyncPeriod_BadDisplay) {
VsyncPeriodNanos vsyncPeriodNanos;
EXPECT_EQ(Error::BAD_DISPLAY,
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Command.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Command.aidl
index 3b31149..e19105d 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Command.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/Command.aidl
@@ -72,4 +72,5 @@
SET_LAYER_PER_FRAME_METADATA_BLOBS = 50593792,
SET_CLIENT_TARGET_PROPERTY = 17104896,
SET_LAYER_GENERIC_METADATA = 68026368,
+ SET_LAYER_WHITE_POINT_NITS = 50659328,
}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl
index 531fd14..8824f5a 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl
@@ -40,7 +40,7 @@
void destroyVirtualDisplay(long display);
android.hardware.graphics.composer3.ExecuteCommandsStatus executeCommands(int inLength, in android.hardware.common.NativeHandle[] inHandles);
int getActiveConfig(long display);
- void getClientTargetSupport(long display, int width, int height, android.hardware.graphics.common.PixelFormat format, android.hardware.graphics.common.Dataspace dataspace);
+ void getClientTargetSupport(long display, int width, int height, in android.hardware.graphics.composer3.ClientTargetProperty clientTargetProperty);
android.hardware.graphics.composer3.ColorMode[] getColorModes(long display);
float[] getDataspaceSaturationMatrix(android.hardware.graphics.common.Dataspace dataspace);
int getDisplayAttribute(long display, int config, android.hardware.graphics.composer3.DisplayAttribute attribute);
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/Command.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/Command.aidl
index 5f987d0..95c07ac 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/Command.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/Command.aidl
@@ -689,8 +689,16 @@
*
* 0 - 3: clientTargetProperty.pixelFormat
* 4 - 7: clientTargetProperty.dataspace
+ * 8 - 11: whitePointNits
*
- * setClientTargetProperty(ClientTargetProperty clientTargetProperty);
+ * The white point parameter describes the intended white point of the client target buffer.
+ * When client composition blends both HDR and SDR content, the client must composite to the
+ * brightness space as specified by the hardware composer. This is so that adjusting the real
+ * display brightness may be applied atomically with compensating the client target output. For
+ * instance, client-compositing a list of SDR layers requires dimming the brightness space of
+ * the SDR buffers when an HDR layer is simultaneously device-composited.
+ *
+ * setClientTargetProperty(ClientTargetProperty clientTargetProperty, float whitePointNits);
*/
SET_CLIENT_TARGET_PROPERTY = 0x105 << OPCODE_SHIFT,
@@ -738,4 +746,18 @@
* corresponding to the key as described above
*/
SET_LAYER_GENERIC_METADATA = 0x40e << OPCODE_SHIFT,
+
+ /**
+ * SET_LAYER_WHITE_POINT_NITS has this pseudo prototype
+ *
+ * setLayerWhitePointNits(float sdrWhitePointNits);
+ *
+ * Sets the desired white point for the layer. This is intended to be used when presenting
+ * an SDR layer alongside HDR content. The HDR content will be presented at the display
+ * brightness in nits, and accordingly SDR content shall be dimmed to the desired white point
+ * provided.
+ *
+ * @param whitePointNits is the white point in nits.
+ */
+ SET_LAYER_WHITE_POINT_NITS = 0x305 << OPCODE_SHIFT,
}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
index 9bde220..20a6ffc 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
@@ -200,15 +200,12 @@
* @param display is the display to query.
* @param width is the client target width in pixels.
* @param height is the client target height in pixels.
- * @param format is the client target format.
- * @param dataspace is the client target dataspace, as described in
- * setLayerDataspace.
+ * @param clientTargetProperty is the client target format and dataspace.
* @exception EX_BAD_DISPLAY when an invalid display handle was passed in.
* @exception EX_UNSUPPORTED when the given configuration is not supported.
*/
- void getClientTargetSupport(long display, int width, int height,
- android.hardware.graphics.common.PixelFormat format,
- android.hardware.graphics.common.Dataspace dataspace);
+ void getClientTargetSupport(
+ long display, int width, int height, in ClientTargetProperty clientTargetProperty);
/**
* Returns the color modes supported on this display.
@@ -690,9 +687,8 @@
* If the display is internally connected (not through HDMI), and such modes are available,
* this method should trigger them.
*
- * This function should only be called if the display reports support for the corresponding
- * content type (ContentType::{GRAPHICS, PHOTO, CINEMA, GAME}) from getSupportedContentTypes.
- * ContentType::NONE is supported by default and can always be set.
+ * This function can be called for a content type even if no support for it is
+ * reported from getSupportedContentTypes.
*
* @exception EX_BAD_DISPLAY when an invalid display handle was passed in.
* @exception EX_UNSUPPORTED when the given content type is not supported by the composer
diff --git a/graphics/mapper/2.0/vts/OWNERS b/graphics/mapper/2.0/vts/OWNERS
index 4177296..62e3f2a 100644
--- a/graphics/mapper/2.0/vts/OWNERS
+++ b/graphics/mapper/2.0/vts/OWNERS
@@ -1,8 +1,5 @@
-# Graphics team
+# Bug component: 25423
chrisforbes@google.com
jreck@google.com
lpy@google.com
-
-# VTS team
-yim@google.com
-zhuoyao@google.com
+sumir@google.com
diff --git a/graphics/mapper/2.0/vts/functional/OWNERS b/graphics/mapper/2.0/vts/functional/OWNERS
deleted file mode 100644
index a2ed8c8..0000000
--- a/graphics/mapper/2.0/vts/functional/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 25423
-sumir@google.com
diff --git a/graphics/mapper/2.1/vts/OWNERS b/graphics/mapper/2.1/vts/OWNERS
index 4177296..43c018a 100644
--- a/graphics/mapper/2.1/vts/OWNERS
+++ b/graphics/mapper/2.1/vts/OWNERS
@@ -1,8 +1,2 @@
-# Graphics team
-chrisforbes@google.com
-jreck@google.com
-lpy@google.com
-
-# VTS team
-yim@google.com
-zhuoyao@google.com
+# Bug component: 25423
+include ../../2.0/vts/OWNERS
diff --git a/graphics/mapper/2.1/vts/functional/OWNERS b/graphics/mapper/2.1/vts/functional/OWNERS
deleted file mode 100644
index a2ed8c8..0000000
--- a/graphics/mapper/2.1/vts/functional/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 25423
-sumir@google.com
diff --git a/graphics/mapper/3.0/vts/OWNERS b/graphics/mapper/3.0/vts/OWNERS
index c9f24d0..43c018a 100644
--- a/graphics/mapper/3.0/vts/OWNERS
+++ b/graphics/mapper/3.0/vts/OWNERS
@@ -1,4 +1,2 @@
-# Graphics team
-chrisforbes@google.com
-jreck@google.com
-lpy@google.com
+# Bug component: 25423
+include ../../2.0/vts/OWNERS
diff --git a/graphics/mapper/4.0/vts/OWNERS b/graphics/mapper/4.0/vts/OWNERS
index c9f24d0..43c018a 100644
--- a/graphics/mapper/4.0/vts/OWNERS
+++ b/graphics/mapper/4.0/vts/OWNERS
@@ -1,4 +1,2 @@
-# Graphics team
-chrisforbes@google.com
-jreck@google.com
-lpy@google.com
+# Bug component: 25423
+include ../../2.0/vts/OWNERS
diff --git a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
index e18b1fa..2ab9c01 100644
--- a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
+++ b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
@@ -1482,6 +1482,18 @@
}
/**
+ * Test IMapper::get(Smpte2094_10)
+ */
+TEST_P(GraphicsMapperHidlTest, GetSmpte2094_10) {
+ testGet(mDummyDescriptorInfo, gralloc4::MetadataType_Smpte2094_10,
+ [](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) {
+ std::optional<std::vector<uint8_t>> smpte2094_10;
+ ASSERT_EQ(NO_ERROR, gralloc4::decodeSmpte2094_10(vec, &smpte2094_10));
+ EXPECT_FALSE(smpte2094_10.has_value());
+ });
+}
+
+/**
* Test IMapper::get(metadata) with a bad buffer
*/
TEST_P(GraphicsMapperHidlTest, GetMetadataBadValue) {
@@ -1545,6 +1557,9 @@
ASSERT_EQ(Error::BAD_BUFFER,
mGralloc->get(bufferHandle, gralloc4::MetadataType_Smpte2094_40, &vec));
ASSERT_EQ(0, vec.size());
+ ASSERT_EQ(Error::BAD_BUFFER,
+ mGralloc->get(bufferHandle, gralloc4::MetadataType_Smpte2094_10, &vec));
+ ASSERT_EQ(0, vec.size());
}
/**
@@ -1937,6 +1952,20 @@
}
/**
+ * Test IMapper::set(Smpte2094_10)
+ */
+TEST_P(GraphicsMapperHidlTest, SetSmpte2094_10) {
+ hidl_vec<uint8_t> vec;
+
+ testSet(mDummyDescriptorInfo, gralloc4::MetadataType_Smpte2094_10, vec,
+ [&](const IMapper::BufferDescriptorInfo& /*info*/, const hidl_vec<uint8_t>& vec) {
+ std::optional<std::vector<uint8_t>> realSmpte2094_10;
+ ASSERT_EQ(NO_ERROR, gralloc4::decodeSmpte2094_10(vec, &realSmpte2094_10));
+ EXPECT_FALSE(realSmpte2094_10.has_value());
+ });
+}
+
+/**
* Test IMapper::set(metadata) with a bad buffer
*/
TEST_P(GraphicsMapperHidlTest, SetMetadataNullBuffer) {
@@ -1977,6 +2006,8 @@
ASSERT_EQ(Error::BAD_BUFFER, mGralloc->set(bufferHandle, gralloc4::MetadataType_Cta861_3, vec));
ASSERT_EQ(Error::BAD_BUFFER,
mGralloc->set(bufferHandle, gralloc4::MetadataType_Smpte2094_40, vec));
+ ASSERT_EQ(Error::BAD_BUFFER,
+ mGralloc->set(bufferHandle, gralloc4::MetadataType_Smpte2094_10, vec));
}
/**
@@ -2482,6 +2513,24 @@
}
/**
+ * Test IMapper::getFromBufferDescriptorInfo(Smpte2094_10)
+ */
+TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoSmpte2094_10) {
+ hidl_vec<uint8_t> vec;
+ auto err = mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo,
+ gralloc4::MetadataType_Smpte2094_10, &vec);
+ if (err == Error::UNSUPPORTED) {
+ GTEST_SUCCEED() << "setting this metadata is unsupported";
+ return;
+ }
+ ASSERT_EQ(err, Error::NONE);
+
+ std::optional<std::vector<uint8_t>> smpte2094_10;
+ ASSERT_EQ(NO_ERROR, gralloc4::decodeSmpte2094_10(vec, &smpte2094_10));
+ EXPECT_FALSE(smpte2094_10.has_value());
+}
+
+/**
* Test IMapper::getFromBufferDescriptorInfo(metadata) for unsupported metadata
*/
TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoUnsupportedMetadata) {
diff --git a/health/1.0/Android.bp b/health/1.0/Android.bp
index 003b106..e793db6 100644
--- a/health/1.0/Android.bp
+++ b/health/1.0/Android.bp
@@ -20,4 +20,8 @@
],
gen_java: true,
gen_java_constants: true,
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.car.framework",
+ ],
}
diff --git a/health/2.0/Android.bp b/health/2.0/Android.bp
index ddd983d..fae25b6 100644
--- a/health/2.0/Android.bp
+++ b/health/2.0/Android.bp
@@ -22,4 +22,8 @@
"android.hidl.base@1.0",
],
gen_java: true,
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.car.framework",
+ ],
}
diff --git a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Utils.h b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Utils.h
index 1baabdf..360b338 100644
--- a/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Utils.h
+++ b/neuralnetworks/1.0/utils/include/nnapi/hal/1.0/Utils.h
@@ -50,8 +50,8 @@
}
template <typename Type>
-nn::GeneralResult<void> compliantVersion(const Type& canonical) {
- const auto version = NN_TRY(hal::utils::makeGeneralFailure(nn::validate(canonical)));
+nn::Result<void> compliantVersion(const Type& canonical) {
+ const auto version = NN_TRY(nn::validate(canonical));
if (version > kVersion) {
return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion;
}
diff --git a/neuralnetworks/1.0/utils/src/PreparedModel.cpp b/neuralnetworks/1.0/utils/src/PreparedModel.cpp
index 00970c0..3060c65 100644
--- a/neuralnetworks/1.0/utils/src/PreparedModel.cpp
+++ b/neuralnetworks/1.0/utils/src/PreparedModel.cpp
@@ -63,12 +63,11 @@
// Ensure that request is ready for IPC.
std::optional<nn::Request> maybeRequestInShared;
hal::utils::RequestRelocation relocation;
- const nn::Request& requestInShared =
- NN_TRY(hal::utils::makeExecutionFailure(hal::utils::convertRequestFromPointerToShared(
- &request, nn::kDefaultRequestMemoryAlignment, nn::kMinMemoryPadding,
- &maybeRequestInShared, &relocation)));
+ const nn::Request& requestInShared = NN_TRY(hal::utils::convertRequestFromPointerToShared(
+ &request, nn::kDefaultRequestMemoryAlignment, nn::kMinMemoryPadding,
+ &maybeRequestInShared, &relocation));
- const auto hidlRequest = NN_TRY(hal::utils::makeExecutionFailure(convert(requestInShared)));
+ const auto hidlRequest = NN_TRY(convert(requestInShared));
return executeInternal(hidlRequest, relocation);
}
diff --git a/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Utils.h b/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Utils.h
index a8cf8cf..09d9fe8 100644
--- a/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Utils.h
+++ b/neuralnetworks/1.1/utils/include/nnapi/hal/1.1/Utils.h
@@ -52,8 +52,8 @@
}
template <typename Type>
-nn::GeneralResult<void> compliantVersion(const Type& canonical) {
- const auto version = NN_TRY(hal::utils::makeGeneralFailure(nn::validate(canonical)));
+nn::Result<void> compliantVersion(const Type& canonical) {
+ const auto version = NN_TRY(nn::validate(canonical));
if (version > kVersion) {
return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion;
}
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Utils.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Utils.h
index 09691b6..5c3b8a7 100644
--- a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Utils.h
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Utils.h
@@ -61,8 +61,8 @@
}
template <typename Type>
-nn::GeneralResult<void> compliantVersion(const Type& canonical) {
- const auto version = NN_TRY(hal::utils::makeGeneralFailure(nn::validate(canonical)));
+nn::Result<void> compliantVersion(const Type& canonical) {
+ const auto version = NN_TRY(nn::validate(canonical));
if (version > kVersion) {
return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion;
}
diff --git a/neuralnetworks/1.2/utils/src/Callbacks.cpp b/neuralnetworks/1.2/utils/src/Callbacks.cpp
index 9f54bb1..01b5e12 100644
--- a/neuralnetworks/1.2/utils/src/Callbacks.cpp
+++ b/neuralnetworks/1.2/utils/src/Callbacks.cpp
@@ -75,8 +75,7 @@
<< "execution failed with " << toString(status);
}
HANDLE_HAL_STATUS(status) << "execution failed with " << toString(status);
- return hal::utils::makeExecutionFailure(
- convertExecutionGeneralResultsHelper(outputShapes, timing));
+ return convertExecutionGeneralResultsHelper(outputShapes, timing);
}
Return<void> PreparedModelCallback::notify(V1_0::ErrorStatus status,
diff --git a/neuralnetworks/1.2/utils/src/Conversions.cpp b/neuralnetworks/1.2/utils/src/Conversions.cpp
index 29945b7..6a80b42 100644
--- a/neuralnetworks/1.2/utils/src/Conversions.cpp
+++ b/neuralnetworks/1.2/utils/src/Conversions.cpp
@@ -120,9 +120,8 @@
NN_TRY(unvalidatedConvert(capabilities.relaxedFloat32toFloat16PerformanceTensor));
auto operandPerformance = NN_TRY(unvalidatedConvert(capabilities.operandPerformance));
- auto table = NN_TRY(hal::utils::makeGeneralFailure(
- Capabilities::OperandPerformanceTable::create(std::move(operandPerformance)),
- nn::ErrorStatus::GENERAL_FAILURE));
+ auto table =
+ NN_TRY(Capabilities::OperandPerformanceTable::create(std::move(operandPerformance)));
return Capabilities{
.relaxedFloat32toFloat16PerformanceScalar = relaxedFloat32toFloat16PerformanceScalar,
diff --git a/neuralnetworks/1.2/utils/src/ExecutionBurstController.cpp b/neuralnetworks/1.2/utils/src/ExecutionBurstController.cpp
index b4b6f68..2746965 100644
--- a/neuralnetworks/1.2/utils/src/ExecutionBurstController.cpp
+++ b/neuralnetworks/1.2/utils/src/ExecutionBurstController.cpp
@@ -176,7 +176,10 @@
std::lock_guard guard(mMutex);
const int32_t slot = mMemoryIdToSlot.at(memory);
if (mBurstContext) {
- mBurstContext->freeMemory(slot);
+ const auto ret = mBurstContext->freeMemory(slot);
+ if (!ret.isOk()) {
+ LOG(ERROR) << "IBustContext::freeMemory failed: " << ret.description();
+ }
}
mMemoryIdToSlot.erase(memory);
mMemoryCache[slot] = {};
@@ -317,8 +320,7 @@
// if the request is valid but of a higher version than what's supported in burst execution,
// fall back to another execution path
- if (const auto version = NN_TRY(hal::utils::makeExecutionFailure(nn::validate(request)));
- version > nn::Version::ANDROID_Q) {
+ if (const auto version = NN_TRY(nn::validate(request)); version > nn::Version::ANDROID_Q) {
// fallback to another execution path if the packet could not be sent
return kPreparedModel->execute(request, measure, deadline, loopTimeoutDuration);
}
@@ -326,17 +328,15 @@
// ensure that request is ready for IPC
std::optional<nn::Request> maybeRequestInShared;
hal::utils::RequestRelocation relocation;
- const nn::Request& requestInShared =
- NN_TRY(hal::utils::makeExecutionFailure(hal::utils::convertRequestFromPointerToShared(
- &request, nn::kDefaultRequestMemoryAlignment, nn::kMinMemoryPadding,
- &maybeRequestInShared, &relocation)));
+ const nn::Request& requestInShared = NN_TRY(hal::utils::convertRequestFromPointerToShared(
+ &request, nn::kDefaultRequestMemoryAlignment, nn::kMinMemoryPadding,
+ &maybeRequestInShared, &relocation));
// clear pools field of request, as they will be provided via slots
const auto requestWithoutPools = nn::Request{
.inputs = requestInShared.inputs, .outputs = requestInShared.outputs, .pools = {}};
- auto hidlRequest = NN_TRY(
- hal::utils::makeExecutionFailure(V1_0::utils::unvalidatedConvert(requestWithoutPools)));
- const auto hidlMeasure = NN_TRY(hal::utils::makeExecutionFailure(convert(measure)));
+ auto hidlRequest = NN_TRY(V1_0::utils::unvalidatedConvert(requestWithoutPools));
+ const auto hidlMeasure = NN_TRY(convert(measure));
std::vector<int32_t> slots;
std::vector<OptionalCacheHold> holds;
@@ -364,8 +364,7 @@
// if the request is valid but of a higher version than what's supported in burst execution,
// fall back to another execution path
- if (const auto version = NN_TRY(hal::utils::makeGeneralFailure(nn::validate(request)));
- version > nn::Version::ANDROID_Q) {
+ if (const auto version = NN_TRY(nn::validate(request)); version > nn::Version::ANDROID_Q) {
// fallback to another execution path if the packet could not be sent
return kPreparedModel->createReusableExecution(request, measure, loopTimeoutDuration);
}
@@ -427,8 +426,7 @@
}
// get result packet
- const auto [status, outputShapes, timing] =
- NN_TRY(hal::utils::makeExecutionFailure(mResultChannelReceiver->getBlocking()));
+ const auto [status, outputShapes, timing] = NN_TRY(mResultChannelReceiver->getBlocking());
if (relocation.output) {
relocation.output->flush();
diff --git a/neuralnetworks/1.2/utils/src/ExecutionBurstServer.cpp b/neuralnetworks/1.2/utils/src/ExecutionBurstServer.cpp
index c67159e..65ec7f5 100644
--- a/neuralnetworks/1.2/utils/src/ExecutionBurstServer.cpp
+++ b/neuralnetworks/1.2/utils/src/ExecutionBurstServer.cpp
@@ -45,8 +45,6 @@
namespace android::hardware::neuralnetworks::V1_2::utils {
namespace {
-using neuralnetworks::utils::makeExecutionFailure;
-
constexpr V1_2::Timing kNoTiming = {std::numeric_limits<uint64_t>::max(),
std::numeric_limits<uint64_t>::max()};
@@ -241,28 +239,25 @@
"ExecutionBurstServer getting memory, executing, and returning results");
// ensure executor with cache has required memory
- const auto cacheEntries =
- NN_TRY(makeExecutionFailure(mMemoryCache.getCacheEntries(slotsOfPools)));
+ const auto cacheEntries = NN_TRY(mMemoryCache.getCacheEntries(slotsOfPools));
// convert request, populating its pools
// This code performs an unvalidated convert because the request object without its pools is
// invalid because it is incomplete. Instead, the validation is performed after the memory pools
// have been added to the request.
- auto canonicalRequest =
- NN_TRY(makeExecutionFailure(nn::unvalidatedConvert(requestWithoutPools)));
+ auto canonicalRequest = NN_TRY(nn::unvalidatedConvert(requestWithoutPools));
CHECK(canonicalRequest.pools.empty());
std::transform(cacheEntries.begin(), cacheEntries.end(),
std::back_inserter(canonicalRequest.pools),
[](const auto& cacheEntry) { return cacheEntry.first; });
- NN_TRY(makeExecutionFailure(validate(canonicalRequest)));
+ NN_TRY(validate(canonicalRequest));
- nn::MeasureTiming canonicalMeasure = NN_TRY(makeExecutionFailure(nn::convert(measure)));
+ nn::MeasureTiming canonicalMeasure = NN_TRY(nn::convert(measure));
const auto [outputShapes, timing] =
NN_TRY(mBurstExecutor->execute(canonicalRequest, canonicalMeasure, {}, {}));
- return std::make_pair(NN_TRY(makeExecutionFailure(convert(outputShapes))),
- NN_TRY(makeExecutionFailure(convert(timing))));
+ return std::make_pair(NN_TRY(convert(outputShapes)), NN_TRY(convert(timing)));
}
} // namespace android::hardware::neuralnetworks::V1_2::utils
diff --git a/neuralnetworks/1.2/utils/src/PreparedModel.cpp b/neuralnetworks/1.2/utils/src/PreparedModel.cpp
index d0ef36e..c261184 100644
--- a/neuralnetworks/1.2/utils/src/PreparedModel.cpp
+++ b/neuralnetworks/1.2/utils/src/PreparedModel.cpp
@@ -95,13 +95,12 @@
// Ensure that request is ready for IPC.
std::optional<nn::Request> maybeRequestInShared;
hal::utils::RequestRelocation relocation;
- const nn::Request& requestInShared =
- NN_TRY(hal::utils::makeExecutionFailure(hal::utils::convertRequestFromPointerToShared(
- &request, nn::kDefaultRequestMemoryAlignment, nn::kMinMemoryPadding,
- &maybeRequestInShared, &relocation)));
+ const nn::Request& requestInShared = NN_TRY(hal::utils::convertRequestFromPointerToShared(
+ &request, nn::kDefaultRequestMemoryAlignment, nn::kMinMemoryPadding,
+ &maybeRequestInShared, &relocation));
- const auto hidlRequest = NN_TRY(hal::utils::makeExecutionFailure(convert(requestInShared)));
- const auto hidlMeasure = NN_TRY(hal::utils::makeExecutionFailure(convert(measure)));
+ const auto hidlRequest = NN_TRY(convert(requestInShared));
+ const auto hidlMeasure = NN_TRY(convert(measure));
return executeInternal(hidlRequest, hidlMeasure, relocation);
}
diff --git a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Utils.h b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Utils.h
index 1d76caa..28525bd 100644
--- a/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Utils.h
+++ b/neuralnetworks/1.3/utils/include/nnapi/hal/1.3/Utils.h
@@ -61,8 +61,8 @@
}
template <typename Type>
-nn::GeneralResult<void> compliantVersion(const Type& canonical) {
- const auto version = NN_TRY(hal::utils::makeGeneralFailure(nn::validate(canonical)));
+nn::Result<void> compliantVersion(const Type& canonical) {
+ const auto version = NN_TRY(nn::validate(canonical));
if (version > kVersion) {
return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion;
}
diff --git a/neuralnetworks/1.3/utils/src/Callbacks.cpp b/neuralnetworks/1.3/utils/src/Callbacks.cpp
index 8e9fb83..156216f 100644
--- a/neuralnetworks/1.3/utils/src/Callbacks.cpp
+++ b/neuralnetworks/1.3/utils/src/Callbacks.cpp
@@ -91,8 +91,7 @@
<< "execution failed with " << toString(status);
}
HANDLE_HAL_STATUS(status) << "execution failed with " << toString(status);
- return hal::utils::makeExecutionFailure(
- convertExecutionGeneralResultsHelper(outputShapes, timing));
+ return convertExecutionGeneralResultsHelper(outputShapes, timing);
}
Return<void> PreparedModelCallback::notify(V1_0::ErrorStatus status,
diff --git a/neuralnetworks/1.3/utils/src/Conversions.cpp b/neuralnetworks/1.3/utils/src/Conversions.cpp
index 11225cf..b35b2cd 100644
--- a/neuralnetworks/1.3/utils/src/Conversions.cpp
+++ b/neuralnetworks/1.3/utils/src/Conversions.cpp
@@ -131,9 +131,8 @@
}
auto operandPerformance = NN_TRY(unvalidatedConvert(capabilities.operandPerformance));
- auto table = NN_TRY(hal::utils::makeGeneralFailure(
- Capabilities::OperandPerformanceTable::create(std::move(operandPerformance)),
- nn::ErrorStatus::GENERAL_FAILURE));
+ auto table =
+ NN_TRY(Capabilities::OperandPerformanceTable::create(std::move(operandPerformance)));
return Capabilities{
.relaxedFloat32toFloat16PerformanceScalar = NN_TRY(
diff --git a/neuralnetworks/1.3/utils/src/Execution.cpp b/neuralnetworks/1.3/utils/src/Execution.cpp
index 3d17cc3..4dc0ddf 100644
--- a/neuralnetworks/1.3/utils/src/Execution.cpp
+++ b/neuralnetworks/1.3/utils/src/Execution.cpp
@@ -65,7 +65,7 @@
nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> Execution::compute(
const nn::OptionalTimePoint& deadline) const {
- const auto hidlDeadline = NN_TRY(hal::utils::makeExecutionFailure(convert(deadline)));
+ const auto hidlDeadline = NN_TRY(convert(deadline));
return kPreparedModel->executeInternal(kRequest, kMeasure, hidlDeadline, kLoopTimeoutDuration,
kRelocation);
}
diff --git a/neuralnetworks/1.3/utils/src/PreparedModel.cpp b/neuralnetworks/1.3/utils/src/PreparedModel.cpp
index 1623de5..d5dee9d 100644
--- a/neuralnetworks/1.3/utils/src/PreparedModel.cpp
+++ b/neuralnetworks/1.3/utils/src/PreparedModel.cpp
@@ -62,8 +62,7 @@
auto resultSyncFence = nn::SyncFence::createAsSignaled();
if (syncFence.getNativeHandle() != nullptr) {
auto sharedHandle = NN_TRY(nn::convert(syncFence));
- resultSyncFence = NN_TRY(hal::utils::makeGeneralFailure(
- nn::SyncFence::create(std::move(sharedHandle)), nn::ErrorStatus::GENERAL_FAILURE));
+ resultSyncFence = NN_TRY(nn::SyncFence::create(std::move(sharedHandle)));
}
if (callback == nullptr) {
@@ -141,16 +140,14 @@
// Ensure that request is ready for IPC.
std::optional<nn::Request> maybeRequestInShared;
hal::utils::RequestRelocation relocation;
- const nn::Request& requestInShared =
- NN_TRY(hal::utils::makeExecutionFailure(hal::utils::convertRequestFromPointerToShared(
- &request, nn::kDefaultRequestMemoryAlignment, nn::kMinMemoryPadding,
- &maybeRequestInShared, &relocation)));
+ const nn::Request& requestInShared = NN_TRY(hal::utils::convertRequestFromPointerToShared(
+ &request, nn::kDefaultRequestMemoryAlignment, nn::kMinMemoryPadding,
+ &maybeRequestInShared, &relocation));
- const auto hidlRequest = NN_TRY(hal::utils::makeExecutionFailure(convert(requestInShared)));
- const auto hidlMeasure = NN_TRY(hal::utils::makeExecutionFailure(convert(measure)));
- const auto hidlDeadline = NN_TRY(hal::utils::makeExecutionFailure(convert(deadline)));
- const auto hidlLoopTimeoutDuration =
- NN_TRY(hal::utils::makeExecutionFailure(convert(loopTimeoutDuration)));
+ const auto hidlRequest = NN_TRY(convert(requestInShared));
+ const auto hidlMeasure = NN_TRY(convert(measure));
+ const auto hidlDeadline = NN_TRY(convert(deadline));
+ const auto hidlLoopTimeoutDuration = NN_TRY(convert(loopTimeoutDuration));
return executeInternal(hidlRequest, hidlMeasure, hidlDeadline, hidlLoopTimeoutDuration,
relocation);
diff --git a/neuralnetworks/1.3/vts/functional/Android.bp b/neuralnetworks/1.3/vts/functional/Android.bp
index 1382bdb..ab0a018 100644
--- a/neuralnetworks/1.3/vts/functional/Android.bp
+++ b/neuralnetworks/1.3/vts/functional/Android.bp
@@ -66,7 +66,7 @@
"VtsHalNeuralNetworksV1_0_utils",
"VtsHalNeuralNetworksV1_2_utils",
"VtsHalNeuralNetworksV1_3_utils",
- "android.hardware.neuralnetworks-V1-ndk",
+ "android.hardware.neuralnetworks-V2-ndk",
"android.hardware.neuralnetworks@1.0",
"android.hardware.neuralnetworks@1.1",
"android.hardware.neuralnetworks@1.2",
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperationType.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperationType.aidl
index de3b438..4259143 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperationType.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/OperationType.aidl
@@ -136,4 +136,5 @@
HARD_SWISH = 99,
FILL = 100,
RANK = 101,
+ BATCH_MATMUL = 102,
}
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/OperationType.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/OperationType.aidl
index 52d2d70..d9951d5 100644
--- a/neuralnetworks/aidl/android/hardware/neuralnetworks/OperationType.aidl
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/OperationType.aidl
@@ -1471,6 +1471,7 @@
* * {@link OperandType::TENSOR_FLOAT32}
* * {@link OperandType::TENSOR_QUANT8_ASYMM}
* * {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} (since HAL version 1.3)
+ * * {@link OperandType::TENSOR_INT32} (since NNAPI feature level 6)
*
* Supported tensor rank: up to 4.
*
@@ -5236,4 +5237,40 @@
* of the input tensor.
*/
RANK = 101,
+
+ /**
+ * Performs multiplication of two tensors in batches.
+ *
+ * Multiplies all slices of two input tensors and arranges the individual
+ * results in a single output tensor of the same batch size. Each pair of
+ * slices in the same batch have identical {@link OperandType}. Each
+ * slice can optionally be adjointed (transpose and conjugate) before
+ * multiplication.
+ *
+ * The two input tensors and the output tensor must be 2-D or higher and
+ * have the same batch size.
+ *
+ * Supported tensor {@link OperandType}:
+ * * {@link OperandType::TENSOR_FLOAT16}
+ * * {@link OperandType::TENSOR_FLOAT32}
+ * * {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED}
+ * * {@link OperandType::TENSOR_INT32}
+ *
+ * Supported tensor rank: at least 2 and up to 4
+ *
+ * Inputs:
+ * * 0: A tensor with 2-D or higher shape [..., r_x, c_x].
+ * * 1: A tensor with 2-D or higher shape [..., r_y, c_y]. It has the same
+ * {@link OperandType} and batch size as input0.
+ * * 2: An optional {@link OperandType::BOOL} scalar adj_x, default
+ * to false. Set to true to adjoint the slices of input0.
+ * * 3: An optional {@link OperandType::BOOL} scalar adj_y, default
+ * to false. Set to true to adjoint the slices of input1.
+ *
+ * Outputs:
+ * * 0: A tensor with 2-D or higher shape [..., r_o, c_o], where
+ * r_o = c_x if adj_x else r_x
+ * c_o = r_y if adj_y else c_y
+ */
+ BATCH_MATMUL = 102,
}
diff --git a/neuralnetworks/aidl/utils/Android.bp b/neuralnetworks/aidl/utils/Android.bp
index 3c80d75..63cf45d 100644
--- a/neuralnetworks/aidl/utils/Android.bp
+++ b/neuralnetworks/aidl/utils/Android.bp
@@ -38,7 +38,7 @@
"neuralnetworks_utils_hal_common",
],
shared_libs: [
- "android.hardware.neuralnetworks-V1-ndk",
+ "android.hardware.neuralnetworks-V2-ndk",
"libbinder_ndk",
"libhidlbase",
],
@@ -58,7 +58,7 @@
static_libs: [
"android.hardware.common-V2-ndk",
"android.hardware.graphics.common-V3-ndk",
- "android.hardware.neuralnetworks-V1-ndk",
+ "android.hardware.neuralnetworks-V2-ndk",
"libaidlcommonsupport",
"libgmock",
"libneuralnetworks_common",
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Utils.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Utils.h
index 316d34f..1b149e4 100644
--- a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Utils.h
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/Utils.h
@@ -50,9 +50,8 @@
}
template <typename Type>
-nn::GeneralResult<void> compliantVersion(const Type& canonical) {
- const auto version = NN_TRY(::android::hardware::neuralnetworks::utils::makeGeneralFailure(
- nn::validate(canonical)));
+nn::Result<void> compliantVersion(const Type& canonical) {
+ const auto version = NN_TRY(nn::validate(canonical));
if (version > kVersion) {
return NN_ERROR() << "Insufficient version: " << version << " vs required " << kVersion;
}
diff --git a/neuralnetworks/aidl/utils/src/Burst.cpp b/neuralnetworks/aidl/utils/src/Burst.cpp
index 800ac32..c59c10b 100644
--- a/neuralnetworks/aidl/utils/src/Burst.cpp
+++ b/neuralnetworks/aidl/utils/src/Burst.cpp
@@ -176,16 +176,14 @@
// Ensure that request is ready for IPC.
std::optional<nn::Request> maybeRequestInShared;
hal::utils::RequestRelocation relocation;
- const nn::Request& requestInShared =
- NN_TRY(hal::utils::makeExecutionFailure(hal::utils::convertRequestFromPointerToShared(
- &request, nn::kDefaultRequestMemoryAlignment, nn::kDefaultRequestMemoryPadding,
- &maybeRequestInShared, &relocation)));
+ const nn::Request& requestInShared = NN_TRY(hal::utils::convertRequestFromPointerToShared(
+ &request, nn::kDefaultRequestMemoryAlignment, nn::kDefaultRequestMemoryPadding,
+ &maybeRequestInShared, &relocation));
- const auto aidlRequest = NN_TRY(hal::utils::makeExecutionFailure(convert(requestInShared)));
- const auto aidlMeasure = NN_TRY(hal::utils::makeExecutionFailure(convert(measure)));
- const auto aidlDeadline = NN_TRY(hal::utils::makeExecutionFailure(convert(deadline)));
- const auto aidlLoopTimeoutDuration =
- NN_TRY(hal::utils::makeExecutionFailure(convert(loopTimeoutDuration)));
+ const auto aidlRequest = NN_TRY(convert(requestInShared));
+ const auto aidlMeasure = NN_TRY(convert(measure));
+ const auto aidlDeadline = NN_TRY(convert(deadline));
+ const auto aidlLoopTimeoutDuration = NN_TRY(convert(loopTimeoutDuration));
std::vector<int64_t> memoryIdentifierTokens;
std::vector<OptionalCacheHold> holds;
@@ -233,8 +231,8 @@
return NN_ERROR(nn::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE, std::move(canonicalOutputShapes))
<< "execution failed with " << nn::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE;
}
- auto [outputShapes, timing] = NN_TRY(hal::utils::makeExecutionFailure(
- convertExecutionResults(executionResult.outputShapes, executionResult.timing)));
+ auto [outputShapes, timing] =
+ NN_TRY(convertExecutionResults(executionResult.outputShapes, executionResult.timing));
if (relocation.output) {
relocation.output->flush();
@@ -308,7 +306,7 @@
nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> BurstExecution::compute(
const nn::OptionalTimePoint& deadline) const {
- const auto aidlDeadline = NN_TRY(hal::utils::makeExecutionFailure(convert(deadline)));
+ const auto aidlDeadline = NN_TRY(convert(deadline));
return kBurst->executeInternal(kRequest, kMemoryIdentifierTokens, kMeasure, aidlDeadline,
kLoopTimeoutDuration, kRelocation);
}
diff --git a/neuralnetworks/aidl/utils/src/Conversions.cpp b/neuralnetworks/aidl/utils/src/Conversions.cpp
index f087156..ddff3f2 100644
--- a/neuralnetworks/aidl/utils/src/Conversions.cpp
+++ b/neuralnetworks/aidl/utils/src/Conversions.cpp
@@ -178,9 +178,8 @@
}
auto operandPerformance = NN_TRY(unvalidatedConvert(capabilities.operandPerformance));
- auto table = NN_TRY(hal::utils::makeGeneralFailure(
- Capabilities::OperandPerformanceTable::create(std::move(operandPerformance)),
- nn::ErrorStatus::GENERAL_FAILURE));
+ auto table =
+ NN_TRY(Capabilities::OperandPerformanceTable::create(std::move(operandPerformance)));
return Capabilities{
.relaxedFloat32toFloat16PerformanceScalar = NN_TRY(
diff --git a/neuralnetworks/aidl/utils/src/Execution.cpp b/neuralnetworks/aidl/utils/src/Execution.cpp
index 2aee8a6..13d4f32 100644
--- a/neuralnetworks/aidl/utils/src/Execution.cpp
+++ b/neuralnetworks/aidl/utils/src/Execution.cpp
@@ -60,7 +60,7 @@
nn::ExecutionResult<std::pair<std::vector<nn::OutputShape>, nn::Timing>> Execution::compute(
const nn::OptionalTimePoint& deadline) const {
- const auto aidlDeadline = NN_TRY(hal::utils::makeExecutionFailure(convert(deadline)));
+ const auto aidlDeadline = NN_TRY(convert(deadline));
return kPreparedModel->executeInternal(kRequest, kMeasure, aidlDeadline, kLoopTimeoutDuration,
kRelocation);
}
diff --git a/neuralnetworks/aidl/utils/src/PreparedModel.cpp b/neuralnetworks/aidl/utils/src/PreparedModel.cpp
index f861d74..0769016 100644
--- a/neuralnetworks/aidl/utils/src/PreparedModel.cpp
+++ b/neuralnetworks/aidl/utils/src/PreparedModel.cpp
@@ -78,16 +78,14 @@
// Ensure that request is ready for IPC.
std::optional<nn::Request> maybeRequestInShared;
hal::utils::RequestRelocation relocation;
- const nn::Request& requestInShared =
- NN_TRY(hal::utils::makeExecutionFailure(hal::utils::convertRequestFromPointerToShared(
- &request, nn::kDefaultRequestMemoryAlignment, nn::kDefaultRequestMemoryPadding,
- &maybeRequestInShared, &relocation)));
+ const nn::Request& requestInShared = NN_TRY(hal::utils::convertRequestFromPointerToShared(
+ &request, nn::kDefaultRequestMemoryAlignment, nn::kDefaultRequestMemoryPadding,
+ &maybeRequestInShared, &relocation));
- const auto aidlRequest = NN_TRY(hal::utils::makeExecutionFailure(convert(requestInShared)));
- const auto aidlMeasure = NN_TRY(hal::utils::makeExecutionFailure(convert(measure)));
- const auto aidlDeadline = NN_TRY(hal::utils::makeExecutionFailure(convert(deadline)));
- const auto aidlLoopTimeoutDuration =
- NN_TRY(hal::utils::makeExecutionFailure(convert(loopTimeoutDuration)));
+ const auto aidlRequest = NN_TRY(convert(requestInShared));
+ const auto aidlMeasure = NN_TRY(convert(measure));
+ const auto aidlDeadline = NN_TRY(convert(deadline));
+ const auto aidlLoopTimeoutDuration = NN_TRY(convert(loopTimeoutDuration));
return executeInternal(aidlRequest, aidlMeasure, aidlDeadline, aidlLoopTimeoutDuration,
relocation);
}
@@ -110,8 +108,8 @@
return NN_ERROR(nn::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE, std::move(canonicalOutputShapes))
<< "execution failed with " << nn::ErrorStatus::OUTPUT_INSUFFICIENT_SIZE;
}
- auto [outputShapes, timing] = NN_TRY(hal::utils::makeExecutionFailure(
- convertExecutionResults(executionResult.outputShapes, executionResult.timing)));
+ auto [outputShapes, timing] =
+ NN_TRY(convertExecutionResults(executionResult.outputShapes, executionResult.timing));
if (relocation.output) {
relocation.output->flush();
diff --git a/neuralnetworks/aidl/vts/OWNERS b/neuralnetworks/aidl/vts/OWNERS
index 6719a5b..f1a757a 100644
--- a/neuralnetworks/aidl/vts/OWNERS
+++ b/neuralnetworks/aidl/vts/OWNERS
@@ -2,11 +2,8 @@
butlermichael@google.com
dgross@google.com
jeanluc@google.com
-levp@google.com
miaowang@google.com
mikie@google.com
-mks@google.com
pszczepaniak@google.com
-slavash@google.com
-vddang@google.com
xusongw@google.com
+ianhua@google.com
diff --git a/neuralnetworks/aidl/vts/functional/Android.bp b/neuralnetworks/aidl/vts/functional/Android.bp
index 40da1fd..f3404a9 100644
--- a/neuralnetworks/aidl/vts/functional/Android.bp
+++ b/neuralnetworks/aidl/vts/functional/Android.bp
@@ -51,7 +51,7 @@
static_libs: [
"android.hardware.common-V2-ndk",
"android.hardware.graphics.common-V3-ndk",
- "android.hardware.neuralnetworks-V1-ndk",
+ "android.hardware.neuralnetworks-V2-ndk",
"android.hidl.allocator@1.0",
"android.hidl.memory@1.0",
"libaidlcommonsupport",
diff --git a/neuralnetworks/utils/adapter/src/PreparedModel.cpp b/neuralnetworks/utils/adapter/src/PreparedModel.cpp
index 8968c2c..7397def 100644
--- a/neuralnetworks/utils/adapter/src/PreparedModel.cpp
+++ b/neuralnetworks/utils/adapter/src/PreparedModel.cpp
@@ -57,6 +57,15 @@
return result;
}
+nn::GeneralResult<nn::Version> validateRequestForModel(const nn::Request& request,
+ const nn::Model& model) {
+ nn::GeneralResult<nn::Version> version = nn::validateRequestForModel(request, model);
+ if (!version.ok()) {
+ version.error().code = nn::ErrorStatus::INVALID_ARGUMENT;
+ }
+ return version;
+}
+
class FencedExecutionCallback final : public V1_3::IFencedExecutionCallback {
public:
explicit FencedExecutionCallback(const nn::ExecuteFencedInfoCallback& callback)
@@ -148,8 +157,7 @@
const std::any resource = preparedModel->getUnderlyingResource();
if (const auto* model = std::any_cast<const nn::Model*>(&resource)) {
CHECK(*model != nullptr);
- NN_TRY(utils::makeGeneralFailure(nn::validateRequestForModel(nnRequest, **model),
- nn::ErrorStatus::INVALID_ARGUMENT));
+ NN_TRY(adapter::validateRequestForModel(nnRequest, **model));
}
Task task = [preparedModel, nnRequest = std::move(nnRequest), callback] {
@@ -175,8 +183,7 @@
const std::any resource = preparedModel->getUnderlyingResource();
if (const auto* model = std::any_cast<const nn::Model*>(&resource)) {
CHECK(*model != nullptr);
- NN_TRY(utils::makeGeneralFailure(nn::validateRequestForModel(nnRequest, **model),
- nn::ErrorStatus::INVALID_ARGUMENT));
+ NN_TRY(adapter::validateRequestForModel(nnRequest, **model));
}
Task task = [preparedModel, nnRequest = std::move(nnRequest), nnMeasure, callback] {
@@ -206,8 +213,7 @@
const std::any resource = preparedModel->getUnderlyingResource();
if (const auto* model = std::any_cast<const nn::Model*>(&resource)) {
CHECK(*model != nullptr);
- NN_TRY(utils::makeGeneralFailure(nn::validateRequestForModel(nnRequest, **model),
- nn::ErrorStatus::INVALID_ARGUMENT));
+ NN_TRY(adapter::validateRequestForModel(nnRequest, **model));
}
Task task = [preparedModel, nnRequest = std::move(nnRequest), nnMeasure, nnDeadline,
@@ -224,14 +230,14 @@
nn::ExecutionResult<std::pair<hidl_vec<V1_2::OutputShape>, V1_2::Timing>> executeSynchronously(
const nn::SharedPreparedModel& preparedModel, const V1_0::Request& request,
V1_2::MeasureTiming measure) {
- const auto nnRequest = NN_TRY(utils::makeExecutionFailure(convertInput(request)));
- const auto nnMeasure = NN_TRY(utils::makeExecutionFailure(convertInput(measure)));
+ const auto nnRequest = NN_TRY(convertInput(request));
+ const auto nnMeasure = NN_TRY(convertInput(measure));
const auto [outputShapes, timing] =
NN_TRY(preparedModel->execute(nnRequest, nnMeasure, {}, {}));
- auto hidlOutputShapes = NN_TRY(utils::makeExecutionFailure(V1_2::utils::convert(outputShapes)));
- const auto hidlTiming = NN_TRY(utils::makeExecutionFailure(V1_2::utils::convert(timing)));
+ auto hidlOutputShapes = NN_TRY(V1_2::utils::convert(outputShapes));
+ const auto hidlTiming = NN_TRY(V1_2::utils::convert(timing));
return std::make_pair(std::move(hidlOutputShapes), hidlTiming);
}
@@ -239,29 +245,30 @@
const nn::SharedPreparedModel& preparedModel, const V1_3::Request& request,
V1_2::MeasureTiming measure, const V1_3::OptionalTimePoint& deadline,
const V1_3::OptionalTimeoutDuration& loopTimeoutDuration) {
- const auto nnRequest = NN_TRY(utils::makeExecutionFailure(convertInput(request)));
- const auto nnMeasure = NN_TRY(utils::makeExecutionFailure(convertInput(measure)));
- const auto nnDeadline = NN_TRY(utils::makeExecutionFailure(convertInput(deadline)));
- const auto nnLoopTimeoutDuration =
- NN_TRY(utils::makeExecutionFailure(convertInput(loopTimeoutDuration)));
+ const auto nnRequest = NN_TRY(convertInput(request));
+ const auto nnMeasure = NN_TRY(convertInput(measure));
+ const auto nnDeadline = NN_TRY(convertInput(deadline));
+ const auto nnLoopTimeoutDuration = NN_TRY(convertInput(loopTimeoutDuration));
const auto [outputShapes, timing] =
NN_TRY(preparedModel->execute(nnRequest, nnMeasure, nnDeadline, nnLoopTimeoutDuration));
- auto hidlOutputShapes = NN_TRY(utils::makeExecutionFailure(V1_3::utils::convert(outputShapes)));
- const auto hidlTiming = NN_TRY(utils::makeExecutionFailure(V1_3::utils::convert(timing)));
+ auto hidlOutputShapes = NN_TRY(V1_3::utils::convert(outputShapes));
+ const auto hidlTiming = NN_TRY(V1_3::utils::convert(timing));
return std::make_pair(std::move(hidlOutputShapes), hidlTiming);
}
nn::GeneralResult<std::vector<nn::SyncFence>> convertSyncFences(
const hidl_vec<hidl_handle>& handles) {
+ auto nnHandles = NN_TRY(convertInput(handles));
std::vector<nn::SyncFence> syncFences;
syncFences.reserve(handles.size());
- for (const auto& handle : handles) {
- auto nativeHandle = NN_TRY(convertInput(handle));
- auto syncFence = NN_TRY(utils::makeGeneralFailure(
- nn::SyncFence::create(std::move(nativeHandle)), nn::ErrorStatus::INVALID_ARGUMENT));
- syncFences.push_back(std::move(syncFence));
+ for (auto&& handle : nnHandles) {
+ if (auto syncFence = nn::SyncFence::create(std::move(handle)); !syncFence.ok()) {
+ return nn::error(nn::ErrorStatus::INVALID_ARGUMENT) << std::move(syncFence).error();
+ } else {
+ syncFences.push_back(std::move(syncFence).value());
+ }
}
return syncFences;
}
diff --git a/neuralnetworks/utils/common/Android.bp b/neuralnetworks/utils/common/Android.bp
index 431885c..f88e407 100644
--- a/neuralnetworks/utils/common/Android.bp
+++ b/neuralnetworks/utils/common/Android.bp
@@ -35,7 +35,7 @@
"neuralnetworks_types",
],
shared_libs: [
- "android.hardware.neuralnetworks-V1-ndk",
+ "android.hardware.neuralnetworks-V2-ndk",
"libhidlbase",
"libbinder_ndk",
],
diff --git a/neuralnetworks/utils/common/include/nnapi/hal/HandleError.h b/neuralnetworks/utils/common/include/nnapi/hal/HandleError.h
index 209b663..e51f916 100644
--- a/neuralnetworks/utils/common/include/nnapi/hal/HandleError.h
+++ b/neuralnetworks/utils/common/include/nnapi/hal/HandleError.h
@@ -52,38 +52,6 @@
std::move(result).value(); \
})
-template <typename Type>
-nn::GeneralResult<Type> makeGeneralFailure(
- nn::Result<Type> result, nn::ErrorStatus status = nn::ErrorStatus::GENERAL_FAILURE) {
- if (!result.has_value()) {
- return nn::error(status) << std::move(result).error();
- }
- if constexpr (!std::is_same_v<Type, void>) {
- return std::move(result).value();
- } else {
- return {};
- }
-}
-
-template <typename Type>
-nn::ExecutionResult<Type> makeExecutionFailure(nn::GeneralResult<Type> result) {
- if (!result.has_value()) {
- const auto [message, status] = std::move(result).error();
- return nn::error(status) << message;
- }
- if constexpr (!std::is_same_v<Type, void>) {
- return std::move(result).value();
- } else {
- return {};
- }
-}
-
-template <typename Type>
-nn::ExecutionResult<Type> makeExecutionFailure(
- nn::Result<Type> result, nn::ErrorStatus status = nn::ErrorStatus::GENERAL_FAILURE) {
- return makeExecutionFailure(makeGeneralFailure(result, status));
-}
-
#define HANDLE_HAL_STATUS(status) \
if (const auto canonical = ::android::nn::convert(status).value_or( \
::android::nn::ErrorStatus::GENERAL_FAILURE); \
diff --git a/neuralnetworks/utils/common/src/CommonUtils.cpp b/neuralnetworks/utils/common/src/CommonUtils.cpp
index ae02c88..235ba29 100644
--- a/neuralnetworks/utils/common/src/CommonUtils.cpp
+++ b/neuralnetworks/utils/common/src/CommonUtils.cpp
@@ -333,7 +333,7 @@
nn::GeneralResult<std::vector<uint32_t>> countNumberOfConsumers(
size_t numberOfOperands, const std::vector<nn::Operation>& operations) {
- return makeGeneralFailure(nn::countNumberOfConsumers(numberOfOperands, operations));
+ return nn::countNumberOfConsumers(numberOfOperands, operations);
}
nn::GeneralResult<hidl_memory> createHidlMemoryFromSharedMemory(const nn::SharedMemory& memory) {
diff --git a/neuralnetworks/utils/service/Android.bp b/neuralnetworks/utils/service/Android.bp
index 653e51a..fbb8679 100644
--- a/neuralnetworks/utils/service/Android.bp
+++ b/neuralnetworks/utils/service/Android.bp
@@ -39,7 +39,7 @@
"neuralnetworks_utils_hal_common",
],
shared_libs: [
- "android.hardware.neuralnetworks-V1-ndk",
+ "android.hardware.neuralnetworks-V2-ndk",
"android.hardware.neuralnetworks@1.0",
"android.hardware.neuralnetworks@1.1",
"android.hardware.neuralnetworks@1.2",
diff --git a/radio/1.0/vts/OWNERS b/radio/1.0/vts/OWNERS
index 9310f8e..117692a 100644
--- a/radio/1.0/vts/OWNERS
+++ b/radio/1.0/vts/OWNERS
@@ -1,7 +1,5 @@
-# Telephony team
-amitmahajan@google.com
+# Bug component: 20868
+jminjie@google.com
+sarahchin@google.com
shuoq@google.com
jackyu@google.com
-
-# VTS team
-dshi@google.com
diff --git a/radio/1.1/vts/OWNERS b/radio/1.1/vts/OWNERS
index a07c917..4d199ca 100644
--- a/radio/1.1/vts/OWNERS
+++ b/radio/1.1/vts/OWNERS
@@ -1 +1,2 @@
+# Bug component: 20868
include ../../1.0/vts/OWNERS
diff --git a/radio/1.2/vts/OWNERS b/radio/1.2/vts/OWNERS
index a07c917..4d199ca 100644
--- a/radio/1.2/vts/OWNERS
+++ b/radio/1.2/vts/OWNERS
@@ -1 +1,2 @@
+# Bug component: 20868
include ../../1.0/vts/OWNERS
diff --git a/radio/1.3/vts/OWNERS b/radio/1.3/vts/OWNERS
index a07c917..4d199ca 100644
--- a/radio/1.3/vts/OWNERS
+++ b/radio/1.3/vts/OWNERS
@@ -1 +1,2 @@
+# Bug component: 20868
include ../../1.0/vts/OWNERS
diff --git a/radio/1.4/vts/OWNERS b/radio/1.4/vts/OWNERS
index a07c917..4d199ca 100644
--- a/radio/1.4/vts/OWNERS
+++ b/radio/1.4/vts/OWNERS
@@ -1 +1,2 @@
+# Bug component: 20868
include ../../1.0/vts/OWNERS
diff --git a/radio/1.5/vts/OWNERS b/radio/1.5/vts/OWNERS
index a07c917..4d199ca 100644
--- a/radio/1.5/vts/OWNERS
+++ b/radio/1.5/vts/OWNERS
@@ -1 +1,2 @@
+# Bug component: 20868
include ../../1.0/vts/OWNERS
diff --git a/radio/1.6/vts/functional/radio_hidl_hal_api.cpp b/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
index e07d2ba..d3f0cf9 100644
--- a/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
@@ -32,23 +32,17 @@
EXPECT_EQ(std::cv_status::no_timeout, wait());
EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
-
- if (getRadioHalCapabilities()) {
- ASSERT_TRUE(CheckAnyOfErrors(
- radioRsp_v1_6->rspInfo.error,
- {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
- } else {
- ASSERT_TRUE(CheckAnyOfErrors(
- radioRsp_v1_6->rspInfo.error,
- {::android::hardware::radio::V1_6::RadioError::NONE,
- ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
- ::android::hardware::radio::V1_6::RadioError::OPERATION_NOT_ALLOWED,
- ::android::hardware::radio::V1_6::RadioError::MODE_NOT_SUPPORTED,
- ::android::hardware::radio::V1_6::RadioError::INTERNAL_ERR,
- ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
- ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
- ::android::hardware::radio::V1_6::RadioError::NO_RESOURCES}));
- }
+ ASSERT_TRUE(
+ CheckAnyOfErrors(radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::NONE,
+ ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+ ::android::hardware::radio::V1_6::RadioError::OPERATION_NOT_ALLOWED,
+ ::android::hardware::radio::V1_6::RadioError::MODE_NOT_SUPPORTED,
+ ::android::hardware::radio::V1_6::RadioError::INTERNAL_ERR,
+ ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
+ ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
+ ::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED,
+ ::android::hardware::radio::V1_6::RadioError::NO_RESOURCES}));
}
/*
@@ -74,23 +68,17 @@
EXPECT_EQ(std::cv_status::no_timeout, wait());
EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
-
- if (getRadioHalCapabilities()) {
- ASSERT_TRUE(CheckAnyOfErrors(
- radioRsp_v1_6->rspInfo.error,
- {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
- } else {
- ASSERT_TRUE(CheckAnyOfErrors(
- radioRsp_v1_6->rspInfo.error,
- {::android::hardware::radio::V1_6::RadioError::NONE,
- ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
- ::android::hardware::radio::V1_6::RadioError::OPERATION_NOT_ALLOWED,
- ::android::hardware::radio::V1_6::RadioError::MODE_NOT_SUPPORTED,
- ::android::hardware::radio::V1_6::RadioError::INTERNAL_ERR,
- ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
- ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
- ::android::hardware::radio::V1_6::RadioError::NO_RESOURCES}));
- }
+ ASSERT_TRUE(CheckAnyOfErrors(
+ radioRsp_v1_6->rspInfo.error,
+ {::android::hardware::radio::V1_6::RadioError::NONE,
+ ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+ ::android::hardware::radio::V1_6::RadioError::OPERATION_NOT_ALLOWED,
+ ::android::hardware::radio::V1_6::RadioError::MODE_NOT_SUPPORTED,
+ ::android::hardware::radio::V1_6::RadioError::INTERNAL_ERR,
+ ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
+ ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
+ ::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED,
+ ::android::hardware::radio::V1_6::RadioError::NO_RESOURCES}));
}
}
diff --git a/radio/config/1.1/vts/OWNERS b/radio/config/1.1/vts/OWNERS
new file mode 100644
index 0000000..4109967
--- /dev/null
+++ b/radio/config/1.1/vts/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 20868
+include /radio/1.0/vts/OWNERS
diff --git a/radio/config/1.2/vts/OWNERS b/radio/config/1.2/vts/OWNERS
new file mode 100644
index 0000000..4109967
--- /dev/null
+++ b/radio/config/1.2/vts/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 20868
+include /radio/1.0/vts/OWNERS
diff --git a/renderscript/1.0/vts/functional/OWNERS b/renderscript/1.0/vts/functional/OWNERS
new file mode 100644
index 0000000..d785790
--- /dev/null
+++ b/renderscript/1.0/vts/functional/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 43047
+butlermichael@google.com
+dgross@google.com
+jeanluc@google.com
+miaowang@google.com
+xusongw@google.com
diff --git a/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp b/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
index d7abf07..6f2f189 100644
--- a/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
+++ b/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
@@ -64,7 +64,9 @@
* attestation.
*/
TEST_P(DeviceUniqueAttestationTest, RsaNonStrongBoxUnimplemented) {
- if (SecLevel() == SecurityLevel::STRONGBOX) return;
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ GTEST_SKIP() << "Test not applicable to StrongBox device";
+ }
vector<uint8_t> key_blob;
vector<KeyCharacteristics> key_characteristics;
@@ -91,7 +93,9 @@
* attestation.
*/
TEST_P(DeviceUniqueAttestationTest, EcdsaNonStrongBoxUnimplemented) {
- if (SecLevel() == SecurityLevel::STRONGBOX) return;
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ GTEST_SKIP() << "Test not applicable to StrongBox device";
+ }
vector<uint8_t> key_blob;
vector<KeyCharacteristics> key_characteristics;
@@ -117,7 +121,9 @@
* attestation correctly, if implemented.
*/
TEST_P(DeviceUniqueAttestationTest, RsaDeviceUniqueAttestation) {
- if (SecLevel() != SecurityLevel::STRONGBOX) return;
+ if (SecLevel() != SecurityLevel::STRONGBOX) {
+ GTEST_SKIP() << "Test not applicable to non-StrongBox device";
+ }
vector<uint8_t> key_blob;
vector<KeyCharacteristics> key_characteristics;
@@ -174,7 +180,9 @@
* attestation correctly, if implemented.
*/
TEST_P(DeviceUniqueAttestationTest, EcdsaDeviceUniqueAttestation) {
- if (SecLevel() != SecurityLevel::STRONGBOX) return;
+ if (SecLevel() != SecurityLevel::STRONGBOX) {
+ GTEST_SKIP() << "Test not applicable to non-StrongBox device";
+ }
vector<uint8_t> key_blob;
vector<KeyCharacteristics> key_characteristics;
@@ -226,7 +234,9 @@
* local device.
*/
TEST_P(DeviceUniqueAttestationTest, EcdsaDeviceUniqueAttestationID) {
- if (SecLevel() != SecurityLevel::STRONGBOX) return;
+ if (SecLevel() != SecurityLevel::STRONGBOX) {
+ GTEST_SKIP() << "Test not applicable to non-StrongBox device";
+ }
// Collection of valid attestation ID tags.
auto attestation_id_tags = AuthorizationSetBuilder();
@@ -292,7 +302,9 @@
* don't match the local device.
*/
TEST_P(DeviceUniqueAttestationTest, EcdsaDeviceUniqueAttestationMismatchID) {
- if (SecLevel() != SecurityLevel::STRONGBOX) return;
+ if (SecLevel() != SecurityLevel::STRONGBOX) {
+ GTEST_SKIP() << "Test not applicable to non-StrongBox device";
+ }
// Collection of invalid attestation ID tags.
auto attestation_id_tags =
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index fe8b48f..53d980d 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -1482,6 +1482,7 @@
.Authorization(TAG_TRUSTED_CONFIRMATION_REQUIRED)
.Authorization(TAG_UNLOCKED_DEVICE_REQUIRED)
.Authorization(TAG_CREATION_DATETIME, 1619621648000);
+
for (const KeyParameter& tag : extra_tags) {
SCOPED_TRACE(testing::Message() << "tag-" << tag);
vector<uint8_t> key_blob;
@@ -1520,19 +1521,19 @@
CheckedDeleteKey(&key_blob);
}
- // Device attestation IDs should be rejected for normal attestation requests; these fields
- // are only used for device unique attestation.
- auto invalid_tags = AuthorizationSetBuilder()
- .Authorization(TAG_ATTESTATION_ID_BRAND, "brand")
- .Authorization(TAG_ATTESTATION_ID_DEVICE, "device")
- .Authorization(TAG_ATTESTATION_ID_PRODUCT, "product")
- .Authorization(TAG_ATTESTATION_ID_SERIAL, "serial")
- .Authorization(TAG_ATTESTATION_ID_IMEI, "imei")
- .Authorization(TAG_ATTESTATION_ID_MEID, "meid")
- .Authorization(TAG_ATTESTATION_ID_MANUFACTURER, "manufacturer")
- .Authorization(TAG_ATTESTATION_ID_MODEL, "model");
+ // Collection of invalid attestation ID tags.
+ auto invalid_tags =
+ AuthorizationSetBuilder()
+ .Authorization(TAG_ATTESTATION_ID_BRAND, "bogus-brand")
+ .Authorization(TAG_ATTESTATION_ID_DEVICE, "devious-device")
+ .Authorization(TAG_ATTESTATION_ID_PRODUCT, "punctured-product")
+ .Authorization(TAG_ATTESTATION_ID_SERIAL, "suspicious-serial")
+ .Authorization(TAG_ATTESTATION_ID_IMEI, "invalid-imei")
+ .Authorization(TAG_ATTESTATION_ID_MEID, "mismatching-meid")
+ .Authorization(TAG_ATTESTATION_ID_MANUFACTURER, "malformed-manufacturer")
+ .Authorization(TAG_ATTESTATION_ID_MODEL, "malicious-model");
for (const KeyParameter& tag : invalid_tags) {
- SCOPED_TRACE(testing::Message() << "tag-" << tag);
+ SCOPED_TRACE(testing::Message() << "-incorrect-tag-" << tag);
vector<uint8_t> key_blob;
vector<KeyCharacteristics> key_characteristics;
AuthorizationSetBuilder builder =
@@ -1552,6 +1553,74 @@
}
/*
+ * NewKeyGenerationTest.EcdsaAttestationIdTags
+ *
+ * Verifies that creation of an attested ECDSA key includes various ID tags in the
+ * attestation extension.
+ */
+TEST_P(NewKeyGenerationTest, EcdsaAttestationIdTags) {
+ auto challenge = "hello";
+ auto app_id = "foo";
+ auto subject = "cert subj 2";
+ vector<uint8_t> subject_der(make_name_from_str(subject));
+ uint64_t serial_int = 0x1010;
+ vector<uint8_t> serial_blob(build_serial_blob(serial_int));
+ const AuthorizationSetBuilder base_builder =
+ AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Digest(Digest::NONE)
+ .AttestationChallenge(challenge)
+ .AttestationApplicationId(app_id)
+ .Authorization(TAG_CERTIFICATE_SERIAL, serial_blob)
+ .Authorization(TAG_CERTIFICATE_SUBJECT, subject_der)
+ .SetDefaultValidity();
+
+ // Various ATTESTATION_ID_* tags that map to fields in the attestation extension ASN.1 schema.
+ auto extra_tags = AuthorizationSetBuilder();
+ add_tag_from_prop(&extra_tags, TAG_ATTESTATION_ID_BRAND, "ro.product.brand");
+ add_tag_from_prop(&extra_tags, TAG_ATTESTATION_ID_DEVICE, "ro.product.device");
+ add_tag_from_prop(&extra_tags, TAG_ATTESTATION_ID_PRODUCT, "ro.product.name");
+ add_tag_from_prop(&extra_tags, TAG_ATTESTATION_ID_SERIAL, "ro.serial");
+ add_tag_from_prop(&extra_tags, TAG_ATTESTATION_ID_MANUFACTURER, "ro.product.manufacturer");
+ add_tag_from_prop(&extra_tags, TAG_ATTESTATION_ID_MODEL, "ro.product.model");
+
+ for (const KeyParameter& tag : extra_tags) {
+ SCOPED_TRACE(testing::Message() << "tag-" << tag);
+ vector<uint8_t> key_blob;
+ vector<KeyCharacteristics> key_characteristics;
+ AuthorizationSetBuilder builder = base_builder;
+ builder.push_back(tag);
+ auto result = GenerateKey(builder, &key_blob, &key_characteristics);
+ if (result == ErrorCode::CANNOT_ATTEST_IDS) {
+ // Device ID attestation is optional; KeyMint may not support it at all.
+ continue;
+ }
+ ASSERT_EQ(result, ErrorCode::OK);
+ ASSERT_GT(key_blob.size(), 0U);
+
+ EXPECT_TRUE(ChainSignaturesAreValid(cert_chain_));
+ ASSERT_GT(cert_chain_.size(), 0);
+ verify_subject_and_serial(cert_chain_[0], serial_int, subject, /* self_signed = */ false);
+
+ AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
+ AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
+
+ // The attested key characteristics will not contain APPLICATION_ID_* fields (their
+ // spec definitions all have "Must never appear in KeyCharacteristics"), but the
+ // attestation extension should contain them, so make sure the extra tag is added.
+ hw_enforced.push_back(tag);
+
+ // Verifying the attestation record will check for the specific tag because
+ // it's included in the authorizations.
+ EXPECT_TRUE(verify_attestation_record(challenge, app_id, sw_enforced, hw_enforced,
+ SecLevel(), cert_chain_[0].encodedCertificate));
+
+ CheckedDeleteKey(&key_blob);
+ }
+}
+
+/*
* NewKeyGenerationTest.EcdsaAttestationTagNoApplicationId
*
* Verifies that creation of an attested ECDSA key does not include APPLICATION_ID.
@@ -1840,7 +1909,9 @@
* INVALID_ARGUMENT.
*/
TEST_P(NewKeyGenerationTest, EcdsaMismatchKeySize) {
- if (SecLevel() == SecurityLevel::STRONGBOX) return;
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ GTEST_SKIP() << "Test not applicable to StrongBox device";
+ }
auto result = GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_ALGORITHM, Algorithm::EC)
@@ -2067,7 +2138,9 @@
* Verifies that keymint rejects HMAC key generation with multiple specified digest algorithms.
*/
TEST_P(NewKeyGenerationTest, HmacMultipleDigests) {
- if (SecLevel() == SecurityLevel::STRONGBOX) return;
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ GTEST_SKIP() << "Test not applicable to StrongBox device";
+ }
ASSERT_EQ(ErrorCode::UNSUPPORTED_DIGEST,
GenerateKey(AuthorizationSetBuilder()
@@ -2291,7 +2364,9 @@
* presented.
*/
TEST_P(SigningOperationsTest, NoUserConfirmation) {
- if (SecLevel() == SecurityLevel::STRONGBOX) return;
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ GTEST_SKIP() << "Test not applicable to StrongBox device";
+ }
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
.RsaSigningKey(1024, 65537)
.Digest(Digest::NONE)
@@ -2381,7 +2456,9 @@
* for a 1024-bit key.
*/
TEST_P(SigningOperationsTest, RsaPssSha512TooSmallKey) {
- if (SecLevel() == SecurityLevel::STRONGBOX) return;
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ GTEST_SKIP() << "Test not applicable to StrongBox device";
+ }
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
.RsaSigningKey(1024, 65537)
.Digest(Digest::SHA_2_512)
@@ -3200,7 +3277,9 @@
* Verifies that importing and using an ECDSA P-521 key pair works correctly.
*/
TEST_P(ImportKeyTest, Ecdsa521Success) {
- if (SecLevel() == SecurityLevel::STRONGBOX) return;
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ GTEST_SKIP() << "Test not applicable to StrongBox device";
+ }
ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
.EcdsaSigningKey(EcCurve::P_521)
@@ -3909,7 +3988,9 @@
* with a different digest than was used to encrypt.
*/
TEST_P(EncryptionOperationsTest, RsaOaepDecryptWithWrongDigest) {
- if (SecLevel() == SecurityLevel::STRONGBOX) return;
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ GTEST_SKIP() << "Test not applicable to StrongBox device";
+ }
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
@@ -5823,7 +5904,9 @@
* Verifies that the max uses per boot tag works correctly with AES keys.
*/
TEST_P(MaxOperationsTest, TestLimitAes) {
- if (SecLevel() == SecurityLevel::STRONGBOX) return;
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ GTEST_SKIP() << "Test not applicable to StrongBox device";
+ }
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
@@ -5850,7 +5933,9 @@
* Verifies that the max uses per boot tag works correctly with RSA keys.
*/
TEST_P(MaxOperationsTest, TestLimitRsa) {
- if (SecLevel() == SecurityLevel::STRONGBOX) return;
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ GTEST_SKIP() << "Test not applicable to StrongBox device";
+ }
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
@@ -5881,7 +5966,9 @@
* Verifies that the usage count limit tag = 1 works correctly with AES keys.
*/
TEST_P(UsageCountLimitTest, TestSingleUseAes) {
- if (SecLevel() == SecurityLevel::STRONGBOX) return;
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ GTEST_SKIP() << "Test not applicable to StrongBox device";
+ }
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
@@ -5925,7 +6012,9 @@
* Verifies that the usage count limit tag > 1 works correctly with AES keys.
*/
TEST_P(UsageCountLimitTest, TestLimitedUseAes) {
- if (SecLevel() == SecurityLevel::STRONGBOX) return;
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ GTEST_SKIP() << "Test not applicable to StrongBox device";
+ }
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
@@ -5970,7 +6059,9 @@
* Verifies that the usage count limit tag = 1 works correctly with RSA keys.
*/
TEST_P(UsageCountLimitTest, TestSingleUseRsa) {
- if (SecLevel() == SecurityLevel::STRONGBOX) return;
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ GTEST_SKIP() << "Test not applicable to StrongBox device";
+ }
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
@@ -6014,7 +6105,9 @@
* Verifies that the usage count limit tag > 1 works correctly with RSA keys.
*/
TEST_P(UsageCountLimitTest, TestLimitUseRsa) {
- if (SecLevel() == SecurityLevel::STRONGBOX) return;
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ GTEST_SKIP() << "Test not applicable to StrongBox device";
+ }
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
@@ -6061,7 +6154,9 @@
* in hardware.
*/
TEST_P(UsageCountLimitTest, TestSingleUseKeyAndRollbackResistance) {
- if (SecLevel() == SecurityLevel::STRONGBOX) return;
+ if (SecLevel() == SecurityLevel::STRONGBOX) {
+ GTEST_SKIP() << "Test not applicable to StrongBox device";
+ }
auto error = GenerateKey(AuthorizationSetBuilder()
.RsaSigningKey(2048, 65537)
@@ -6070,38 +6165,39 @@
.Authorization(TAG_NO_AUTH_REQUIRED)
.Authorization(TAG_ROLLBACK_RESISTANCE)
.SetDefaultValidity());
- ASSERT_TRUE(error == ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE || error == ErrorCode::OK);
-
- if (error == ErrorCode::OK) {
- // Rollback resistance is supported by KeyMint, verify it is enforced in hardware.
- AuthorizationSet hardwareEnforced(SecLevelAuthorizations());
- ASSERT_TRUE(hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE));
- ASSERT_EQ(ErrorCode::OK, DeleteKey());
-
- // The KeyMint should also enforce single use key in hardware when it supports rollback
- // resistance.
- ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
- .Authorization(TAG_NO_AUTH_REQUIRED)
- .RsaSigningKey(1024, 65537)
- .NoDigestOrPadding()
- .Authorization(TAG_USAGE_COUNT_LIMIT, 1)
- .SetDefaultValidity()));
-
- // Check the usage count limit tag appears in the hardware authorizations.
- AuthorizationSet hardware_auths = HwEnforcedAuthorizations(key_characteristics_);
- EXPECT_TRUE(hardware_auths.Contains(TAG_USAGE_COUNT_LIMIT, 1U))
- << "key usage count limit " << 1U << " missing";
-
- string message = "1234567890123456";
- auto params = AuthorizationSetBuilder().NoDigestOrPadding();
-
- // First usage of RSA key should work.
- SignMessage(message, params);
-
- // Usage count limit tag is enforced by hardware. After using the key, the key blob
- // must be invalidated from secure storage (such as RPMB partition).
- EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB, Begin(KeyPurpose::SIGN, params));
+ if (error == ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE) {
+ GTEST_SKIP() << "Rollback resistance not supported";
}
+
+ // Rollback resistance is supported by KeyMint, verify it is enforced in hardware.
+ ASSERT_EQ(ErrorCode::OK, error);
+ AuthorizationSet hardwareEnforced(SecLevelAuthorizations());
+ ASSERT_TRUE(hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE));
+ ASSERT_EQ(ErrorCode::OK, DeleteKey());
+
+ // The KeyMint should also enforce single use key in hardware when it supports rollback
+ // resistance.
+ ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .RsaSigningKey(1024, 65537)
+ .NoDigestOrPadding()
+ .Authorization(TAG_USAGE_COUNT_LIMIT, 1)
+ .SetDefaultValidity()));
+
+ // Check the usage count limit tag appears in the hardware authorizations.
+ AuthorizationSet hardware_auths = HwEnforcedAuthorizations(key_characteristics_);
+ EXPECT_TRUE(hardware_auths.Contains(TAG_USAGE_COUNT_LIMIT, 1U))
+ << "key usage count limit " << 1U << " missing";
+
+ string message = "1234567890123456";
+ auto params = AuthorizationSetBuilder().NoDigestOrPadding();
+
+ // First usage of RSA key should work.
+ SignMessage(message, params);
+
+ // Usage count limit tag is enforced by hardware. After using the key, the key blob
+ // must be invalidated from secure storage (such as RPMB partition).
+ EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB, Begin(KeyPurpose::SIGN, params));
}
INSTANTIATE_KEYMINT_AIDL_TEST(UsageCountLimitTest);
@@ -6178,24 +6274,25 @@
.Authorization(TAG_NO_AUTH_REQUIRED)
.Authorization(TAG_ROLLBACK_RESISTANCE)
.SetDefaultValidity());
- ASSERT_TRUE(error == ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE || error == ErrorCode::OK);
+ if (error == ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE) {
+ GTEST_SKIP() << "Rollback resistance not supported";
+ }
// Delete must work if rollback protection is implemented
- if (error == ErrorCode::OK) {
- AuthorizationSet hardwareEnforced(SecLevelAuthorizations());
- ASSERT_TRUE(hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE));
+ ASSERT_EQ(ErrorCode::OK, error);
+ AuthorizationSet hardwareEnforced(SecLevelAuthorizations());
+ ASSERT_TRUE(hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE));
- ASSERT_EQ(ErrorCode::OK, DeleteKey(true /* keep key blob */));
+ ASSERT_EQ(ErrorCode::OK, DeleteKey(true /* keep key blob */));
- string message = "12345678901234567890123456789012";
- AuthorizationSet begin_out_params;
- EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
- Begin(KeyPurpose::SIGN, key_blob_,
- AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE),
- &begin_out_params));
- AbortIfNeeded();
- key_blob_ = AidlBuf();
- }
+ string message = "12345678901234567890123456789012";
+ AuthorizationSet begin_out_params;
+ EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
+ Begin(KeyPurpose::SIGN, key_blob_,
+ AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE),
+ &begin_out_params));
+ AbortIfNeeded();
+ key_blob_ = AidlBuf();
}
/**
@@ -6212,21 +6309,22 @@
.Authorization(TAG_NO_AUTH_REQUIRED)
.Authorization(TAG_ROLLBACK_RESISTANCE)
.SetDefaultValidity());
- ASSERT_TRUE(error == ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE || error == ErrorCode::OK);
+ if (error == ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE) {
+ GTEST_SKIP() << "Rollback resistance not supported";
+ }
// Delete must work if rollback protection is implemented
- if (error == ErrorCode::OK) {
- AuthorizationSet enforced(SecLevelAuthorizations());
- ASSERT_TRUE(enforced.Contains(TAG_ROLLBACK_RESISTANCE));
+ ASSERT_EQ(ErrorCode::OK, error);
+ AuthorizationSet enforced(SecLevelAuthorizations());
+ ASSERT_TRUE(enforced.Contains(TAG_ROLLBACK_RESISTANCE));
- // Delete the key we don't care about the result at this point.
- DeleteKey();
+ // Delete the key we don't care about the result at this point.
+ DeleteKey();
- // Now create an invalid key blob and delete it.
- key_blob_ = AidlBuf("just some garbage data which is not a valid key blob");
+ // Now create an invalid key blob and delete it.
+ key_blob_ = AidlBuf("just some garbage data which is not a valid key blob");
- ASSERT_EQ(ErrorCode::OK, DeleteKey());
- }
+ ASSERT_EQ(ErrorCode::OK, DeleteKey());
}
/**
@@ -6241,7 +6339,10 @@
* credentials stored in Keystore/Keymint.
*/
TEST_P(KeyDeletionTest, DeleteAllKeys) {
- if (!arm_deleteAllKeys) return;
+ if (!arm_deleteAllKeys) {
+ GTEST_SKIP() << "Option --arm_deleteAllKeys not set";
+ return;
+ }
auto error = GenerateKey(AuthorizationSetBuilder()
.RsaSigningKey(2048, 65537)
.Digest(Digest::NONE)
@@ -6249,25 +6350,26 @@
.Authorization(TAG_NO_AUTH_REQUIRED)
.Authorization(TAG_ROLLBACK_RESISTANCE)
.SetDefaultValidity());
- ASSERT_TRUE(error == ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE || error == ErrorCode::OK);
+ if (error == ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE) {
+ GTEST_SKIP() << "Rollback resistance not supported";
+ }
// Delete must work if rollback protection is implemented
- if (error == ErrorCode::OK) {
- AuthorizationSet hardwareEnforced(SecLevelAuthorizations());
- ASSERT_TRUE(hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE));
+ ASSERT_EQ(ErrorCode::OK, error);
+ AuthorizationSet hardwareEnforced(SecLevelAuthorizations());
+ ASSERT_TRUE(hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE));
- ASSERT_EQ(ErrorCode::OK, DeleteAllKeys());
+ ASSERT_EQ(ErrorCode::OK, DeleteAllKeys());
- string message = "12345678901234567890123456789012";
- AuthorizationSet begin_out_params;
+ string message = "12345678901234567890123456789012";
+ AuthorizationSet begin_out_params;
- EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
- Begin(KeyPurpose::SIGN, key_blob_,
- AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE),
- &begin_out_params));
- AbortIfNeeded();
- key_blob_ = AidlBuf();
- }
+ EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
+ Begin(KeyPurpose::SIGN, key_blob_,
+ AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE),
+ &begin_out_params));
+ AbortIfNeeded();
+ key_blob_ = AidlBuf();
}
INSTANTIATE_KEYMINT_AIDL_TEST(KeyDeletionTest);
@@ -6340,7 +6442,7 @@
size_t i;
for (i = 0; i < max_operations; i++) {
- result = Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params, op_handles[i]);
+ result = Begin(KeyPurpose::DECRYPT, key_blob_, params, &out_params, op_handles[i]);
if (ErrorCode::OK != result) {
break;
}
@@ -6348,12 +6450,12 @@
EXPECT_EQ(ErrorCode::TOO_MANY_OPERATIONS, result);
// Try again just in case there's a weird overflow bug
EXPECT_EQ(ErrorCode::TOO_MANY_OPERATIONS,
- Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params));
+ Begin(KeyPurpose::DECRYPT, key_blob_, params, &out_params));
for (size_t j = 0; j < i; j++) {
EXPECT_EQ(ErrorCode::OK, Abort(op_handles[j]))
<< "Aboort failed for i = " << j << std::endl;
}
- EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params));
+ EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, key_blob_, params, &out_params));
AbortIfNeeded();
}
diff --git a/uwb/aidl/Android.bp b/uwb/aidl/Android.bp
index 5d21753..0d1ebc2 100755
--- a/uwb/aidl/Android.bp
+++ b/uwb/aidl/Android.bp
@@ -17,6 +17,7 @@
backend: {
java: {
sdk_version: "module_current",
+ enabled: false,
},
ndk: {
vndk: {
@@ -37,3 +38,29 @@
},
},
}
+
+aidl_interface {
+ name: "android.hardware.uwb.fira_android",
+ vendor_available: true,
+ srcs: ["android/hardware/uwb/fira_android/*.aidl"],
+ stability: "vintf",
+ backend: {
+ java: {
+ sdk_version: "module_current",
+ enabled: true,
+ apex_available: [
+ "com.android.uwb",
+ ],
+ },
+ ndk: {
+ vndk: {
+ enabled: true,
+ },
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.uwb",
+ ],
+ min_sdk_version: "current",
+ },
+ },
+}
diff --git a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorGids.aidl b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorGids.aidl
new file mode 100644
index 0000000..b0d88e0
--- /dev/null
+++ b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorGids.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.uwb.fira_android;
+@Backing(type="byte") @VintfStability
+enum UwbVendorGids {
+ ANDROID = 14,
+}
diff --git a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorSessionSetAppConfigCmdParams.aidl b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorSessionSetAppConfigCmdParams.aidl
new file mode 100644
index 0000000..37b7efb
--- /dev/null
+++ b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorSessionSetAppConfigCmdParams.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.uwb.fira_android;
+@Backing(type="int") @VintfStability
+enum UwbVendorSessionSetAppConfigCmdParams {
+ CCC_RANGING_PROTOCOL_VER = 163,
+ CCC_UWB_CONFIG_ID = 164,
+ CCC_PULSESHAPE_COMBO = 165,
+ CCC_URSK_TTL = 166,
+}
diff --git a/uwb/aidl/android/hardware/uwb/fira_android/README.md b/uwb/aidl/android/hardware/uwb/fira_android/README.md
new file mode 100644
index 0000000..e658d93
--- /dev/null
+++ b/uwb/aidl/android/hardware/uwb/fira_android/README.md
@@ -0,0 +1,15 @@
+The `android.hardware.uwb.fira_android` package is used to add any Android specific
+additions to the UCI specification defined by FIRA standards body. These
+additions should be added to the vendor specific portions carved out in the UCI
+specification.
+
+These include:
+ - Android specific GIDs/OIDs for commands/responses/notifications.
+ - Andriod specific params in an existing UCI specified command/response/notification.
+
+All other interactions sent/received over the HAL interface is expected to
+comply with the UCI specification that can be found [here](
+https://groups.firaconsortium.org/wg/Technical/document/folder/127).
+
+TODO([b/196004116](b/196004116)): Link to the published specification.
+
diff --git a/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorGids.aidl b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorGids.aidl
new file mode 100644
index 0000000..c7bc6b0
--- /dev/null
+++ b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorGids.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 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.uwb.fira_android;
+
+/**
+ * Android specific vendor command GIDs (Group ID) should be defined here.
+ *
+ * For each vendor GID defined here, also create a corresponding AIDL file enumerating the
+ * OIDs (Opcode Identifier) allowed within that GID.
+ * For ex: VENDOR_GID_XXX = 1110b -> UwbVendorGidXXXOids.aidl
+ */
+@VintfStability
+@Backing(type="byte")
+enum UwbVendorGids {
+ /**
+ * Use values from the Proprietary Group range: 1110b – 1111b defined in Table 36 of
+ * UCI specification.
+ */
+
+ /** All Android specific commands/response/notification should use this GID */
+ ANDROID = 0xE,
+}
diff --git a/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorSessionSetAppConfigCmdParams.aidl b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorSessionSetAppConfigCmdParams.aidl
new file mode 100644
index 0000000..850e2da
--- /dev/null
+++ b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorSessionSetAppConfigCmdParams.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 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.uwb.fira_android;
+
+/**
+ * Android specific vendor app params set in UCI command:
+ * GID: 0001b (UWB Session config Group)
+ * OID: 000011b (SESSION_SET_APP_CONFIG_CMD)
+ *
+ * Note: Refer to Table 34 of the UCI specification for the other params
+ * expected in this command.
+ */
+@VintfStability
+@Backing(type="int")
+enum UwbVendorSessionSetAppConfigCmdParams {
+ /** CCC params for ranging start */
+
+ /** Added in vendor version 0. */
+ CCC_RANGING_PROTOCOL_VER = 0xA3,
+ CCC_UWB_CONFIG_ID = 0xA4,
+ CCC_PULSESHAPE_COMBO = 0xA5,
+ CCC_URSK_TTL = 0xA6,
+}
diff --git a/vibrator/1.0/vts/OWNERS b/vibrator/1.0/vts/OWNERS
new file mode 100644
index 0000000..75b9a4b
--- /dev/null
+++ b/vibrator/1.0/vts/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 345036
+michaelwr@google.com
+leungv@google.com
diff --git a/vibrator/1.1/vts/OWNERS b/vibrator/1.1/vts/OWNERS
new file mode 100644
index 0000000..44bfe56
--- /dev/null
+++ b/vibrator/1.1/vts/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 345036
+include ../../1.0/vts/OWNERS
diff --git a/vibrator/1.2/vts/OWNERS b/vibrator/1.2/vts/OWNERS
new file mode 100644
index 0000000..44bfe56
--- /dev/null
+++ b/vibrator/1.2/vts/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 345036
+include ../../1.0/vts/OWNERS
diff --git a/vibrator/1.3/vts/OWNERS b/vibrator/1.3/vts/OWNERS
new file mode 100644
index 0000000..44bfe56
--- /dev/null
+++ b/vibrator/1.3/vts/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 345036
+include ../../1.0/vts/OWNERS
diff --git a/vibrator/aidl/OWNERS b/vibrator/aidl/OWNERS
index 4bd5614..ae10db6 100644
--- a/vibrator/aidl/OWNERS
+++ b/vibrator/aidl/OWNERS
@@ -1,4 +1,4 @@
+# Bug component: 345036
+include platform/frameworks/base:/services/core/java/com/android/server/vibrator/OWNERS
chasewu@google.com
leungv@google.com
-lsandrade@google.com
-michaelwr@google.com
diff --git a/weaver/1.0/vts/functional/OWNERS b/weaver/1.0/vts/functional/OWNERS
new file mode 100644
index 0000000..ec8c304
--- /dev/null
+++ b/weaver/1.0/vts/functional/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 186411
+chengyouho@google.com
+frankwoo@google.com
diff --git a/wifi/1.0/vts/OWNERS b/wifi/1.0/vts/OWNERS
index cf81c79..287152d 100644
--- a/wifi/1.0/vts/OWNERS
+++ b/wifi/1.0/vts/OWNERS
@@ -1,2 +1,3 @@
+# Bug component: 33618
arabawy@google.com
etancohen@google.com
diff --git a/wifi/1.0/vts/functional/Android.bp b/wifi/1.0/vts/functional/Android.bp
index e4948b4..6c0ebf7 100644
--- a/wifi/1.0/vts/functional/Android.bp
+++ b/wifi/1.0/vts/functional/Android.bp
@@ -107,8 +107,10 @@
static_libs: [
"VtsHalWifiV1_0TargetTestUtil",
"android.hardware.wifi@1.0",
+ "android.hardware.wifi.hostapd@1.0",
"libwifi-system-iface",
],
+ disable_framework: true,
test_suites: [
"general-tests",
"vts",
diff --git a/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp
index 96b4501..28b1616 100644
--- a/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_ap_iface_hidl_test.cpp
@@ -15,9 +15,9 @@
*/
#include <android-base/logging.h>
-
#include <android/hardware/wifi/1.0/IWifi.h>
#include <android/hardware/wifi/1.0/IWifiApIface.h>
+#include <android/hardware/wifi/hostapd/1.0/IHostapd.h>
#include <gtest/gtest.h>
#include <hidl/GtestPrinter.h>
#include <hidl/ServiceManagement.h>
@@ -26,6 +26,7 @@
#include "wifi_hidl_test_utils.h"
using ::android::sp;
+using ::android::hardware::wifi::hostapd::V1_0::IHostapd;
using ::android::hardware::wifi::V1_0::IfaceType;
using ::android::hardware::wifi::V1_0::IWifi;
using ::android::hardware::wifi::V1_0::IWifiApIface;
@@ -38,6 +39,10 @@
class WifiApIfaceHidlTest : public ::testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
+ if (android::hardware::getAllHalInstanceNames(IHostapd::descriptor)
+ .empty()) {
+ GTEST_SKIP() << "Device does not support AP";
+ }
// Make sure test starts with a clean state
stopWifi(GetInstanceName());
diff --git a/wifi/1.0/vts/functional/wifi_chip_hidl_ap_test.cpp b/wifi/1.0/vts/functional/wifi_chip_hidl_ap_test.cpp
index 2e6ad32..66e1a80 100644
--- a/wifi/1.0/vts/functional/wifi_chip_hidl_ap_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_chip_hidl_ap_test.cpp
@@ -15,9 +15,9 @@
*/
#include <android-base/logging.h>
-
#include <android/hardware/wifi/1.0/IWifi.h>
#include <android/hardware/wifi/1.0/IWifiChip.h>
+#include <android/hardware/wifi/hostapd/1.0/IHostapd.h>
#include <gtest/gtest.h>
#include <hidl/GtestPrinter.h>
#include <hidl/ServiceManagement.h>
@@ -26,6 +26,7 @@
#include "wifi_hidl_test_utils.h"
using ::android::sp;
+using ::android::hardware::wifi::hostapd::V1_0::IHostapd;
using ::android::hardware::wifi::V1_0::ChipModeId;
using ::android::hardware::wifi::V1_0::IfaceType;
using ::android::hardware::wifi::V1_0::IWifi;
@@ -41,6 +42,10 @@
class WifiChipHidlApTest : public ::testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
+ if (android::hardware::getAllHalInstanceNames(IHostapd::descriptor)
+ .empty()) {
+ GTEST_SKIP() << "Device does not support AP";
+ }
// Make sure test starts with a clean state
stopWifi(GetInstanceName());
diff --git a/wifi/1.1/vts/OWNERS b/wifi/1.1/vts/OWNERS
index cf81c79..294fc82 100644
--- a/wifi/1.1/vts/OWNERS
+++ b/wifi/1.1/vts/OWNERS
@@ -1,2 +1,2 @@
-arabawy@google.com
-etancohen@google.com
+# Bug component: 33618
+include ../../1.0/vts/OWNERS
diff --git a/wifi/1.1/vts/functional/Android.bp b/wifi/1.1/vts/functional/Android.bp
index 8048642..a8f3470 100644
--- a/wifi/1.1/vts/functional/Android.bp
+++ b/wifi/1.1/vts/functional/Android.bp
@@ -39,6 +39,7 @@
"android.hardware.wifi@1.5",
"libwifi-system-iface",
],
+ disable_framework: true,
test_suites: [
"general-tests",
"vts",
diff --git a/wifi/1.2/vts/OWNERS b/wifi/1.2/vts/OWNERS
index cf81c79..294fc82 100644
--- a/wifi/1.2/vts/OWNERS
+++ b/wifi/1.2/vts/OWNERS
@@ -1,2 +1,2 @@
-arabawy@google.com
-etancohen@google.com
+# Bug component: 33618
+include ../../1.0/vts/OWNERS
diff --git a/wifi/1.3/vts/OWNERS b/wifi/1.3/vts/OWNERS
index cf81c79..294fc82 100644
--- a/wifi/1.3/vts/OWNERS
+++ b/wifi/1.3/vts/OWNERS
@@ -1,2 +1,2 @@
-arabawy@google.com
-etancohen@google.com
+# Bug component: 33618
+include ../../1.0/vts/OWNERS
diff --git a/wifi/1.4/vts/OWNERS b/wifi/1.4/vts/OWNERS
index cf81c79..294fc82 100644
--- a/wifi/1.4/vts/OWNERS
+++ b/wifi/1.4/vts/OWNERS
@@ -1,2 +1,2 @@
-arabawy@google.com
-etancohen@google.com
+# Bug component: 33618
+include ../../1.0/vts/OWNERS
diff --git a/wifi/1.4/vts/functional/Android.bp b/wifi/1.4/vts/functional/Android.bp
index 14ebbe3..f86869b 100644
--- a/wifi/1.4/vts/functional/Android.bp
+++ b/wifi/1.4/vts/functional/Android.bp
@@ -14,7 +14,6 @@
// limitations under the License.
//
-// SoftAP-specific tests, similar to VtsHalWifiApV1_0TargetTest.
package {
// See: http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
@@ -25,10 +24,9 @@
}
cc_test {
- name: "VtsHalWifiApV1_4TargetTest",
+ name: "VtsHalWifiV1_4TargetTest",
defaults: ["VtsHalTargetTestDefaults"],
srcs: [
- "wifi_ap_iface_hidl_test.cpp",
"wifi_chip_hidl_test.cpp",
],
static_libs: [
@@ -46,6 +44,30 @@
],
}
+// SoftAP-specific tests, similar to VtsHalWifiApV1_0TargetTest.
+cc_test {
+ name: "VtsHalWifiApV1_4TargetTest",
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: [
+ "wifi_ap_iface_hidl_test.cpp",
+ ],
+ static_libs: [
+ "VtsHalWifiV1_0TargetTestUtil",
+ "android.hardware.wifi@1.0",
+ "android.hardware.wifi@1.1",
+ "android.hardware.wifi@1.2",
+ "android.hardware.wifi@1.3",
+ "android.hardware.wifi@1.4",
+ "android.hardware.wifi.hostapd@1.0",
+ "libwifi-system-iface",
+ ],
+ disable_framework: true,
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+}
+
// These tests are split out so that they can be conditioned on presence of the
// "android.hardware.wifi.aware" feature.
cc_test {
diff --git a/wifi/1.4/vts/functional/wifi_ap_iface_hidl_test.cpp b/wifi/1.4/vts/functional/wifi_ap_iface_hidl_test.cpp
index 5b0f173..756afa5 100644
--- a/wifi/1.4/vts/functional/wifi_ap_iface_hidl_test.cpp
+++ b/wifi/1.4/vts/functional/wifi_ap_iface_hidl_test.cpp
@@ -16,6 +16,7 @@
#include <android/hardware/wifi/1.4/IWifi.h>
#include <android/hardware/wifi/1.4/IWifiApIface.h>
+#include <android/hardware/wifi/hostapd/1.0/IHostapd.h>
#include <gtest/gtest.h>
#include <hidl/GtestPrinter.h>
#include <hidl/ServiceManagement.h>
@@ -25,6 +26,7 @@
using ::android::sp;
using ::android::hardware::hidl_array;
+using ::android::hardware::wifi::hostapd::V1_0::IHostapd;
using ::android::hardware::wifi::V1_0::WifiStatus;
using ::android::hardware::wifi::V1_0::WifiStatusCode;
using ::android::hardware::wifi::V1_4::IWifi;
@@ -36,6 +38,10 @@
class WifiApIfaceHidlTest : public ::testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
+ if (android::hardware::getAllHalInstanceNames(IHostapd::descriptor)
+ .empty()) {
+ GTEST_SKIP() << "Device does not support AP";
+ }
// Make sure to start with a clean state
stopWifi(GetInstanceName());
diff --git a/wifi/1.5/default/wifi.cpp b/wifi/1.5/default/wifi.cpp
index b9f20a4..a85b242 100644
--- a/wifi/1.5/default/wifi.cpp
+++ b/wifi/1.5/default/wifi.cpp
@@ -131,8 +131,14 @@
WifiStatus wifi_status =
createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, error);
for (const auto& callback : event_cb_handler_.getCallbacks()) {
+ LOG(INFO) << "Attempting to invoke onSubsystemRestart "
+ "callback";
if (!callback->onSubsystemRestart(wifi_status).isOk()) {
- LOG(ERROR) << "Failed to invoke onFailure callback";
+ LOG(ERROR)
+ << "Failed to invoke onSubsystemRestart callback";
+ } else {
+ LOG(INFO) << "Succeeded to invoke onSubsystemRestart "
+ "callback";
}
}
};
diff --git a/wifi/1.5/default/wifi_chip.cpp b/wifi/1.5/default/wifi_chip.cpp
index 82d794c..6bdff42 100644
--- a/wifi/1.5/default/wifi_chip.cpp
+++ b/wifi/1.5/default/wifi_chip.cpp
@@ -28,6 +28,8 @@
#include "wifi_chip.h"
#include "wifi_status_util.h"
+#define P2P_MGMT_DEVICE_PREFIX "p2p-dev-"
+
namespace {
using android::sp;
using android::base::unique_fd;
@@ -126,8 +128,37 @@
}
std::string getPredefinedP2pIfaceName() {
+ std::array<char, PROPERTY_VALUE_MAX> primaryIfaceName;
+ char p2pParentIfname[100];
+ std::string p2pDevIfName = "";
std::array<char, PROPERTY_VALUE_MAX> buffer;
property_get("wifi.direct.interface", buffer.data(), "p2p0");
+ if (strncmp(buffer.data(), P2P_MGMT_DEVICE_PREFIX,
+ strlen(P2P_MGMT_DEVICE_PREFIX)) == 0) {
+ /* Get the p2p parent interface name from p2p device interface name set
+ * in property */
+ strncpy(p2pParentIfname, buffer.data() + strlen(P2P_MGMT_DEVICE_PREFIX),
+ strlen(buffer.data()) - strlen(P2P_MGMT_DEVICE_PREFIX));
+ if (property_get(kActiveWlanIfaceNameProperty, primaryIfaceName.data(),
+ nullptr) == 0) {
+ return buffer.data();
+ }
+ /* Check if the parent interface derived from p2p device interface name
+ * is active */
+ if (strncmp(p2pParentIfname, primaryIfaceName.data(),
+ strlen(buffer.data()) - strlen(P2P_MGMT_DEVICE_PREFIX)) !=
+ 0) {
+ /*
+ * Update the predefined p2p device interface parent interface name
+ * with current active wlan interface
+ */
+ p2pDevIfName += P2P_MGMT_DEVICE_PREFIX;
+ p2pDevIfName += primaryIfaceName.data();
+ LOG(INFO) << "update the p2p device interface name to "
+ << p2pDevIfName.c_str();
+ return p2pDevIfName;
+ }
+ }
return buffer.data();
}
diff --git a/wifi/1.5/vts/OWNERS b/wifi/1.5/vts/OWNERS
index cf81c79..294fc82 100644
--- a/wifi/1.5/vts/OWNERS
+++ b/wifi/1.5/vts/OWNERS
@@ -1,2 +1,2 @@
-arabawy@google.com
-etancohen@google.com
+# Bug component: 33618
+include ../../1.0/vts/OWNERS
diff --git a/wifi/hostapd/1.0/vts/OWNERS b/wifi/hostapd/1.0/vts/OWNERS
index cf81c79..287152d 100644
--- a/wifi/hostapd/1.0/vts/OWNERS
+++ b/wifi/hostapd/1.0/vts/OWNERS
@@ -1,2 +1,3 @@
+# Bug component: 33618
arabawy@google.com
etancohen@google.com
diff --git a/wifi/hostapd/1.1/vts/OWNERS b/wifi/hostapd/1.1/vts/OWNERS
index cf81c79..294fc82 100644
--- a/wifi/hostapd/1.1/vts/OWNERS
+++ b/wifi/hostapd/1.1/vts/OWNERS
@@ -1,2 +1,2 @@
-arabawy@google.com
-etancohen@google.com
+# Bug component: 33618
+include ../../1.0/vts/OWNERS
diff --git a/wifi/hostapd/1.2/vts/OWNERS b/wifi/hostapd/1.2/vts/OWNERS
index cf81c79..294fc82 100644
--- a/wifi/hostapd/1.2/vts/OWNERS
+++ b/wifi/hostapd/1.2/vts/OWNERS
@@ -1,2 +1,2 @@
-arabawy@google.com
-etancohen@google.com
+# Bug component: 33618
+include ../../1.0/vts/OWNERS
diff --git a/wifi/hostapd/1.3/vts/OWNERS b/wifi/hostapd/1.3/vts/OWNERS
index cf81c79..294fc82 100644
--- a/wifi/hostapd/1.3/vts/OWNERS
+++ b/wifi/hostapd/1.3/vts/OWNERS
@@ -1,2 +1,2 @@
-arabawy@google.com
-etancohen@google.com
+# Bug component: 33618
+include ../../1.0/vts/OWNERS
diff --git a/wifi/offload/1.0/vts/OWNERS b/wifi/offload/1.0/vts/OWNERS
new file mode 100644
index 0000000..287152d
--- /dev/null
+++ b/wifi/offload/1.0/vts/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 33618
+arabawy@google.com
+etancohen@google.com
diff --git a/wifi/supplicant/1.0/vts/OWNERS b/wifi/supplicant/1.0/vts/OWNERS
new file mode 100644
index 0000000..cf81c79
--- /dev/null
+++ b/wifi/supplicant/1.0/vts/OWNERS
@@ -0,0 +1,2 @@
+arabawy@google.com
+etancohen@google.com
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
index 8cb7e22..114fe4f 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
@@ -317,7 +317,7 @@
}
bool waitForFrameworkReady() {
- int waitCount = 10;
+ int waitCount = 15;
do {
// Check whether package service is ready or not.
if (!testing::checkSubstringInCommandOutput(
diff --git a/wifi/supplicant/1.1/vts/OWNERS b/wifi/supplicant/1.1/vts/OWNERS
new file mode 100644
index 0000000..cf81c79
--- /dev/null
+++ b/wifi/supplicant/1.1/vts/OWNERS
@@ -0,0 +1,2 @@
+arabawy@google.com
+etancohen@google.com