Рекламный сигнал поставщика
Реклама: когда её можно обнаружить
Когда устройство провайдера обнаруживается через BR/EDR (то есть находится в режиме сопряжения), оно должно передавать данные идентификатора модели быстрого сопряжения по BLE, при этом адрес BLE не должен меняться.
Интервал показа рекламы: Когда это становится возможным
Интервал между рекламными объявлениями не должен превышать 100 мс (10 Гц). Высокая частота позволяет устройству Seeker быстро находить провайдера, даже при сканировании в режиме низкого энергопотребления.
Рекламная нагрузка: данные идентификатора модели Fast Pair
В объявлении должен содержаться тип данных «Сервисные данные», см. там же, § 1.11. UUID должен соответствовать UUID службы быстрого сопряжения 0xFE2C . Сервисные данные должны содержать следующее:
| Октет | Тип данных | Описание | Ценить |
|---|---|---|---|
| 0-2 | uint24 | 24-битный идентификатор модели | варьируется |
Полезная нагрузка LE Audio Sharing Advertising: данные идентификатора модели Fast Pair и карта возможностей FP.
Данные об услуге должны содержать следующее:
| Октет | Тип данных | Описание | Ценить |
|---|---|---|---|
| 0 | uint8 | Версия и флаги 0bVVVVFFFF
| 0x00 |
| 1 | uint8 | Длина и тип поля 0bLLLLTTTT
| 0bLLLL0111
|
| 2 - с | Идентификатор модели | варьируется | |
| с + 1 | uint8 | Длина и тип поля 0bLLLLTTTT
| 0bLLLL1000
|
| с + 2 | uint8 | Карта возможностей FP | варьируется |
Карта возможностей FP
Карта возможностей функциональных возможностей (FP Capability Map) представляет собой битовую карту, отображающую, какие функциональные возможности поддерживаются поставщиком. Первый байт битовой карты определяется следующим образом:
| Растровое изображение | Описание |
|---|---|
| 0bRRRRRRSO | R — Зарезервированный бит, пока игнорируется устройством поиска и устанавливается в значение 0. S - Поддержка совместного использования аудио FP LE (установите значение 1, если включено, иначе 0). O - Бит "Из коробки" (OOB), устанавливается в 1, если устройство новое с завода. |
Если провайдер поддерживает спецификацию FP LE Audio Sharing (то есть поддерживает временное сопряжение , рекламную нагрузку LE Audio Sharing и управление Hearable версии 2 ), установите бит поддержки FP LE Audio Sharing в 1; в противном случае установите его в 0.
Если провайдер не сопряжен ни с одним FP Seeker и является новым (то есть у провайдера отсутствуют ключи учетных записей FP), установите бит OOB в 1; в противном случае установите его в 0.
Реклама: когда её невозможно обнаружить
Если устройство не обнаруживается (то есть, не находится в режиме сопряжения), оно должно передавать данные учетной записи быстрого сопряжения, используя следующие рекомендации.
Передача данных учетной записи позволяет находящимся поблизости пользователям Seekers распознавать, когда провайдер принадлежит их учетной записи, и инициировать сопряжение без необходимости принудительного перевода провайдера в режим сопряжения, что является распространенной причиной жалоб пользователей. Seekers предоставит пользователям возможность игнорировать это широковещательное сообщение, если они не ждут сопряжения с провайдером или сообщение неактуально (например, если сопряжение уже выполнено). Seekers также будет автоматически отфильтровывать явно некорректные широковещательные сообщения, например, если данные учетной записи настроены неправильно.
Интервал рекламной паузы: Когда невозможно обнаружить
Интервал между рекламными объявлениями должен составлять не более 250 мс (4 Гц).
Рекламный контент: данные учетной записи Fast Pair
В объявлении должен содержаться тип данных «Сервисные данные», см. там же, § 1.11. UUID должен соответствовать UUID службы быстрого сопряжения 0xFE2C . Сервисные данные должны содержать следующее:
| Октет | Тип данных | Описание | Ценить |
|---|---|---|---|
| 0 | uint8 | Версия и флаги 0bVVVVFFFF
| 0x00(зарезервировано для использования в будущем) |
| 1 - варьируется | Данные ключа учетной записи | варьируется |
Данные ключа учетной записи содержат:
| Октет | Тип данных | Описание | Ценить |
|---|---|---|---|
| 0 | uint8 | Длина и тип поля 0bLLLLTTTT
| 0bLLLL0000
|
| 1 - с | Фильтр по ключу учетной записи | варьируется | |
| с + 1 | uint8 | Длина и тип поля 0bLLLLTTTT
| 0b00100001
|
| s + 2 - s + 3 | uint16 | Соль | варьируется |
Фильтр по ключу учетной записи
Рекламируемый фильтр ключей учетных записей позволяет пользователю Seeker быстро проверить, может ли поставщик услуг обладать определенным ключом учетной записи (с низкой вероятностью ложноположительных результатов, в среднем значительно менее 0,5%), прежде чем взаимодействовать с ним. Пользователь Seeker может автоматически подключиться и попытаться начать процедуру, когда увидит передаваемый фильтр типа 0, то есть отображающий в пользовательском интерфейсе индикацию, которая потенциально содержит один из его ключей учетных записей, чтобы еще больше снизить частоту ложноположительных результатов. В некоторых ситуациях поставщик услуг может захотеть, чтобы его распознавал пользователь Seeker, даже если он еще не готов к сопряжению. Например, когда наушники помещаются обратно в чехол, мы хотим прекратить показ последующего уведомления о сопряжении, поскольку это сопряжение может быть отклонено гарнитурой.
Фильтр «Ключ учетной записи» представляет собой фильтр Блума переменной длины, построенный следующим образом:
- Пусть n — количество ключей учетных записей ( n >= 1) в сохраненном списке ключей учетных записей .
- Пусть s — размер фильтра в байтах, усеченный до (1,2 * n + 3). Например, если сохраняется 1 ключ, то s = 4 байта.
uint8_t s = (((uint8_t)(( float )1.2 * n)) + 3); - Инициализируйте фильтр F как массив из s байтов, каждый из которых должен быть равен 0.
uint8_t F[s] = {0}; Для каждого ключа учетной записи K в сохраненном списке ключей учетных записей :
а. Пусть V — это concat( K , Salt ).// In the sample code, the size of salt is 2 bytes. #define SALT_SIZE 2 uint8_t V[FASTPAIR_ACCOUNT_KEY_SIZE + SALT_SIZE]; for (uint8_t keyIndex = 0; keyIndex < n; keyIndex++) { // concat (K, Salt) fastpair_get_account_key_by_index(keyIndex, V); uint8_t randomSalt = (uint8_t)rand(); V[FASTPAIR_ACCOUNT_KEY_SIZE] = randomSalt; ... }b. Хэш V с использованием SHA256, в результате чего получается 32-байтовое значение H = {H 0 , …, H 31 }.
uint8_t H[32] = {0}; SHA256_hash_function(V, H);c. Разделите H на восемь 4-байтовых беззнаковых целых чисел в формате big-endian, X = {X 0 , …, X 7 }, где X 0 = 0xH 0 H 1 H 2 H 3 .
uint32_t X[8]; for (index = 0; index < 8; index++) { X[index] = (((uint32_t)(H[index * 4])) << 24) | (((uint32_t)(H[index * 4 + 1])) << 16) | (((uint32_t)(H[index * 4 + 2])) << 8) | (((uint32_t)(H[index * 4 + 3])) << 0); }г. Для каждого X i :
i. Пусть M — X i по модулю количества бит в фильтре ( s * 8).
ii. Получите байт в регистре F по индексу ( M / 8), округленный в меньшую сторону.
iii. Внутри байта установите бит по индексу ( M % 8) в 1.
iv. Другими словами:// M = Xi % (s * 8) // F[M/8] = F[M/8] | (1 << (M % 8)) for (index = 0; index < 8; index++) { uint32_t M = X[index] % (s * 8); F[M / 8] = F[M / 8] | (1 << (M % 8)); }
Включите фильтр F в поле «Фильтр ключа учетной записи» в рекламных данных. Обратите внимание, что для этого значения нет «порядка байтов», поскольку нет более или менее значимого байта — не изменяйте порядок байтов.
Соляное поле
Соль — это случайное значение, которое добавляется к ключам учетных записей при создании фильтра Блума. Эту соль следует генерировать заново каждый раз при обновлении RPA для провайдера, чтобы избежать отслеживания изменений при ротации адресов.
Для создания фильтра по ключу учетной записи с использованием соли:
- Сгенерируйте случайное 2-байтовое значение S. Обратите внимание, что у этого значения нет "порядка байтов", поскольку нет более или менее значимого байта — не изменяйте порядок байтов.
- Используйте 2-байтовый символ S в качестве соли.
- В заявленных данных учетной записи Fast Pair укажите сгенерированный фильтр в поле «Фильтр ключа учетной записи», а букву S — в поле «Соль».