diff --git a/presence/action_factory.cc b/presence/action_factory.cc index 7ba60e3f..8c0de49a 100644 --- a/presence/action_factory.cc +++ b/presence/action_factory.cc @@ -26,10 +26,37 @@ constexpr int kContentTimestampMask = 0x0F; constexpr int kContentTimestampShift = 12; constexpr int kEmptyMask = 0; +// The values below match the bitmasks in Base NP Intent. +constexpr int kTapToTransferMask = 1 << 11; +constexpr int kActiveUnlockMask = 1 << 7; +constexpr int kNearbyShareMask = 1 << 6; +constexpr int kFastPairMask = 1 << 5; +constexpr int kFitCastMask = 1 << 4; + +namespace { +int GetActionMask(int action) { + switch (action) { + case action::kActiveUnlockAction: + return kActiveUnlockMask; + case action::kTapToTransferAction: + return kTapToTransferMask; + case action::kNearbyShareAction: + return kNearbyShareMask; + case action::kFastPairAction: + return kFastPairMask; + case action::kFitCastAction: + return kFitCastMask; + } + NEARBY_LOG(WARNING, "Unsupported action %d", action); + return kEmptyMask; +} + +} // namespace + int ActionFactory::GetMask(const DataElement& element) { int type = element.GetType(); switch (type) { - case DataElement::kContextTimestamp: { + case DataElement::kContextTimestampFieldType: { auto value = element.GetValue(); if (!value.empty()) { return (value[0] & kContentTimestampMask) << kContentTimestampShift; @@ -38,13 +65,13 @@ int ActionFactory::GetMask(const DataElement& element) { return kEmptyMask; } } - case DataElement::kActiveUnlock: - case DataElement::kTapToTransfer: - case DataElement::kNearbyShare: - case DataElement::kFastPair: - case DataElement::kFitCast: - case DataElement::kPresenceManager: - return type; + case DataElement::kActionFieldType: { + if (element.GetValue().empty()) { + NEARBY_LOG(WARNING, "Action Data Element without value"); + return kEmptyMask; + } + return GetActionMask(element.GetValue()[0]); + } } NEARBY_LOG(WARNING, "Data Element 0x%x not supported in base advertisement", type); diff --git a/presence/action_factory_test.cc b/presence/action_factory_test.cc index 1ea0e831..041e4c35 100644 --- a/presence/action_factory_test.cc +++ b/presence/action_factory_test.cc @@ -30,18 +30,20 @@ namespace { TEST(ActionFactory, CreateActiveUnlockAction) { std::vector data_elements; - data_elements.emplace_back(DataElement::kActiveUnlock, ""); + data_elements.emplace_back(DataElement::kActionFieldType, + action::kActiveUnlockAction); Action action = ActionFactory::createAction(data_elements); - EXPECT_EQ(action.action, 1 << 11); + EXPECT_EQ(action.action, 1 << 7); } TEST(ActionFactory, CreateContextTimestamp) { const std::string kTimestamp = absl::HexStringToBytes("0B"); std::vector data_elements; - data_elements.emplace_back(DataElement::kContextTimestamp, kTimestamp); + data_elements.emplace_back(DataElement::kContextTimestampFieldType, + kTimestamp); Action action = ActionFactory::createAction(data_elements); @@ -52,12 +54,14 @@ TEST(ActionFactory, CreateContextTimestampAndFastPair) { const std::string kTimestamp = absl::HexStringToBytes("0B"); std::vector data_elements; - data_elements.emplace_back(DataElement::kContextTimestamp, kTimestamp); - data_elements.emplace_back(DataElement::kFastPair, ""); + data_elements.emplace_back(DataElement::kContextTimestampFieldType, + kTimestamp); + data_elements.emplace_back(DataElement::kActionFieldType, + action::kFastPairAction); Action action = ActionFactory::createAction(data_elements); - EXPECT_EQ(action.action, (0x0B << 12) | 0x100); + EXPECT_EQ(action.action, (0x0B << 12) | 0x20); } } // namespace diff --git a/presence/advertisement_factory_test.cc b/presence/advertisement_factory_test.cc index 0021f133..7c229d07 100644 --- a/presence/advertisement_factory_test.cc +++ b/presence/advertisement_factory_test.cc @@ -50,7 +50,8 @@ TEST(AdvertisementFactory, CreateAdvertisementFromPrivateIdentity) { NiceMock certificate_manager; PresenceIdentity identity; std::vector data_elements; - data_elements.emplace_back(DataElement::kActiveUnlock, ""); + data_elements.emplace_back(DataElement::kActionFieldType, + action::kActiveUnlockAction); Action action = ActionFactory::createAction(data_elements); BroadcastRequest request = BroadcastRequest(BasePresenceRequestBuilder(identity) @@ -61,7 +62,7 @@ TEST(AdvertisementFactory, CreateAdvertisementFromPrivateIdentity) { .WillOnce(Return(absl::HexStringToBytes("1011121314151617181920212223"))); EXPECT_CALL( certificate_manager, - EncryptDataElements(identity, salt, absl::HexStringToBytes("1505260800"))) + EncryptDataElements(identity, salt, absl::HexStringToBytes("1505260080"))) .WillOnce(Return(absl::HexStringToBytes("5051525354"))); AdvertisementFactory factory(&certificate_manager); @@ -84,7 +85,8 @@ TEST(AdvertisementFactory, NiceMock certificate_manager; PresenceIdentity identity; std::vector data_elements; - data_elements.emplace_back(DataElement::kActiveUnlock, ""); + data_elements.emplace_back(DataElement::kActionFieldType, + action::kActiveUnlockAction); Action action = ActionFactory::createAction(data_elements); BroadcastRequest request = BroadcastRequest(BasePresenceRequestBuilder(identity) diff --git a/presence/data_element.h b/presence/data_element.h index e774e37b..511be724 100644 --- a/presence/data_element.h +++ b/presence/data_element.h @@ -23,24 +23,18 @@ namespace nearby { namespace presence { +// Reserved Action types when the field type is kActionFieldType +namespace action { +constexpr int kTapToTransferAction = 4; +constexpr int kActiveUnlockAction = 8; +constexpr int kNearbyShareAction = 9; +constexpr int kFastPairAction = 10; +constexpr int kFitCastAction = 11; +} // namespace action + /** Describes a custom Data element in NP advertisement. */ class DataElement { public: - DataElement(uint16_t type, absl::string_view value) - : type_(type), value_(value) {} - - uint16_t GetType() const { return type_; } - absl::string_view GetValue() const { return value_; } - - static constexpr int kContextTimestamp = 1 << 12; - // The values below match the bitmasks in Base NP Intent. - static constexpr int kActiveUnlock = 1 << 11; - static constexpr int kTapToTransfer = 1 << 10; - static constexpr int kNearbyShare = 1 << 9; - static constexpr int kFastPair = 1 << 8; - static constexpr int kFitCast = 1 << 7; - static constexpr int kPresenceManager = 1 << 6; - // The field types listed below require special processing when generating and // parsing NP advertisements. static constexpr int kSaltFieldType = 0; @@ -50,6 +44,13 @@ class DataElement { static constexpr int kProvisionedIdentityFieldType = 4; static constexpr int kTxPowerFieldType = 5; static constexpr int kActionFieldType = 6; + static constexpr int kModelIdFieldType = 7; + static constexpr int kEddystoneIdFieldType = 8; + static constexpr int kAccountKeyDataFieldType = 9; + static constexpr int kConnectionStatusFieldType = 10; + static constexpr int kBatteryFieldType = 11; + static constexpr int kAdvertisementSignature = 12; + static constexpr int kContextTimestampFieldType = 13; // Maximum allowed Data Element's value length static constexpr int kMaxDataElementLength = 15; // Maximum allowed Data Element's type @@ -57,6 +58,16 @@ class DataElement { // The DE header is (length << kDataElementLengthShift | type) static constexpr int kDataElementLengthShift = 4; + DataElement(uint16_t type, absl::string_view value) + : type_(type), value_(value) {} + + DataElement(uint16_t type, uint8_t value) + : type_(type), + value_(reinterpret_cast(&value), sizeof(value)) {} + + uint16_t GetType() const { return type_; } + absl::string_view GetValue() const { return value_; } + private: uint16_t type_; std::string value_;