Merge "Add new vibrator effects."
diff --git a/authsecret/1.0/IAuthSecret.hal b/authsecret/1.0/IAuthSecret.hal
index d2cb5da..6b573b3 100644
--- a/authsecret/1.0/IAuthSecret.hal
+++ b/authsecret/1.0/IAuthSecret.hal
@@ -24,25 +24,23 @@
*/
interface IAuthSecret {
/**
- * When the primary user correctly enters their credential, this method is
- * passed a secret derived from that credential to prove that their
- * credential is known.
+ * When the primary user is unlocked, this method is passed a secret to
+ * prove that is has been successfully unlocked. The primary user can either
+ * be unlocked by a person entering their credential or by another party
+ * using an escrow token e.g. a device administrator.
*
* The first time this is called, the secret must be used to provision state
- * that depends on the primary user's credential. The same secret is passed
- * on each call until a factory reset after which there must be a new
- * secret.
+ * that depends on the primary user's secret. The same secret must be passed
+ * on each call until the next factory reset.
*
- * The secret must be at lesat 16 bytes.
+ * Upon factory reset, any dependence on the secret must be removed as that
+ * secret is now lost and must never be derived again. A new secret must be
+ * created for the new primary user which must be used to newly provision
+ * state the first time this method is called after factory reset.
+ *
+ * The secret must be at least 16 bytes.
*
* @param secret blob derived from the primary user's credential.
*/
primaryUserCredential(vec<uint8_t> secret);
-
- /**
- * Called from recovery during factory reset. The secret is now lost and can
- * no longer be derived. Any data linked to the secret must be destroyed and
- * any dependence on the secret must be removed.
- */
- factoryReset();
};
diff --git a/authsecret/1.0/default/AuthSecret.cpp b/authsecret/1.0/default/AuthSecret.cpp
index 46a3ec1..f9271e9 100644
--- a/authsecret/1.0/default/AuthSecret.cpp
+++ b/authsecret/1.0/default/AuthSecret.cpp
@@ -29,16 +29,12 @@
return Void();
}
-Return<void> AuthSecret::factoryReset() {
- // Clear all dependency on the secret.
- //
- // With the example of updating a security module, the stored value must be
- // cleared so that the new primary user enrolled as the approver of updates.
- //
- // This implementation does nothing as there is no dependence on the secret.
-
- return Void();
-}
+// Note: on factory reset, clear all dependency on the secret.
+//
+// With the example of updating a security module, the stored value must be
+// cleared so that the new primary user enrolled as the approver of updates.
+//
+// This implementation does nothing as there is no dependence on the secret.
} // namespace implementation
} // namespace V1_0
diff --git a/authsecret/1.0/default/AuthSecret.h b/authsecret/1.0/default/AuthSecret.h
index edb49b8..387fa67 100644
--- a/authsecret/1.0/default/AuthSecret.h
+++ b/authsecret/1.0/default/AuthSecret.h
@@ -22,7 +22,6 @@
struct AuthSecret : public IAuthSecret {
// Methods from ::android::hardware::authsecret::V1_0::IAuthSecret follow.
Return<void> primaryUserCredential(const hidl_vec<uint8_t>& secret) override;
- Return<void> factoryReset() override;
// Methods from ::android::hidl::base::V1_0::IBase follow.
};
diff --git a/authsecret/1.0/vts/functional/VtsHalAuthSecretV1_0TargetTest.cpp b/authsecret/1.0/vts/functional/VtsHalAuthSecretV1_0TargetTest.cpp
index b0cbd91..a610a75 100644
--- a/authsecret/1.0/vts/functional/VtsHalAuthSecretV1_0TargetTest.cpp
+++ b/authsecret/1.0/vts/functional/VtsHalAuthSecretV1_0TargetTest.cpp
@@ -30,68 +30,42 @@
virtual void SetUp() override {
authsecret = ::testing::VtsHalHidlTargetTestBase::getService<IAuthSecret>();
ASSERT_NE(authsecret, nullptr);
- authsecret->factoryReset();
+
+ // All tests must enroll the correct secret first as this cannot be changed
+ // without a factory reset and the order of tests could change.
+ authsecret->primaryUserCredential(CORRECT_SECRET);
}
sp<IAuthSecret> authsecret;
+ hidl_vec<uint8_t> CORRECT_SECRET{61, 93, 124, 240, 5, 0, 7, 201, 9, 129, 11, 12, 0, 14, 0, 16};
+ hidl_vec<uint8_t> WRONG_SECRET{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
};
/* Provision the primary user with a secret. */
TEST_F(AuthSecretHidlTest, provisionPrimaryUserCredential) {
- hidl_vec<uint8_t> secret{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
- authsecret->primaryUserCredential(secret);
-}
-
-/* Provision the primary user with a large secret. */
-TEST_F(AuthSecretHidlTest, provisionPrimaryUserCredentialWithLargeSecret) {
- hidl_vec<uint8_t> secret{89, 233, 52, 29, 130, 210, 229, 170, 124, 102, 56, 238, 198,
- 199, 246, 152, 185, 123, 155, 215, 29, 252, 30, 70, 118, 29,
- 149, 36, 222, 203, 163, 7, 72, 56, 247, 19, 198, 76, 71,
- 37, 120, 201, 220, 70, 150, 18, 23, 22, 236, 57, 184, 86,
- 190, 122, 210, 207, 74, 51, 222, 157, 74, 196, 86, 208};
- authsecret->primaryUserCredential(secret);
+ // Secret provisioned by SetUp()
}
/* Provision the primary user with a secret and pass the secret again. */
TEST_F(AuthSecretHidlTest, provisionPrimaryUserCredentialAndPassAgain) {
- hidl_vec<uint8_t> secret{64, 2, 3, 0, 5, 6, 7, 172, 9, 10, 11, 255, 13, 14, 15, 83};
- authsecret->primaryUserCredential(secret);
- authsecret->primaryUserCredential(secret);
+ // Secret provisioned by SetUp()
+ authsecret->primaryUserCredential(CORRECT_SECRET);
}
/* Provision the primary user with a secret and pass the secret again repeatedly. */
TEST_F(AuthSecretHidlTest, provisionPrimaryUserCredentialAndPassAgainMultipleTimes) {
- hidl_vec<uint8_t> secret{1, 2, 34, 4, 5, 6, 7, 8, 9, 105, 11, 12, 13, 184, 15, 16};
- authsecret->primaryUserCredential(secret);
+ // Secret provisioned by SetUp()
constexpr int N = 5;
for (int i = 0; i < N; ++i) {
- authsecret->primaryUserCredential(secret);
+ authsecret->primaryUserCredential(CORRECT_SECRET);
}
}
-/* Factory reset before provisioning the primary user with a secret. */
-TEST_F(AuthSecretHidlTest, factoryResetWithoutProvisioningPrimaryUserCredential) {
- authsecret->factoryReset();
-}
-
-/* Provision the primary user with a secret then factory reset. */
-TEST_F(AuthSecretHidlTest, provisionPrimaryUserCredentialAndFactoryReset) {
- hidl_vec<uint8_t> secret{1, 24, 124, 240, 5, 6, 7, 8, 9, 13, 11, 12, 189, 14, 195, 16};
- authsecret->primaryUserCredential(secret);
- authsecret->factoryReset();
-}
-
-/* Provision the primary differently after factory reset. */
-TEST_F(AuthSecretHidlTest, provisionPrimaryUserCredentialDifferentlyAfterFactoryReset) {
- {
- hidl_vec<uint8_t> secret1{19, 0, 65, 20, 65, 12, 7, 8, 9, 13, 29, 12, 189, 32, 195, 16};
- authsecret->primaryUserCredential(secret1);
- }
-
- authsecret->factoryReset();
-
- {
- hidl_vec<uint8_t> secret2{61, 93, 124, 240, 5, 0, 7, 201, 9, 129, 11, 12, 0, 14, 0, 16};
- authsecret->primaryUserCredential(secret2);
- }
+/* Provision the primary user with a secret and then pass the wrong secret. This
+ * should never happen and is an framework bug if it does. As the secret is
+ * wrong, the HAL implementation may not be able to function correctly but it
+ * should fail gracefully. */
+TEST_F(AuthSecretHidlTest, provisionPrimaryUserCredentialAndWrongSecret) {
+ // Secret provisioned by SetUp()
+ authsecret->primaryUserCredential(WRONG_SECRET);
}
diff --git a/automotive/vehicle/2.0/Android.bp b/automotive/vehicle/2.0/Android.bp
index a13359e..a0d20f3 100644
--- a/automotive/vehicle/2.0/Android.bp
+++ b/automotive/vehicle/2.0/Android.bp
@@ -56,6 +56,7 @@
"VehiclePropertyChangeMode",
"VehiclePropertyGroup",
"VehiclePropertyOperation",
+ "VehiclePropertyStatus",
"VehiclePropertyType",
"VehicleRadioConstants",
"VehicleTurnSignal",
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/SubscriptionManager.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/SubscriptionManager.h
index 8e9089d..6086c01 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/SubscriptionManager.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/SubscriptionManager.h
@@ -49,7 +49,7 @@
}
void addOrUpdateSubscription(const SubscribeOptions &opts);
- bool isSubscribed(int32_t propId, int32_t areaId, SubscribeFlags flags);
+ bool isSubscribed(int32_t propId, SubscribeFlags flags);
std::vector<int32_t> getSubscribedProperties() const;
private:
@@ -87,8 +87,7 @@
/**
* Constructs SubscriptionManager
*
- * @param onPropertyUnsubscribed - this callback function will be called when there are no
- * more client subscribed to particular property.
+ * @param onPropertyUnsubscribed - called when no more clients are subscribed to the property.
*/
SubscriptionManager(const OnPropertyUnsubscribed& onPropertyUnsubscribed)
: mOnPropertyUnsubscribed(onPropertyUnsubscribed),
@@ -115,9 +114,7 @@
const std::vector<recyclable_ptr<VehiclePropValue>>& propValues,
SubscribeFlags flags) const;
- std::list<sp<HalClient>> getSubscribedClients(int32_t propId,
- int32_t area,
- SubscribeFlags flags) const;
+ std::list<sp<HalClient>> getSubscribedClients(int32_t propId, SubscribeFlags flags) const;
/**
* If there are no clients subscribed to given properties than callback function provided
* in the constructor will be called.
@@ -125,10 +122,9 @@
void unsubscribe(ClientId clientId, int32_t propId);
private:
std::list<sp<HalClient>> getSubscribedClientsLocked(int32_t propId,
- int32_t area,
SubscribeFlags flags) const;
- bool updateHalEventSubscriptionLocked(const SubscribeOptions &opts, SubscribeOptions* out);
+ bool updateHalEventSubscriptionLocked(const SubscribeOptions& opts, SubscribeOptions* out);
void addClientToPropMapLocked(int32_t propId, const sp<HalClient>& client);
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHal.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHal.h
index 8203a1e..fd28483 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHal.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleHal.h
@@ -48,17 +48,14 @@
/**
* Subscribe to HAL property events. This method might be called multiple
- * times for the same vehicle property to update subscribed areas or sample
- * rate.
+ * times for the same vehicle property to update sample rate.
*
* @param property to subscribe
- * @param areas a bitwise vehicle areas or 0 for all supported areas
* @param sampleRate sample rate in Hz for properties that support sample
* rate, e.g. for properties with
* VehiclePropertyChangeMode::CONTINUOUS
*/
virtual StatusCode subscribe(int32_t property,
- int32_t areas,
float sampleRate) = 0;
/**
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleObjectPool.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleObjectPool.h
index 05c649b..359bb6d 100644
--- a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleObjectPool.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/VehicleObjectPool.h
@@ -191,9 +191,8 @@
VehiclePropValuePool& operator=(VehiclePropValuePool&) = delete;
private:
bool isDisposable(VehiclePropertyType type, size_t vecSize) const {
- return vecSize > mMaxRecyclableVectorSize ||
- VehiclePropertyType::STRING == type ||
- VehiclePropertyType::COMPLEX == type;
+ return vecSize > mMaxRecyclableVectorSize || VehiclePropertyType::STRING == type ||
+ VehiclePropertyType::MIXED == type;
}
RecyclableType obtainDisposable(VehiclePropertyType valueType,
diff --git a/automotive/vehicle/2.0/default/common/src/SubscriptionManager.cpp b/automotive/vehicle/2.0/default/common/src/SubscriptionManager.cpp
index 74f0a5f..a7d5f50 100644
--- a/automotive/vehicle/2.0/default/common/src/SubscriptionManager.cpp
+++ b/automotive/vehicle/2.0/default/common/src/SubscriptionManager.cpp
@@ -34,23 +34,12 @@
bool mergeSubscribeOptions(const SubscribeOptions &oldOpts,
const SubscribeOptions &newOpts,
SubscribeOptions *outResult) {
-
- int32_t updatedAreas = oldOpts.vehicleAreas;
- if (updatedAreas != kAllSupportedAreas) {
- updatedAreas = newOpts.vehicleAreas != kAllSupportedAreas
- ? updatedAreas | newOpts.vehicleAreas
- : kAllSupportedAreas;
- }
-
float updatedRate = std::max(oldOpts.sampleRate, newOpts.sampleRate);
SubscribeFlags updatedFlags = SubscribeFlags(oldOpts.flags | newOpts.flags);
- bool updated = updatedRate > oldOpts.sampleRate
- || updatedAreas != oldOpts.vehicleAreas
- || updatedFlags != oldOpts.flags;
+ bool updated = (updatedRate > oldOpts.sampleRate) || (updatedFlags != oldOpts.flags);
if (updated) {
*outResult = oldOpts;
- outResult->vehicleAreas = updatedAreas;
outResult->sampleRate = updatedRate;
outResult->flags = updatedFlags;
}
@@ -75,15 +64,13 @@
}
bool HalClient::isSubscribed(int32_t propId,
- int32_t areaId,
SubscribeFlags flags) {
auto it = mSubscriptions.find(propId);
if (it == mSubscriptions.end()) {
return false;
}
const SubscribeOptions& opts = it->second;
- bool res = (opts.flags & flags)
- && (opts.vehicleAreas == 0 || areaId == 0 || opts.vehicleAreas & areaId);
+ bool res = (opts.flags & flags);
return res;
}
@@ -139,8 +126,7 @@
MuxGuard g(mLock);
for (const auto& propValue: propValues) {
VehiclePropValue* v = propValue.get();
- auto clients = getSubscribedClientsLocked(
- v->prop, v->areaId, flags);
+ auto clients = getSubscribedClientsLocked(v->prop, flags);
for (const auto& client : clients) {
clientValuesMap[client].push_back(v);
}
@@ -158,21 +144,21 @@
return clientValues;
}
-std::list<sp<HalClient>> SubscriptionManager::getSubscribedClients(
- int32_t propId, int32_t area, SubscribeFlags flags) const {
+std::list<sp<HalClient>> SubscriptionManager::getSubscribedClients(int32_t propId,
+ SubscribeFlags flags) const {
MuxGuard g(mLock);
- return getSubscribedClientsLocked(propId, area, flags);
+ return getSubscribedClientsLocked(propId, flags);
}
std::list<sp<HalClient>> SubscriptionManager::getSubscribedClientsLocked(
- int32_t propId, int32_t area, SubscribeFlags flags) const {
+ int32_t propId, SubscribeFlags flags) const {
std::list<sp<HalClient>> subscribedClients;
sp<HalClientVector> propClients = getClientsForPropertyLocked(propId);
if (propClients.get() != nullptr) {
for (size_t i = 0; i < propClients->size(); i++) {
const auto& client = propClients->itemAt(i);
- if (client->isSubscribed(propId, area, flags)) {
+ if (client->isSubscribed(propId, flags)) {
subscribedClients.push_back(client);
}
}
diff --git a/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp b/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
index ae543bb..1918421 100644
--- a/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
+++ b/automotive/vehicle/2.0/default/common/src/VehicleHalManager.cpp
@@ -142,15 +142,6 @@
return StatusCode::INVALID_ARG;
}
- int32_t areas = isGlobalProp(prop) ? 0 : ops.vehicleAreas;
- if (areas != 0 && ((areas & config->supportedAreas) != areas)) {
- ALOGE("Failed to subscribe property 0x%x. Requested areas 0x%x are "
- "out of supported range of 0x%x", prop, ops.vehicleAreas,
- config->supportedAreas);
- return StatusCode::INVALID_ARG;
- }
-
- ops.vehicleAreas = areas;
ops.sampleRate = checkSampleRate(*config, ops.sampleRate);
}
@@ -164,7 +155,7 @@
}
for (auto opt : updatedOptions) {
- mHal->subscribe(opt.propId, opt.vehicleAreas, opt.sampleRate);
+ mHal->subscribe(opt.propId, opt.sampleRate);
}
return StatusCode::OK;
@@ -224,8 +215,8 @@
void VehicleHalManager::onHalPropertySetError(StatusCode errorCode,
int32_t property,
int32_t areaId) {
- const auto& clients = mSubscriptionManager.getSubscribedClients(
- property, 0, SubscribeFlags::HAL_EVENT);
+ const auto& clients =
+ mSubscriptionManager.getSubscribedClients(property, SubscribeFlags::HAL_EVENT);
for (auto client : clients) {
client->getCallback()->onPropertySetError(errorCode, property, areaId);
@@ -326,8 +317,7 @@
}
void VehicleHalManager::handlePropertySetEvent(const VehiclePropValue& value) {
- auto clients = mSubscriptionManager.getSubscribedClients(
- value.prop, value.areaId, SubscribeFlags::SET_CALL);
+ auto clients = mSubscriptionManager.getSubscribedClients(value.prop, SubscribeFlags::SET_CALL);
for (auto client : clients) {
client->getCallback()->onPropertySet(value);
}
diff --git a/automotive/vehicle/2.0/default/common/src/VehicleObjectPool.cpp b/automotive/vehicle/2.0/default/common/src/VehicleObjectPool.cpp
index ac1245a..3f98a94 100644
--- a/automotive/vehicle/2.0/default/common/src/VehicleObjectPool.cpp
+++ b/automotive/vehicle/2.0/default/common/src/VehicleObjectPool.cpp
@@ -82,7 +82,7 @@
}
VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainComplex() {
- return obtain(VehiclePropertyType::COMPLEX);
+ return obtain(VehiclePropertyType::MIXED);
}
VehiclePropValuePool::RecyclableType VehiclePropValuePool::obtainRecylable(
@@ -138,18 +138,14 @@
}
bool VehiclePropValuePool::InternalPool::check(VehiclePropValue::RawValue* 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)
- && check(&v->bytes,
- VehiclePropertyType::BYTES == mPropType)
- && v->stringValue.size() == 0;
+ 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->bytes, VehiclePropertyType::BYTES == mPropType) && v->stringValue.size() == 0;
}
VehiclePropValue* VehiclePropValuePool::InternalPool::createObject() {
diff --git a/automotive/vehicle/2.0/default/common/src/VehicleUtils.cpp b/automotive/vehicle/2.0/default/common/src/VehicleUtils.cpp
index 9146fa1..34a6380 100644
--- a/automotive/vehicle/2.0/default/common/src/VehicleUtils.cpp
+++ b/automotive/vehicle/2.0/default/common/src/VehicleUtils.cpp
@@ -42,13 +42,14 @@
val->value.floatValues.resize(vecSize);
break;
case VehiclePropertyType::INT64:
+ case VehiclePropertyType::INT64_VEC:
val->value.int64Values.resize(vecSize);
break;
case VehiclePropertyType::BYTES:
val->value.bytes.resize(vecSize);
break;
case VehiclePropertyType::STRING:
- case VehiclePropertyType::COMPLEX:
+ case VehiclePropertyType::MIXED:
break; // Valid, but nothing to do.
default:
ALOGE("createVehiclePropValue: unknown type: %d", type);
@@ -68,6 +69,7 @@
case VehiclePropertyType::FLOAT_VEC:
return value.floatValues.size();
case VehiclePropertyType::INT64:
+ case VehiclePropertyType::INT64_VEC:
return value.int64Values.size();
case VehiclePropertyType::BYTES:
return value.bytes.size();
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 71601a0..18e8c40 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
@@ -54,10 +54,8 @@
* floatValues[1] - dispersion defines min and max range relative to initial value
* floatValues[2] - increment, with every timer tick the value will be incremented by this amount
*/
-const int32_t kGenerateFakeDataControllingProperty = 0x0666
- | VehiclePropertyGroup::VENDOR
- | VehicleArea::GLOBAL
- | VehiclePropertyType::COMPLEX;
+const int32_t kGenerateFakeDataControllingProperty =
+ 0x0666 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::MIXED;
const int32_t kHvacPowerProperties[] = {
toInt(VehicleProperty::HVAC_FAN_SPEED),
@@ -238,7 +236,8 @@
.prop = toInt(VehicleProperty::HVAC_POWER_ON),
.access = VehiclePropertyAccess::READ_WRITE,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .supportedAreas = toInt(VehicleAreaZone::ROW_1),
+ .areaConfigs = {VehicleAreaConfig{
+ .areaId = (VehicleAreaZone::ROW_1_LEFT | VehicleAreaZone::ROW_1_RIGHT)}},
// TODO(bryaneyler): Ideally, this is generated dynamically from
// kHvacPowerProperties.
.configString = "0x12400500,0x12400501" // HVAC_FAN_SPEED,HVAC_FAN_DIRECTION
@@ -249,51 +248,52 @@
.config = {.prop = toInt(VehicleProperty::HVAC_DEFROSTER),
.access = VehiclePropertyAccess::READ_WRITE,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .supportedAreas =
- VehicleAreaWindow::FRONT_WINDSHIELD | VehicleAreaWindow::REAR_WINDSHIELD},
+ .areaConfigs =
+ {VehicleAreaConfig{.areaId = toInt(VehicleAreaWindow::FRONT_WINDSHIELD)},
+ VehicleAreaConfig{.areaId = toInt(VehicleAreaWindow::REAR_WINDSHIELD)}}},
.initialValue = {.int32Values = {0}} // Will be used for all areas.
},
{.config = {.prop = toInt(VehicleProperty::HVAC_RECIRC_ON),
.access = VehiclePropertyAccess::READ_WRITE,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .supportedAreas = toInt(VehicleAreaZone::ROW_1)},
+ .areaConfigs = {VehicleAreaConfig{
+ .areaId = (VehicleAreaZone::ROW_1_LEFT | VehicleAreaZone::ROW_1_RIGHT)}}},
.initialValue = {.int32Values = {1}}},
{.config = {.prop = toInt(VehicleProperty::HVAC_AC_ON),
.access = VehiclePropertyAccess::READ_WRITE,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .supportedAreas = toInt(VehicleAreaZone::ROW_1)},
+ .areaConfigs = {VehicleAreaConfig{
+ .areaId = (VehicleAreaZone::ROW_1_LEFT | VehicleAreaZone::ROW_1_RIGHT)}}},
.initialValue = {.int32Values = {1}}},
{.config = {.prop = toInt(VehicleProperty::HVAC_AUTO_ON),
.access = VehiclePropertyAccess::READ_WRITE,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .supportedAreas = toInt(VehicleAreaZone::ROW_1)},
+ .areaConfigs = {VehicleAreaConfig{
+ .areaId = (VehicleAreaZone::ROW_1_LEFT | VehicleAreaZone::ROW_1_RIGHT)}}},
.initialValue = {.int32Values = {1}}},
{.config = {.prop = toInt(VehicleProperty::HVAC_FAN_SPEED),
.access = VehiclePropertyAccess::READ_WRITE,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .supportedAreas = toInt(VehicleAreaZone::ROW_1),
- .areaConfigs = {VehicleAreaConfig{.areaId = toInt(VehicleAreaZone::ROW_1),
- .minInt32Value = 1,
- .maxInt32Value = 7}}},
+ .areaConfigs = {VehicleAreaConfig{
+ .areaId = (VehicleAreaZone::ROW_1_LEFT | VehicleAreaZone::ROW_1_RIGHT),
+ .minInt32Value = 1,
+ .maxInt32Value = 7}}},
.initialValue = {.int32Values = {3}}},
- {.config =
- {
- .prop = toInt(VehicleProperty::HVAC_FAN_DIRECTION),
- .access = VehiclePropertyAccess::READ_WRITE,
- .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .supportedAreas = toInt(VehicleAreaZone::ROW_1),
- },
+ {.config = {.prop = toInt(VehicleProperty::HVAC_FAN_DIRECTION),
+ .access = VehiclePropertyAccess::READ_WRITE,
+ .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+ .areaConfigs = {VehicleAreaConfig{
+ .areaId = (VehicleAreaZone::ROW_1_LEFT | VehicleAreaZone::ROW_1_RIGHT)}}},
.initialValue = {.int32Values = {toInt(VehicleHvacFanDirection::FACE)}}},
{.config = {.prop = toInt(VehicleProperty::HVAC_TEMPERATURE_SET),
.access = VehiclePropertyAccess::READ_WRITE,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .supportedAreas = VehicleAreaZone::ROW_1_LEFT | VehicleAreaZone::ROW_1_RIGHT,
.areaConfigs = {VehicleAreaConfig{
.areaId = toInt(VehicleAreaZone::ROW_1_LEFT),
.minFloatValue = 16,
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
index 6bc0522..16d2b0b 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
@@ -138,8 +138,9 @@
return status;
}
} else if (mHvacPowerProps.count(propValue.prop)) {
- auto hvacPowerOn = mPropStore->readValueOrNull(toInt(VehicleProperty::HVAC_POWER_ON),
- toInt(VehicleAreaZone::ROW_1));
+ auto hvacPowerOn = mPropStore->readValueOrNull(
+ toInt(VehicleProperty::HVAC_POWER_ON),
+ (VehicleAreaZone::ROW_1_LEFT | VehicleAreaZone::ROW_1_RIGHT));
if (hvacPowerOn && hvacPowerOn->value.int32Values.size() == 1
&& hvacPowerOn->value.int32Values[0] == 0) {
@@ -177,7 +178,7 @@
void EmulatedVehicleHal::onCreate() {
for (auto& it : kVehicleProperties) {
VehiclePropConfig cfg = it.config;
- int32_t supportedAreas = cfg.supportedAreas;
+ int32_t numAreas = cfg.areaConfigs.size();
if (isDiagnosticProperty(cfg)) {
// do not write an initial empty value for the diagnostic properties
@@ -185,22 +186,26 @@
continue;
}
- // A global property will have supportedAreas = 0
+ // A global property will have only a single area
if (isGlobalProp(cfg.prop)) {
- supportedAreas = 0;
+ numAreas = 1;
}
- // This loop is a do-while so it executes at least once to handle global properties
- do {
- int32_t curArea = supportedAreas;
- supportedAreas &= supportedAreas - 1; // Clear the right-most bit of supportedAreas.
- curArea ^= supportedAreas; // Set curArea to the previously cleared bit.
+ for (int i = 0; i < numAreas; i++) {
+ int32_t curArea;
+
+ if (isGlobalProp(cfg.prop)) {
+ curArea = 0;
+ } else {
+ curArea = cfg.areaConfigs[i].areaId;
+ }
// Create a separate instance for each individual zone
VehiclePropValue prop = {
.prop = cfg.prop,
.areaId = curArea,
};
+
if (it.initialAreaValues.size() > 0) {
auto valueForAreaIt = it.initialAreaValues.find(curArea);
if (valueForAreaIt != it.initialAreaValues.end()) {
@@ -213,8 +218,7 @@
prop.value = it.initialValue;
}
mPropStore->writeValue(prop);
-
- } while (supportedAreas != 0);
+ }
}
initObd2LiveFrame(*mPropStore->getConfigOrDie(OBD2_LIVE_FRAME));
initObd2FreezeFrame(*mPropStore->getConfigOrDie(OBD2_FREEZE_FRAME));
@@ -246,8 +250,7 @@
}
}
-StatusCode EmulatedVehicleHal::subscribe(int32_t property, int32_t,
- float sampleRate) {
+StatusCode EmulatedVehicleHal::subscribe(int32_t property, float sampleRate) {
ALOGI("%s propId: 0x%x, sampleRate: %f", __func__, property, sampleRate);
if (isContinuousProperty(property)) {
@@ -389,7 +392,7 @@
}
void EmulatedVehicleHal::initObd2LiveFrame(const VehiclePropConfig& propConfig) {
- auto liveObd2Frame = createVehiclePropValue(VehiclePropertyType::COMPLEX, 0);
+ auto liveObd2Frame = createVehiclePropValue(VehiclePropertyType::MIXED, 0);
auto sensorStore = fillDefaultObd2Frame(static_cast<size_t>(propConfig.configArray[0]),
static_cast<size_t>(propConfig.configArray[1]));
sensorStore->fillPropValue("", liveObd2Frame.get());
@@ -406,7 +409,7 @@
"P0102"
"P0123"};
for (auto&& dtc : sampleDtcs) {
- auto freezeFrame = createVehiclePropValue(VehiclePropertyType::COMPLEX, 0);
+ auto freezeFrame = createVehiclePropValue(VehiclePropertyType::MIXED, 0);
sensorStore->fillPropValue(dtc, freezeFrame.get());
freezeFrame->prop = OBD2_FREEZE_FRAME;
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
index 99d7edb..62fc126 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
@@ -53,7 +53,7 @@
VehiclePropValuePtr get(const VehiclePropValue& requestedPropValue,
StatusCode* outStatus) override;
StatusCode set(const VehiclePropValue& propValue) override;
- StatusCode subscribe(int32_t property, int32_t areas, float sampleRate) override;
+ StatusCode subscribe(int32_t property, float sampleRate) override;
StatusCode unsubscribe(int32_t property) override;
// Methods from EmulatedVehicleHalIface
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp
index 38cb743..fca8e9e 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleEmulator.cpp
@@ -234,10 +234,6 @@
protoCfg->set_change_mode(toInt(cfg.changeMode));
protoCfg->set_value_type(toInt(getPropType(cfg.prop)));
- if (!isGlobalProp(cfg.prop)) {
- protoCfg->set_supported_areas(cfg.supportedAreas);
- }
-
for (auto& configElement : cfg.configArray) {
protoCfg->add_config_array(configElement);
}
@@ -251,9 +247,10 @@
case VehiclePropertyType::STRING:
case VehiclePropertyType::BOOLEAN:
case VehiclePropertyType::INT32_VEC:
+ case VehiclePropertyType::INT64_VEC:
case VehiclePropertyType::FLOAT_VEC:
case VehiclePropertyType::BYTES:
- case VehiclePropertyType::COMPLEX:
+ case VehiclePropertyType::MIXED:
// Do nothing. These types don't have min/max values
break;
case VehiclePropertyType::INT64:
diff --git a/automotive/vehicle/2.0/default/tests/SubscriptionManager_test.cpp b/automotive/vehicle/2.0/default/tests/SubscriptionManager_test.cpp
index 5688dd6..4865e9e 100644
--- a/automotive/vehicle/2.0/default/tests/SubscriptionManager_test.cpp
+++ b/automotive/vehicle/2.0/default/tests/SubscriptionManager_test.cpp
@@ -51,11 +51,7 @@
}
hidl_vec<SubscribeOptions> subscrToProp1 = {
- SubscribeOptions {
- .propId = PROP1,
- .vehicleAreas = toInt(VehicleAreaZone::ROW_1_LEFT),
- .flags = SubscribeFlags::HAL_EVENT
- },
+ SubscribeOptions{.propId = PROP1, .flags = SubscribeFlags::HAL_EVENT},
};
hidl_vec<SubscribeOptions> subscrToProp2 = {
@@ -66,15 +62,8 @@
};
hidl_vec<SubscribeOptions> subscrToProp1and2 = {
- SubscribeOptions {
- .propId = PROP1,
- .vehicleAreas = toInt(VehicleAreaZone::ROW_1_LEFT),
- .flags = SubscribeFlags::HAL_EVENT
- },
- SubscribeOptions {
- .propId = PROP2,
- .flags = SubscribeFlags::HAL_EVENT
- },
+ SubscribeOptions{.propId = PROP1, .flags = SubscribeFlags::HAL_EVENT},
+ SubscribeOptions{.propId = PROP2, .flags = SubscribeFlags::HAL_EVENT},
};
static std::list<sp<IVehicleCallback>> extractCallbacks(
@@ -87,14 +76,11 @@
}
std::list<sp<HalClient>> clientsToProp1() {
- return manager.getSubscribedClients(PROP1,
- toInt(VehicleAreaZone::ROW_1_LEFT),
- SubscribeFlags::DEFAULT);
+ return manager.getSubscribedClients(PROP1, SubscribeFlags::DEFAULT);
}
std::list<sp<HalClient>> clientsToProp2() {
- return manager.getSubscribedClients(PROP2, 0,
- SubscribeFlags::DEFAULT);
+ return manager.getSubscribedClients(PROP2, SubscribeFlags::DEFAULT);
}
void onPropertyUnsubscribed(int propertyId) {
@@ -126,7 +112,6 @@
auto clients = manager.getSubscribedClients(
PROP1,
- toInt(VehicleAreaZone::ROW_1_LEFT),
SubscribeFlags::HAL_EVENT);
ASSERT_ALL_EXISTS({cb1, cb2}, extractCallbacks(clients));
@@ -137,24 +122,14 @@
ASSERT_EQ(StatusCode::OK,
manager.addOrUpdateSubscription(1, cb1, subscrToProp1, &updatedOptions));
- // Wrong zone
- auto clients = manager.getSubscribedClients(
- PROP1,
- toInt(VehicleAreaZone::ROW_2_LEFT),
- SubscribeFlags::HAL_EVENT);
- ASSERT_TRUE(clients.empty());
-
// Wrong prop
- clients = manager.getSubscribedClients(
- toInt(VehicleProperty::AP_POWER_BOOTUP_REASON),
- toInt(VehicleAreaZone::ROW_1_LEFT),
- SubscribeFlags::HAL_EVENT);
+ auto clients = manager.getSubscribedClients(toInt(VehicleProperty::AP_POWER_BOOTUP_REASON),
+ SubscribeFlags::HAL_EVENT);
ASSERT_TRUE(clients.empty());
// Wrong flag
clients = manager.getSubscribedClients(
PROP1,
- toInt(VehicleAreaZone::ROW_1_LEFT),
SubscribeFlags::SET_CALL);
ASSERT_TRUE(clients.empty());
}
@@ -166,7 +141,6 @@
auto clients = manager.getSubscribedClients(
PROP1,
- toInt(VehicleAreaZone::ROW_1_LEFT),
SubscribeFlags::DEFAULT);
ASSERT_EQ((size_t) 1, clients.size());
ASSERT_EQ(cb1, clients.front()->getCallback());
@@ -176,18 +150,15 @@
ASSERT_EQ(StatusCode::OK, manager.addOrUpdateSubscription(1, cb1, {
SubscribeOptions {
.propId = PROP1,
- .vehicleAreas = toInt(VehicleAreaZone::ROW_2),
.flags = SubscribeFlags::DEFAULT
}
}, &updatedOptions));
clients = manager.getSubscribedClients(PROP1,
- toInt(VehicleAreaZone::ROW_1_LEFT),
SubscribeFlags::DEFAULT);
ASSERT_ALL_EXISTS({cb1}, extractCallbacks(clients));
clients = manager.getSubscribedClients(PROP1,
- toInt(VehicleAreaZone::ROW_2),
SubscribeFlags::DEFAULT);
ASSERT_ALL_EXISTS({cb1}, extractCallbacks(clients));
}
diff --git a/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp b/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
index 4864d5d..5b195db 100644
--- a/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
+++ b/automotive/vehicle/2.0/default/tests/VehicleHalManager_test.cpp
@@ -106,7 +106,6 @@
}
StatusCode subscribe(int32_t /* property */,
- int32_t /* areas */,
float /* sampleRate */) override {
return StatusCode::OK;
}
@@ -286,6 +285,7 @@
cb->reset();
VehiclePropValue actualValue(*subscribedValue.get());
+ actualValue.status = VehiclePropertyStatus::AVAILABLE;
hal->sendPropEvent(std::move(subscribedValue));
ASSERT_TRUE(cb->waitForExpectedEvents(1)) << "Events received: "
diff --git a/automotive/vehicle/2.0/default/tests/VehicleHalTestUtils.h b/automotive/vehicle/2.0/default/tests/VehicleHalTestUtils.h
index 2a06417..3cabcf2 100644
--- a/automotive/vehicle/2.0/default/tests/VehicleHalTestUtils.h
+++ b/automotive/vehicle/2.0/default/tests/VehicleHalTestUtils.h
@@ -29,10 +29,8 @@
namespace vehicle {
namespace V2_0 {
-constexpr int32_t kCustomComplexProperty = 0xbeef
- | VehiclePropertyGroup::VENDOR
- | VehiclePropertyType::COMPLEX
- | VehicleArea::GLOBAL;
+constexpr int32_t kCustomComplexProperty =
+ 0xbeef | VehiclePropertyGroup::VENDOR | VehiclePropertyType::MIXED | VehicleArea::GLOBAL;
const VehiclePropConfig kVehicleProperties[] = {
{
@@ -46,8 +44,6 @@
.prop = toInt(VehicleProperty::HVAC_FAN_SPEED),
.access = VehiclePropertyAccess::READ_WRITE,
.changeMode = VehiclePropertyChangeMode::ON_CHANGE,
- .supportedAreas = static_cast<int32_t>(
- VehicleAreaZone::ROW_1_LEFT | VehicleAreaZone::ROW_1_RIGHT),
.areaConfigs = {
VehicleAreaConfig {
.areaId = toInt(VehicleAreaZone::ROW_1_LEFT),
@@ -66,8 +62,6 @@
.prop = toInt(VehicleProperty::HVAC_SEAT_TEMPERATURE),
.access = VehiclePropertyAccess::WRITE,
.changeMode = VehiclePropertyChangeMode::ON_SET,
- .supportedAreas = static_cast<int32_t>(
- VehicleAreaZone::ROW_1_LEFT | VehicleAreaZone::ROW_1_RIGHT),
.areaConfigs = {
VehicleAreaConfig {
.areaId = toInt(VehicleAreaZone::ROW_1_LEFT),
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index d88479a..f673d1a 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -27,6 +27,7 @@
INT32 = 0x00400000,
INT32_VEC = 0x00410000,
INT64 = 0x00500000,
+ INT64_VEC = 0x00510000,
FLOAT = 0x00600000,
FLOAT_VEC = 0x00610000,
BYTES = 0x00700000,
@@ -35,7 +36,7 @@
* Any combination of scalar or vector types. The exact format must be
* provided in the description of the property.
*/
- COMPLEX = 0x00e00000,
+ MIXED = 0x00e00000,
MASK = 0x00ff0000
};
@@ -315,7 +316,7 @@
WHEEL_TICK = (
0x0306
| VehiclePropertyGroup:SYSTEM
- | VehiclePropertyType:COMPLEX
+ | VehiclePropertyType:MIXED
| VehicleArea:GLOBAL),
@@ -1673,7 +1674,7 @@
/**
* Vehicle Maps Service (VMS) message
*
- * This property uses COMPLEX data to communicate vms messages.
+ * This property uses MIXED data to communicate vms messages.
*
* Its contents are to be interpreted as follows:
* the indices defined in VmsMessageIntegerValuesIndex are to be used to
@@ -1689,7 +1690,7 @@
VEHICLE_MAP_SERVICE = (
0x0C00
| VehiclePropertyGroup:SYSTEM
- | VehiclePropertyType:COMPLEX
+ | VehiclePropertyType:MIXED
| VehicleArea:GLOBAL),
/**
@@ -1736,7 +1737,7 @@
OBD2_LIVE_FRAME = (
0x0D00
| VehiclePropertyGroup:SYSTEM
- | VehiclePropertyType:COMPLEX
+ | VehiclePropertyType:MIXED
| VehicleArea:GLOBAL),
/**
@@ -1766,7 +1767,7 @@
OBD2_FREEZE_FRAME = (
0x0D01
| VehiclePropertyGroup:SYSTEM
- | VehiclePropertyType:COMPLEX
+ | VehiclePropertyType:MIXED
| VehicleArea:GLOBAL),
/**
@@ -1787,7 +1788,7 @@
OBD2_FREEZE_FRAME_INFO = (
0x0D02
| VehiclePropertyGroup:SYSTEM
- | VehiclePropertyType:COMPLEX
+ | VehiclePropertyType:MIXED
| VehicleArea:GLOBAL),
/**
@@ -1813,7 +1814,7 @@
OBD2_FREEZE_FRAME_CLEAR = (
0x0D03
| VehiclePropertyGroup:SYSTEM
- | VehiclePropertyType:COMPLEX
+ | VehiclePropertyType:MIXED
| VehicleArea:GLOBAL),
};
@@ -2169,6 +2170,21 @@
};
/**
+ * Property status is a dynamic value that may change based on the vehicle state.
+ */
+enum VehiclePropertyStatus : int32_t {
+ /** Property is available and behaving normally */
+ AVAILABLE = 0x00,
+ /**
+ * Property is not available, for read and/or write. This is a transient state, as the
+ * property is expected to be available at a later time.
+ */
+ UNAVAILABLE = 0x01,
+ /** There is an error with this property. */
+ ERROR = 0x02,
+};
+
+/**
* Car states.
*
* The driving states determine what features of the UI will be accessible.
@@ -2212,20 +2228,15 @@
ROW_1_LEFT = 0x00000001,
ROW_1_CENTER = 0x00000002,
ROW_1_RIGHT = 0x00000004,
- ROW_1 = 0x00000008,
ROW_2_LEFT = 0x00000010,
ROW_2_CENTER = 0x00000020,
ROW_2_RIGHT = 0x00000040,
- ROW_2 = 0x00000080,
ROW_3_LEFT = 0x00000100,
ROW_3_CENTER = 0x00000200,
ROW_3_RIGHT = 0x00000400,
- ROW_3 = 0x00000800,
ROW_4_LEFT = 0x00001000,
ROW_4_CENTER = 0x00002000,
ROW_4_RIGHT = 0x00004000,
- ROW_4 = 0x00008000,
- WHOLE_CABIN = 0x80000000,
};
/**
@@ -2313,13 +2324,6 @@
VehiclePropertyChangeMode changeMode;
/**
- * Some of the properties may have associated areas (for example, some hvac
- * properties are associated with VehicleAreaZone), in these
- * cases the config may contain an ORed value for the associated areas.
- */
- int32_t supportedAreas;
-
- /**
* Contains per-area configuration.
*/
vec<VehicleAreaConfig> areaConfigs;
@@ -2372,6 +2376,9 @@
*/
int32_t areaId;
+ /** Status of the property */
+ VehiclePropertyStatus status;
+
/**
* Contains value for a single property. Depending on property data type of
* this property (VehiclePropetyType) one field of this structure must be filled in.
@@ -2484,12 +2491,6 @@
int32_t propId;
/**
- * Area ids - this must be a bit mask of areas to subscribe or 0 to subscribe
- * to all areas.
- */
- int32_t vehicleAreas;
-
- /**
* Sample rate in Hz.
*
* Must be provided for properties with
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerTestUtils.h b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerTestUtils.h
index 29b9de3..00d9d8c 100644
--- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerTestUtils.h
+++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerTestUtils.h
@@ -58,10 +58,12 @@
std::string dumpDebugInfo();
std::unique_ptr<ComposerClient> createClient();
+ protected:
+ sp<IComposer> mComposer;
+
private:
void init();
- sp<IComposer> mComposer;
std::unordered_set<IComposer::Capability> mCapabilities;
};
diff --git a/graphics/composer/2.2/Android.bp b/graphics/composer/2.2/Android.bp
new file mode 100644
index 0000000..633a208
--- /dev/null
+++ b/graphics/composer/2.2/Android.bp
@@ -0,0 +1,20 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+ name: "android.hardware.graphics.composer@2.2",
+ root: "android.hardware",
+ vndk: {
+ enabled: true,
+ },
+ srcs: [
+ "IComposer.hal",
+ "IComposerClient.hal",
+ ],
+ interfaces: [
+ "android.hardware.graphics.common@1.0",
+ "android.hardware.graphics.composer@2.1",
+ "android.hidl.base@1.0",
+ ],
+ gen_java: false,
+}
+
diff --git a/graphics/composer/2.2/IComposer.hal b/graphics/composer/2.2/IComposer.hal
new file mode 100644
index 0000000..05052c8
--- /dev/null
+++ b/graphics/composer/2.2/IComposer.hal
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer@2.2;
+
+import @2.1::IComposer;
+
+interface IComposer extends @2.1::IComposer {
+
+ /* createClient from @2.1::IComposer must return an instance of @2.2::IComposerClient */
+
+};
diff --git a/graphics/composer/2.2/IComposerClient.hal b/graphics/composer/2.2/IComposerClient.hal
new file mode 100644
index 0000000..dcd9c8d
--- /dev/null
+++ b/graphics/composer/2.2/IComposerClient.hal
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.composer@2.2;
+
+import android.hardware.graphics.common@1.0::PixelFormat;
+import android.hardware.graphics.common@1.0::Dataspace;
+import @2.1::IComposerClient;
+import @2.1::Display;
+import @2.1::Error;
+
+interface IComposerClient extends @2.1::IComposerClient {
+
+ enum PowerMode : @2.1::IComposerClient.PowerMode {
+ /**
+ * The display is configured as in ON but may stop applying display
+ * updates from the client. This is effectively a hint to the device
+ * that drawing to the display has been suspended and that the the
+ * device must remain on and continue displaying its current contents
+ * indefinitely until the power mode changes.
+ *
+ * This mode may also be used as a signal to enable hardware-based
+ * functionality to take over the display and manage it autonomously
+ * to implement a low power always-on display.
+ */
+ ON_SUSPEND = 4
+ };
+
+ /**
+ * Following enums define keys for metadata defined by SMPTE ST 2086:2014
+ * and CTA 861.3.
+ */
+ enum PerFrameMetadataKey : int32_t {
+ /** SMPTE ST 2084:2014.
+ * Coordinates defined in CIE 1931 xy chromaticity space
+ */
+ /** SMPTE ST 2084:2014 */
+ DISPLAY_RED_PRIMARY_X,
+ /** SMPTE ST 2084:2014 */
+ DISPLAY_RED_PRIMARY_Y,
+ /** SMPTE ST 2084:2014 */
+ DISPLAY_GREEN_PRIMARY_X,
+ /** SMPTE ST 2084:2014 */
+ DISPLAY_GREEN_PRIMARY_Y,
+ /** SMPTE ST 2084:2014 */
+ DISPLAY_BLUE_PRIMARY_X,
+ /** SMPTE ST 2084:2014 */
+ DISPLAY_BLUE_PRIMARY_Y,
+ /** SMPTE ST 2084:2014 */
+ WHITE_POINT_X,
+ /** SMPTE ST 2084:2014 */
+ WHITE_POINT_Y,
+ /** SMPTE ST 2084:2014.
+ * Units: nits
+ * max as defined by ST 2048: 10,000 nits
+ */
+ MAX_LUMINANCE,
+ /** SMPTE ST 2084:2014 */
+ MIN_LUMINANCE,
+ /** CTA 861.3 */
+ MAX_CONTENT_LIGHT_LEVEL,
+ /** CTA 861.3 */
+ MAX_FRAME_AVERAGE_LIGHT_LEVEL,
+ };
+
+ struct PerFrameMetadata {
+ PerFrameMetadataKey key;
+ float value;
+ };
+
+ struct FloatColor {
+ float r;
+ float g;
+ float b;
+ float a;
+ };
+
+ enum Command : @2.1::IComposerClient.Command {
+ /**
+ * setPerFrameMetadata(Display display, vec<PerFrameMetadata> data)
+ * Sets the PerFrameMetadata for the display. This metadata must be used
+ * by the implementation to better tone map content to that display.
+ *
+ * This is a method that may be called every frame. Thus it's
+ * implemented using buffered transport.
+ * SET_PER_FRAME_METADATA is the command used by the buffered transport
+ * mechanism.
+ */
+ SET_PER_FRAME_METADATA = 0x207 << @2.1::IComposerClient.Command:OPCODE_SHIFT,
+
+ /**
+ * SET_LAYER_COLOR has this pseudo prototype
+ *
+ * setLayerColor(FloatColor color);
+ *
+ * Sets the color of the given layer. If the composition type of the layer
+ * is not Composition::SOLID_COLOR, this call must succeed and have no
+ * other effect.
+ *
+ * @param color is the new color using float type.
+ */
+ SET_LAYER_FLOAT_COLOR = 0x40c << @2.1::IComposerClient.Command:OPCODE_SHIFT,
+ };
+
+ /**
+ * Returns the PerFrameMetadataKeys that are supported by this device.
+ *
+ * @param display is the display on which to create the layer.
+ * @return keys is the vector of PerFrameMetadataKey keys that are
+ * supported by this device.
+ * @return error is NONE upon success. Otherwise,
+ * UNSUPPORTED if not supported on underlying HAL
+ */
+ getPerFrameMetadataKeys(Display display)
+ generates (Error error,
+ vec<PerFrameMetadataKey> keys);
+
+ /**
+ * getReadbackBufferAttributes
+ * Returns the format which should be used when allocating a buffer for use by
+ * device readback as well as the dataspace in which its contents should be
+ * interpreted.
+ *
+ * The width and height of this buffer must be those of the currently-active
+ * display configuration, and the usage flags must consist of the following:
+ * BufferUsage::CPU_READ | BufferUsage::GPU_TEXTURE |
+ * BufferUsage::COMPOSER_OUTPUT
+ *
+ * The format and dataspace provided must be sufficient such that if a
+ * correctly-configured buffer is passed into setReadbackBuffer, filled by
+ * the device, and then displayed by the client as a full-screen buffer, the
+ * output of the display remains the same (subject to the note about protected
+ * content in the description of setReadbackBuffer).
+ *
+ * Parameters:
+ * @param display - the display on which to create the layer.
+ *
+ * @return format - the format the client should use when allocating a device
+ * readback buffer
+ * @return dataspace - the dataspace to use when interpreting the
+ * contents of a device readback buffer
+ * @return error is NONE upon success. Otherwise,
+ * BAD_DISPLAY when an invalid display handle was passed in.
+ * UNSUPPORTED if not supported on underlying HAL
+ *
+ * See also:
+ * setReadbackBuffer
+ * getReadbackBufferFence
+ */
+ getReadbackBufferAttributes(Display display)
+ generates (Error error,
+ PixelFormat format,
+ Dataspace dataspace);
+
+ /**
+ * getReadbackBufferFence
+ * Returns an acquire sync fence file descriptor which must signal when the
+ * buffer provided to setReadbackBuffer has been filled by the device and is
+ * safe for the client to read.
+ *
+ * If it is already safe to read from this buffer, -1 may be returned instead.
+ * The client takes ownership of this file descriptor and is responsible for
+ * closing it when it is no longer needed.
+ *
+ * This function must be called immediately after the composition cycle being
+ * captured into the readback buffer. The complete ordering of a readback buffer
+ * capture is as follows:
+ *
+ * getReadbackBufferAttributes
+ * // Readback buffer is allocated
+ * // Many frames may pass
+ *
+ * setReadbackBuffer
+ * validateDisplay
+ * presentDisplay
+ * getReadbackBufferFence
+ * // Implicitly wait on the acquire fence before accessing the buffer
+ *
+ * Parameters:
+ * @param display - the display on which to create the layer.
+ *
+ * @return acquireFence - a sync fence file descriptor as described above; pointer
+ * must be non-NULL
+ * @return error - is HWC2_ERROR_NONE or one of the following errors:
+ * BAD_DISPLAY - an invalid display handle was passed in
+ * UNSUPPORTED if not supported on underlying HAL
+ *
+ * See also:
+ * getReadbackBufferAttributes
+ * setReadbackBuffer
+ */
+ getReadbackBufferFence(Display display)
+ generates (Error error,
+ handle acquireFence);
+
+ /**
+ * setReadbackBuffer
+ * Sets the readback buffer to be filled with the contents of the next
+ * composition performed for this display (i.e., the contents present at the
+ * time of the next validateDisplay/presentDisplay cycle).
+ *
+ * This buffer must have been allocated as described in
+ * getReadbackBufferAttributes and is in the dataspace provided by the same.
+ *
+ * If there is hardware protected content on the display at the time of the next
+ * composition, the area of the readback buffer covered by such content must be
+ * completely black. Any areas of the buffer not covered by such content may
+ * optionally be black as well.
+ *
+ * The release fence file descriptor provided works identically to the one
+ * described for setOutputBuffer.
+ *
+ * This function must not be called between any call to validateDisplay and a
+ * subsequent call to presentDisplay.
+ *
+ * Parameters:
+ * @param display - the display on which to create the layer.
+ * @param buffer - the new readback buffer
+ * @param releaseFence - a sync fence file descriptor as described in setOutputBuffer
+ *
+ * @return error - is HWC2_ERROR_NONE or one of the following errors:
+ * HWC2_ERROR_BAD_DISPLAY - an invalid display handle was passed in
+ * HWC2_ERROR_BAD_PARAMETER - the new readback buffer handle was invalid
+ *
+ * See also:
+ * getReadbackBufferAttributes
+ * getReadbackBufferFence
+ */
+ setReadbackBuffer(Display display, handle buffer, handle releaseFence) generates (Error error);
+
+ /**
+ * setPowerMode_2_2
+ * Sets the power mode of the given display. The transition must be
+ * complete when this function returns. It is valid to call this function
+ * multiple times with the same power mode.
+ *
+ * All displays must support PowerMode::ON and PowerMode::OFF. Whether a
+ * display supports PowerMode::DOZE or PowerMode::DOZE_SUSPEND may be
+ * queried using getDozeSupport.
+ *
+ * @param display is the display to which the power mode is set.
+ * @param mode is the new power mode.
+ * @return error is NONE upon success. Otherwise,
+ * BAD_DISPLAY when an invalid display handle was passed in.
+ * BAD_PARAMETER when mode was not a valid power mode.
+ * UNSUPPORTED when mode is not supported on this display.
+ */
+ setPowerMode_2_2(Display display, PowerMode mode) generates (Error error);
+
+};
diff --git a/graphics/composer/2.2/utils/OWNERS b/graphics/composer/2.2/utils/OWNERS
new file mode 100644
index 0000000..1beb074
--- /dev/null
+++ b/graphics/composer/2.2/utils/OWNERS
@@ -0,0 +1,8 @@
+# Graphics team
+courtneygo@google.com
+olv@google.com
+stoza@google.com
+
+# VTS team
+yim@google.com
+zhuoyao@google.com
diff --git a/graphics/composer/2.2/utils/command-buffer/Android.bp b/graphics/composer/2.2/utils/command-buffer/Android.bp
new file mode 100644
index 0000000..efaabd4
--- /dev/null
+++ b/graphics/composer/2.2/utils/command-buffer/Android.bp
@@ -0,0 +1,13 @@
+cc_library_headers {
+ name: "android.hardware.graphics.composer@2.2-command-buffer",
+ defaults: ["hidl_defaults"],
+ vendor_available: true,
+ shared_libs: [
+ "android.hardware.graphics.composer@2.1",
+ "android.hardware.graphics.composer@2.2",
+ ],
+ header_libs: [
+ "android.hardware.graphics.composer@2.1-command-buffer",
+ ],
+ export_include_dirs: ["include"],
+}
diff --git a/graphics/composer/2.2/utils/command-buffer/include/composer-command-buffer/2.2/ComposerCommandBuffer.h b/graphics/composer/2.2/utils/command-buffer/include/composer-command-buffer/2.2/ComposerCommandBuffer.h
new file mode 100644
index 0000000..c803d3c
--- /dev/null
+++ b/graphics/composer/2.2/utils/command-buffer/include/composer-command-buffer/2.2/ComposerCommandBuffer.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#ifndef LOG_TAG
+#warn "ComposerCommandBuffer.h included without LOG_TAG"
+#endif
+
+#undef LOG_NDEBUG
+#define LOG_NDEBUG 0
+
+#include <algorithm>
+#include <limits>
+#include <memory>
+#include <vector>
+
+#include <inttypes.h>
+#include <string.h>
+
+#include <android/hardware/graphics/composer/2.2/IComposer.h>
+#include <android/hardware/graphics/composer/2.2/IComposerClient.h>
+#include <fmq/MessageQueue.h>
+#include <log/log.h>
+#include <sync/sync.h>
+
+#include <composer-command-buffer/2.1/ComposerCommandBuffer.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+
+using android::hardware::MessageQueue;
+using android::hardware::graphics::common::V1_0::ColorTransform;
+using android::hardware::graphics::common::V1_0::Dataspace;
+using android::hardware::graphics::common::V1_0::Transform;
+using android::hardware::graphics::composer::V2_1::Config;
+using android::hardware::graphics::composer::V2_1::Display;
+using android::hardware::graphics::composer::V2_1::Error;
+using android::hardware::graphics::composer::V2_1::IComposerCallback;
+using android::hardware::graphics::composer::V2_1::Layer;
+using android::hardware::graphics::composer::V2_2::IComposerClient;
+
+using CommandQueueType = MessageQueue<uint32_t, kSynchronizedReadWrite>;
+
+// This class helps build a command queue. Note that all sizes/lengths are in
+// units of uint32_t's.
+class CommandWriterBase : public V2_1::CommandWriterBase {
+ public:
+ CommandWriterBase(uint32_t initialMaxSize) : V2_1::CommandWriterBase(initialMaxSize) {}
+
+ static constexpr uint16_t kSetLayerFloatColorLength = 4;
+ void setLayerFloatColor(IComposerClient::FloatColor color) {
+ beginCommand_2_2(IComposerClient::Command::SET_LAYER_FLOAT_COLOR,
+ kSetLayerFloatColorLength);
+ writeFloatColor(color);
+ endCommand();
+ }
+
+ void setPerFrameMetadata(const hidl_vec<IComposerClient::PerFrameMetadata>& metadataVec) {
+ beginCommand_2_2(IComposerClient::Command::SET_PER_FRAME_METADATA, metadataVec.size() * 2);
+ for (const auto& metadata : metadataVec) {
+ writeSigned(static_cast<int32_t>(metadata.key));
+ writeFloat(metadata.value);
+ }
+ endCommand();
+ }
+
+ protected:
+ void beginCommand_2_2(IComposerClient::Command command, uint16_t length) {
+ V2_1::CommandWriterBase::beginCommand(
+ static_cast<V2_1::IComposerClient::Command>(static_cast<int32_t>(command)), length);
+ }
+
+ void writeFloatColor(const IComposerClient::FloatColor& color) {
+ writeFloat(color.r);
+ writeFloat(color.g);
+ writeFloat(color.b);
+ writeFloat(color.a);
+ }
+};
+
+// This class helps parse a command queue. Note that all sizes/lengths are in
+// units of uint32_t's.
+class CommandReaderBase : public V2_1::CommandReaderBase {
+ public:
+ CommandReaderBase() : V2_1::CommandReaderBase(){};
+
+ protected:
+ IComposerClient::FloatColor readFloatColor() {
+ float r = readFloat();
+ float g = readFloat();
+ float b = readFloat();
+ float a = readFloat();
+ return IComposerClient::FloatColor{r, g, b, a};
+ }
+};
+
+} // namespace V2_2
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.2/vts/functional/Android.bp b/graphics/composer/2.2/vts/functional/Android.bp
new file mode 100644
index 0000000..0325a6c
--- /dev/null
+++ b/graphics/composer/2.2/vts/functional/Android.bp
@@ -0,0 +1,74 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_library_static {
+ name: "libVtsHalGraphicsComposerTestUtils@2.2",
+ defaults: ["hidl_defaults"],
+ srcs: [
+ "VtsHalGraphicsComposerTestUtils.cpp",
+ ],
+ shared_libs: [
+ "android.hardware.graphics.composer@2.1",
+ "android.hardware.graphics.composer@2.2",
+ "libfmq",
+ "libsync",
+ ],
+ static_libs: [
+ "libVtsHalGraphicsComposerTestUtils",
+ "VtsHalHidlTargetTestBase",
+ ],
+ header_libs: [
+ "android.hardware.graphics.composer@2.1-command-buffer",
+ "android.hardware.graphics.composer@2.2-command-buffer",
+ ],
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ "-Werror",
+ "-O0",
+ "-g",
+ "-DLOG_TAG=\"GraphicsComposerTestUtils@2.2\"",
+ ],
+ export_include_dirs: ["include"],
+}
+
+cc_test {
+ name: "VtsHalGraphicsComposerV2_2TargetTest",
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: ["VtsHalGraphicsComposerV2_2TargetTest.cpp"],
+
+ // TODO(b/64437680): Assume these libs are always available on the device.
+ shared_libs: [
+ "libfmq",
+ "libhidltransport",
+ "libsync",
+ ],
+ static_libs: [
+ "android.hardware.graphics.allocator@2.0",
+ "android.hardware.graphics.composer@2.2",
+ "android.hardware.graphics.composer@2.1",
+ "android.hardware.graphics.mapper@2.0",
+ "android.hardware.graphics.mapper@2.1",
+ "libVtsHalGraphicsComposerTestUtils",
+ "libVtsHalGraphicsComposerTestUtils@2.2",
+ "libVtsHalGraphicsMapperTestUtils",
+ "libnativehelper",
+ ],
+ header_libs: [
+ "android.hardware.graphics.composer@2.1-command-buffer",
+ "android.hardware.graphics.composer@2.2-command-buffer",
+ ],
+}
diff --git a/graphics/composer/2.2/vts/functional/OWNERS b/graphics/composer/2.2/vts/functional/OWNERS
new file mode 100644
index 0000000..1beb074
--- /dev/null
+++ b/graphics/composer/2.2/vts/functional/OWNERS
@@ -0,0 +1,8 @@
+# Graphics team
+courtneygo@google.com
+olv@google.com
+stoza@google.com
+
+# VTS team
+yim@google.com
+zhuoyao@google.com
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerTestUtils.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerTestUtils.cpp
new file mode 100644
index 0000000..00946ce
--- /dev/null
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerTestUtils.cpp
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <hidl/HidlTransportUtils.h>
+
+#include <composer-command-buffer/2.2/ComposerCommandBuffer.h>
+#include "2.2/VtsHalGraphicsComposerTestUtils.h"
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace tests {
+
+using android::hardware::graphics::composer::V2_2::IComposerClient;
+using android::hardware::details::getDescriptor;
+using android::hardware::details::canCastInterface;
+
+std::unique_ptr<ComposerClient_v2_2> Composer_v2_2::createClient_v2_2() {
+ std::unique_ptr<ComposerClient_v2_2> client;
+ mComposer->createClient([&](const auto& tmpError, const auto& tmpClient) {
+ ASSERT_EQ(Error::NONE, tmpError) << "failed to create client";
+ ALOGV("tmpClient is a %s", getDescriptor(&(*tmpClient)).c_str());
+ ASSERT_TRUE(canCastInterface(
+ &(*tmpClient), "android.hardware.graphics.composer@2.2::IComposerClient", false))
+ << "Cannot create 2.2 IComposerClient";
+ client = std::make_unique<ComposerClient_v2_2>(IComposerClient::castFrom(tmpClient, true));
+ });
+
+ return client;
+}
+
+std::vector<IComposerClient::PerFrameMetadataKey> ComposerClient_v2_2::getPerFrameMetadataKeys(
+ Display display) {
+ std::vector<IComposerClient::PerFrameMetadataKey> keys;
+ mClient_v2_2->getPerFrameMetadataKeys(display, [&](const auto& tmpError, const auto& tmpKeys) {
+ ASSERT_EQ(Error::NONE, tmpError) << "failed to get HDR metadata keys";
+ keys = tmpKeys;
+ });
+
+ return keys;
+}
+
+void ComposerClient_v2_2::execute_v2_2(V2_1::tests::TestCommandReader* reader,
+ V2_2::CommandWriterBase* writer) {
+ bool queueChanged = false;
+ uint32_t commandLength = 0;
+ hidl_vec<hidl_handle> commandHandles;
+ ASSERT_TRUE(writer->writeQueue(&queueChanged, &commandLength, &commandHandles));
+
+ if (queueChanged) {
+ auto ret = mClient_v2_2->setInputCommandQueue(*writer->getMQDescriptor());
+ ASSERT_EQ(Error::NONE, static_cast<Error>(ret));
+ return;
+ }
+
+ mClient_v2_2->executeCommands(commandLength, commandHandles,
+ [&](const auto& tmpError, const auto& tmpOutQueueChanged,
+ const auto& tmpOutLength, const auto& tmpOutHandles) {
+ ASSERT_EQ(Error::NONE, tmpError);
+
+ if (tmpOutQueueChanged) {
+ mClient_v2_2->getOutputCommandQueue(
+ [&](const auto& tmpError, const auto& tmpDescriptor) {
+ ASSERT_EQ(Error::NONE, tmpError);
+ reader->setMQDescriptor(tmpDescriptor);
+ });
+ }
+
+ ASSERT_TRUE(reader->readQueue(tmpOutLength, tmpOutHandles));
+ reader->parse();
+ });
+}
+
+void ComposerClient_v2_2::setPowerMode_2_2(Display display, V2_2::IComposerClient::PowerMode mode) {
+ Error error = mClient_v2_2->setPowerMode_2_2(display, mode);
+ ASSERT_TRUE(error == Error::NONE || error == Error::UNSUPPORTED) << "failed to set power mode";
+}
+
+void ComposerClient_v2_2::setReadbackBuffer(Display display, const native_handle_t* buffer,
+ int32_t /* releaseFence */) {
+ // Ignoring fence, HIDL doesn't care
+ Error error = mClient_v2_2->setReadbackBuffer(display, buffer, nullptr);
+ ASSERT_EQ(Error::NONE, error) << "failed to setReadbackBuffer";
+}
+
+void ComposerClient_v2_2::getReadbackBufferAttributes(Display display, PixelFormat* outPixelFormat,
+ Dataspace* outDataspace) {
+ mClient_v2_2->getReadbackBufferAttributes(
+ display,
+ [&](const auto& tmpError, const auto& tmpOutPixelFormat, const auto& tmpOutDataspace) {
+ ASSERT_EQ(Error::NONE, tmpError) << "failed to get readback buffer attributes";
+ *outPixelFormat = tmpOutPixelFormat;
+ *outDataspace = tmpOutDataspace;
+ });
+}
+
+void ComposerClient_v2_2::getReadbackBufferFence(Display display, int32_t* outFence) {
+ hidl_handle handle;
+ mClient_v2_2->getReadbackBufferFence(display, [&](const auto& tmpError, const auto& tmpHandle) {
+ ASSERT_EQ(Error::NONE, tmpError) << "failed to get readback fence";
+ handle = tmpHandle;
+ });
+ *outFence = 0;
+}
+
+} // namespace tests
+} // namespace V2_2
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
new file mode 100644
index 0000000..8b44d61
--- /dev/null
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "graphics_composer_hidl_hal_test@2.2"
+
+#include <android-base/logging.h>
+#include <android/hardware/graphics/mapper/2.1/IMapper.h>
+#include <sync/sync.h>
+#include "2.2/VtsHalGraphicsComposerTestUtils.h"
+#include "GraphicsComposerCallback.h"
+#include "TestCommandReader.h"
+#include "VtsHalGraphicsComposerTestUtils.h"
+#include "VtsHalGraphicsMapperTestUtils.h"
+
+#include <VtsHalHidlTargetTestBase.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace tests {
+namespace {
+
+using android::hardware::graphics::common::V1_0::BufferUsage;
+using android::hardware::graphics::common::V1_0::ColorMode;
+using android::hardware::graphics::common::V1_0::ColorTransform;
+using android::hardware::graphics::common::V1_0::Dataspace;
+using android::hardware::graphics::common::V1_0::PixelFormat;
+using android::hardware::graphics::common::V1_0::Transform;
+using android::hardware::graphics::composer::V2_2::IComposerClient;
+using android::hardware::graphics::mapper::V2_0::IMapper;
+using android::hardware::graphics::mapper::V2_0::tests::Gralloc;
+using GrallocError = android::hardware::graphics::mapper::V2_0::Error;
+
+// Test environment for graphics.composer
+class GraphicsComposerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+ public:
+ // get the test environment singleton
+ static GraphicsComposerHidlEnvironment* Instance() {
+ static GraphicsComposerHidlEnvironment* instance = new GraphicsComposerHidlEnvironment;
+ return instance;
+ }
+
+ virtual void registerTestServices() override { registerTestService<IComposer>(); }
+
+ private:
+ GraphicsComposerHidlEnvironment() {}
+
+ GTEST_DISALLOW_COPY_AND_ASSIGN_(GraphicsComposerHidlEnvironment);
+};
+
+class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+ protected:
+ void SetUp() override {
+ ASSERT_NO_FATAL_FAILURE(
+ mComposer = std::make_unique<Composer_v2_2>(
+ GraphicsComposerHidlEnvironment::Instance()->getServiceName<IComposer>()));
+ ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient_v2_2());
+
+ mComposerCallback = new V2_1::tests::GraphicsComposerCallback;
+ mComposerClient->registerCallback(mComposerCallback);
+
+ // assume the first display is primary and is never removed
+ mPrimaryDisplay = waitForFirstDisplay();
+
+ // explicitly disable vsync
+ mComposerClient->setVsyncEnabled(mPrimaryDisplay, false);
+ mComposerCallback->setVsyncAllowed(false);
+ }
+
+ void TearDown() override {
+ if (mComposerCallback != nullptr) {
+ EXPECT_EQ(0, mComposerCallback->getInvalidHotplugCount());
+ EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount());
+ EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount());
+ }
+ }
+
+ // use the slot count usually set by SF
+ static constexpr uint32_t kBufferSlotCount = 64;
+
+ std::unique_ptr<Composer_v2_2> mComposer;
+ std::unique_ptr<ComposerClient_v2_2> mComposerClient;
+ sp<V2_1::tests::GraphicsComposerCallback> mComposerCallback;
+ // the first display and is assumed never to be removed
+ Display mPrimaryDisplay;
+
+ private:
+ Display waitForFirstDisplay() {
+ while (true) {
+ std::vector<Display> displays = mComposerCallback->getDisplays();
+ if (displays.empty()) {
+ usleep(5 * 1000);
+ continue;
+ }
+
+ return displays[0];
+ }
+ }
+};
+
+// Tests for IComposerClient::Command.
+class GraphicsComposerHidlCommandTest : public GraphicsComposerHidlTest {
+ protected:
+ void SetUp() override {
+ ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::SetUp());
+
+ ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
+
+ mWriter = std::make_unique<V2_2::CommandWriterBase>(1024);
+ mReader = std::make_unique<V2_1::tests::TestCommandReader>();
+ }
+
+ void TearDown() override { ASSERT_NO_FATAL_FAILURE(GraphicsComposerHidlTest::TearDown()); }
+
+ const native_handle_t* allocate() {
+ IMapper::BufferDescriptorInfo info{};
+ info.width = 64;
+ info.height = 64;
+ info.layerCount = 1;
+ info.format = PixelFormat::RGBA_8888;
+ info.usage =
+ static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
+
+ return mGralloc->allocate(info);
+ }
+
+ void execute() { mComposerClient->execute_v2_2(mReader.get(), mWriter.get()); }
+
+ std::unique_ptr<V2_2::CommandWriterBase> mWriter;
+ std::unique_ptr<V2_1::tests::TestCommandReader> mReader;
+
+ private:
+ std::unique_ptr<Gralloc> mGralloc;
+};
+
+/**
+ * Test IComposerClient::Command::SET_PER_FRAME_METADATA.
+ */
+TEST_F(GraphicsComposerHidlCommandTest, SET_PER_FRAME_METADATA) {
+ Layer layer;
+ ASSERT_NO_FATAL_FAILURE(layer =
+ mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+
+ /**
+ * DISPLAY_P3 is a color space that uses the DCI_P3 primaries,
+ * the D65 white point and the SRGB transfer functions.
+ * Rendering Intent: Colorimetric
+ * Primaries:
+ * x y
+ * green 0.265 0.690
+ * blue 0.150 0.060
+ * red 0.680 0.320
+ * white (D65) 0.3127 0.3290
+ */
+
+ std::vector<IComposerClient::PerFrameMetadata> hidlMetadata;
+ hidlMetadata.push_back({IComposerClient::PerFrameMetadataKey::DISPLAY_RED_PRIMARY_X, 0.680});
+ hidlMetadata.push_back({IComposerClient::PerFrameMetadataKey::DISPLAY_RED_PRIMARY_Y, 0.320});
+ hidlMetadata.push_back({IComposerClient::PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_X, 0.265});
+ hidlMetadata.push_back({IComposerClient::PerFrameMetadataKey::DISPLAY_GREEN_PRIMARY_Y, 0.690});
+ hidlMetadata.push_back({IComposerClient::PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_X, 0.150});
+ hidlMetadata.push_back({IComposerClient::PerFrameMetadataKey::DISPLAY_BLUE_PRIMARY_Y, 0.060});
+ hidlMetadata.push_back({IComposerClient::PerFrameMetadataKey::WHITE_POINT_X, 0.3127});
+ hidlMetadata.push_back({IComposerClient::PerFrameMetadataKey::WHITE_POINT_Y, 0.3290});
+ hidlMetadata.push_back({IComposerClient::PerFrameMetadataKey::MAX_LUMINANCE, 100.0});
+ hidlMetadata.push_back({IComposerClient::PerFrameMetadataKey::MIN_LUMINANCE, 0.1});
+ hidlMetadata.push_back({IComposerClient::PerFrameMetadataKey::MAX_CONTENT_LIGHT_LEVEL, 78.0});
+ hidlMetadata.push_back(
+ {IComposerClient::PerFrameMetadataKey::MAX_FRAME_AVERAGE_LIGHT_LEVEL, 62.0});
+ mWriter->setPerFrameMetadata(hidlMetadata);
+ execute();
+}
+
+/**
+ * Test IComposerClient::getPerFrameMetadataKeys.
+ */
+TEST_F(GraphicsComposerHidlTest, GetPerFrameMetadataKeys) {
+ mComposerClient->getPerFrameMetadataKeys(mPrimaryDisplay);
+}
+/**
+ * Test IComposerClient::setPowerMode_2_2.
+ */
+TEST_F(GraphicsComposerHidlTest, setPowerMode_2_2) {
+ std::vector<IComposerClient::PowerMode> modes;
+ modes.push_back(IComposerClient::PowerMode::OFF);
+ modes.push_back(IComposerClient::PowerMode::ON_SUSPEND);
+ modes.push_back(IComposerClient::PowerMode::ON);
+
+ for (auto mode : modes) {
+ mComposerClient->setPowerMode_2_2(mPrimaryDisplay, mode);
+ }
+}
+
+TEST_F(GraphicsComposerHidlTest, setReadbackBuffer) {
+ mComposerClient->setReadbackBuffer(mPrimaryDisplay, nullptr, -1);
+}
+
+TEST_F(GraphicsComposerHidlTest, getReadbackBufferFence) {
+ int32_t fence;
+ mComposerClient->getReadbackBufferFence(mPrimaryDisplay, &fence);
+}
+
+TEST_F(GraphicsComposerHidlTest, getReadbackBufferAttributes) {
+ PixelFormat pixelFormat;
+ Dataspace dataspace;
+ mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay, &pixelFormat, &dataspace);
+}
+
+/**
+ * Test IComposerClient::Command::SET_LAYER_FLOAT_COLOR.
+ */
+TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_FLOAT_COLOR) {
+ V2_1::Layer layer;
+ ASSERT_NO_FATAL_FAILURE(layer =
+ mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+
+ mWriter->selectDisplay(mPrimaryDisplay);
+ mWriter->selectLayer(layer);
+ mWriter->setLayerFloatColor(IComposerClient::FloatColor{1.0, 1.0, 1.0, 1.0});
+ mWriter->setLayerFloatColor(IComposerClient::FloatColor{0.0, 0.0, 0.0, 0.0});
+}
+
+} // namespace
+} // namespace tests
+} // namespace V2_2
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
+
+int main(int argc, char** argv) {
+ using android::hardware::graphics::composer::V2_2::tests::GraphicsComposerHidlEnvironment;
+ ::testing::AddGlobalTestEnvironment(GraphicsComposerHidlEnvironment::Instance());
+ ::testing::InitGoogleTest(&argc, argv);
+ GraphicsComposerHidlEnvironment::Instance()->init(&argc, argv);
+ int status = RUN_ALL_TESTS();
+ return status;
+}
diff --git a/graphics/composer/2.2/vts/functional/include/2.2/VtsHalGraphicsComposerTestUtils.h b/graphics/composer/2.2/vts/functional/include/2.2/VtsHalGraphicsComposerTestUtils.h
new file mode 100644
index 0000000..c5756ed
--- /dev/null
+++ b/graphics/composer/2.2/vts/functional/include/2.2/VtsHalGraphicsComposerTestUtils.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+#include <VtsHalGraphicsComposerTestUtils.h>
+#include <VtsHalHidlTargetTestBase.h>
+#include <android/hardware/graphics/composer/2.2/IComposer.h>
+#include <android/hardware/graphics/composer/2.2/IComposerClient.h>
+#include <composer-command-buffer/2.2/ComposerCommandBuffer.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_2 {
+namespace tests {
+
+using android::hardware::graphics::common::V1_0::ColorMode;
+using android::hardware::graphics::common::V1_0::Dataspace;
+using android::hardware::graphics::common::V1_0::Hdr;
+using android::hardware::graphics::common::V1_0::PixelFormat;
+using android::hardware::graphics::composer::V2_2::IComposer;
+using android::hardware::graphics::composer::V2_2::IComposerClient;
+
+class ComposerClient_v2_2;
+
+// Only thing I need for Composer_v2_2 is to create a v2_2 ComposerClient
+// Everything else is the same
+class Composer_v2_2 : public V2_1::tests::Composer {
+ public:
+ Composer_v2_2() : V2_1::tests::Composer(){};
+ explicit Composer_v2_2(const std::string& name) : V2_1::tests::Composer(name){};
+
+ std::unique_ptr<ComposerClient_v2_2> createClient_v2_2();
+};
+
+// A wrapper to IComposerClient.
+class ComposerClient_v2_2
+ : public android::hardware::graphics::composer::V2_1::tests::ComposerClient {
+ public:
+ ComposerClient_v2_2(const sp<IComposerClient>& client)
+ : V2_1::tests::ComposerClient(client), mClient_v2_2(client){};
+
+ void execute_v2_2(V2_1::tests::TestCommandReader* reader, V2_2::CommandWriterBase* writer);
+
+ std::vector<IComposerClient::PerFrameMetadataKey> getPerFrameMetadataKeys(Display display);
+
+ void setPowerMode_2_2(Display display, V2_2::IComposerClient::PowerMode mode);
+ void setReadbackBuffer(Display display, const native_handle_t* buffer, int32_t releaseFence);
+ void getReadbackBufferAttributes(Display display, PixelFormat* outPixelFormat,
+ Dataspace* outDataspace);
+ void getReadbackBufferFence(Display display, int32_t* outFence);
+
+ private:
+ sp<V2_2::IComposerClient> mClient_v2_2;
+};
+
+} // namespace tests
+} // namespace V2_2
+} // namespace composer
+} // namespace graphics
+} // namespace hardware
+} // namespace android
diff --git a/graphics/mapper/2.1/IMapper.hal b/graphics/mapper/2.1/IMapper.hal
index a23656d..6047e96 100644
--- a/graphics/mapper/2.1/IMapper.hal
+++ b/graphics/mapper/2.1/IMapper.hal
@@ -16,10 +16,47 @@
package android.hardware.graphics.mapper@2.1;
-import android.hardware.graphics.mapper@2.0::Error;
-import android.hardware.graphics.mapper@2.0::IMapper;
+import android.hardware.graphics.common@1.1::BufferUsage;
+import android.hardware.graphics.common@1.1::PixelFormat;
+import @2.0::BufferDescriptor;
+import @2.0::Error;
+import @2.0::IMapper;
-interface IMapper extends android.hardware.graphics.mapper@2.0::IMapper {
+interface IMapper extends @2.0::IMapper {
+ /**
+ * This is the same as @2.0::IMapper::BufferDescriptorInfo except that it
+ * accepts @1.1::PixelFormat and @1.1::BufferUsage.
+ */
+ struct BufferDescriptorInfo {
+ /**
+ * The width specifies how many columns of pixels must be in the
+ * allocated buffer, but does not necessarily represent the offset in
+ * columns between the same column in adjacent rows. The rows may be
+ * padded.
+ */
+ uint32_t width;
+
+ /**
+ * The height specifies how many rows of pixels must be in the
+ * allocated buffer.
+ */
+ uint32_t height;
+
+ /**
+ * The number of image layers that must be in the allocated buffer.
+ */
+ uint32_t layerCount;
+
+ /** Buffer pixel format. */
+ PixelFormat format;
+
+ /**
+ * Buffer usage mask; valid flags can be found in the definition of
+ * BufferUsage.
+ */
+ bitfield<BufferUsage> usage;
+ };
+
/**
* Validate that the buffer can be safely accessed by a caller who assumes
* the specified descriptorInfo and stride. This must at least validate
@@ -58,4 +95,30 @@
generates (Error error,
uint32_t numFds,
uint32_t numInts);
+
+ /**
+ * This is the same as @2.0::IMapper::createDescriptor except that it
+ * accepts @2.1::IMapper::BufferDescriptorInfo.
+ *
+ * Creates a buffer descriptor. The descriptor can be used with IAllocator
+ * to allocate buffers.
+ *
+ * Since the buffer descriptor fully describes a buffer, any device
+ * dependent or device independent checks must be performed here whenever
+ * possible. Specifically, when layered buffers are not supported, this
+ * function must return UNSUPPORTED if layerCount is great than 1.
+ *
+ * @param descriptorInfo specifies the attributes of the descriptor.
+ * @return error is NONE upon success. Otherwise,
+ * BAD_VALUE when any of the specified attributes is
+ * invalid or conflicting.
+ * NO_RESOURCES when the creation cannot be fullfilled at
+ * this time.
+ * UNSUPPORTED when any of the specified attributes is
+ * not supported.
+ * @return descriptor is the newly created buffer descriptor.
+ */
+ createDescriptor_2_1(BufferDescriptorInfo descriptorInfo)
+ generates (Error error,
+ BufferDescriptor descriptor);
};
diff --git a/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp b/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp
index 4067c8d..88b96ae 100644
--- a/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp
+++ b/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp
@@ -30,10 +30,27 @@
namespace tests {
namespace {
+using android::hardware::graphics::mapper::V2_0::BufferDescriptor;
using android::hardware::graphics::mapper::V2_0::Error;
-using android::hardware::graphics::common::V1_0::BufferUsage;
-using android::hardware::graphics::common::V1_0::PixelFormat;
+using android::hardware::graphics::common::V1_1::BufferUsage;
+using android::hardware::graphics::common::V1_1::PixelFormat;
+
+// abuse VTS to check binary compatibility between BufferDescriptorInfos
+using OldBufferDescriptorInfo =
+ android::hardware::graphics::mapper::V2_0::IMapper::BufferDescriptorInfo;
+static_assert(sizeof(OldBufferDescriptorInfo) == sizeof(IMapper::BufferDescriptorInfo) &&
+ offsetof(OldBufferDescriptorInfo, width) ==
+ offsetof(IMapper::BufferDescriptorInfo, width) &&
+ offsetof(OldBufferDescriptorInfo, height) ==
+ offsetof(IMapper::BufferDescriptorInfo, height) &&
+ offsetof(OldBufferDescriptorInfo, layerCount) ==
+ offsetof(IMapper::BufferDescriptorInfo, layerCount) &&
+ offsetof(OldBufferDescriptorInfo, format) ==
+ offsetof(IMapper::BufferDescriptorInfo, format) &&
+ offsetof(OldBufferDescriptorInfo, usage) ==
+ offsetof(IMapper::BufferDescriptorInfo, usage),
+ "");
class Gralloc : public V2_0::tests::Gralloc {
public:
@@ -72,6 +89,32 @@
});
}
+ BufferDescriptor createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo) {
+ BufferDescriptor descriptor;
+ mMapper->createDescriptor_2_1(
+ descriptorInfo, [&](const auto& tmpError, const auto& tmpDescriptor) {
+ ASSERT_EQ(Error::NONE, tmpError) << "failed to create descriptor";
+ descriptor = tmpDescriptor;
+ });
+
+ return descriptor;
+ }
+
+ const native_handle_t* allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
+ bool import, uint32_t* outStride = nullptr) {
+ BufferDescriptor descriptor = createDescriptor(descriptorInfo);
+ if (::testing::Test::HasFatalFailure()) {
+ return nullptr;
+ }
+
+ auto buffers = V2_0::tests::Gralloc::allocate(descriptor, 1, import, outStride);
+ if (::testing::Test::HasFatalFailure()) {
+ return nullptr;
+ }
+
+ return buffers[0];
+ }
+
private:
void init() {
mMapper = IMapper::castFrom(V2_0::tests::Gralloc::getMapper());
@@ -229,6 +272,24 @@
native_handle_delete(rawBufferHandle);
}
+/**
+ * Test IMapper::createDescriptor with valid descriptor info.
+ */
+TEST_F(GraphicsMapperHidlTest, CreateDescriptor_2_1Basic) {
+ ASSERT_NO_FATAL_FAILURE(mGralloc->createDescriptor(mDummyDescriptorInfo));
+}
+
+/**
+ * Test IMapper::createDescriptor with invalid descriptor info.
+ */
+TEST_F(GraphicsMapperHidlTest, CreateDescriptor_2_1Negative) {
+ auto info = mDummyDescriptorInfo;
+ info.width = 0;
+ mGralloc->getMapper()->createDescriptor_2_1(info, [&](const auto& tmpError, const auto&) {
+ EXPECT_EQ(Error::BAD_VALUE, tmpError) << "createDescriptor did not fail with BAD_VALUE";
+ });
+}
+
} // namespace
} // namespace tests
} // namespace V2_1
@@ -238,7 +299,10 @@
} // namespace android
int main(int argc, char** argv) {
+ using android::hardware::graphics::mapper::V2_0::tests::GraphicsMapperHidlEnvironment;
+ ::testing::AddGlobalTestEnvironment(GraphicsMapperHidlEnvironment::Instance());
::testing::InitGoogleTest(&argc, argv);
+ GraphicsMapperHidlEnvironment::Instance()->init(&argc, argv);
int status = RUN_ALL_TESTS();
LOG(INFO) << "Test result = " << status;
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_voice.cpp b/radio/1.0/vts/functional/radio_hidl_hal_voice.cpp
index b3d5648..d0320b9 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_voice.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_voice.cpp
@@ -489,4 +489,4 @@
RadioError::MODEM_ERR, RadioError::OPERATION_NOT_ALLOWED},
CHECK_GENERAL_ERROR));
}
-}
\ No newline at end of file
+}
diff --git a/wifi/1.2/Android.bp b/wifi/1.2/Android.bp
index 100b36b..f41324e 100644
--- a/wifi/1.2/Android.bp
+++ b/wifi/1.2/Android.bp
@@ -10,6 +10,7 @@
"types.hal",
"IWifi.hal",
"IWifiChip.hal",
+ "IWifiChipEventCallback.hal",
"IWifiNanIface.hal",
"IWifiNanIfaceEventCallback.hal",
],
diff --git a/wifi/1.2/IWifiChip.hal b/wifi/1.2/IWifiChip.hal
index 72cbf81..d336a33 100644
--- a/wifi/1.2/IWifiChip.hal
+++ b/wifi/1.2/IWifiChip.hal
@@ -16,7 +16,9 @@
package android.hardware.wifi@1.2;
+import @1.0::WifiStatus;
import @1.1::IWifiChip;
+import IWifiChipEventCallback;
/**
* Interface that represents a chip that must be configured as a single unit.
@@ -24,4 +26,18 @@
* to perform operations like NAN, RTT, etc.
*/
interface IWifiChip extends @1.1::IWifiChip {
+ /**
+ * Requests notifications of significant events on this chip. Multiple calls
+ * to this must register multiple callbacks each of which must receive all
+ * events.
+ *
+ * @param callback An instance of the |IWifiChipEventCallback| HIDL interface
+ * object.
+ * @return status WifiStatus of the operation.
+ * Possible status codes:
+ * |WifiStatusCode.SUCCESS|,
+ * |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|
+ */
+ registerEventCallback_1_2(IWifiChipEventCallback callback)
+ generates (WifiStatus status);
};
diff --git a/wifi/1.2/IWifiChipEventCallback.hal b/wifi/1.2/IWifiChipEventCallback.hal
new file mode 100644
index 0000000..5d2e7e9
--- /dev/null
+++ b/wifi/1.2/IWifiChipEventCallback.hal
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi@1.2;
+
+import @1.0::IWifiChipEventCallback;
+import @1.0::WifiBand;
+
+/**
+ * Wifi chip event callbacks.
+ */
+interface IWifiChipEventCallback extends @1.0::IWifiChipEventCallback {
+ /**
+ * Struct describing the state of each iface operating on the radio chain
+ * (hardware MAC) on the device.
+ */
+ struct IfaceInfo {
+ /** Name of the interface (For ex: "wlan0"). */
+ string name;
+ /** Wifi channel on which this interface is operating. */
+ uint32_t channel;
+ };
+
+ /**
+ * Struct describing the state of each hardware radio chain (hardware MAC)
+ * on the device.
+ */
+ struct RadioModeInfo {
+ /**
+ * Identifier for this radio chain. This is vendor dependent & used
+ * only for debugging purposes.
+ */
+ uint32_t radioId;
+ /**
+ * List of bands on which this radio chain is operating.
+ * Can be one of:
+ * a) WifiBand.BAND_24GHZ => 2.4Ghz.
+ * b) WifiBand.BAND_5GHZ => 5Ghz.
+ * c) WifiBand.BAND_24GHZ_5GHZ = 2.4Ghz + 5Ghz (Radio is time sharing
+ * across the 2 bands).
+ */
+ WifiBand bandInfo;
+ /** List of interfaces on this radio chain (hardware MAC). */
+ vec<IfaceInfo> ifaceInfos;
+ };
+
+ /**
+ * Asynchronous callback indicating a radio mode change.
+ * Radio mode change could be a result of:
+ * a) Bringing up concurrent interfaces (For ex: STA + AP).
+ * b) Change in operating band of one of the concurrent interfaces (For ex:
+ * STA connection moved from 2.4G to 5G)
+ *
+ * @param radioModeInfos List of RadioModeInfo structures for each
+ * radio chain (hardware MAC) on the device.
+ */
+ oneway onRadioModeChange(vec<RadioModeInfo> radioModeInfos);
+};
diff --git a/wifi/1.2/default/Android.mk b/wifi/1.2/default/Android.mk
index 8d0262b..978cf63 100644
--- a/wifi/1.2/default/Android.mk
+++ b/wifi/1.2/default/Android.mk
@@ -94,6 +94,7 @@
LOCAL_MODULE := android.hardware.wifi@1.0-service-tests
LOCAL_PROPRIETARY_MODULE := true
LOCAL_SRC_FILES := \
+ tests/hidl_struct_util_unit_tests.cpp \
tests/main.cpp \
tests/mock_wifi_feature_flags.cpp \
tests/mock_wifi_legacy_hal.cpp \
diff --git a/wifi/1.2/default/hidl_struct_util.cpp b/wifi/1.2/default/hidl_struct_util.cpp
index f87828c..b1c609e 100644
--- a/wifi/1.2/default/hidl_struct_util.cpp
+++ b/wifi/1.2/default/hidl_struct_util.cpp
@@ -266,6 +266,57 @@
CHECK(false);
}
+bool convertLegacyWifiMacInfoToHidl(
+ const legacy_hal::WifiMacInfo& legacy_mac_info,
+ IWifiChipEventCallback::RadioModeInfo* hidl_radio_mode_info) {
+ if (!hidl_radio_mode_info) {
+ return false;
+ }
+ *hidl_radio_mode_info = {};
+
+ hidl_radio_mode_info->radioId = legacy_mac_info.wlan_mac_id;
+ // Convert from bitmask of bands in the legacy HAL to enum value in
+ // the HIDL interface.
+ if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_2_4_BAND &&
+ legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_5_0_BAND) {
+ hidl_radio_mode_info->bandInfo = WifiBand::BAND_24GHZ_5GHZ;
+ } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_2_4_BAND) {
+ hidl_radio_mode_info->bandInfo = WifiBand::BAND_24GHZ;
+ } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_5_0_BAND) {
+ hidl_radio_mode_info->bandInfo = WifiBand::BAND_5GHZ;
+ } else {
+ hidl_radio_mode_info->bandInfo = WifiBand::BAND_UNSPECIFIED;
+ }
+ std::vector<IWifiChipEventCallback::IfaceInfo> iface_info_vec;
+ for (const auto& legacy_iface_info : legacy_mac_info.iface_infos) {
+ IWifiChipEventCallback::IfaceInfo iface_info;
+ iface_info.name = legacy_iface_info.name;
+ iface_info.channel = legacy_iface_info.channel;
+ iface_info_vec.push_back(iface_info);
+ }
+ hidl_radio_mode_info->ifaceInfos = iface_info_vec;
+ return true;
+}
+
+bool convertLegacyWifiMacInfosToHidl(
+ const std::vector<legacy_hal::WifiMacInfo>& legacy_mac_infos,
+ std::vector<IWifiChipEventCallback::RadioModeInfo>* hidl_radio_mode_infos) {
+ if (!hidl_radio_mode_infos) {
+ return false;
+ }
+ *hidl_radio_mode_infos = {};
+
+ for (const auto& legacy_mac_info : legacy_mac_infos) {
+ IWifiChipEventCallback::RadioModeInfo hidl_radio_mode_info;
+ if (!convertLegacyWifiMacInfoToHidl(legacy_mac_info,
+ &hidl_radio_mode_info)) {
+ return false;
+ }
+ hidl_radio_mode_infos->push_back(hidl_radio_mode_info);
+ }
+ return true;
+}
+
bool convertLegacyFeaturesToHidlStaCapabilities(
uint32_t legacy_feature_set, uint32_t legacy_logger_feature_set,
uint32_t* hidl_caps) {
diff --git a/wifi/1.2/default/hidl_struct_util.h b/wifi/1.2/default/hidl_struct_util.h
index 1208afd..ce4bb81 100644
--- a/wifi/1.2/default/hidl_struct_util.h
+++ b/wifi/1.2/default/hidl_struct_util.h
@@ -22,6 +22,7 @@
#include <android/hardware/wifi/1.0/IWifiChip.h>
#include <android/hardware/wifi/1.0/types.h>
#include <android/hardware/wifi/1.1/IWifiChip.h>
+#include <android/hardware/wifi/1.2/IWifiChipEventCallback.h>
#include <android/hardware/wifi/1.2/types.h>
#include "wifi_legacy_hal.h"
@@ -55,6 +56,9 @@
WifiDebugHostWakeReasonStats* hidl_stats);
legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy(
V1_1::IWifiChip::TxPowerScenario hidl_scenario);
+bool convertLegacyWifiMacInfosToHidl(
+ const std::vector<legacy_hal::WifiMacInfo>& legacy_mac_infos,
+ std::vector<IWifiChipEventCallback::RadioModeInfo>* hidl_radio_mode_infos);
// STA iface conversion methods.
bool convertLegacyFeaturesToHidlStaCapabilities(
diff --git a/wifi/1.2/default/tests/hidl_struct_util_unit_tests.cpp b/wifi/1.2/default/tests/hidl_struct_util_unit_tests.cpp
new file mode 100644
index 0000000..1d6e9e4
--- /dev/null
+++ b/wifi/1.2/default/tests/hidl_struct_util_unit_tests.cpp
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <android-base/macros.h>
+#include <gmock/gmock.h>
+
+#undef NAN
+#include "hidl_struct_util.h"
+
+using testing::Test;
+
+namespace {
+constexpr uint32_t kMacId1 = 1;
+constexpr uint32_t kMacId2 = 2;
+constexpr uint32_t kIfaceChannel1 = 3;
+constexpr uint32_t kIfaceChannel2 = 5;
+constexpr char kIfaceName1[] = "wlan0";
+constexpr char kIfaceName2[] = "wlan1";
+} // namespace
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_2 {
+namespace implementation {
+using namespace android::hardware::wifi::V1_0;
+
+class HidlStructUtilTest : public Test {};
+
+TEST_F(HidlStructUtilTest, CanConvertLegacyWifiMacInfosToHidlWithOneMac) {
+ std::vector<legacy_hal::WifiMacInfo> legacy_mac_infos;
+ legacy_hal::WifiMacInfo legacy_mac_info1 = {
+ .wlan_mac_id = kMacId1,
+ .mac_band =
+ legacy_hal::WLAN_MAC_5_0_BAND | legacy_hal::WLAN_MAC_2_4_BAND};
+ legacy_hal::WifiIfaceInfo legacy_iface_info1 = {.name = kIfaceName1,
+ .channel = kIfaceChannel1};
+ legacy_hal::WifiIfaceInfo legacy_iface_info2 = {.name = kIfaceName2,
+ .channel = kIfaceChannel2};
+ legacy_mac_info1.iface_infos.push_back(legacy_iface_info1);
+ legacy_mac_info1.iface_infos.push_back(legacy_iface_info2);
+ legacy_mac_infos.push_back(legacy_mac_info1);
+
+ std::vector<IWifiChipEventCallback::RadioModeInfo> hidl_radio_mode_infos;
+ ASSERT_TRUE(hidl_struct_util::convertLegacyWifiMacInfosToHidl(
+ legacy_mac_infos, &hidl_radio_mode_infos));
+
+ ASSERT_EQ(1u, hidl_radio_mode_infos.size());
+ auto hidl_radio_mode_info1 = hidl_radio_mode_infos[0];
+ EXPECT_EQ(legacy_mac_info1.wlan_mac_id, hidl_radio_mode_info1.radioId);
+ EXPECT_EQ(WifiBand::BAND_24GHZ_5GHZ, hidl_radio_mode_info1.bandInfo);
+ ASSERT_EQ(2u, hidl_radio_mode_info1.ifaceInfos.size());
+ auto hidl_iface_info1 = hidl_radio_mode_info1.ifaceInfos[0];
+ EXPECT_EQ(legacy_iface_info1.name, hidl_iface_info1.name);
+ EXPECT_EQ(static_cast<uint32_t>(legacy_iface_info1.channel),
+ hidl_iface_info1.channel);
+ auto hidl_iface_info2 = hidl_radio_mode_info1.ifaceInfos[1];
+ EXPECT_EQ(legacy_iface_info2.name, hidl_iface_info2.name);
+ EXPECT_EQ(static_cast<uint32_t>(legacy_iface_info2.channel),
+ hidl_iface_info2.channel);
+}
+
+TEST_F(HidlStructUtilTest, CanConvertLegacyWifiMacInfosToHidlWithTwoMac) {
+ std::vector<legacy_hal::WifiMacInfo> legacy_mac_infos;
+ legacy_hal::WifiMacInfo legacy_mac_info1 = {
+ .wlan_mac_id = kMacId1, .mac_band = legacy_hal::WLAN_MAC_5_0_BAND};
+ legacy_hal::WifiIfaceInfo legacy_iface_info1 = {.name = kIfaceName1,
+ .channel = kIfaceChannel1};
+ legacy_hal::WifiMacInfo legacy_mac_info2 = {
+ .wlan_mac_id = kMacId2, .mac_band = legacy_hal::WLAN_MAC_2_4_BAND};
+ legacy_hal::WifiIfaceInfo legacy_iface_info2 = {.name = kIfaceName2,
+ .channel = kIfaceChannel2};
+ legacy_mac_info1.iface_infos.push_back(legacy_iface_info1);
+ legacy_mac_infos.push_back(legacy_mac_info1);
+ legacy_mac_info2.iface_infos.push_back(legacy_iface_info2);
+ legacy_mac_infos.push_back(legacy_mac_info2);
+
+ std::vector<IWifiChipEventCallback::RadioModeInfo> hidl_radio_mode_infos;
+ ASSERT_TRUE(hidl_struct_util::convertLegacyWifiMacInfosToHidl(
+ legacy_mac_infos, &hidl_radio_mode_infos));
+
+ ASSERT_EQ(2u, hidl_radio_mode_infos.size());
+
+ // Find mac info 1.
+ const auto hidl_radio_mode_info1 = std::find_if(
+ hidl_radio_mode_infos.begin(), hidl_radio_mode_infos.end(),
+ [&legacy_mac_info1](const IWifiChipEventCallback::RadioModeInfo& x) {
+ return x.radioId == legacy_mac_info1.wlan_mac_id;
+ });
+ ASSERT_NE(hidl_radio_mode_infos.end(), hidl_radio_mode_info1);
+ EXPECT_EQ(WifiBand::BAND_5GHZ, hidl_radio_mode_info1->bandInfo);
+ ASSERT_EQ(1u, hidl_radio_mode_info1->ifaceInfos.size());
+ auto hidl_iface_info1 = hidl_radio_mode_info1->ifaceInfos[0];
+ EXPECT_EQ(legacy_iface_info1.name, hidl_iface_info1.name);
+ EXPECT_EQ(static_cast<uint32_t>(legacy_iface_info1.channel),
+ hidl_iface_info1.channel);
+
+ // Find mac info 2.
+ const auto hidl_radio_mode_info2 = std::find_if(
+ hidl_radio_mode_infos.begin(), hidl_radio_mode_infos.end(),
+ [&legacy_mac_info2](const IWifiChipEventCallback::RadioModeInfo& x) {
+ return x.radioId == legacy_mac_info2.wlan_mac_id;
+ });
+ ASSERT_NE(hidl_radio_mode_infos.end(), hidl_radio_mode_info2);
+ EXPECT_EQ(WifiBand::BAND_24GHZ, hidl_radio_mode_info2->bandInfo);
+ ASSERT_EQ(1u, hidl_radio_mode_info2->ifaceInfos.size());
+ auto hidl_iface_info2 = hidl_radio_mode_info2->ifaceInfos[0];
+ EXPECT_EQ(legacy_iface_info2.name, hidl_iface_info2.name);
+ EXPECT_EQ(static_cast<uint32_t>(legacy_iface_info2.channel),
+ hidl_iface_info2.channel);
+}
+} // namespace implementation
+} // namespace V1_2
+} // namespace wifi
+} // namespace hardware
+} // namespace android
diff --git a/wifi/1.2/default/wifi.cpp b/wifi/1.2/default/wifi.cpp
index d6106b4..79f921f 100644
--- a/wifi/1.2/default/wifi.cpp
+++ b/wifi/1.2/default/wifi.cpp
@@ -80,6 +80,9 @@
Return<void> Wifi::debug(const hidl_handle& handle,
const hidl_vec<hidl_string>&) {
LOG(INFO) << "-----------Debug is called----------------";
+ if (!chip_.get()) {
+ return Void();
+ }
return chip_->debug(handle, {});
}
diff --git a/wifi/1.2/default/wifi_chip.cpp b/wifi/1.2/default/wifi_chip.cpp
index bc3404a..38301e9 100644
--- a/wifi/1.2/default/wifi_chip.cpp
+++ b/wifi/1.2/default/wifi_chip.cpp
@@ -306,7 +306,7 @@
}
Return<void> WifiChip::registerEventCallback(
- const sp<IWifiChipEventCallback>& event_callback,
+ const sp<V1_0::IWifiChipEventCallback>& event_callback,
registerEventCallback_cb hidl_status_cb) {
return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
&WifiChip::registerEventCallbackInternal,
@@ -520,6 +520,14 @@
hidl_status_cb);
}
+Return<void> WifiChip::registerEventCallback_1_2(
+ const sp<IWifiChipEventCallback>& event_callback,
+ registerEventCallback_cb hidl_status_cb) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::registerEventCallbackInternal_1_2,
+ hidl_status_cb, event_callback);
+}
+
Return<void> WifiChip::debug(const hidl_handle& handle,
const hidl_vec<hidl_string>&) {
if (handle != nullptr && handle->numFds >= 1) {
@@ -556,11 +564,9 @@
}
WifiStatus WifiChip::registerEventCallbackInternal(
- const sp<IWifiChipEventCallback>& event_callback) {
- if (!event_cb_handler_.addCallback(event_callback)) {
- return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
- }
- return createWifiStatus(WifiStatusCode::SUCCESS);
+ const sp<V1_0::IWifiChipEventCallback>& /* event_callback */) {
+ // Deprecated support for this callback.
+ return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
}
std::pair<WifiStatus, uint32_t> WifiChip::getCapabilitiesInternal() {
@@ -997,6 +1003,14 @@
return createWifiStatusFromLegacyError(legacy_status);
}
+WifiStatus WifiChip::registerEventCallbackInternal_1_2(
+ const sp<IWifiChipEventCallback>& event_callback) {
+ if (!event_cb_handler_.addCallback(event_callback)) {
+ return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+ }
+ return createWifiStatus(WifiStatusCode::SUCCESS);
+}
+
WifiStatus WifiChip::handleChipConfiguration(
/* NONNULL */ std::unique_lock<std::recursive_mutex>* lock,
ChipModeId mode_id) {
@@ -1030,6 +1044,13 @@
<< legacyErrorToString(legacy_status);
return createWifiStatusFromLegacyError(legacy_status);
}
+ // Every time the HAL is restarted, we need to register the
+ // radio mode change callback.
+ WifiStatus status = registerRadioModeChangeCallback();
+ if (status.code != WifiStatusCode::SUCCESS) {
+ // This probably is not a critical failure?
+ LOG(ERROR) << "Failed to register radio mode change callback";
+ }
return createWifiStatus(WifiStatusCode::SUCCESS);
}
@@ -1073,6 +1094,36 @@
return createWifiStatusFromLegacyError(legacy_status);
}
+WifiStatus WifiChip::registerRadioModeChangeCallback() {
+ android::wp<WifiChip> weak_ptr_this(this);
+ const auto& on_radio_mode_change_callback =
+ [weak_ptr_this](const std::vector<legacy_hal::WifiMacInfo>& mac_infos) {
+ const auto shared_ptr_this = weak_ptr_this.promote();
+ if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+ LOG(ERROR) << "Callback invoked on an invalid object";
+ return;
+ }
+ std::vector<IWifiChipEventCallback::RadioModeInfo>
+ hidl_radio_mode_infos;
+ if (!hidl_struct_util::convertLegacyWifiMacInfosToHidl(
+ mac_infos, &hidl_radio_mode_infos)) {
+ LOG(ERROR) << "Error converting wifi mac info";
+ return;
+ }
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->onRadioModeChange(hidl_radio_mode_infos)
+ .isOk()) {
+ LOG(ERROR) << "Failed to invoke onRadioModeChange"
+ << " callback on: " << toString(callback);
+ }
+ }
+ };
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->registerRadioModeChangeCallbackHandler(
+ getWlan0IfaceName(), on_radio_mode_change_callback);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
void WifiChip::populateModes() {
// The chip combination supported for current devices is fixed.
// They can be one of the following based on device features:
diff --git a/wifi/1.2/default/wifi_chip.h b/wifi/1.2/default/wifi_chip.h
index 4ffa8da..24a5486 100644
--- a/wifi/1.2/default/wifi_chip.h
+++ b/wifi/1.2/default/wifi_chip.h
@@ -74,7 +74,7 @@
// HIDL methods exposed.
Return<void> getId(getId_cb hidl_status_cb) override;
Return<void> registerEventCallback(
- const sp<IWifiChipEventCallback>& event_callback,
+ const sp<V1_0::IWifiChipEventCallback>& event_callback,
registerEventCallback_cb hidl_status_cb) override;
Return<void> getCapabilities(getCapabilities_cb hidl_status_cb) override;
Return<void> getAvailableModes(
@@ -138,6 +138,9 @@
resetTxPowerScenario_cb hidl_status_cb) override;
Return<void> debug(const hidl_handle& handle,
const hidl_vec<hidl_string>& options) override;
+ Return<void> registerEventCallback_1_2(
+ const sp<IWifiChipEventCallback>& event_callback,
+ registerEventCallback_1_2_cb hidl_status_cb) override;
private:
void invalidateAndRemoveAllIfaces();
@@ -145,7 +148,7 @@
// Corresponding worker functions for the HIDL methods.
std::pair<WifiStatus, ChipId> getIdInternal();
WifiStatus registerEventCallbackInternal(
- const sp<IWifiChipEventCallback>& event_callback);
+ const sp<V1_0::IWifiChipEventCallback>& event_callback);
std::pair<WifiStatus, uint32_t> getCapabilitiesInternal();
std::pair<WifiStatus, std::vector<ChipMode>> getAvailableModesInternal();
WifiStatus configureChipInternal(
@@ -192,10 +195,13 @@
WifiStatus enableDebugErrorAlertsInternal(bool enable);
WifiStatus selectTxPowerScenarioInternal(TxPowerScenario scenario);
WifiStatus resetTxPowerScenarioInternal();
+ WifiStatus registerEventCallbackInternal_1_2(
+ const sp<IWifiChipEventCallback>& event_callback);
WifiStatus handleChipConfiguration(
std::unique_lock<std::recursive_mutex>* lock, ChipModeId mode_id);
WifiStatus registerDebugRingBufferCallback();
+ WifiStatus registerRadioModeChangeCallback();
void populateModes();
std::vector<IWifiChip::ChipIfaceCombination>
diff --git a/wifi/1.2/default/wifi_legacy_hal.cpp b/wifi/1.2/default/wifi_legacy_hal.cpp
index 9abe514..5f40d50 100644
--- a/wifi/1.2/default/wifi_legacy_hal.cpp
+++ b/wifi/1.2/default/wifi_legacy_hal.cpp
@@ -148,6 +148,17 @@
}
}
+// Callback to be invoked for radio mode change indication.
+std::function<void(wifi_request_id, uint32_t, wifi_mac_info*)>
+ on_radio_mode_change_internal_callback;
+void onAsyncRadioModeChange(wifi_request_id id, uint32_t num_macs,
+ wifi_mac_info* mac_infos) {
+ const auto lock = hidl_sync_util::acquireGlobalLock();
+ if (on_radio_mode_change_internal_callback) {
+ on_radio_mode_change_internal_callback(id, num_macs, mac_infos);
+ }
+}
+
// Callback to be invoked for rtt results results.
std::function<void(wifi_request_id, unsigned num_results,
wifi_rtt_result* rtt_results[])>
@@ -937,6 +948,41 @@
0, getIfaceHandle(iface_name));
}
+wifi_error WifiLegacyHal::registerRadioModeChangeCallbackHandler(
+ const std::string& iface_name,
+ const on_radio_mode_change_callback& on_user_change_callback) {
+ if (on_radio_mode_change_internal_callback) {
+ return WIFI_ERROR_NOT_AVAILABLE;
+ }
+ on_radio_mode_change_internal_callback = [on_user_change_callback](
+ wifi_request_id /* id */,
+ uint32_t num_macs,
+ wifi_mac_info* mac_infos_arr) {
+ if (num_macs > 0 && mac_infos_arr) {
+ std::vector<WifiMacInfo> mac_infos_vec;
+ for (uint32_t i = 0; i < num_macs; i++) {
+ WifiMacInfo mac_info;
+ mac_info.wlan_mac_id = mac_infos_arr[i].wlan_mac_id;
+ mac_info.mac_band = mac_infos_arr[i].mac_band;
+ for (int32_t j = 0; j < mac_infos_arr[i].num_iface; j++) {
+ WifiIfaceInfo iface_info;
+ iface_info.name = mac_infos_arr[i].iface_info[j].iface_name;
+ iface_info.channel = mac_infos_arr[i].iface_info[j].channel;
+ mac_info.iface_infos.push_back(iface_info);
+ }
+ mac_infos_vec.push_back(mac_info);
+ }
+ on_user_change_callback(mac_infos_vec);
+ }
+ };
+ wifi_error status = global_func_table_.wifi_set_radio_mode_change_handler(
+ 0, getIfaceHandle(iface_name), {onAsyncRadioModeChange});
+ if (status != WIFI_SUCCESS) {
+ on_radio_mode_change_internal_callback = nullptr;
+ }
+ return status;
+}
+
wifi_error WifiLegacyHal::startRttRangeRequest(
const std::string& iface_name, wifi_request_id id,
const std::vector<wifi_rtt_config>& rtt_configs,
@@ -1324,6 +1370,7 @@
on_rssi_threshold_breached_internal_callback = nullptr;
on_ring_buffer_data_internal_callback = nullptr;
on_error_alert_internal_callback = nullptr;
+ on_radio_mode_change_internal_callback = nullptr;
on_rtt_results_internal_callback = nullptr;
on_nan_notify_response_user_callback = nullptr;
on_nan_event_publish_terminated_user_callback = nullptr;
diff --git a/wifi/1.2/default/wifi_legacy_hal.h b/wifi/1.2/default/wifi_legacy_hal.h
index da88f6b..bd68bcd 100644
--- a/wifi/1.2/default/wifi_legacy_hal.h
+++ b/wifi/1.2/default/wifi_legacy_hal.h
@@ -132,6 +132,26 @@
// Callback for alerts.
using on_error_alert_callback =
std::function<void(int32_t, const std::vector<uint8_t>&)>;
+
+// Struct for the mac info from the legacy HAL. This is a cleaner version
+// of the |wifi_mac_info| & |wifi_iface_info|.
+typedef struct {
+ std::string name;
+ wifi_channel channel;
+} WifiIfaceInfo;
+
+typedef struct {
+ uint32_t wlan_mac_id;
+ /* BIT MASK of BIT(WLAN_MAC*) as represented by wlan_mac_band */
+ uint32_t mac_band;
+ /* Represents the connected Wi-Fi interfaces associated with each MAC */
+ std::vector<WifiIfaceInfo> iface_infos;
+} WifiMacInfo;
+
+// Callback for radio mode change
+using on_radio_mode_change_callback =
+ std::function<void(const std::vector<WifiMacInfo>&)>;
+
/**
* Class that encapsulates all legacy HAL interactions.
* This class manages the lifetime of the event loop thread used by legacy HAL.
@@ -253,6 +273,10 @@
const on_error_alert_callback& on_alert_callback);
wifi_error deregisterErrorAlertCallbackHandler(
const std::string& iface_name);
+ // Radio mode functions.
+ wifi_error registerRadioModeChangeCallbackHandler(
+ const std::string& iface_name,
+ const on_radio_mode_change_callback& on_user_change_callback);
// RTT functions.
wifi_error startRttRangeRequest(
const std::string& iface_name, wifi_request_id id,
diff --git a/wifi/1.2/default/wifi_legacy_hal_stubs.cpp b/wifi/1.2/default/wifi_legacy_hal_stubs.cpp
index 28972cb..2ee2aa2 100644
--- a/wifi/1.2/default/wifi_legacy_hal_stubs.cpp
+++ b/wifi/1.2/default/wifi_legacy_hal_stubs.cpp
@@ -134,6 +134,7 @@
populateStubFor(&hal_fn->wifi_configure_roaming);
populateStubFor(&hal_fn->wifi_select_tx_power_scenario);
populateStubFor(&hal_fn->wifi_reset_tx_power_scenario);
+ populateStubFor(&hal_fn->wifi_set_radio_mode_change_handler);
return true;
}
} // namespace legacy_hal