Esta página descreve como melhorar o desempenho identificando e removendo pacotes que não são necessários para o usuário do sistema.
Desativar pacotes desnecessários
No Automotive, o usuário do sistema é headless, o que significa que ele não foi projetado para ser usado ou acessado diretamente por humanos. Como resultado, muitos apps e serviços não precisam ser executados no usuário do sistema e podem ser desativados para melhorar o desempenho. Portanto, há uma opção para remover apps desnecessários para o usuário do sistema (Usuário 0).
Nesta página, abordamos dois tipos de usuários:
- SYSTEM. Sempre usuário 0
- FULL. Usuário que deve ser usado por uma pessoa (um usuário não do sistema), Usuário 10+
Android 11
No Android 11, mude a configuração
config_userTypePackageWhitelistMode
. As flags podem ser combinadas. Nesse caso, 5
equivale a 1
.
mais 4
(uma combinação das sinalizações 1
e 4
).
Sinalização | Descrição |
---|---|
0 |
Desativar lista de permissões. Instala todos os pacotes do sistema, sem registro. |
1 |
Aplicar. Instalar pacotes do sistema apenas quando eles estiverem na lista de permissões. |
2 |
Registra pacotes que não estão na lista de permissões. |
4 |
Todos os pacotes não mencionados no arquivo da lista de permissões são implicitamente permitidos para todos os usuários. |
8 |
Igual a 4 , para o usuário do sistema. |
16 |
Ignorar OTAs. Não instale pacotes do sistema durante atualizações OTA. |
Considere estes cenários comuns:
- Para ativar um recurso para uma lista de permissões completa,
1
(aplicação total) - Para ativar um recurso para uma lista de permissões incompleta,
5
- Para ativar um recurso para que o usuário
SYSTEM
facilite o desenvolvimento local,9
(lista de permissões implícitas) - Para desativar um recurso como se ele nunca tivesse sido ativado,
16
- Para desativar um recurso e desfazer todos os efeitos anteriores,
0
Instale o arquivo XML no diretório sysconfig
do dispositivo,
que é o mesmo que contém o makefile (.mk
) usado para criar a
imagem do sistema do dispositivo. Ao nomear o arquivo XML, inclua o local
em que o pacote é definido no build, por exemplo, preinstalled-packages-product-car-CAR_PRODUCT_NAME.xml
.
<!- this package will be installed for both FULL and SYSTEM user --> <install-in-user-type package="com.android.bluetooth"-> <install-in user-type="FULL" /-> <install-in user-type="SYSTEM" /-> </install-in-user-type-> <!- this package will only be installed for both FULL user --> <install-in-user-type package="com.android.car.calendar"-> <install-in user-type="FULL" > </install-in-user-type->
Android 9 e Android 10
Para configurar esse recurso no Android 9 e no Android 10:
- Sobrepor a
config_systemUserPackagesBlacklistSupported
de configuração deframeworks/base/core/res/res/values/config.xml
e defina paratrue
. Quando o recurso está ativado, por padrão, todos os pacotes deve ser instalado para o usuário do sistema e para o usuário FULL. - Crie um arquivo
config.xml
que liste quais pacotes precisam ser desativados para o usuário do sistema, por exemplo:<config> <!-- This package will be uninstalled for the system user --> <system-user-blacklisted-app package="com.google.car.calendar" /> </config>
- Adicione uma linha ao
device.mk
para copiar o arquivo para o pasta de destinosystem/etc/sysconfig/
, por exemplo:PRODUCT_COPY_FILES += <full path to the config file>:system/etc/sysconfig/<new denylist config file>.xml
Verificar o resultado
Para verificar o resultado, execute:
$ adb shell dumpsys user | grep PACKAGE_SUBSTRING $ adb shell pm list packages --user USER_ID PACKAGE_SUBSTRING $ adb shell cmd user report-system-user-package-whitelist-problems
Premissa
Para determinar se um pacote precisa ser instalado no usuário do sistema, examine o
arquivo AndroidManifest.xml
do pacote localizado na raiz da
origem do projeto, incluindo os atributos e os componentes do
app, que incluem todas as atividades, serviços, broadcast receivers e provedores de
conteúdo. Para saber mais, consulte
Visão geral do
manifesto do app.
Figura 1. Desativar o fluxo de trabalho de pacotes.
Nível 1, nível do app
1. Verificar se o app (ou os componentes dele) está declarado como um singleton
Se o aplicativo for um singleton; o sistema instancia o app apenas no usuário do sistema. É provável que o app tenha sido criado para ser multiusuário. Para saber mais sobre apps multiusuário, consulte Criar apps multiusuário.
- Verifique o manifesto do Android para
android:singleUser="true"
. - Se
true
, adicione à lista de permissões. Necessário para o usuário do sistema. - Se
false
, continue. Verifique outros critérios antes de remover.
2. Verificar se o app precisa de acesso ao armazenamento protegido
Muitos serviços de inicialização do sistema geralmente dependem do armazenamento criptografado do dispositivo (DE). do armazenamento criptografado por credenciais (CE). Além disso, os apps do sistema que são com reconhecimento de inicialização também dependem do armazenamento criptografado do dispositivo. Para saber mais sobre apps compatíveis com a inicialização direta, consulte Suporte à inicialização direta em apps do sistema.
- Verifique o manifesto do Android para
android:defaultToDeviceProtectedStorage="true"
, que é necessário para vários serviços de inicialização do sistema. - Se
true
, adicione à lista de permissões. - Se
false
, continue.
Nível 2, componentes de apps
Atividades
Para saber mais sobre atividades, consulte Introdução às atividades.
a. Verificar se o app contém apenas atividades
As atividades são orientadas pela interface do usuário. Como o usuário do sistema é sem comando no Automotive, nenhum humano pode interagir com ele. Como resultado, se o aplicativo tiver somente atividades, ele será provavelmente irrelevante para o usuário do sistema.
Verifique se há prioridade e privilégio especial:
- Se Sim, pode ser necessário para o usuário do sistema.
- Se a resposta for Não, não inclua o usuário do sistema na lista de permissões.
Por exemplo, o conjunto de testes de compatibilidade (CTS)
(com.android.cts.priv.ctsshim
) contém apenas atividades, e
as atividades são definidas para testar filtros de intent. No entanto, como o CTS tem um alto
ele precisa ser instalado para o usuário do sistema para fins de teste.
Serviço
Para saber mais sobre os serviços, consulte Visão geral dos serviços.
b. Verificar se o serviço foi declarado como particular e não pode ser acessado de outros apps
Se o serviço for declarado como privado, outros pacotes não usarão o
serviço. Procure por android:exported="false"
. Se o serviço for declarado
como privado ou não puder ser acessado por outros apps, ele não poderá ser vinculado
a outros apps. Portanto, as etapas c e d abaixo são irrelevantes. Como resultado,
esse componente não fornece mais dicas sobre se o serviço é necessário
para o usuário do sistema.
- Se Sim, verifique o próximo componente.
- Se a resposta for Não, continue verificando esse componente.
c. Conferir se os apps instalados no usuário do sistema podem ser vinculados a este serviço
Procure pacotes na lista de permissões no nível 1 e identifique os serviços
às quais eles estão vinculados. Trace do filtro de intent neste serviço e startService
em outros pacotes.
Se esse serviço estiver vinculado a apps instalados no usuário do sistema (por exemplo,
com.android.car.companiondevicesupport
está na lista de permissões para ser executado no
usuário do sistema), adicione o serviço à lista de permissões:
- Se Sim, coloque na lista de permissões.
- Se a resposta for Não, continue verificando esse componente.
d. Verificar se o serviço está vinculado a outros apps e declarado para ser executado em primeiro plano
Procure por startForeground
. Isso significa que as pessoas vão interagir com
o app em primeiro plano. Muito provavelmente, esse serviço não seria necessário para a
usuário do sistema e não precisa estar na lista de permissões:
- Se a resposta for Sim, não adicione à lista de permissões.
- Se a resposta for Não, continue verificando o próximo componente.
e. Verificar se o serviço está definido para ser executado no processo do sistema
No arquivo AndroidManifest, procure android:process="system"
.
Se o serviço for definido intencionalmente para execução no processo do sistema,
ele é executado no mesmo processo que o serviço do sistema e
precisa estar na lista de permissões para execução no usuário do sistema. Como parte da memória do Android
design de alocação, serviços do sistema são alguns dos últimos processos a serem encerrados,
o que implica a importância dos serviços definidos com esse atributo. Para
saber mais sobre o design de alocação de memória do Android, consulte Low-memory
killer.
- Se Sim, não coloque na lista de permissões.
- Se a resposta for Não, continue verificando os outros componentes.
Por exemplo, o pacote com.android.networkstack.inprocess
precisa ser
está na lista de permissões porque contém RegularMaintenanceJobService
, que
tem a tag android:process="system"
.
Provedor de conteúdo
Para saber mais sobre provedores de conteúdo, consulte Provedores de conteúdo.
f. Verificar se o app instalado no usuário do sistema depende desse provedor
Procure pacotes na lista de permissões no nível 1 e confira os provedores
dependerão dele. Se um aplicativo em execução no usuário do sistema (por exemplo,
com.android.car.companiondevicesupport
está na lista de permissões para execução no
usuário do sistema) e depende desse provedor de conteúdo, verifique se esse conteúdo
provedor também está na lista de permissões.
- Se a resposta for Sim, adicione à lista de permissões.
- Se a resposta for Não, não coloque na lista de permissões.
Por exemplo, se com.android.car.EXAMPLE
contiver singleton
provedores (SystemActionsContentProvider
e
ManagedProvisioningActionsContentProvider
), ele deve ser
na lista de permissões para o usuário do sistema. Se com.android.car.EXAMPLE
depender de android.webkit
para WebViewFactoryProvider
,
com.android.webview
precisa estar na lista de permissões permitidas para o usuário do sistema,
já que ele carrega android.webkit
.
Exemplo de tutorial de pacote
O exemplo a seguir mostra como avaliar o AndroidManifest.xml
de um
pacote:
<?xml version="1.0" encoding="utf-8"?> <!-- 1. Search in the entire manifest for singleUser attribute. No. Move to step 2 --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.providers.calendar" android:sharedUserId="android.uid.calendar"> We can ignore the entire permission section <uses-permission android:name="android.permission.READ_CALENDAR" /> ... <uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" /> <!-- 2. Look for defaultToDeviceProtectedStorage in application's attribute. No. Continue evaluating app components. --> <application android:label="@string/calendar_storage" android:allowBackup="false" android:icon="@drawable/app_icon" android:usesCleartextTraffic="false"> <!-- a. Contain only activities? No. Continue to evaluate components other than activities. --> <provider android:name="CalendarProvider2" android:authorities="com.android.calendar" <!-- b. Is this component exported? Yes. Continue evaluating this component. f. App on u0 might depend on this? Search for CalendarProvider2 in dumpsys, shows ContentProviderRecord{b710923 u0 com.android.providers.calendar/.CalendarProvider2} Yes. Whitelist for system user. --> android:label="@string/provider_label" android:multiprocess="false" android:exported="true" android:readPermission="android.permission.READ_CALENDAR" android:writePermission="android.permission.WRITE_CALENDAR" />
<activity android:name="CalendarContentProviderTests" android:label="Calendar Content Provider" android:exported="false"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.UNIT_TEST" /> </intent-filter> </activity> <!-- Not service/content provider. Ignore. --> <receiver android:name="CalendarProviderBroadcastReceiver" android:exported="false"> <intent-filter> <action android:name="com.android.providers.calendar.intent.CalendarProvider2"/> <category android:name="com.android.providers.calendar"/> </intent-filter> <intent-filter> <action android:name="android.intent.action.EVENT_REMINDER"/> <data android:scheme="content" /> </intent-filter> </receiver> <service android:name="CalendarProviderIntentService"/> </application> </manifest>