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

A partir do Android 17, os apps destinados ao Android 17 ou versões mais recentes recebem uma nova implementação sem bloqueio de android.os.MessageQueue. A nova implementação melhora a performance e reduz os frames perdidos, mas pode causar falhas em clientes que refletem em campos e métodos particulares de MessageQueue.

O Android 17 introduz uma revisão significativa de como Looper e Handler funcionam, reescrevendo a classe MessageQueue subjacente. Desde o primeiro lançamento 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 disputa de bloqueio. A linha de execução principal podia ser bloqueada por uma linha de execução em segundo plano, o que levava a perda de frames e instabilidade na interface.

Reduzir o impacto

Seu app pode ser afetado por essa mudança se ele ou as dependências dele usarem reflexão de tempo de execução para espiar dentro de MessageQueue. Evite usar a reflexão de tempo 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, será necessário atualizar as bibliotecas para que sejam compatíveis com a nova implementação do 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 fazer asserções corretas no estado da UI. 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. Esta 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 internos.

Robolectric

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

Ação

Atualize para o Robolectric 4.17 ou mais recente. Se você estiver usando @LooperMode(LEGACY), migre seus testes para o novo @LooperMode(PAUSED). Consulte o guia de migração do Robolectric para mais informações.

Testar o comportamento

Você pode testar o app com a mudança de comportamento no Android 17 sem atualizar targetSDK executando o seguinte comando:

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

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

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

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

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

  2. Executando o seguinte comando 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.