Sử dụng bộ sưu tập để sắp xếp ngăn nắp các trang
Lưu và phân loại nội dung dựa trên lựa chọn ưu tiên của bạn.
Tín hiệu Quảng cáo của nhà cung cấp
Quảng cáo: Khi có thể phát hiện
Khi thiết bị Nhà cung cấp có thể phát hiện được BR/EDR (tức là ở chế độ ghép nối), thiết bị đó sẽ quảng cáo Dữ liệu mã nhận dạng mẫu Ghép nối nhanh qua BLE và địa chỉ BLE sẽ không được xoay.
Khoảng thời gian quảng cáo: Khi có thể khám phá
Khoảng thời gian giữa các quảng cáo không được lớn hơn 100 mili giây (10 Hz). Tốc độ nhanh cho phép Trình tìm kiếm nhanh chóng tìm thấy Nhà cung cấp, ngay cả khi quét ở chế độ tiết kiệm pin.
Quảng cáo phải chứa loại dữ liệu Dữ liệu dịch vụ, tương tự như vậy, § 1.11. UUID sẽ là UUID Dịch vụ ghép nối nhanh của 0xFE2C. Dữ liệu dịch vụ phải chứa những thông tin sau:
Octet
Loại dữ liệu
Mô tả
Giá trị
0-2
uint24
Mã mẫu 24 bit
thay đổi
Quảng cáo: Khi không thể tìm thấy
Khi không thể phát hiện (tức là không ở chế độ ghép nối), thiết bị của Nhà cung cấp sẽ quảng cáo Dữ liệu tài khoản Ghép nối nhanh theo các nguyên tắc sau.
Việc quảng cáo dữ liệu tài khoản cho phép Người tìm kiếm ở gần nhận ra thời điểm một nhà cung cấp thuộc về tài khoản của họ và bắt đầu ghép nối mà không cần phải buộc nhà cung cấp quay lại chế độ ghép nối trước (đây là nguyên nhân phổ biến khiến người dùng khiếu nại). Trình tìm kiếm sẽ cho phép người dùng bỏ qua thông báo truyền tin này trong trường hợp họ không đợi ghép nối với nhà cung cấp hoặc thông báo truyền tin không liên quan (ví dụ: nếu họ đã ghép nối).
Trình tìm kiếm cũng sẽ tự động lọc ra các chương trình phát sóng rõ ràng là không tốt, chẳng hạn như khi dữ liệu tài khoản được định cấu hình không chính xác.
Khoảng thời gian quảng cáo: Khi không thể phát hiện
Khoảng thời gian giữa các quảng cáo tối đa là 250 mili giây (4 Hz).
Quảng cáo phải chứa loại dữ liệu Dữ liệu dịch vụ, Ibid., § 1.11. UUID sẽ là UUID Dịch vụ ghép nối nhanh của 0xFE2C. Dữ liệu dịch vụ phải chứa những thông tin sau:
Octet
Loại dữ liệu
Mô tả
Giá trị
0
uint8
Phiên bản và cờ 0bVVVVFFFF
V = phiên bản
F = cờ
0x00 (dành để sử dụng trong tương lai)
1 – biến đổi
Dữ liệu khoá tài khoản
biến đổi
Dữ liệu khoá tài khoản chứa:
Octet
Loại dữ liệu
Mô tả
Giá trị
0
uint8
Độ dài và loại trường 0bLLLLTTTT
L = độ dài của bộ lọc khoá tài khoản tính bằng byte
T = loại
0bLLLL0000
length = 0bLLLL = varies
type = 0b0000 (hiển thị chỉ báo giao diện người dùng) hoặc 0b0010 (ẩn chỉ báo giao diện người dùng), Bộ lọc khoá tài khoản
Bộ lọc khoá tài khoản được quảng cáo cho phép Người tìm kiếm nhanh chóng kiểm tra xem Nhà cung cấp có thể sở hữu một khoá tài khoản nhất định hay không (với xác suất dương tính giả thấp, trung bình ít hơn 0,5% nhiều) trước khi tương tác thêm. Trình tìm kiếm có thể tự động kết nối và cố gắng bắt đầu quy trình khi thấy một bộ lọc đang được truyền tin với loại 0, tức là hiển thị chỉ báo giao diện người dùng, có thể chứa một trong các khoá tài khoản của bộ lọc đó, để giảm tỷ lệ dương tính giả hơn nữa. Trong một số trường hợp, Trình cung cấp có thể muốn Trình tìm kiếm nhận dạng mình trong khi chưa sẵn sàng ghép nối. Ví dụ: khi người dùng đặt lại tai nghe vào hộp, chúng ta muốn ngừng hiển thị thông báo ghép nối tiếp theo vì tai nghe có thể từ chối ghép nối đó.
Bộ lọc khoá tài khoản là một bộ lọc Bloom có độ dài biến đổi được tạo như sau:
Giả sử s, kích thước của bộ lọc tính bằng byte, là (1,2*n + 3) bị cắt bớt. Ví dụ: nếu 1 khoá được duy trì, s = 4 byte. uint8_t s = (((uint8_t)(( float )1.2 * n)) + 3);
Khởi chạy bộ lọc F dưới dạng một mảng gồm các byte s, mỗi byte được đặt thành 0. uint8_t F[s] = {0};
// In the sample code, the size of salt is 2 bytes.#define SALT_SIZE 2uint8_tV[FASTPAIR_ACCOUNT_KEY_SIZE+SALT_SIZE];for(uint8_tkeyIndex=0;keyIndex < n;keyIndex++){// concat (K, Salt)fastpair_get_account_key_by_index(keyIndex,V);uint8_trandomSalt=(uint8_t)rand();V[FASTPAIR_ACCOUNT_KEY_SIZE]=randomSalt;...}
b. Hàm băm V bằng SHA256, nhận được giá trị 32 byte H =
{H0, …, H31}.
uint8_tH[32]={0};SHA256_hash_function(V,H);
c. Chia H thành 8 số nguyên không dấu 4 byte theo thứ tự big-endian,
X = {X0, …, X7}, trong đó
X0 = 0xH0H1H2H3.
d. Đối với mỗi Xi:
i. Gọi M là Xi theo số bit trong bộ lọc,
(s * 8).
ii. Lấy byte trong F tại chỉ mục (M / 8), làm tròn xuống.
iii. Trong byte, hãy đặt bit tại chỉ mục (M % 8) thành 1.
iv. Nói cách khác:
// M = Xi % (s * 8)// F[M/8] = F[M/8] | (1 << (M % 8))for(index=0;index < 8;index++){uint32_tM=X[index]%(s*8);F[M/8]=F[M/8]|(1 << (M%8));}
Thêm bộ lọc F làm trường Bộ lọc khoá tài khoản trong dữ liệu quảng cáo.
Xin lưu ý rằng không có "thứ tự byte" nào cho giá trị này, vì không có byte nào quan trọng hơn hoặc ít quan trọng hơn – đừng thay đổi thứ tự byte.
Ruộng muối
Giá trị băm là một giá trị ngẫu nhiên được thêm vào khoá tài khoản khi tạo bộ lọc bloom. Bạn nên tạo lại muối này mỗi khi cập nhật RPA cho Nhà cung cấp để tránh việc theo dõi khi xoay vòng địa chỉ.
Cách tạo Bộ lọc khoá tài khoản bằng muối:
Tạo một S 2 byte ngẫu nhiên. Xin lưu ý rằng không có "thứ tự byte" đối với giá trị này, vì không có byte nào quan trọng hơn hoặc ít quan trọng hơn — đừng thay đổi thứ tự byte.
Sử dụng S 2 byte làm Salt.
Trong Dữ liệu tài khoản Ghép nối nhanh được quảng cáo, hãy đưa bộ lọc đã tạo vào trường Bộ lọc khoá tài khoản và S vào trường Salt (Muối).
[[["Dễ hiểu","easyToUnderstand","thumb-up"],["Giúp tôi giải quyết được vấn đề","solvedMyProblem","thumb-up"],["Khác","otherUp","thumb-up"]],[["Thiếu thông tin tôi cần","missingTheInformationINeed","thumb-down"],["Quá phức tạp/quá nhiều bước","tooComplicatedTooManySteps","thumb-down"],["Đã lỗi thời","outOfDate","thumb-down"],["Vấn đề về bản dịch","translationIssue","thumb-down"],["Vấn đề về mẫu/mã","samplesCodeIssue","thumb-down"],["Khác","otherDown","thumb-down"]],["Cập nhật lần gần đây nhất: 2025-08-13 UTC."],[[["\u003cp\u003eProvider devices advertise Fast Pair Model ID Data over BLE when in pairing mode to enable quick discovery by Seeker devices.\u003c/p\u003e\n"],["\u003cp\u003eWhen not discoverable, Provider devices advertise Fast Pair Account Data, allowing Seekers to recognize them and initiate pairing without requiring the Provider to re-enter pairing mode.\u003c/p\u003e\n"],["\u003cp\u003eThe Account Key Filter, a Bloom filter included in the Account Key Data, helps Seekers quickly assess the potential presence of a specific account key on the Provider, reducing false positives and unnecessary pairing attempts.\u003c/p\u003e\n"],["\u003cp\u003eThe salt, a random value appended to account keys during Bloom filter construction, is regenerated with each Provider RPA update to prevent tracking across address rotations, enhancing privacy.\u003c/p\u003e\n"]]],[],null,["Provider Advertising signal\n---------------------------\n\n### Advertising: When discoverable\n\nWhen the Provider device is BR/EDR discoverable (that is, in pairing mode), it\nshall advertise Fast Pair Model ID Data over BLE, and the BLE address shall not\nbe rotated.\n\n#### Advertising interval: When discoverable\n\nThe interval between advertisements should be no larger than 100ms (10Hz). A\nfast rate allows the Seeker to quickly find the Provider, even when scanning in\nlow-power mode.\n\n#### Advertising payload: Fast Pair Model ID Data\n\nThe advertisement shall contain the Service Data data type, ibid., § 1.11. The\nUUID shall be the Fast Pair Service UUID of `0xFE2C`. The service data shall\ncontain the following:\n\n| Octet | Data type | Description | Value |\n|-------|-----------|-----------------|----------|\n| 0-2 | `uint24` | 24-bit model ID | *varies* |\n\n### Advertising: When not discoverable\n\nWhen not discoverable (that is, not in pairing mode), the Provider device shall\nadvertise Fast Pair Account Data, using the following guidelines.\n\nAdvertising the account data allows Seekers nearby to recognize when a provider\nbelongs to their account and initiate pairing without having to force the\nprovider back into pairing mode first, which is a common cause for user\ncomplaint. Seekers will provide the opportunity for users to be able to ignore\nthis broadcast in the case where they do not wait to pair with the provider or\nthe broadcast is not relevant (for example, if they have already paired).\nSeekers will also filter out obviously bad broadcasts automatically, such as\nwhen the account data is misconfigured.\n\n#### Advertising interval: When not discoverable\n\nThe interval between advertisements should be at most 250ms (4Hz).\n\n#### Advertising payload: Fast Pair Account Data\n\nThe advertisement shall contain the Service Data data type, Ibid., § 1.11. The\nUUID shall be the Fast Pair Service UUID of `0xFE2C`. The service data shall\ncontain the following:\n\n| Octet | Data type | Description | Value |\n|--------------|-----------|--------------------------------------------------------|----------------------------------|\n| 0 | `uint8` | Version and flags 0bVVVVFFFF - V = version - F = flags | `0x00` (reserved for future use) |\n| 1 - *varies* | | Account Key Data | *varies* |\n\n| **Note:** The provider shall advertise its Fast PairAccount Data only if the Account Key List has one or more entries.\n\nThe Account Key Data contains:\n\n| Octet | Data type | Description | Value |\n|-------------------|-----------|-----------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------|\n| 0 | `uint8` | Field length and type 0bLLLLTTTT - L = length of account key filter in bytes - T = type | 0bLLLL0000 - length = 0bLLLL = *varies* - type = 0b0000 (show UI indication) or 0b0010 (hide UI indication), Account Key Filter |\n| 1 - *s* | | Account Key Filter | *varies* |\n| *s* + 1 | `uint8` | Field length and type 0bLLLLTTTT - L = length in bytes - T = type | 0b00100001 - length = 0b0010 = 2 - type = 0b0001, [Salt](#SaltField) |\n| *s* + 2 - *s* + 3 | `uint16` | Salt | *varies* |\n\n#### Account Key Filter\n\n| **Note:** Google recommends implementing the [Cryptographic Test Cases](/nearby/fast-pair/specifications/appendix/cryptotestcases \"Link to the Cryptographic Test Cases.\") to ease verification of these requirements.\n\nThe advertised Account Key Filter allows a Seeker to quickly check whether a\nProvider might possess a certain account key (with a low false-positive\nprobability, on average much less than 0.5%), before further interactions. The\nSeeker may automatically connect and attempt to start the procedure when it sees\na filter being broadcast with type 0, i.e. showing UI indication, that\npotentially contains one of its account keys, so as to reduce the rate of false\npositives further. In some situations, the Provider may want to be recognized\nby the Seeker while not ready for pairing. One example is that when buds get put\nback into case, we want to stop showing the subsequent pairing notification\nsince that pairing could be rejected by the headset.\n\nThe Account Key Filter is a variable-length\n[Bloom filter](https://en.wikipedia.org/wiki/Bloom_filter) constructed as\nfollows:\n\n1. Let *n* be the number of account keys (*n* \\\u003e= 1) in the persisted [Account Key list](/nearby/fast-pair/specifications/configuration#AccountKeyList \"Account Key List\").\n2. Let *s* , the size of the filter in bytes, be (1.2\\**n* + 3) truncated. For example, if 1 key is persisted, *s* = 4 bytes. \n `uint8_t s = (((uint8_t)(( float )1.2 * n)) + 3);`\n3. Initialize the filter *F* as an array of *s* bytes, each set to 0. \n `uint8_t F[s] = {0};`\n4. For each account key *K* in the persisted [Account Key list](/nearby/fast-pair/specifications/configuration#AccountKeyList \"Account Key List\"): \n\n a. Let *V* be concat(*K* , [Salt](#SaltField)). \n\n // In the sample code, the size of salt is 2 bytes.\n #define SALT_SIZE 2\n\n uint8_t V[FASTPAIR_ACCOUNT_KEY_SIZE + SALT_SIZE];\n for (uint8_t keyIndex = 0; keyIndex \u003c n; keyIndex++)\n {\n // concat (K, Salt)\n fastpair_get_account_key_by_index(keyIndex, V);\n\n uint8_t randomSalt = (uint8_t)rand();\n V[FASTPAIR_ACCOUNT_KEY_SIZE] = randomSalt;\n ... }\n\n b. Hash *V* using SHA256, obtaining a 32-byte value *H* =\n {H~0~, ..., H~31~}. \n\n uint8_t H[32] = {0};\n SHA256_hash_function(V, H);\n\n c. Divide *H* into eight 4-byte unsigned integers in big-endian,\n X = {X~0~, ..., X~7~}, where\n X~0~ = 0xH~0~H~1~H~2~H~3~. \n\n uint32_t X[8];\n for (index = 0; index \u003c 8; index++)\n {\n X[index] = (((uint32_t)(H[index * 4])) \u003c\u003c 24) |\n (((uint32_t)(H[index * 4 + 1])) \u003c\u003c 16) |\n (((uint32_t)(H[index * 4 + 2])) \u003c\u003c 8) |\n (((uint32_t)(H[index * 4 + 3])) \u003c\u003c 0);\n }\n\n d. For each X~i~: \n\n i. Let *M* be *X~i~* modulo the number of bits in the filter,\n (*s* \\* 8). \n\n ii. Get the byte in *F* at index (*M* / 8), rounded down. \n\n iii. Within the byte, set the bit at index (*M* % 8) to 1. \n\n iv. In other words: \n\n // M = Xi % (s * 8)\n // F[M/8] = F[M/8] | (1 \u003c\u003c (M % 8))\n for (index = 0; index \u003c 8; index++)\n {\n uint32_t M = X[index] % (s * 8);\n F[M / 8] = F[M / 8] | (1 \u003c\u003c (M % 8));\n }\n\nInclude the filter *F* as the Account Key Filter field, in the advertising data.\nNote that there is no \"endianness\" to this value, since there is no more or less\nsignificant byte---don't alter the byte order.\n\n##### Salt field\n\nThe salt is a random value that is appended to account keys when building the\nbloom filter. This salt should be regenerated every time the RPA is updated for\nthe Provider to avoid tracking across address rotation.\n\nTo generate the Account Key Filter using the salt:\n\n1. Generate a random 2-byte *S*. Note that there is no \"endianness\" to this value, since there is no more or less significant byte --- don't alter the byte order.\n2. Use the 2-byte *S* as the Salt.\n3. In the advertised Fast Pair Account Data, include the generated filter in the Account Key Filter field, and *S* in the Salt field."]]