Android 7.0 refactorizó la capa de interfaz de radio (RIL) utilizando un conjunto de funciones para mejorar la funcionalidad de RIL. Se requieren cambios en el código de socio para implementar estas funciones, que son opcionales pero recomendables. Los cambios de refactorización son compatibles con versiones anteriores, por lo que las implementaciones anteriores de las funciones refactorizadas continúan funcionando.
La refactorización RIL incluye las siguientes mejoras:
- Códigos de error RIL. Habilita códigos de error específicos además del código
GENERIC_FAILURE
existente. Esto ayuda en la resolución de errores al proporcionar información más específica sobre la causa de los errores. - Versionado RIL. Proporciona información de versión más precisa y más fácil de configurar.
- Comunicación RIL mediante wakelocks. Mejora el rendimiento de la batería del dispositivo.
Puede implementar cualquiera o todas las mejoras anteriores. Para obtener más detalles, consulte los comentarios del código sobre el control de versiones de RIL en https://android.googlesource.com/platform/hardware/ril/+/main/include/telephony/ril.h
.
Implementación de códigos de error RIL mejorados
Casi todas las llamadas de solicitud RIL pueden devolver el código de error GENERIC_FAILURE
en respuesta a un error. Este es un problema con todas las respuestas solicitadas devueltas por los OEM, lo que puede dificultar la depuración de un problema del informe de error si las llamadas RIL devuelven el mismo código de error GENERIC_FAILURE
por diferentes motivos. Los proveedores pueden tardar un tiempo considerable en identificar siquiera qué parte del código podría haber devuelto un código GENERIC_FAILURE
.
En Android 7.x y versiones posteriores, los OEM pueden devolver un valor de código de error distinto asociado con cada error diferente que actualmente está categorizado como GENERIC_FAILURE
. Los OEM que no quieran revelar públicamente sus códigos de error personalizados pueden devolver errores como un conjunto distinto de números enteros (como 1 a x) asignados como OEM_ERROR_1
a OEM_ERROR_X
. Los proveedores deben asegurarse de que cada código de error enmascarado devuelto se corresponda con un motivo de error único en el código. El uso de códigos de error específicos puede acelerar la depuración de RIL cada vez que el OEM devuelve errores genéricos, ya que a menudo puede llevar demasiado tiempo identificar la causa exacta de un código de error GENERIC_FAILURE
(y a veces es imposible determinarlo).
Además, ril.h
agrega más códigos de error para las enumeraciones RIL_LastCallFailCause
y RIL_DataCallFailCause
para que el código del proveedor pueda evitar devolver errores genéricos como CALL_FAIL_ERROR_UNSPECIFIED
y PDP_FAIL_ERROR_UNSPECIFIED
.
Validación de códigos de error RIL mejorados
Después de agregar nuevos códigos de error para reemplazar el código GENERIC_FAILURE
, verifique que la llamada RIL devuelva los nuevos códigos de error en lugar de GENERIC_FAILURE
.
Implementación de versiones RIL mejoradas
El control de versiones RIL en versiones anteriores de Android era problemático: la versión en sí era imprecisa, el mecanismo para informar una versión RIL no estaba claro (lo que provocó que algunos proveedores informaran una versión incorrecta) y la solución alternativa para estimar la versión era propensa a ser inexacta.
En Android 7.x y versiones posteriores, ril.h
documenta todos los valores de la versión RIL, describe la versión RIL correspondiente y enumera todos los cambios para esa versión. Al realizar cambios que corresponden a una versión de RIL, los proveedores deben actualizar su versión en el código y devolver esa versión en RIL_REGISTER
.
Validación de versiones RIL mejoradas
Verifique que la versión RIL correspondiente a su código RIL se devuelva durante RIL_REGISTER
(en lugar de RIL_VERSION
definida en ril.h
).
Implementación de la comunicación RIL mediante wakelocks
Los wakelocks temporizados se utilizan en la comunicación RIL de forma imprecisa, lo que afecta negativamente al rendimiento de la batería. En Android 7.x y versiones posteriores, puede mejorar el rendimiento clasificando las solicitudes RIL y actualizando el código para manejar los wakelocks de manera diferente para diferentes tipos de solicitudes.
Clasificación de solicitudes RIL
Las solicitudes RIL pueden ser solicitadas o no solicitadas. Los proveedores deben clasificar además las solicitudes solicitadas como una de las siguientes:
- sincrónico . Solicitudes que no requieren un tiempo considerable para responder. Por ejemplo,
RIL_REQUEST_GET_SIM_STATUS
. - asincrónico . Solicitudes que tardan un tiempo considerable en responder. Por ejemplo,
RIL_REQUEST_QUERY_AVAILABLE_NETWORKS
.
Las solicitudes RIL solicitadas asíncronamente pueden llevar un tiempo considerable. Después de recibir una confirmación del código del proveedor, RIL Java libera el wakelock, lo que podría provocar que el procesador de la aplicación pase del estado inactivo al estado suspendido. Cuando la respuesta está disponible en el código del proveedor, RIL Java (el procesador de aplicaciones) vuelve a adquirir el wakelock, procesa la respuesta y luego vuelve al estado inactivo. Pasar de inactivo a suspendido a inactivo puede consumir mucha energía.
Si el tiempo de respuesta no es lo suficientemente largo, mantener el wakelock y permanecer inactivo durante todo el tiempo necesario para responder puede ser más eficiente desde el punto de vista energético que entrar en estado de suspensión soltando el wakelock y despertando cuando llegue la respuesta. Los proveedores deben utilizar mediciones de potencia específicas de la plataforma para determinar el valor umbral del tiempo T cuando la energía consumida al permanecer inactivo durante todo el tiempo T es mayor que la energía consumida al pasar de inactivo a suspendido y a inactivo al mismo tiempo T Cuando se conoce el tiempo T , los comandos RIL que tardan más que el tiempo T se pueden clasificar como asíncronos y los comandos restantes se pueden clasificar como síncronos.
Escenarios de comunicación RIL
Los siguientes diagramas ilustran escenarios de comunicación RIL comunes y brindan soluciones para modificar el código para manejar solicitudes solicitadas y no solicitadas de RIL.
Nota: Para obtener detalles de implementación sobre las funciones utilizadas en los siguientes diagramas, consulte los métodos acquireWakeLock()
, decrementWakeLock()
y clearWakeLock(
) en ril.cpp
.
Escenario: solicitud RIL y respuesta asincrónica solicitada
En este escenario, si se espera que la respuesta solicitada por RIL demore un tiempo considerable (es decir, una respuesta a RIL_REQUEST_GET_AVAILABLE_NETWORKS
), el wakelock se mantiene durante mucho tiempo en el lado del procesador de la aplicación. Los problemas con el módem también pueden provocar una espera larga.
Solución 1: el módem mantiene el wakelock para la solicitud RIL y la respuesta asincrónica.
- Se envía la solicitud RIL y el módem adquiere wakelock para procesar esa solicitud.
- El módem envía un reconocimiento que hace que el lado Java disminuya el contador de wakelock y lo libere cuando el valor del contador es 0.
Nota: La duración del tiempo de espera de wakelock para la secuencia de confirmación de solicitud sería menor que la duración del tiempo de espera actualmente utilizado porque la confirmación debe recibirse con bastante rapidez.
- Después de procesar la solicitud, el módem envía una interrupción al código del proveedor que adquiere wakelock y envía una respuesta a ril.cpp, que a su vez adquiere wakelock y envía una respuesta al lado de Java.
- Cuando la respuesta llega al lado de Java, se adquiere wakelock y se devuelve una respuesta a la persona que llama.
- Después de que todos los módulos procesan la respuesta, el reconocimiento se envía (a través del socket) de regreso a
ril.cpp
, que luego libera el wakelock adquirido en el paso 3.
Solución 2: El módem no mantiene el wakelock y la respuesta es rápida (solicitud y respuesta RIL síncrona). El comportamiento sincrónico versus asincrónico está codificado para un comando RIL específico y se decide llamada por llamada.
- La solicitud RIL se envía llamando a
acquireWakeLock()
en el lado de Java. - El código de proveedor no necesita adquirir wakelock y puede procesar la solicitud y responder rápidamente.
- Cuando el lado de Java recibe la respuesta, se llama a
decrementWakeLock()
, lo que disminuye el contador de wakelock y libera el wakelock si el valor del contador es 0.
Escenario: respuesta no solicitada de RIL
En este escenario, las respuestas no solicitadas de RIL tienen un indicador de tipo de wakelock que indica si es necesario adquirir un wakelock para la respuesta del proveedor. Si se establece la bandera, se establece un wakelock cronometrado y la respuesta se envía a través de un socket al lado de Java. Cuando el temporizador expira, se libera el wakelock. El wakelock cronometrado podría ser demasiado largo o demasiado corto para diferentes respuestas no solicitadas de RIL.
Solución: se envía una confirmación desde el código Java al lado nativo ( ril.cpp
) en lugar de mantener un wakelock cronometrado en el lado nativo mientras se envía una respuesta no solicitada.
Validando wakelocks rediseñados
Verifique que las llamadas RIL estén identificadas como sincrónicas o asincrónicas. Debido a que el consumo de energía de la batería puede depender del hardware/plataforma, los proveedores deben realizar algunas pruebas internas para determinar si el uso de la nueva semántica de wakelock para llamadas asincrónicas genera ahorros de energía de la batería.