Wake locks parciais são um mecanismo da API PowerManager
que possibilita que os desenvolvedores mantenham a CPU em funcionamento após a tela de um dispositivo ser desativada,
seja devido ao tempo limite do sistema ou porque o usuário pressionou o botão liga/desliga. Seu
app recebe um wake lock parcial ao chamar
acquire()
com a
flag
PARTIAL_WAKE_LOCK
. Um wake lock parcial fica
travado se for retido por muito tempo enquanto o app está sendo executado em
segundo plano. Ou seja, quando nenhuma parte do app está visível para o usuário. Essa condição consome
a bateria do dispositivo porque impede que ele entre em estados de baixo consumo
de energia. Os wake locks parciais só devem ser usados quando for preciso e liberados assim
que não forem mais necessários.
Caso seu app tenha um wake lock parcial travado, você pode usar as orientações nesta página para diagnosticar e corrigir o problema.
Detectar o problema
Nem sempre você sabe que os wake locks parciais do seu app estão travados. Se você já publicou o app, o recurso Android vitals pode ajudar a identificar o problema.
Android vitals
O recurso Android vitals pode ajudar a melhorar a performance do app alertando você, pelo Play Console, quando o app apresentar wake locks parciais travados. O Android vitals informa que há wake locks parciais travados quando ocorre pelo menos um wake lock parcial com duração de uma hora em segundo plano, em uma sessão de bateria.
A definição de duração da bateria depende da versão da plataforma.
- No Android 10, a duração da bateria é a agregação de todos os relatórios de bateria recebidos em um determinado período de 24 horas. Um relatório de bateria se refere ao intervalo entre duas cargas, seja de menos de 20% a mais de 80% ou de qualquer nível de carga até 100%.
- No Android 11, a duração da bateria é de um período fixo de 24 horas.
A duração da bateria mostrada é uma estimativa com base em informações de todos os usuários medidos do app. Parar informações sobre como o Google Play coleta dados do Android vitals, consulte a documentação do Play Console.
Depois de identificar wake locks parciais travados em excesso no app, a próxima etapa é resolver o problema.
Corrigir o problema
Os wake locks foram introduzidos nas primeiras versões da plataforma Android, mas, com o passar do tempo, muitos casos de uso que antes exigiam wake locks agora são mais bem atendidos por APIs mais recentes, como a WorkManager.
Esta seção contém dicas para corrigir wake locks, mas, a longo prazo, considere a possibilidade de migrar seu app para seguir as recomendações da seção de práticas recomendadas.
Identificar e corrigir lugares no código que adquirem um wake lock, como chamadas para
newWakeLock(int, String)
ou
WakefulBroadcastReceiver
das subclasses. Veja algumas dicas:
- Recomendamos que você inclua o nome do pacote, da classe ou do método no nome da tag do wake
lock para identificar facilmente o local no código-fonte
em que o wake lock foi criado. Confira mais algumas dicas:
- Não inclua informações de identificação pessoal (PII, na sigla em inglês) no nome,
como um endereço de e-mail. Caso contrário, o dispositivo vai registrar
_UNKNOWN
, em vez do nome do wake lock. - Não busque o nome da classe ou do método de forma programática, por exemplo, chamando
getName()
, porque o nome pode ser ofuscado pelo Proguard. Em vez disso, use uma string codificada. - Não adicione um contador ou identificadores exclusivos às tags de wake lock. O sistema não vai poder agregar wake locks criados pelo mesmo método, porque todos têm identificadores exclusivos.
- Não inclua informações de identificação pessoal (PII, na sigla em inglês) no nome,
como um endereço de e-mail. Caso contrário, o dispositivo vai registrar
Verifique se o código libera todos os wake locks que adquire. Isso é mais complicado do que garantir que todas as chamadas para
acquire()
tenham uma chamada correspondente pararelease()
. Confira um exemplo de wake lock que não foi liberado devido a uma exceção não capturada:Kotlin
@Throws(MyException::class) fun doSomethingAndRelease() { wakeLock.apply { acquire() doSomethingThatThrows() release() // does not run if an exception is thrown } }
Java
void doSomethingAndRelease() throws MyException { wakeLock.acquire(); doSomethingThatThrows(); wakeLock.release(); // does not run if an exception is thrown }
Veja a seguir uma versão correta do código:
Kotlin
@Throws(MyException::class) fun doSomethingAndRelease() { wakeLock.apply { try { acquire() doSomethingThatThrows() } finally { release() } } }
Java
void doSomethingAndRelease() throws MyException { try { wakeLock.acquire(); doSomethingThatThrows(); } finally { wakeLock.release(); } }
Não esqueça de liberar os wake locks assim que não forem mais necessários. Por exemplo, se você usa um wake lock para permitir que uma tarefa em segundo plano seja concluída, verifique se a liberação aconteça quando a tarefa é concluída. Se um wake lock for mantido por mais tempo do que o esperado sem ser liberado, isso pode significar que a tarefa em segundo plano está levando mais tempo do que o esperado.
Depois de corrigir o problema no código, verifique se o app libera os wake locks corretamente usando as ferramentas do Android abaixo:
dumpsys: uma ferramenta que fornece informações sobre o status dos serviços do sistema em um dispositivo. Para verificar o status do serviço de energia, que inclui uma lista de wake locks, execute
adb shell dumpsys power
.Battery Historian: uma ferramenta que analisa a saída de um relatório de bugs do Android em uma representação visual de eventos relacionados à energia.
Práticas recomendadas
Em geral, seu app precisa evitar wake locks parciais, porque é muito provável que eles consumam a bateria do usuário rapidamente. O Android fornece APIs alternativas para quase todos os casos de uso que antes precisavam de um wake lock parcial. Um caso de uso restante para wake locks parciais é garantir que um app de música continue sendo executado quando a tela estiver desligada. Se você estiver usando wake locks para executar tarefas, considere as alternativas descritas no guia de processamento em segundo plano.
Se você precisar usar wake locks parciais, siga estas recomendações:
- Não se esqueça de manter parte do seu app em primeiro plano. Por exemplo, se você precisar executar um serviço, inicie-o em primeiro plano. Isso indica visualmente para o usuário que seu app ainda está em execução.
- Confira se a lógica para adquirir e liberar wake locks é o mais simples possível. Quando sua lógica de wake lock está vinculada a máquinas de estado, tempos limite, pool de executores e/ou eventos de callback complexos, qualquer bug sutil nessa lógica pode fazer com que o wake lock seja mantido por mais tempo do que o esperado. Esses bugs são difíceis de diagnosticar e depurar.
Recomendados para você
- Observação: o texto do link aparece quando o JavaScript está desativado
- Frames congelados
- Executar comparativos na integração contínua
- Criar e medir perfis de referência sem a Macrobenchmark