Fix Action Data Elements construction.

Data Elements representing an action should have the type set to
kActionFieldType, and the actual action stored in the value.

PiperOrigin-RevId: 465365230
This commit is contained in:
jsobczak
2022-08-04 11:40:04 -07:00
committed by Copybara-Service
parent 4d6bc3d62f
commit ce6c5893d7
4 changed files with 76 additions and 32 deletions
+35 -8
View File
@@ -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);
+10 -6
View File
@@ -30,18 +30,20 @@ namespace {
TEST(ActionFactory, CreateActiveUnlockAction) {
std::vector<DataElement> 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<DataElement> 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<DataElement> 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
+5 -3
View File
@@ -50,7 +50,8 @@ TEST(AdvertisementFactory, CreateAdvertisementFromPrivateIdentity) {
NiceMock<MockCertificateManager> certificate_manager;
PresenceIdentity identity;
std::vector<DataElement> 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<MockCertificateManager> certificate_manager;
PresenceIdentity identity;
std::vector<DataElement> 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)
+26 -15
View File
@@ -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<const char*>(&value), sizeof(value)) {}
uint16_t GetType() const { return type_; }
absl::string_view GetValue() const { return value_; }
private:
uint16_t type_;
std::string value_;