Android 7.0 ha eseguito il refactoring del Radio Interface Layer (RIL) utilizzando un insieme di funzionalità per migliorare la funzionalità RIL. Per implementare queste funzionalità, che sono facoltative ma consigliate, è necessario apportare modifiche al codice del partner. Le modifiche al refactoring sono compatibili con le versioni precedenti, quindi le implementazioni precedenti delle funzionalità sottoposte a refactoring continuano a funzionare.
Il refactoring di RIL include i seguenti miglioramenti:
- Codici di errore RIL. Attiva codici di errore specifici
oltre al codice
GENERIC_FAILURE
esistente. Ciò aiuta a risolvere gli errori fornendo informazioni più specifiche sulla causa degli errori. - Controllo delle versioni RIL. Fornisce informazioni sulla versione più accurate e più facili da configurare.
- Comunicazione RIL tramite wakelock. Migliora le prestazioni della batteria del dispositivo.
Puoi implementare uno o tutti i miglioramenti sopra indicati. Per maggiori dettagli,
consulta i commenti al codice sul controllo delle versioni RIL in
https://android.googlesource.com/platform/hardware/ril/+/android16-release/include/telephony/ril.h
.
Implementare codici di errore RIL avanzati
Quasi tutte le chiamate di richiesta RIL possono restituire il codice di errore GENERIC_FAILURE
in risposta a un errore. Si tratta di un problema con tutte le risposte
sollecitate restituite dagli OEM, che può rendere difficile il debug di un problema
dal report sui bug se lo stesso codice di errore GENERIC_FAILURE
viene
restituito dalle chiamate RIL per motivi diversi. Potrebbe essere necessario molto tempo
prima che i fornitori identifichino la parte del codice che potrebbe aver restituito un
codice GENERIC_FAILURE
.
In Android 7.x e versioni successive, gli OEM possono restituire un valore di codice di errore distinto
associato a ogni errore diverso attualmente classificato come
GENERIC_FAILURE
. Gli OEM che non vogliono rivelare pubblicamente i propri
codici di errore personalizzati possono restituire gli errori come un insieme distinto di numeri interi (ad esempio da 1 a
x) mappati come OEM_ERROR_1
a OEM_ERROR_X
. I fornitori
devono assicurarsi che ogni codice di errore mascherato restituito corrisponda a un motivo di errore univoco
nel codice. L'utilizzo di codici di errore specifici può accelerare il debug di RIL ogni volta che
vengono restituiti errori generici dall'OEM, in quanto spesso è necessario troppo tempo per
identificare la causa esatta di un codice di errore GENERIC_FAILURE
(e
a volte è impossibile scoprirlo).
Inoltre, ril.h
aggiunge altri codici di errore per gli enum
RIL_LastCallFailCause
e RIL_DataCallFailCause
, in modo che
il codice del fornitore possa evitare di restituire errori generici come
CALL_FAIL_ERROR_UNSPECIFIED
e
PDP_FAIL_ERROR_UNSPECIFIED
.
Convalida dei codici di errore RIL avanzati
Dopo aver aggiunto nuovi codici di errore per sostituire il codice GENERIC_FAILURE
, verifica che i nuovi codici di errore vengano restituiti dalla chiamata RIL anziché
da GENERIC_FAILURE
.
Implementare il controllo delle versioni RIL avanzato
Il controllo delle versioni RIL nelle versioni precedenti di Android era problematico: la versione stessa era imprecisa, il meccanismo per segnalare una versione RIL non era chiaro (alcuni fornitori segnalavano una versione errata) e la soluzione alternativa per stimare la versione era soggetta a imprecisioni.
In Android 7.x e versioni successive, ril.h
documenta tutti i valori della versione RIL, descrive la versione RIL corrispondente ed elenca tutte le modifiche per quella versione. Quando apportano modifiche corrispondenti a una versione RIL, i fornitori devono
aggiornare la propria versione nel codice e restituirla in
RIL_REGISTER
.
Convalida il controllo delle versioni RIL avanzato
Verifica che la versione RIL corrispondente al codice RIL venga restituita
durante RIL_REGISTER
(anziché RIL_VERSION
definito in ril.h
).
Implementa la comunicazione RIL utilizzando i wakelock
I wakelock temporizzati vengono utilizzati nella comunicazione RIL in modo impreciso, il che influisce negativamente sulle prestazioni della batteria. In Android 7.x e versioni successive, puoi migliorare le prestazioni classificando le richieste RIL e aggiornando il codice per gestire i wakelock in modo diverso per i diversi tipi di richieste.
Classificare le richieste RIL
Le richieste RIL possono essere sollecitate o non sollecitate. I fornitori devono classificare ulteriormente le richieste sollecitate come una delle seguenti:
- sincrono. Richieste che non richiedono molto tempo per
rispondere. Ad esempio,
RIL_REQUEST_GET_SIM_STATUS
. - asincrono. Richieste che richiedono molto tempo per
ricevere una risposta. Ad esempio,
RIL_REQUEST_QUERY_AVAILABLE_NETWORKS
.
Le richieste RIL asincrone sollecitate possono richiedere molto tempo. Dopo aver ricevuto un ACK dal codice del fornitore, RIL Java rilascia il wakelock, il che potrebbe far passare il processore dell'app dallo stato di inattività a quello di sospensione. Quando la risposta è disponibile dal codice del fornitore, RIL Java (il processore dell'app) riacquisisce il wakelock, elabora la risposta e torna in modalità inattiva. Questo passaggio dallo stato di inattività alla sospensione e di nuovo all'inattività può consumare molta energia.
Se il tempo di risposta non è sufficiente, mantenere il wakelock e rimanere in idle per tutto il tempo necessario per rispondere può essere più efficiente dal punto di vista energetico rispetto all'entrare in stato di sospensione rilasciando il wakelock e riattivandosi all'arrivo della risposta. I fornitori devono utilizzare misurazioni del consumo energetico specifiche della piattaforma per determinare il valore di soglia del tempo T quando l'energia consumata rimanendo inattiva per l'intero periodo di tempo T è maggiore dell'energia consumata passando dallo stato di inattività alla sospensione e di nuovo all'inattività nello stesso periodo di tempo T. Quando è noto il tempo T, i comandi RIL che richiedono più tempo T possono essere classificati come asincroni e i comandi rimanenti come sincroni.
Scenari di comunicazione RIL
I seguenti diagrammi illustrano scenari comuni di comunicazione RIL e forniscono soluzioni per modificare il codice in modo da gestire le richieste RIL sollecitate e non sollecitate.
Nota:per i dettagli di implementazione delle funzioni
utilizzate nei seguenti diagrammi, consulta i metodi acquireWakeLock()
,
decrementWakeLock()
e clearWakeLock(
in
ril.cpp
.
Scenario: richiesta RIL e risposta asincrona sollecitata
In questo scenario, se la risposta richiesta dall'intent integrato
richiede molto tempo (ad es. una risposta a
RIL_REQUEST_GET_AVAILABLE_NETWORKS
), il wakelock viene mantenuto
a lungo lato processore dell'app. I problemi con il modem possono anche comportare
una lunga attesa.
Soluzione 1: il modem mantiene il wakelock per la richiesta RIL e la risposta asincrona.
- La richiesta RIL viene inviata e il modem acquisisce il wakelock per elaborarla.
- Il modem invia un riconoscimento che fa sì che la parte Java decrementi
il contatore di riattivazione e lo rilasci quando il valore del contatore è 0.
Nota: la durata del timeout di wakelock per la sequenza richiesta-ack sarà inferiore a quella attualmente utilizzata perché l'ack deve essere ricevuto abbastanza rapidamente.
- Dopo aver elaborato la richiesta, il modem invia un interrupt al codice fornitore che acquisisce il wakelock e invia una risposta a ril.cpp, che a sua volta acquisisce il wakelock e invia una risposta al lato Java.
- Quando la risposta raggiunge il lato Java, viene acquisita la sospensione della riattivazione e una risposta viene restituita al chiamante.
- Dopo che la risposta è stata elaborata da tutti i moduli, viene inviato (tramite socket) un riconoscimento a
ril.cpp
, che rilascia il wakelock acquisito nel passaggio 3.
Soluzione 2: il modem non mantiene il wakelock e la risposta è rapida (richiesta e risposta RIL sincrone). Il comportamento sincrono e asincrono è hardcoded per un comando RIL specifico e viene deciso in base alle chiamate.
- La richiesta RIL viene inviata chiamando
acquireWakeLock()
sul lato Java. - Il codice fornitore non deve acquisire il wakelock e può elaborare la richiesta e rispondere rapidamente.
- Quando la risposta viene ricevuta dal lato Java,
viene chiamato
decrementWakeLock()
, che decrementa il contatore di wakelock e rilascia il wakelock se il valore del contatore è 0.
Scenario: RIL unsolicited response
In questo scenario, le risposte non richieste RIL hanno un flag di tipo wakelock in che indica se è necessario acquisire un wakelock per la risposta del fornitore. Se il flag è impostato, viene impostato un wakelock temporizzato e la risposta viene inviata tramite un socket al lato Java. Quando il timer scade, il wakelock viene rilasciato. Il wakelock temporizzato potrebbe essere troppo lungo o troppo breve per le diverse risposte RIL non richieste.
Soluzione:viene inviato un riconoscimento dal codice Java al lato nativo (ril.cpp
) anziché mantenere un wakelock temporizzato sul lato nativo durante l'invio di una risposta non richiesta.
Convalidare i wakelock riprogettati
Verifica che le chiamate RIL siano identificate come sincrone o asincrone. Poiché il consumo di energia della batteria può dipendere dall'hardware/dalla piattaforma, i fornitori devono eseguire alcuni test interni per scoprire se l'utilizzo della nuova semantica di wakelock per le chiamate asincrone comporta un risparmio di energia della batteria.