プロバイダの広告シグナル
広告: 目に留まりやすいタイミング
プロバイダ デバイスが BR/EDR で検出可能(つまりペア設定モード)の場合、BLE を介してファスト ペアリング モデル ID データをアドバタイズしなければならず、BLE アドレスはローテーションされません。
広告間隔: 見つかりやすさ
広告の間隔は 100 ミリ秒(10 Hz)以下とします。高速モードでは、低電力モードでスキャンする場合であっても、シーカーがプロバイダをすばやく見つけることができます。
広告ペイロード: ファスト ペアリング モデル ID データ
広告には、サービスデータのデータ型、前述、§ 1.11. UUID は 0xFE2C
のファスト ペア サービス UUID でなければなりません。サービスデータには以下が含まれます。
オクテット | データ型 | 説明 | 値 |
---|---|---|---|
0~2 | uint24 |
24 ビットのモデル ID | 場合によって異なる |
広告: 広告を見つけられないとき
検出できない(ペア設定モードではない)場合、プロバイダ デバイスは以下のガイドラインを使用してファスト ペアリング アカウント データを宣伝するものとします。
アカウント データをアドバタイズすることで、近くのシーカーは、プロバイダがアカウントに属していることを認識し、最初にプロバイダを強制的にペア設定モードにしなくてもペア設定を開始できます。これはユーザーの不満の一般的な原因です。検索者は、プロバイダとのペアリングを待たなかった場合や、ブロードキャストと関連性がない場合(すでにペア設定している場合など)に、ユーザーがこのブロードキャストを無視する機会を提供します。検索ユーザーは、アカウント データが正しく構成されていない場合など、明らかに不適切なブロードキャストを自動的に除外します。
広告間隔: 見つけられない場合
広告の間隔は 250 ミリ秒(4Hz)以下にしてください。
広告ペイロード: ファスト ペアリング アカウント データ
広告には、サービス データの種類(上記、§ 1.11. UUID は 0xFE2C
のファスト ペア サービス UUID でなければなりません。サービスデータには以下が含まれます。
オクテット | データ型 | 説明 | 値 |
---|---|---|---|
0 | uint8 |
バージョンとフラグ 0bVVVVFFFF
|
0x00 (将来の使用のために予約済み) |
1 - 場合によって異なる | アカウント キーデータ | バリエーション または 0x00 (アカウントキーのリストが空の場合) |
アカウント キーのデータには以下が含まれます。
オクテット | データ型 | 説明 | 値 |
---|---|---|---|
0 | uint8 |
フィールドの長さと型 0bLLLLTTTT
|
0bLLLL0000
|
1 ~s | アカウント キー フィルタ | 場合によって異なる | |
S+1 | uint8 |
フィールドの長さと型 0bLLLLTTTT
|
0b00100001
|
S+2 ~S+3 | uint16 |
Salt | 場合によって異なる |
アカウント キー フィルタ
アドバタイズされたアカウント キー フィルタにより、シーカーは、さらなるインタラクションの前に、プロバイダが特定のアカウントキー(偽陽性率が低く平均 0.5% 未満)を持っているかどうかをすばやく確認できます。シーカーはタイプ 0 のフィルタがブロードキャストされているとき、自動的に接続してプロシージャの開始を試みることができます。つまり、偽陽性率をさらに減らすために、いずれかのアカウント キーを含む可能性がある UI 表示を示しています。場合によっては、ペアリングの準備ができていないときに、プロバイダがシーカーに認識されたい場合があります。たとえば、イヤフォンをケースに戻すときは、ヘッドセットでペア設定が拒否される可能性があるため、後続のペア設定通知の表示は停止します。
アカウントキー フィルタは、次のように作成された可変長の Bloom フィルタです。
- 永続化されたアカウントキー リストにあるアカウント キーの数を n とします(n >= 1)。
- フィルタのサイズ(バイト単位) を (1.2×n + 3) だけ切り捨てます。たとえば、1 個の鍵が永続化されている場合、s = 4 バイトです。
uint8_t s = (((uint8_t)(( float )1.2 * n)) + 3);
- フィルタ F を 0 に設定した s バイトの配列として初期化します。
uint8_t F[s] = {0};
永続アカウントキーリストのアカウント キー K ごとに、次の操作を行います。
a. V を連結します(K、ソルト)。// 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. SHA256 を使用して V をハッシュし、32 バイトの値 H = {H0, ..., H31} を取得します。
uint8_t H[32] = {0}; SHA256_hash_function(V, H);
c. H をビッグ エンディアンで 4 バイトの符号なし整数に分割する。X = X0, ..., X7}。ここで X0 = 0xH0H1H2H3 です。
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); }
d. 各 Xi で以下を行います。
i. フィルタのビット数を mi で割ります(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 をソルトとして使用します。
- アドバタイズされたファスト ペアリング アカウント データの [Account Key Filter] フィールドには生成されたフィルタを、[Salt] フィールドには S を含めます。