초광대역 (UWB) 통신

초광대역 통신은 기기 간의 정확한 범위(위치 10cm 정확도 측정)에 중점을 둔 무선 기술입니다. 이 무선 기술은 단거리 측정에 저에너지 밀도를 사용하고 무선 스펙트럼의 상당 부분에서 고대역폭 신호를 실행할 수 있습니다. UWB의 대역폭이 500MHz를 초과 (또는 부분 대역폭의 20% 초과)합니다.

컨트롤러/시작자 vs. 관리자/응답자

UWB 통신은 두 기기 간에 발생합니다. 여기서 하나는 컨트롤러이고 다른 하나는 Controlee입니다. 컨트롤러는 두 기기가 공유할 복잡한 채널(UwbComplexChannel)을 결정하고 시작자이고 피제어자는 응답자입니다.

컨트롤러는 여러 Controlee를 처리할 수 있지만 Controlee는 단일 컨트롤러만 구독할 수 있습니다. 컨트롤러/시작자와 제어 대상/응답자 구성이 모두 지원됩니다.

범위 지정 매개변수

컨트롤러와 제어자는 서로를 식별하고 범위 설정 매개변수를 통신하여 범위 설정을 시작해야 합니다. 이러한 교환은 애플리케이션이 저전력 블루투스 (BLE)와 같이 사용자가 선택한 안전한 대역 외 (OOB) 메커니즘을 사용하여 구현해야 합니다.

범위 설정 매개변수에는 로컬 주소, 복합 채널, 세션 키 등이 포함됩니다. 이러한 매개변수는 범위 설정 세션이 종료된 후 순환되거나 변경될 수 있으며 범위 지정을 다시 시작하려면 다시 전달해야 합니다.

백그라운드 범위 설정

백그라운드에서 실행되는 앱은 UWB 범위 세션을 시작할 수 있습니다(기기에서 지원하는 경우). 기기 기능을 확인하려면 RangingCapabilities를 참고하세요.

앱은 백그라운드에서 실행될 때 범위 보고서를 수신하지 않으며, 앱이 포그라운드로 이동할 때 범위 보고서를 수신합니다.

STS 구성

앱 또는 서비스가 스크램블된 타임스탬프 시퀀스 (STS)를 사용하여 각 세션의 세션 키를 프로비저닝합니다. 프로비저닝된 STS는 정적 STS 구성보다 안전합니다. 프로비저닝된 STS는 Android 14 이상을 실행하는 모든 UWB 지원 기기에서 지원됩니다.

위협 카테고리 정적 STS 프로비저닝된 STS
공기: 수동 관찰자 완화됨 완화됨
공기: 신호 증폭 완화됨 완화됨
공기: 리플레이/중계 공격 민감성 완화됨

프로비저닝된 STS의 경우:

  1. 프로비저닝된 STS를 지원하는 RangingParametersuwbConfigType를 사용합니다.

  2. sessionKeyInfo 필드에 16바이트 키를 입력합니다.

정적 STS:

  1. 정적 STS를 지원하는 RangingParametersuwbConfigType를 사용합니다.

  2. sessionKeyInfo 필드에 8바이트 키를 제공합니다.

걸음수

UWB API를 사용하려면 다음 단계를 따르세요.

  1. Android 기기가 Android 12 이상을 실행하고 PackageManager#hasSystemFeature("android.hardware.uwb")를 사용하여 UWB를 지원하는지 확인합니다.
  2. IoT 기기의 범위를 지정하는 경우 FiRa MAC 1.3을 준수하는지 확인합니다.
  3. BluetoothLeScanner와 같은 원하는 OOB 메커니즘을 사용하여 UWB 지원 동종 기기를 탐색합니다.
  4. 선택한 보안 OOB 메커니즘(예: BluetoothGatt)을 사용하여 범위 설정 매개변수를 교환합니다.
  5. 사용자가 세션을 중지하고자 한다면 세션 범위를 취소합니다.

사용 제한

UWB API 사용에는 다음 제한사항이 적용됩니다.

  1. 새 UWB 범위 지정 세션을 시작하는 앱은 앞에서 설명한 것처럼 백그라운드 범위 설정이 지원되지 않는 한 포그라운드 앱 또는 서비스여야 합니다.
  2. 앱이 백그라운드로 이동하면 (세션이 진행되는 동안) 앱이 더 이상 범위 보고서를 수신하지 않을 수 있습니다. 하지만 UWB 세션은 하위 레이어에서 계속 유지됩니다. 앱이 포그라운드로 다시 이동하면 범위 설정 보고서가 재개됩니다.

코드 샘플

샘플 앱

UWB Jetpack 라이브러리를 사용하는 방법에 관한 전체 예는 GitHub의 샘플 애플리케이션을 참고하세요. 이 샘플 앱에서는 Android 기기에서 UWB 호환성을 검증하고, OOB 메커니즘을 사용하여 검색 프로세스를 사용 설정하고, 두 UWB 지원 기기 간의 UWB 범위를 설정하는 방법을 다룹니다. 이 샘플은 기기 제어 및 미디어 공유 사용 사례도 다룹니다.

UWB 범위

다음 코드 샘플은 Controlee의 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 지원을 사용할 수 있습니다. 이 라이브러리는 범위 설정 결과를 Observable 또는 Flowable 스트림으로 가져오고 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, 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 스택이 이러한 필드를 배열이 아닌 값으로 취급하기 때문입니다. Google은 이러한 필드가 배열로 취급되어야 한다고 명시적으로 명시하기 위해 FiRa와 협력하여 UCI 사양(CR-1112)을 업데이트하고 있습니다.

이 문제는 2320XXXX 버전의 GMS 코어 업데이트를 통해 해결될 예정입니다. 이 시점부터 Android 기기를 준수하려면 IoT 공급업체는 이러한 필드의 바이트 순서를 반대로 되돌리지 않도록 구현을 수정해야 합니다.