Os processos de apps no Android não existem isoladamente. Os aplicativos geralmente dependem de serviços fornecidos por outros aplicativos ou pelo próprio sistema. Quando um processo se conecta a outro por uma vinculação de serviço, ele cria uma dependência que tem um impacto profundo na forma como o framework do Android gerencia a memória.
Estados de processo e pontuações de OOM
O framework do Android usa estados de processo para acompanhar a importância de cada processo em execução. Esses estados são usados pelo OomAdjuster para atribuir um valor de ajuste de pontuação de OOM (oom_score_adj), que varia de -1000 a 1000.
Um oom_score_adj menor significa que o processo é mais importante e tem menos probabilidade de ser encerrado pelo Low Memory Killer (LMK).
Estados de processo comuns
A tabela a seguir mostra alguns dos estados de processo mais comuns e os valores típicos de oom_score_adj. Para uma lista completa e atualizada, consulte android.app.ActivityManager e com.android.server.am.psc.Constants no código-fonte do Android.
| Estado do processo (abreviação) | Descrição | oom_score_adj típico |
|---|---|---|
| PER (persistente) | Processos do sistema que precisam ser executados sempre (por exemplo, telefonia). | -800 |
| TOP | O processo com que o usuário está interagindo no momento. | 0 |
| VIS (visível) | O processo tem uma atividade visível (por exemplo, atrás de uma caixa de diálogo translúcida). | 100 |
| PERC (perceptível) | Processo em segundo plano de que o usuário está ciente (por exemplo, reprodução de música). | 200 |
| FGS | Processo que hospeda um serviço em primeiro plano. | 0 a 200 (varia) |
| BTOP (vinculado ao topo) | Processo vinculado por um aplicativo TOP. | 100 |
| BFGS | Serviço em primeiro plano vinculado (normalmente vinculado ao sistema). | 0 |
| PREV (anterior) | O último processo em que o usuário estava antes do atual. | 700 |
| CACHED | Apps em segundo plano que podem ser encerrados com segurança. | 900 a 999 |
O impacto das vinculações de serviço
Quando um processo do cliente (por exemplo, um app no estado TOP) é vinculado a um serviço em um processo do servidor, o processo do servidor geralmente herda uma prioridade elevada. Isso garante que o serviço permaneça disponível enquanto o cliente precisar dele.

Como controlar a herança com flags BIND
A herança é o comportamento padrão ao usar Context.BIND_AUTO_CREATE.
No entanto, os desenvolvedores podem controlar como a vinculação afeta a importância do processo de destino usando várias flags em bindService().
Flags BIND principais para a pontuação de OOM
As flags a seguir são mais relevantes ao gerenciar a pressão de memória em todo o sistema:
BIND_AUTO_CREATE: a flag mais comum. Ela garante que o processo de serviço seja iniciado e mantido ativo enquanto a vinculação existir. Por padrão, ela também eleva a prioridade do processo do servidor para corresponder ao cliente.BIND_NOT_FOREGROUND: impede que o processo do serviço de destino seja elevado à prioridade de programação em primeiro plano (prioridade da CPU). No entanto, ainda permite que a prioridade de memória (oom_score_adj) seja elevada. Isso é útil para trabalhos em segundo plano que não devem competir com a interface do usuário por ciclos de CPU, mas ainda precisam ser protegidos contra o encerramento.BIND_WAIVE_PRIORITY: uma flag muito forte que instrui o sistema a não afetar a programação ou a prioridade de gerenciamento de memória do processo de destino. O processo de serviço será gerenciado como se fosse um processo em segundo plano normal na lista de LRU, tornando-o qualificado para o encerramento de OOM mesmo quando vinculado.BIND_ABOVE_CLIENT: indica que o serviço é mais importante do que o próprio app cliente. Quando o sistema precisar recuperar a memória, ele vai preferir encerrar o app cliente antes de encerrar o serviço vinculado. Essa flag é "mais forte" do queBIND_AUTO_CREATE, porque oferece uma camada extra de proteção para o serviço às custas do cliente.BIND_NOT_PERCEPTIBLE: diminui a importância do serviço de destino para abaixo doPERCEPTIBLEnível, permitindo que o sistema recupere a memória para abrir espaço para processos mais críticos perceptíveis pelo usuário.
Prática: observação dos efeitos de vinculação
Vamos usar o aplicativo MemoryLab para demonstrar como uma vinculação de um app TOP afeta o estado de um processo separado.
1. Iniciar o MemoryLab
O comando a seguir inicia o app. Depois que ele for aberto, verifique se o app permanece em primeiro plano (não pressione o botão Home nem troque de app ainda).
adb shell am start -n com.android.memorylab/.MainActivity
2. Identificar processos
Verifique os estados do processo antes da vinculação. O MemoryLab executa a interface principal em um processo e tem um RemoteService que é executado em um processo :remote.
adb shell dumpsys activity processes com.android.memorylab
Exemplo de snippet de saída:
Process OOM control (154 total, non-act at 7, non-svc at 7):
Proc #0: fg T/A/TOP LCMNFUATI t: 0 13470:com.android.memorylab/u0a417 (top-activity)
oom: max=1001 curRaw=0 setRaw=0 cur=0 set=0
state: cur=TOP set=TOP lastRss=0.00 lastCachedRss=0.00
Você verá o processo principal com.android.memorylab no estado TOP. O processo :remote ainda não foi iniciado.
3. Acionar a vinculação
Envie uma transmissão para o app para acionar a vinculação de serviço:
adb shell am broadcast -a com.android.memorylab.LEAK_BINDER
4. Observar o estado elevado
Verifique os estados do processo novamente:
adb shell dumpsys activity processes | grep -A 10 "com.android.memorylab"
Exemplo de snippet de saída:
Proc # 1: vis F/ /BTOP ---NFUATI t: 0 13560:com.android.memorylab:remote/u0a417 (service)
com.android.memorylab/.RemoteService<=Proc{13470:com.android.memorylab/u0a417}
oom: max=1001 curRaw=100 setRaw=100 cur=100 set=100
state: cur=BTOP set=BTOP lastRss=0.00 lastCachedRss=0.00
O processo :remote agora está em execução e no estado BTOP (vinculado ao topo) com um oom_score_adj de 100. Isso é significativamente mais protegido do que um serviço em segundo plano típico (que estaria em 500 ou mais). A notação
<=Proc{...} mostra qual processo é responsável por essa elevação de prioridade.
5. Enviar para segundo plano
Pressione o botão HOME no dispositivo. Verifique os estados novamente:
adb shell dumpsys activity processes | grep -A 10 "com.android.memorylab"
Exemplo de snippet de saída:
Proc # 2: prev b/ /LAST --------I t: 0 13560:com.android.memorylab:remote/u0a417 (service)
com.android.memorylab/.RemoteService<=Proc{13470:com.android.memorylab/u0a417}
oom: max=1001 curRaw=700 setRaw=700 cur=700 set=700
state: cur=LAST set=LAST lastRss=0.00 lastCachedRss=0.00
Proc # 1: prev b/ /LAST --------I t: 0 13470:com.android.memorylab/u0a417 (previous)
oom: max=1001 curRaw=700 setRaw=700 cur=700 set=700
state: cur=LAST set=LAST lastRss=209MB lastCachedRss=0.00
Agora, os dois processos mudaram para um estado de prioridade mais baixa (PREV / oom_score_adj 700), porque o processo do cliente não é mais TOP. (Observação:
LAST no despejo de estado se refere ao estado interno LAST_ACTIVITY, que
é mapeado para PREV em resumos de alto nível).
Análise com procstats
A ferramenta procstats oferece uma visualização histórica desses estados.
# View stats for MemoryLab over the last hour
adb shell dumpsys procstats --hours 1 com.android.memorylab
Exemplo de snippet de saída:
* com.android.memorylab / u0a417 / v37:
* Prc com.android.memorylab / u0a417 / v37:
TOTAL: 0.89% (0.00-0.00-0.00/0.00-0.00-0.00/210MB-210MB-210MB over 1)
Top: 0.89% (0.00-0.00-0.00/0.00-0.00-0.00/210MB-210MB-210MB over 1)
* Prc com.android.memorylab:remote / u0a417 / v37:
TOTAL: 0.19%
Bnd Top: 0.19%
Aqui, Bnd Top indica a porcentagem de tempo que o processo remoto passou vinculado por um aplicativo no estado TOP.
Como capturar e analisar vinculações com o Perfetto
Embora o dumpsys ofereça um snapshot, o Perfetto permite que você veja o momento exato em que uma vinculação ocorre e como a pontuação de OOM muda em tempo real.
1. Gravar um rastreamento
Use uma configuração que inclua linux.process_stats e a categoria am do atrace:
adb shell perfetto -c - --txt -o /data/misc/perfetto-traces/service_bindings.perfetto-trace <<EOF
buffers: { size_kb: 65536 }
data_sources: {
config {
name: "linux.process_stats"
process_stats_config { proc_stats_poll_ms: 100 }
}
}
data_sources: {
config {
name: "linux.ftrace"
ftrace_config { ftrace_events: "am/am_proc_bound" }
}
}
duration_ms: 15000
EOF
2. Consultar transições de pontuação de OOM
Usando o PerfettoSQL, é possível conferir como a pontuação de OOM do processo remoto mudou em relação ao processo da interface:
SELECT ts, p.name, value AS oom_score_adj
FROM counter c
JOIN process_counter_track t ON c.track_id = t.id
JOIN process p USING (upid)
WHERE p.name LIKE 'com.android.memorylab%'
AND t.name = 'oom_score_adj'
ORDER BY ts;
3. Identificar eventos de vinculação
Para saber exatamente quando uma dependência de vinculação foi estabelecida e qual processo a iniciou, use esta consulta:
SELECT
s.ts,
p.name AS process_name,
t.name AS thread_name,
s.name AS slice_name
FROM slice s
JOIN thread_track tt ON s.track_id = tt.id
JOIN thread t USING (utid)
JOIN process p USING (upid)
WHERE s.name LIKE 'bindService:{com.android.memorylab%';
Vinculações do sistema para o app
O próprio sistema Android geralmente se vincula a serviços em apps de terceiros para fornecer funcionalidades principais. Muitas vezes, o objetivo dessas vinculações é a redução da latência. Ao manter um processo ativo e na memória, o sistema evita a sobrecarga dispendiosa de uma "inicialização a frio" (carregar o APK, inicializar o ambiente de execução e criar o objeto do aplicativo) quando ocorre uma interação do usuário crítica. Outras vinculações existem para evitar inicializações a frio frequentes para apps que precisam processar fluxos de eventos em segundo plano.
Confira alguns exemplos reais que podem ser observados em um dispositivo típico:
VoiceInteractor
Os usuários esperam que um assistente digital seja incorporado ao sistema operacional do smartphone, que possa ser invocado instantaneamente com uma palavra-chave falada ou um gesto de entrada rápido e que a interação seja suave e perfeita.
Quando um acionador do assistente ocorre (como a palavra-chave "OK Google" em smartphones Google Pixel), o assistente digital precisa responder instantaneamente. Para garantir isso,
system_server mantém uma vinculação permanente ao serviço de interação por voz selecionado pelo usuário.

Se você verificar os estados do processo (por exemplo, usando dumpsys activity processes), poderá ver um processo como com.google.android.googlequicksearchbox:interactor no estado BFGS (serviço em primeiro plano vinculado), mantido ativo por uma vinculação de system_server (UID 1000).
NotificationListenerService
Para algumas vinculações do sistema para o app, o objetivo não é a latência, mas sim evitar inicializações a frio frequentes.
NotificationListenerService, um serviço que recebe chamadas do sistema quando novas notificações são postadas ou removidas, é um ótimo exemplo. Um usuário típico de smartphone pode receber centenas de notificações ao longo do dia. Se o sistema desvinculasse de um listener de notificação, o processo desse app provavelmente cairia no estado armazenado em cache e poderia ser encerrado pelo LMK.
Quando a próxima notificação chegar, possivelmente segundos depois, o sistema será forçado a fazer a inicialização a frio do processo do app novamente para entregar o evento. Esse ciclo constante de encerramento e inicialização a frio consumiria muito mais CPU e bateria do que simplesmente manter o processo vinculado e ativo em segundo plano.
A tela "-1" do inicializador (feed de notícias)
Os apps de inicialização modernos geralmente combinam a funcionalidade de navegação principal (ícones e widgets da tela inicial) com um feed de notícias disponível em uma das telas do inicializador e integrado à experiência do usuário do inicializador. O feed de notícias pode ser fornecido por outro app. Por exemplo, no Google Pixel, o inicializador é integrado a um feed fornecido pelo app Google.
Quando você desliza para a esquerda na tela inicial para ver o feed de notícias, a transição precisa ser suave. O inicializador consegue isso vinculando-se a uma interface de serviço no app que fornece o feed de notícias e mantendo essa vinculação ativa enquanto o inicializador estiver ativo. Isso mantém o conteúdo do feed renderizado e pronto na memória, mesmo quando você não está olhando para ele.
Outros exemplos comuns
- O inicializador (HOME_APP_ADJ): o app de inicialização (tela inicial) tem um slot especial
na lista de prioridades. Embora nem sempre esteja vinculado por um serviço, ele recebe o
HOME_APP_ADJ(normalmente 600). O sistema prefere manter o inicializador ativo, porque o usuário retorna a ele com frequência. Na verdade, o sistema prefere encerrar o app usado anteriormente (PREV_APP_ADJ = 700) do que encerrar o inicializador, porque isso resultaria em uma experiência do usuário lenta ao sair de qualquer app, já que o usuário precisaria esperar que o inicializador fosse iniciado a frio. - Editor de método de entrada (IME): ao digitar, o sistema se vincula ao app de teclado escolhido (por exemplo, Gboard). Isso mantém o processo do teclado em um estado elevado, mesmo que o teclado esteja temporariamente oculto. Isso garante que o teclado possa reaparecer instantaneamente quando você tocar em outro campo de texto.
- Pagamentos por aproximação: quando você toca no smartphone para pagar, o sistema se vincula ao serviço de pagamento por aproximação (por exemplo, Carteira do Google). Essas transações geralmente têm requisitos rigorosos em tempo real do terminal do comerciante. Se o app de pagamento precisasse ser iniciado a frio, a transação poderia expirar e falhar.
Compromissos e o limite de performance
Embora as vinculações sejam necessárias para a performance e a correção, elas têm um custo para a integridade da memória do sistema.
- Flexibilidade reduzida: cada processo vinculado é um processo que o LMK não pode encerrar facilmente. Isso reduz o "colchão" de processos armazenados em cache que o sistema pode usar para liberar memória sob pressão.
- Agravamento do limite de performance: se muitos processos estiverem vinculados, o sistema poderá ficar quase sem processos em segundo plano que possam ser encerrados. Quando a pressão de memória aumenta, o sistema "cai do limite de performance" muito mais rápido, já que é forçado a encerrar processos mais importantes ou a sobrecarregar o cache de página.
← Localidade | ↑ Acima | Em todo o sistema →