Comunicación de banda ultraancha (UWB)

La comunicación de banda ultraancha es una tecnología de radio que se centra en la precisión del rango de distancia. (mide la ubicación con una precisión de 10 cm) entre dispositivos. Esta tecnología de radio puede usar una densidad de energía baja para las mediciones de corto alcance. y realizar señales de gran ancho de banda en gran parte del espectro de radio. El ancho de banda de UWB es superior a 500 MHz (o superior al 20% ancho de banda).

Controlador/iniciador en comparación con el control/la persona que responde

La comunicación UWB se produce entre dos dispositivos: uno es un controlador, y es un controle. El controlador determina el canal complejo (UwbComplexChannel) que ambos dispositivos lo compartirán y es el iniciador, mientras que el Controlado es el persona que responde.

Un controlador puede manejar varios controles, pero uno solo puede suscribirse a un solo Controlador. Tanto el controlador/iniciador como el control/la persona que responde parámetros de configuración admitidos.

Parámetros de rango

El Responsable del Tratamiento de Datos y el Controle deben identificarse entre sí y comunicarse de rango para empezar a establecer rangos. Este intercambio queda a cargo de las aplicaciones implementar con un mecanismo seguro fuera de banda (OOB) de su elección, como Bluetooth de bajo consumo (BLE):

Los parámetros de rango incluyen la dirección local, el canal complejo y la clave de sesión, entre otros. Nota que estos parámetros pueden rotar o cambiar después de la sesión de rango y se deberá volver a comunicar para reiniciar el rango.

Rango de fondo

Una app que se ejecuta en segundo plano puede iniciar una sesión de rango de UWB si el dispositivo lo respaldan. Para verificar las capacidades del dispositivo, consulta RangingCapabilities.

La app no recibe informes de rango cuando se ejecuta en segundo plano. la app recibe informes de rango cuando se mueve al primer plano.

Parámetros de configuración de STS

La app o el servicio aprovisiona una clave de sesión para cada sesión con un código Secuencia de marca de tiempo (STS). El STS aprovisionado es más seguro que uno estático configuración. El STS aprovisionado es compatible con todos los dispositivos habilitados para UWB que se ejecutan Android 14 o una versión posterior.

Categoría de amenaza STS estático STS proporcionado
Air: Observador pasivo Mitigado Mitigado
Air: Amplificación de la señal Mitigado Mitigado
Aire: Ataque de repetición/retransmisión Susceptibles Mitigado

Para STS aprovisionados:

  1. Usa el uwbConfigType en RangingParameters que admita STS aprovisionado.

  2. Proporciona la clave de 16 bytes en el campo sessionKeyInfo.

Para STS estático:

  1. Usa el uwbConfigType en RangingParameters que admita STS estático.

  2. Proporciona la clave de 8 bytes en el campo sessionKeyInfo.

Pasos

Para usar la API de UWB, sigue estos pasos:

  1. Asegúrate de que los dispositivos Android se ejecuten en Android 12 o versiones posteriores, y de que admiten UWB con PackageManager#hasSystemFeature("android.hardware.uwb")
  2. Si van contra dispositivos de IoT, asegúrese de que sean FiRa MAC 1.3. que cumplen con los requisitos.
  3. Descubre dispositivos de intercambio de tráfico compatibles con UWB usando el mecanismo OOB de tu elección. como, por ejemplo, BluetoothLeScanner
  4. Intercambia parámetros de rango utilizando un mecanismo seguro de OOB de tu elección. como BluetoothGatt.
  5. Si el usuario desea detener la sesión, cancela el alcance de la sesión.

Restricciones de uso

Se aplican las siguientes restricciones al uso de la API de UWB:

  1. La app que inicia nuevas sesiones de rango de UWB debe estar en primer plano app o servicio, a menos que se admita el rango de fondo como se muestra en la ilustración anteriormente.
  2. Cuando la app pasa a segundo plano (mientras la sesión está en curso), esta es posible que ya no reciban informes de rango. Sin embargo, la sesión de UWB siguen manteniéndose en las capas inferiores. Cuando la aplicación regresa en primer plano, se reanudarán los informes de rango.

Muestras de código

App de ejemplo

Si quieres ver un ejemplo de extremo a extremo sobre cómo usar la biblioteca de UWB Jetpack, consulta nuestra aplicación de ejemplo en GitHub. Esta app de ejemplo abarca la validación de la compatibilidad con UWB en un dispositivo Android, la habilitación del proceso de descubrimiento mediante un mecanismo OOB y la configuración de un rango de UWB entre dos dispositivos compatibles con UWB. La muestra también abarca casos de uso de control de dispositivos y uso compartido de contenido multimedia.

Rango de UWB

Esta muestra de código inicia y finaliza el rango de UWB para un controlado:

// 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()
    }
}

Compatibilidad con RxJava3

Ahora está disponible la compatibilidad con Rxjava3 para ayudar a lograr la interoperabilidad con Java. clientes. Esta biblioteca proporciona una forma de obtener resultados del rango como un Flowable y para recuperar UwbClientSessionScope como un objeto único.

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();

Compatibilidad con ecosistemas

A continuación, se muestran los dispositivos de socios y SDKs de terceros compatibles.

Dispositivos móviles compatibles con UWB

A partir de marzo de 2024, estos dispositivos serán compatibles con la biblioteca de Android UWB Jetpack:

Proveedor Modelo del dispositivo
Google Pixel 6 Pro, 7 Pro, 8 Pro, Fold y Tablet
Samsung Galaxy Note 20, S21+, S22+, S23+, S24+ Z Fold 2, 3, 4 y 5

SDKs de terceros

Desde abril de 2023, estas soluciones de socios son compatibles con el biblioteca de Jetpack actual.

Problema conocido: Se revirtió el orden de bytes para los campos de dirección MAC y de ID del proveedor de STS estáticos

En Android 13 y versiones anteriores, la pila de UWB de Android revierte el byte de manera incorrecta. los siguientes campos:

  • Dirección MAC del dispositivo
  • Dirección MAC de destino
  • ID del proveedor de STS estático

La reversión del orden de bytes se produce porque la pila de Android trata estos campos como valores, no como arrays. Estamos trabajando con FiRa para actualizar la especificación de UCI (CR-1112). para indicar explícitamente que estos campos deben tratarse como arrays.

Este problema se solucionará mediante la actualización de GMS Core de la versión 2320XXXX. Para cumplir con los dispositivos Android a partir de ese momento, los proveedores de IoT deben modificar tu implementación para evitar revertir el orden de bytes de estos campos.