O Android 7.0 refatorou a camada de interface de rádio (RIL, na sigla em inglês) usando um conjunto de recursos para melhorar a funcionalidade da RIL. É necessário fazer mudanças no código do parceiro para implementar esses recursos, que são opcionais, mas recomendados. As mudanças de refatoração são compatíveis com versões anteriores, então as implementações anteriores dos recursos refatorados continuam funcionando.
A refatoração da RIL inclui as seguintes melhorias:
- Códigos de erro da RIL. Ativa códigos de erro específicos
além do código
GENERIC_FAILURE
atual. Isso ajuda na solução de problemas de erros, fornecendo informações mais específicas sobre a causa deles. - Controle de versões da RIL. Fornece informações de versão mais precisas e fáceis de configurar.
- Comunicação RIL usando wakelocks. Melhora o desempenho da bateria do dispositivo.
Você pode implementar algumas ou todas as melhorias acima. Para mais detalhes, consulte os comentários de código sobre o controle de versões da RIL em https://android.googlesource.com/platform/hardware/ril/+/android16-release/include/telephony/ril.h
.
Implementar códigos de erro RIL aprimorados
Quase todas as chamadas de solicitação da RIL podem retornar o código de erro GENERIC_FAILURE
em resposta a um erro. Esse é um problema com todas as respostas solicitadas retornadas pelos OEMs, o que pode dificultar a depuração de um problema no relatório de bug se o mesmo código de erro GENERIC_FAILURE
for retornado por chamadas RIL por motivos diferentes. Pode levar muito tempo para os fornecedores identificarem qual parte do código poderia ter retornado um código GENERIC_FAILURE
.
No Android 7.x e versões mais recentes, os OEMs podem retornar um valor de código de erro distinto
associado a cada erro diferente que atualmente é categorizado como
GENERIC_FAILURE
. Os OEMs que não quiserem revelar publicamente os códigos de erro personalizados podem retornar erros como um conjunto distinto de números inteiros (como 1 a x) mapeados como OEM_ERROR_1
para OEM_ERROR_X
. Os fornecedores
precisam garantir que cada código de erro mascarado retornado seja mapeado para um motivo de erro exclusivo
no código. Usar códigos de erro específicos pode acelerar a depuração da RIL sempre que
erros genéricos são retornados pelo OEM, já que muitas vezes leva muito tempo para
identificar a causa exata de um código de erro GENERIC_FAILURE
(e
às vezes é impossível descobrir).
Além disso, ril.h
adiciona mais códigos de erro para as enumerações
RIL_LastCallFailCause
e RIL_DataCallFailCause
para que
o código do fornecedor evite retornar erros genéricos, como
CALL_FAIL_ERROR_UNSPECIFIED
e
PDP_FAIL_ERROR_UNSPECIFIED
.
Validar códigos de erro aprimorados da RIL
Depois de adicionar novos códigos de erro para substituir o código GENERIC_FAILURE
, verifique se os novos códigos de erro são retornados pela chamada da RIL em vez
de GENERIC_FAILURE
.
Implementar o controle de versões avançado da RIL
O controle de versões da RIL em versões mais antigas do Android era problemático: a versão em si era imprecisa, o mecanismo para informar uma versão da RIL não era claro (fazendo com que alguns fornecedores informassem uma versão incorreta), e a solução alternativa para estimar a versão era propensa a imprecisões.
No Android 7.x e versões mais recentes, o ril.h
documenta todos os valores da versão da RIL,
descreve a versão correspondente e lista todas as mudanças dessa
versão. Ao fazer mudanças que correspondem a uma versão da RIL, os fornecedores precisam
atualizar a versão no código e retornar essa versão em
RIL_REGISTER
.
Validar o controle de versões avançado da RIL
Verifique se a versão da RIL correspondente ao seu código da RIL é retornada
durante RIL_REGISTER
(em vez do RIL_VERSION
definido em ril.h
).
Implementar a comunicação RIL usando wakelocks
Os wakelocks temporizados são usados na comunicação RIL de maneira imprecisa, o que afeta negativamente o desempenho da bateria. No Android 7.x e versões mais recentes, é possível melhorar o desempenho classificando solicitações de RIL e atualizando o código para processar wakelocks de maneira diferente para diferentes tipos de solicitação.
Classificar solicitações de RIL
As solicitações de RIL podem ser solicitadas ou não. Os fornecedores também precisam classificar os pedidos solicitados como um dos seguintes:
- síncrona. Solicitações que não levam muito tempo para serem respondidas. Por exemplo,
RIL_REQUEST_GET_SIM_STATUS
. - assíncrono. Solicitações que levam muito tempo para
responder. Por exemplo,
RIL_REQUEST_QUERY_AVAILABLE_NETWORKS
.
As solicitações assíncronas de RIL podem levar muito tempo. Depois de receber um ACK do código do fornecedor, o RIL Java libera o wakelock, o que pode fazer com que o processador de apps passe do estado ocioso para o suspenso. Quando a resposta está disponível no código do fornecedor, o RIL Java (o processador do app) adquire novamente o wakelock, processa a resposta e volta ao estado inativo. Essa transição do estado inativo para suspenso e de volta para inativo pode consumir muita energia.
Se o tempo de resposta não for longo o suficiente, manter o wakelock e ficar ocioso durante todo o tempo necessário para responder pode ser mais eficiente em termos de energia do que entrar em estado de suspensão liberando o wakelock e ativando quando a resposta chegar. Os fornecedores precisam usar medições de energia específicas da plataforma para determinar o valor de limite de tempo T quando a energia consumida ao ficar ocioso durante todo o tempo T é maior do que a energia consumida ao passar do estado ocioso para o suspenso e para o ocioso no mesmo tempo T. Quando o tempo T é conhecido, os comandos da RIL que levam mais tempo que T podem ser classificados como assíncronos, e os comandos restantes, como síncronos.
Cenários de comunicação da RIL
Os diagramas a seguir ilustram cenários comuns de comunicação da RIL e fornecem soluções para modificar o código e processar solicitações da RIL solicitadas e não solicitadas.
Observação:para detalhes de implementação sobre funções usadas nos diagramas a seguir, consulte os métodos acquireWakeLock()
, decrementWakeLock()
e clearWakeLock(
em ril.cpp
.
Cenário: solicitação de RIL e resposta assíncrona solicitada
Nesse cenário, se a resposta solicitada pela RIL levar um tempo considerável (por exemplo, uma resposta a RIL_REQUEST_GET_AVAILABLE_NETWORKS
), o wakelock será mantido por um longo período no lado do processador do app. Problemas no modem também podem causar uma longa espera.
Solução 1:o modem mantém o wakelock para a solicitação da RIL e a resposta assíncrona.
- A solicitação de RIL é enviada, e o modem adquire um wakelock para processar essa solicitação.
- O modem envia um reconhecimento que faz com que o lado Java diminua
o contador de wakelock e o libere quando o valor do contador for 0.
Observação:a duração do tempo limite de wakelock para a sequência de solicitação-confirmação seria menor do que a duração do tempo limite usada atualmente porque a confirmação precisa ser recebida rapidamente.
- Depois de processar a solicitação, o modem envia uma interrupção ao código do fornecedor que adquire o wakelock e envia uma resposta para ril.cpp, que, por sua vez, adquire o wakelock e envia uma resposta para o lado Java.
- Quando a resposta chega ao lado Java, o wakelock é adquirido e uma resposta é retornada ao autor da chamada.
- Depois que a resposta é processada por todos os módulos, o reconhecimento é
enviado (via soquete) de volta para
ril.cpp
, que libera o wakelock adquirido na etapa 3.
Solução 2:o modem não mantém o wakelock, e a resposta é rápida (solicitação e resposta síncronas da RIL). O comportamento síncrono x assíncrono é codificado para um comando RIL específico e decidido em uma base de chamada por chamada.
- A solicitação de RIL é enviada chamando
acquireWakeLock()
no lado Java. - O código do fornecedor não precisa adquirir o wakelock e pode processar a solicitação e responder rapidamente.
- Quando a resposta é recebida pelo lado Java,
decrementWakeLock()
é chamado, o que diminui o contador de wakelock e libera o wakelock se o valor do contador for 0.
Cenário: resposta não solicitada da RIL
Nesse cenário, as respostas não solicitadas da RIL têm uma flag de tipo wakelock no que indica se um wakelock precisa ser adquirido para a resposta do fornecedor. Se a flag estiver definida, um wakelock temporizado será definido e a resposta será enviada por um socket para o lado Java. Quando o timer expira, o wakelock é liberado. O wakelock cronometrado pode ser muito longo ou muito curto para diferentes respostas não solicitadas da RIL.
Solução:um reconhecimento é enviado do código Java para o lado nativo (ril.cpp
) em vez de manter um wakelock cronometrado no lado nativo ao enviar uma resposta não solicitada.
Validar wakelocks redesenhados
Verifique se as chamadas da RIL são identificadas como síncronas ou assíncronas. Como o consumo de energia da bateria pode depender do hardware/plataforma, os fornecedores precisam fazer alguns testes internos para descobrir se o uso da nova semântica de wakelock para chamadas assíncronas leva a uma economia de energia da bateria.