超寬頻 (UWB) 通訊

超寬頻通訊是一種無線電技術,可精確進行測距 (以 10 公分的精確度測量裝置之間的距離)。 這項無線電技術可使用低功耗密度進行短程測量 並執行高頻寬訊號 UWB 的頻寬超過 500 MHz (或超過 20% 小數) 頻寬)。

控管者/發起人與受控者/作答者

UWB 會在兩部裝置間通訊,其中一部是控制器, 另一個是控制人員控制器會決定複雜的管道 (UwbComplexChannel)。 這兩個裝置會共用,發起人為發起者,「控制者」則是 作答者。

一個控制器可以處理多位受控者,但受控者只能訂閱 單一控制器控管者/發起人和受控者/作答者 設定檔

範圍參數

控管者和控制人員必須識別彼此並相互溝通 計算範圍參數。應用程式就會交由應用程式交換 採用自選的架構外安全機制 (OOB) 機制,例如 藍牙低功耗 (BLE)。

範圍參數 包括本機地址、複雜頻道和工作階段金鑰等等注意事項 這些參數可能會在測距工作階段結束後旋轉或以其他方式變更 並且需要重新通訊才能重新開始範圍。

背景範圍

在背景中執行的應用程式可在裝置中啟動 UWB 測距工作階段 但 AI 會支援該執行緒。如要查看裝置功能,請參閱 RangingCapabilities

應用程式在背景執行時不會收到精細報表。應用程式 等到應用程式移至前景時,就會收到詳盡的報表。

STS 設定

應用程式或服務使用亂碼,為每個工作階段佈建工作階段金鑰 時間戳記順序 (STS)。佈建的 STS 比靜態 STS 更安全 此外還會從 0 自動調整資源配置 您完全不必調整資源調度設定所有支援 UWB 的裝置皆支援已佈建的 STS 搭載 Android 14 以上版本。

威脅類別 靜態 STS 提議的 STS
空氣:被動觀察器 已緩解 已緩解
空氣:訊號擴大 已緩解 已緩解
空氣:重播/重播攻擊 容易 已緩解

已佈建的 STS:

  1. 在支援已佈建 STS 的 RangingParameters 中使用 uwbConfigType

  2. sessionKeyInfo 欄位中提供 16 位元組的金鑰。

靜態 STS:

  1. 在支援靜態 STS 的 RangingParameters 中使用 uwbConfigType

  2. sessionKeyInfo 欄位中提供 8 位元組的金鑰。

操作步驟

如要使用 UWB API,請按照下列步驟操作:

  1. 確保 Android 裝置搭載 Android 12 以上版本,並 支援 UWB PackageManager#hasSystemFeature("android.hardware.uwb")
  2. 如要對 IoT 裝置進行傳輸,請確認這些裝置為 FiRa MAC 1.3 確保符合規定
  3. 透過您選擇的 OOB 機制探索支援 UWB 的對等互連裝置。 例如 BluetoothLeScanner
  4. 使用您選擇的安全 OOB 機制交換參數。 例如 BluetoothGatt
  5. 如果使用者想停止工作階段,請取消工作階段範圍。

使用限制

使用 UWB API 時須遵守下列限制:

  1. 啟動新的 UWB 測距工作階段的應用程式必須是前景 應用程式或服務,除非上述圖表不支援背景測距功能
  2. 當應用程式移至背景 (工作階段執行期間) 時,應用程式 可能就不會繼續收到精細報表UWB 工作階段 都會繼續維持在較低層當應用程式回到 系統就會繼續分析取樣報表

程式碼範例

範例應用程式

如需 UWB Jetpack 程式庫的端對端範例,請參閱 GitHub 上的範例應用程式。此範例應用程式說明如何在 Android 裝置上驗證 UWB 相容性、使用 OOB 機制啟用探索程序,以及設定在兩部支援 UWB 的裝置間設定 UWB。此外,此範例也涵蓋了裝置控制和媒體分享的用途。

UWB 量表

以下程式碼範例會啟動和終止受控人的 UWB 範圍:

// The coroutineScope responsible for handling uwb ranging.
// This will be initialized when startRanging is called.
var job: Job?

// A code snippet that initiates uwb ranging for a Controlee.
suspend fun startRanging() {

    // Get the ranging parameter of a partnering Controller using an OOB mechanism of choice.
    val partnerAddress : Pair<UwbAddress, UwbComplexChannel> = listenForPartnersAddress()

    // Create the ranging parameters.
    val partnerParameters = RangingParameters(
        uwbConfigType = UwbRangingParameters.UWB_CONFIG_ID_1,
        // SessionKeyInfo is used to encrypt the ranging session.
        sessionKeyInfo = null,
        complexChannel = partnerAddress.second,
        peerDevices = listOf(UwbDevice.createForAddress(partnerAddress.first)),
        updateRateType = UwbRangingParameters.RANGING_UPDATE_RATE_AUTOMATIC
    )

    // Initiate a session that will be valid for a single ranging session.
    val clientSession = uwbManager.clientSessionScope()

    // Share the localAddress of the current session to the partner device.
    broadcastMyParameters(clientSession.localAddress)

    val sessionFlow = clientSession.prepareSession(partnerParameters)

    // Start a coroutine scope that initiates ranging.
    CoroutineScope(Dispatchers.Main.immediate).launch {
        sessionFlow.collect {
            when(it) {
                is RangingResultPosition -> doSomethingWithPosition(it.position)
                is RangingResultPeerDisconnected -> peerDisconnected(it)
            }
        }
    }
}

// A code snippet that cancels uwb ranging.
fun cancelRanging() {

    // Canceling the CoroutineScope will stop the ranging.
    job?.let {
        it.cancel()
    }
}

RxJava3 支援

現已支援 Rxjava3 來協助實現與 Java 的互通性 用戶端。這個程式庫可讓您以可觀察或 可 Flow 串流,以及將 UwbClientSessionScope 擷取為單一物件。

private final UwbManager uwbManager;

// Retrieve uwbManager.clientSessionScope as a Single object
Single<UwbClientSessionScope> clientSessionScopeSingle =
                UwbManagerRx.clientSessionScopeSingle(uwbManager);
UwbClientSessionScope uwbClientSessionScope = clientSessionScopeSingle.blockingGet();

// Retrieve uwbClientSessionScope.prepareSession Flow as an Observable object
Observable<RangingResult> rangingResultObservable =
                UwbClientSessionScopeRx.rangingResultsObservable(clientSessionScope,
                        rangingParameters);

// Consume ranging results from Observable
rangingResultObservable.subscribe(
   rangingResult -> doSomethingWithRangingResult(result), // onNext
   (error) -> doSomethingWithError(error), // onError
   () -> doSomethingOnResultEventsCompleted(), //onCompleted
);
// Unsubscribe
rangingResultObservable.unsubscribe();
   

// Retrieve uwbClientSessionScope.prepareSession Flow as a Flowable object
Flowable<RangingResult> rangingResultFlowable =
                UwbClientSessionScopeRx.rangingResultsFlowable(clientSessionScope,
                        rangingParameters);

// Consume ranging results from Flowable using Disposable
Disposable disposable = rangingResultFlowable
   .delay(1, TimeUnit.SECONDS)
   .subscribeWith(new DisposableSubscriber<RangingResult> () {
      @Override public void onStart() {
          request(1);
      }
      
      @Override public void onNext(RangingResult rangingResult) {
             doSomethingWithRangingResult(rangingResult);
             request(1);
      }


      @Override public void onError(Throwable t) {
             t.printStackTrace();
      }


         @Override public void onComplete() {
            doSomethingOnEventsCompleted();
         }
   });

// Stop subscription
disposable.dispose();

支援生態系統

以下列出支援的合作夥伴裝置和第三方 SDK。

支援 UWB 的行動裝置

自 2024 年 3 月起,以下裝置支援 Android UWB Jetpack 程式庫:

供應商 裝置型號
Google Pixel 6 Pro、7 Pro、8 Pro、Pixel Fold、平板電腦
Samsung Galaxy Note 20、S21+、S22+、S23+、S24+ Z Fold 2、3、4、5

第三方 SDK

自 2023 年 4 月起,這些合作夥伴解決方案與 新版 Jetpack 程式庫

已知問題:對 MAC 位址和靜態 STS 供應商 ID 欄位反向的位元組順序

在 Android 13 以下版本中,Android UWB 堆疊會錯誤反轉位元組 排序以下欄位:

  • 裝置的 MAC 位址
  • 目標 MAC 位址
  • 靜態 STS 供應商 ID

系統會撤銷位元組順序,因為 Android 堆疊會處理這些欄位 而非陣列我們正與 FiRa 合作更新 UCI 規格 (CR-1112)。 明確指出這些欄位應視為陣列。

這個問題將透過 2320XXXX 版本中的 GMS Core 更新修正。 之後,IoT 供應商必須修改 Android 裝置才能與 Android 裝置相容 以避免對這些欄位的位元組順序反轉。