ARTE TI

No Android 8.0 e versões posteriores, a ART Tooling Interface (ART TI) expõe determinados aspectos internos do tempo de execução e permite que criadores de perfil e depuradores influenciem o comportamento dos aplicativos em tempo de execução. Isso pode ser usado para implementar ferramentas de desempenho de última geração fornecidas para implementar agentes nativos em outras plataformas.

Os internos do tempo de execução são expostos a agentes que foram carregados no processo de tempo de execução. Eles se comunicam com o ART por meio de chamadas diretas e retornos de chamada. O tempo de execução oferece suporte a vários agentes para que diferentes preocupações de criação de perfil ortogonal possam ser separadas. Os agentes podem ser fornecidos no início do tempo de execução (quando dalvikvm ou app_process são invocados) ou anexados a um processo já em execução.

Como a capacidade de instrumentar e modificar o comportamento do aplicativo e do tempo de execução é muito poderosa, duas medidas de segurança foram integradas ao ART TI:

  • Primeiro, o código que expõe a interface do agente, JVMTI, é implementado como um plugin de tempo de execução, não como um componente central do tempo de execução. O carregamento do plug-in pode ser restrito, para que os agentes possam ser impedidos de encontrar qualquer um dos pontos da interface.
  • Em segundo lugar, tanto a classe ActivityManager quanto o processo de tempo de execução permitem apenas que os agentes se conectem a aplicativos depuráveis. Os aplicativos depuráveis ​​foram aprovados por seus desenvolvedores para serem analisados ​​e instrumentados e não são distribuídos aos usuários finais. A Google Play Store não permite a distribuição de aplicativos depuráveis. Isso garante que aplicativos normais (incluindo componentes principais) não possam ser instrumentados ou manipulados.

Projeto

O fluxo geral e a interconexão em um aplicativo instrumentado são mostrados na Figura 1 .

Flow and interconnection in an instrumented app
Figura 1. Fluxo e interconexão de um app instrumentado

O plugin ART libopenjdkjvmti expõe o ART TI, que foi projetado para acomodar as necessidades e restrições da plataforma:

  • A redefinição de classe é baseada em arquivos Dex , contendo apenas uma única definição de classe, em vez de arquivos de classe.
  • As APIs da linguagem Java para instrumentação e redefinição não são expostas.

O ART TI também oferece suporte a criadores de perfil do Android Studio.

Carregar ou anexar um agente

Para anexar um agente na inicialização do tempo de execução, use este comando para carregar o plug-in JVMTI e o agente fornecido:

dalvikvm -Xplugin:libopenjdkjvmti.so -agentpath:/path/to/agent/libagent.so …

Não há medidas de segurança em vigor quando um agente é carregado na inicialização do tempo de execução, portanto, lembre-se de que um tempo de execução iniciado manualmente permite modificação completa sem medidas de segurança. (Isso permite testes de ART.)

Nota: Isto não se aplica a aplicativos normais (incluindo o servidor do sistema) em um dispositivo. Os aplicativos são bifurcados de um zigoto já em execução, e um processo zigoto não tem permissão para carregar agentes.

Para anexar um agente a um aplicativo que já está em execução, use este comando:

adb shell cmd activity attach-agent [process]
/path/to/agent/libagent.so[=agent-options]

Se o plug-in JVMTI ainda não tiver sido carregado, anexar um agente carrega o plug-in e a biblioteca do agente.

Um agente só pode ser anexado a um aplicativo em execução marcado como depurável (parte do manifesto do aplicativo, com o atributo android:debuggable definido como true no nó do aplicativo). Tanto a classe ActivityManager quanto o ART realizam verificações antes de permitir que um agente seja anexado. A classe ActivityManager verifica as informações atuais do aplicativo (derivadas dos dados da classe PackageManager ) para o status depurável e o tempo de execução verifica seu status atual, que foi definido quando o aplicativo foi iniciado.

Locais dos agentes

O tempo de execução precisa carregar agentes no processo atual, para que o agente possa vincular-se diretamente e se comunicar com ele. A própria ART é agnóstica quanto ao local específico de origem do agente. A string é usada para uma chamada dlopen . As permissões do sistema de arquivos e as políticas do SELinux restringem o carregamento real.

Para entregar agentes que podem ser executados por um aplicativo depurável, faça o seguinte:

  • Incorpore o agente no diretório da biblioteca do APK do aplicativo.
  • Use run-as para copiar o agente no diretório de dados do aplicativo.

APIs

O método a seguir foi adicionado a android.os.Debug .

/**
     * Attach a library as a jvmti agent to the current runtime, with the given classloader
     * determining the library search path.
     * Note: agents may only be attached to debuggable apps. Otherwise, this function will
     * throw a SecurityException.
     *
     * @param library the library containing the agent.
     * @param options the options passed to the agent.
     * @param classLoader the classloader determining the library search path.
     *
     * @throws IOException if the agent could not be attached.
     * @throws a SecurityException if the app is not debuggable.
     */
    public static void attachJvmtiAgent(@NonNull String library, @Nullable String options,
            @Nullable ClassLoader classLoader) throws IOException {

Outras APIs Android

O comando attachment-agent é visível publicamente. Este comando anexa um agente JVMTI a um processo em execução:

adb shell 'am attach-agent com.example.android.displayingbitmaps
\'/data/data/com.example.android.displayingbitmaps/code_cache/libfieldnulls.so=Ljava/lang/Class;.name:Ljava/lang/String;\''

Os comandos am start -P e am start-profiler/stop-profiler são semelhantes ao comando attachment-agent.

JVMTI

Este recurso expõe a API JVMTI aos agentes (código nativo). Os recursos importantes incluem:

  • Redefinindo uma classe.
  • Rastreamento de alocação de objetos e coleta de lixo.
  • Iterando sobre todos os objetos em um heap, seguindo a árvore de referência de objetos.
  • Inspecionando pilhas de chamadas Java.
  • Suspendendo (e retomando) todos os threads.

Diferentes recursos podem estar disponíveis em diferentes versões do Android.

Compatibilidade

Este recurso precisa de suporte de tempo de execução principal, disponível apenas no Android 8.0 e superior. Os fabricantes de dispositivos não precisam fazer alterações para implementar esse recurso. Faz parte da AOSP.

Validação

O CTS testa o seguinte no Android 8 e superior:

  • Testa que os agentes se conectam a aplicativos depuráveis ​​e não conseguem se conectar a aplicativos não depuráveis.
  • Testa todas as APIs JVMTI implementadas
  • Testa se a interface binária para agentes é estável

Testes adicionais foram adicionados ao Android 9 e versões posteriores e estão incluídos nos testes CTS dessas versões.