Orientação sobre mudanças no comportamento do MessageQueue

A partir do Android 17, os apps destinados ao Android 17 (nível 37 da API) ou mais recente recebem uma nova implementação sem bloqueio de android.os.MessageQueue. A nova implementação melhora o desempenho e reduz os frames perdidos, mas pode causar falhas em clientes que refletem em campos e métodos particulares de MessageQueue.

O Android 17 apresenta uma reformulação significativa no funcionamento de Looper e Handler, reescrevendo a classe MessageQueue. Desde a primeira versão do sistema operacional Android, o MessageQueue dependia de um único bloqueio para gerenciar a fila de tarefas da linha de execução principal. Esse design geralmente causava contenção de bloqueio. A linha de execução principal podia ser bloqueada por uma linha de execução em segundo plano, levando a frames perdidos e instabilidade na interface.

Mitigar o impacto

Seu app poderá ser afetado por essa mudança se ele ou as dependências dele usarem a reflexão de tempo de execução para analisar o MessageQueue. Evite usar a reflexão do ambiente de execução para inspecionar MessageQueue.

Com a implementação legada, os desenvolvedores às vezes acessavam campos particulares, como MessageQueue.mMessages, para inspecionar mensagens pendentes. Com a nova implementação sem bloqueio, as estruturas de dados internas mudaram completamente. Para manter a compatibilidade binária, o Android 17 mantém o campo mMessages, mas, na nova implementação, esse campo é sempre nulo, independente de haver mensagens na fila.

Além disso, se você usa algumas bibliotecas de teste conhecidas, precisa atualizá-las para que sejam compatíveis com a nova implementação de MessageQueue.

Espresso

O Espresso é usado com frequência para testes de interface. A biblioteca Espresso precisa saber quando a linha de execução principal está inativa para declarar corretamente o estado da IU. As versões anteriores do Espresso dependiam de técnicas de reflexão que não são mais compatíveis com a MessageQueue sem bloqueio.

Ação

Atualize para o Espresso 3.7.0 ou mais recente. Essa versão usa a API TestLooperManager, principalmente as novas APIs introduzidas pelo Android 16, para interagir com segurança com o Looper sem depender de detalhes de implementação interna.

Robolectric

Da mesma forma, se você executar testes de unidade usando o Robolectric, poderá encontrar problemas se os testes dependerem do modo Looper legado.

Ação

Atualize para o Robolectric 4.17 ou mais recente. Se você estiver usando @LooperMode(LEGACY), será necessário migrar seus testes para o novo @LooperMode(PAUSED). Consulte o guia de migração do Robolectric (link em inglês) para mais informações.

Testar o comportamento

Para testar o app com a mudança de comportamento no Android 17 sem atualizar o targetSDK, execute o seguinte comando:

adb am compat enable USE_NEW_MESSAGEQUEUE <your-package-name>

Esse comando ativa o MessageQueue sem bloqueio no app, se ele for um build depurável.

Se o app for direcionado ao Android 17 (nível 37 da API), o novo comportamento será ativado por padrão. Se você notar um comportamento inesperado ou falhas após segmentar esse nível da API, desative temporariamente a nova implementação para verificar se MessageQueue é a causa.

É possível alternar a mudança usando uma das duas opções:

  1. O menu Mudanças na compatibilidade do app em Opções do desenvolvedor.

  2. Execute o seguinte comando do ADB:

    adb am compat disable USE_NEW_MESSAGEQUEUE <your-package-name>
    

Isso reverte o app para a implementação legada baseada em bloqueio, permitindo que você identifique se o problema foi resultado de uma mudança no comportamento da fila de mensagens.