Estudos de caso

Como a WHOOP reduziu as sessões de wake lock parcial em excesso em mais de 90%

Leitura de 4 min

Ao criar um app Android para um wearable, o trabalho de verdade começa quando a tela é desligada. O WHOOP ajuda os membros a entender como o corpo responde ao treino, à recuperação, ao sono e ao estresse. Para os muitos membros do WHOOP no Android, a sincronização e a conectividade confiáveis em segundo plano são o que tornam esses insights possíveis.

No início deste ano, o Google Play lançou uma nova métrica no Android vitals: wake locks parciais excessivos. Essa métrica mede a porcentagem de sessões do usuário em que o uso cumulativo de wake locks não isentos excede 2 horas em um período de 24 horas. O objetivo dessa métrica é ajudar você a identificar e resolver possíveis fontes de consumo de bateria, o que é crucial para oferecer uma ótima experiência do usuário.

A partir de 1º de março de 2026, os apps que não atenderem ao limite de qualidade poderão ser excluídos das plataformas de descoberta do Google Play. Um aviso também pode ser colocado na página "Detalhes do app" na Google Play Store, indicando que o app pode usar mais bateria do que o esperado.

De acordo com Mayank Saini, engenheiro sênior de Android na WHOOP, isso "deu à equipe a oportunidade de aumentar a eficiência do Android", depois que o Android vitals sinalizou que a porcentagem de wake locks parciais em excesso do app era de 15%, o que excedia o limite recomendado de 5%.

mayank.png

A equipe interpretou a métrica do Android vitals como um sinal claro de que o trabalho em segundo plano estava mantendo a CPU ativa por mais tempo do que o necessário. Resolver isso permitiria que eles continuassem a oferecer uma ótima experiência ao usuário, ao mesmo tempo em que diminuiriam o tempo de segundo plano desperdiçado e manteriam a conectividade e a sincronização do Bluetooth confiáveis e oportunas.

Identificar o problema

Para descobrir por onde começar, a equipe primeiro recorreu ao Android vitals para entender melhor quais wake locks estavam afetando a métrica. Ao consultar o painel de wake locks parciais excessivos do Android vitals, eles identificaram que o maior contribuinte para os wake locks parciais excessivos era um dos workers do WorkManager (identificado no painel como androidx.work.impl.background.systemjob.SystemJobService). Para oferecer suporte à "experiência sempre ativa" do WHOOP, o app usa o WorkManager para tarefas em segundo plano, como sincronização periódica e envio de atualizações recorrentes para o wearable. 

Embora a equipe soubesse que o WorkManager adquire um wake lock ao executar tarefas em segundo plano, ela não tinha visibilidade de como todo o trabalho em segundo plano (além do WorkManager) era distribuído até a introdução da métrica de wake locks parciais excessivos no Android vitals.

Com o painel identificando o WorkManager como o principal responsável, a equipe conseguiu concentrar os esforços para identificar qual dos workers estava contribuindo mais e trabalhar para resolver o problema.

Usar métricas e dados internos para identificar melhor a causa

A WHOOP já tinha uma infraestrutura interna configurada para monitorar as métricas do WorkManager. Eles monitoram periodicamente:

  1. Tempo de execução médio: por quanto tempo o worker é executado?
  2. Tempo limite: com que frequência o worker atinge o tempo limite em vez de concluir?
  3. Novas tentativas: com que frequência o worker tenta novamente se o trabalho expirar ou falhar?
  4. Cancelamentos: com que frequência o trabalho foi cancelado?

Rastrear mais do que apenas os sucessos e as falhas do worker dá à equipe visibilidade sobre a eficiência do trabalho.

As métricas internas sinalizaram um tempo de execução médio alto para alguns workers, o que permitiu restringir ainda mais a investigação. 

Além das métricas internas, a equipe também usou o Inspetor de tarefas em segundo plano do Android Studio para inspecionar e depurar os workers de interesse, com foco específico nos wake locks associados, para se alinhar à métrica sinalizada no Android vitals.

Investigação: como distinguir as variantes de worker

O WHOOP usa o agendamento único e periódico para alguns workers. Isso permite que o app reutilize a mesma lógica do Worker para tarefas idênticas com os mesmos critérios de sucesso, diferindo apenas no tempo.

Usando as métricas internas, foi possível restringir a pesquisa a um worker específico, mas não foi possível saber se o bug ocorreu quando o worker era único, periódico ou ambos. Por isso, eles lançaram uma atualização para usar o método setTraceTag do WorkManager para distinguir entre as variantes únicas e periódicas do mesmo Worker.

Esse detalhe extra permitiria identificar definitivamente qual variante do Worker (periódica ou única) estava contribuindo mais para as sessões com wake locks parciais excessivos. No entanto, a equipe se surpreendeu quando os dados revelaram que nenhuma das variantes parecia estar contribuindo mais do que a outra.

Manmeet Tuteja, engenheiro de Android II na WHOOP, disse: "Essa divisão também nos ajudou a confirmar que o problema estava acontecendo em ambas as variantes, o que nos levou a descartar a configuração de programação e a focar em um problema de lógica de negócios compartilhada na implementação do worker".

manmeet.png

Análise detalhada do comportamento do worker e correção da causa raiz

Sabendo que precisavam analisar a lógica dentro do worker,  a equipe reexaminou o comportamento dos workers que foram sinalizados durante a investigação. Especificamente, eles estavam procurando instâncias em que o trabalho poderia estar travado e não sendo concluído.

Tudo isso culminou na descoberta da causa raiz dos wake locks excessivos:

Um CoroutineWorker projetado para aguardar uma conexão com o sensor WHOOP antes de continuar. 

Se o trabalho começou sem nenhum sensor conectado, whoopSensorFlow, que indica se o sensor está conectado, era null. O SensorWorker não tratou isso como uma condição de saída antecipada e continuou em execução, aguardando indefinidamente por uma conexão. Como resultado, o WorkManager manteve um wake lock parcial até o tempo limite do trabalho, o que levou a um alto uso de wake lock em segundo plano e ao reagendamento frequente e indesejado do SensorWorker.

Para resolver isso, a equipe do WHOOP atualizou a lógica do worker para verificar o status da conexão antes de tentar executar a lógica de negócios principal.

Se o sensor não estiver disponível, o worker será encerrado, evitando um cenário de tempo limite e liberando o wake lock. O snippet de código abaixo mostra a solução:

class SensorWorker(appContext: Context, params: WorkerParameters): CoroutineWorker(appContext, params) {
   override suspend fun doWork(): Result {
      ...
      // Check the sensor state and perform work or return failure
       return whoopSensorFlow.replayCache
            .firstOrNull()
            ?.let { cachedData ->
                processSensorData(cachedData)
                Result.success()
            } ?: run {
                Result.failure()
            }
}

Como reduzir em 90% as sessões com wake locks parciais em excesso

Depois de lançar a correção, a equipe continuou monitorando o painel do Android vitals para confirmar o impacto das mudanças. 

Por fim, a WHOOP viu a porcentagem de wake locks parciais excessivos cair de 15% para menos de 1% apenas 30 dias depois de implementar as mudanças no Worker. 

partialWake.png

Como resultado das mudanças, a equipe observou menos instâncias de tempo limite de trabalho sem conclusão, o que resultou em tempos de execução médios mais baixos. 

O conselho da equipe do WHOOP para outros desenvolvedores que querem melhorar a eficiência do trabalho em segundo plano:

sarthak.png

Começar

Se você quiser reduzir os wake locks parciais em excesso do app ou melhorar a eficiência do worker, confira a métrica de wake locks parciais em excesso do app no Android vitals e consulte a documentação de wake locks para mais práticas recomendadas e estratégias de depuração. 

Escrito por:
Continue lendo