Remover pacotes para o usuário do sistema

Este artigo descreve como melhorar o desempenho identificando e removendo pacotes desnecessários para o usuário do sistema.

Desative pacotes desnecessários

No setor automotivo, o usuário do sistema não tem cabeça , o que significa que o usuário do sistema não se destina a ser usado ou acessado diretamente por um ser humano. Como resultado, muitos aplicativos e serviços não precisam ser executados no usuário do sistema e podem ser desativados para melhorar o desempenho. Portanto, é fornecida uma opção para remover aplicativos desnecessários para o usuário do sistema (usuário 0).

Nesta página, dois tipos de usuários são discutidos:

  • SISTEMA . Sempre usuário 0
  • COMPLETO . Usuário que se destina a ser usado por um ser humano (um usuário que não seja do sistema), Usuário 10+

Android 11

No Android 11, você altera a configuração config_userTypePackageWhitelistMode . As bandeiras podem ser combinadas. Neste caso, 5 equivale a 1 mais 4 (uma combinação dos sinalizadores 1 e 4 ).

Bandeira Descrição
0 Desativar lista de permissões. Instale todos os pacotes do sistema; sem registro.
1 Aplicar. Instale pacotes do sistema somente quando eles estiverem na lista de permissões.
2 Registrar pacotes não permitidos.
4 Qualquer pacote não mencionado no arquivo da lista de permissões é implicitamente incluído na lista de permissões para todos os usuários.
8 O mesmo que 4 , para o usuário do sistema.
16 Ignore as OTAs. Não instale pacotes de sistema durante OTAs.
Considere estes cenários comuns.
  • Para ativar um recurso para uma lista de permissões completa, 1 ( totalmente aplicado )
  • Para ativar um recurso para uma lista de permissões incompleta, 5
  • Para habilitar um recurso para o usuário SYSTEM para facilitar o desenvolvimento local, 9 ( lista de permissões implícita )
  • Para desabilitar um recurso como se ele nunca tivesse sido habilitado, 16
  • Para desativar um recurso e desfazer todos os efeitos anteriores, 0

Certifique-se de instalar o arquivo XML no diretório sysconfig do dispositivo (este é o mesmo diretório que contém o makefile (`.mk`) usado para construir a imagem do sistema para o dispositivo). Ao nomear o arquivo XML, inclua o local em que o pacote está 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 Android 10:

  1. Sobreponha a configuração config_systemUserPackagesBlacklistSupported de frameworks/base/core/res/res/values/config.xml e defina-a como true . Quando o recurso está ativado, por padrão, todos os pacotes devem ser instalados tanto para o usuário do sistema quanto para o usuário COMPLETO.
  2. Crie um arquivo config.xml listando quais pacotes devem ser desabilitados 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>
    
  3. Adicione uma linha a device.mk para copiar o arquivo para a pasta de destino do dispositivo system/etc/sysconfig/ . Por exemplo:
    PRODUCT_COPY_FILES += <full path to the config file>:system/etc/sysconfig/<new denylist config file>.xml
    

Verifique 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 deve ser instalado no usuário do sistema, examine o arquivo AndroidManifest.xml do pacote localizado na raiz da fonte do projeto, incluindo os atributos e os componentes do aplicativo, que incluem todas as atividades, serviços, receptores de transmissão, e provedores de conteúdo. Para saber mais, consulte Visão geral do manifesto do aplicativo .

Desativar fluxo de trabalho de pacotes

Figura 1. Desativar fluxo de trabalho de pacotes

Nível 1, nível de aplicativo

1. Verifique se o aplicativo (ou componentes do aplicativo) está declarado como singleton

Se o aplicativo for singleton , o sistema instanciará o aplicativo apenas no Usuário do sistema. É provável que o aplicativo fosse projetado para ser compatível com vários usuários. Para saber mais sobre aplicativos com reconhecimento de multiusuário, consulte Construindo aplicativos com reconhecimento de multiusuário .

  1. Verifique o manifesto do Android para android:singleUser="true" .
  2. Se true , coloque na lista de permissões. Necessário para o usuário do sistema.
  3. Se false , continue. Verifique outros critérios antes de remover.

2. Verifique se o aplicativo requer acesso protegido ao armazenamento

Muitos serviços de inicialização do sistema geralmente dependem de armazenamento criptografado por dispositivo (DE) em vez de armazenamento criptografado por credencial (CE). Além disso, os aplicativos do sistema com reconhecimento de inicialização direta também dependem do armazenamento criptografado do dispositivo. Para saber mais sobre aplicativos com reconhecimento de inicialização direta, consulte Suporte à inicialização direta em aplicativos do sistema .

  1. Verifique o manifesto do Android para android:defaultToDeviceProtectedStorage="true" , ​​que é necessário para vários serviços de inicialização do sistema.
  2. Se true , coloque na lista de permissões.
  3. Se false , continue.

Nível 2, componentes do aplicativo

Atividades

Para saber mais sobre atividades, consulte Introdução às atividades .

a. Verifique se o aplicativo contém apenas atividades

As atividades são orientadas à interface do usuário. Como o usuário do sistema não tem cabeça no setor automotivo, nenhum ser humano deve interagir com o usuário do sistema. Como resultado, se o aplicativo contiver apenas atividades, o aplicativo provavelmente não será relevante para o usuário do sistema.

Verifique a prioridade e o privilégio especial.

  1. Se sim , talvez seja necessário para o usuário do sistema.
  2. Se Não , não coloque na lista de permissões o usuário do sistema.

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 intenções. Porém, por ter um privilégio alto, ele precisa ser instalado para o usuário do sistema para fins de teste.

Serviço

Para saber mais sobre serviços, consulte Visão geral dos serviços .

b. Verifique se o serviço está declarado como privado e não pode ser acessado por outros aplicativos

Se o serviço for declarado como private , outros pacotes não utilizarã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 aplicativos, ele não poderá ser vinculado a outros aplicativos. Portanto, a Etapa C e a Etapa D abaixo são irrelevantes. Como resultado, este componente não forneceria mais dicas sobre se o serviço é ou não necessário para o Usuário do Sistema.

  1. Se sim , verifique o próximo componente.
  2. Se Não , continue verificando este componente.

c. Verifique se os aplicativos instalados no usuário do sistema podem estar vinculados a este serviço

Verifique se há pacotes permitidos no Nível 1 e identifique os serviços aos quais eles estão vinculados. Rastreie o filtro de intenções neste serviço e startService em outros pacotes.

Se este serviço estiver vinculado a aplicativos instalados 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), coloque o serviço na lista de permissões.

  1. Se sim , coloque na lista de permissões.
  2. Se Não , continue verificando este componente.

d. Verifique se o serviço está vinculado a outros aplicativos e declarado para execução em primeiro plano

Procure startForeground . Isso significa que as pessoas interagiriam com o aplicativo em primeiro plano. Muito provavelmente, este serviço não seria necessário para o usuário do sistema e não precisaria estar na lista de permissões.

  1. Se sim , não coloque na lista de permissões.
  2. Se Não , continue verificando o próximo componente.

e. Verifique se o serviço está definido para ser executado no processo do sistema

No AndroidManifest, procure android:process="system" .
Se o serviço for definido intencionalmente para ser executado no processo do sistema, isso significa que ele será executado explicitamente no mesmo processo que o serviço do sistema e deverá estar na lista de permissões para execução no Usuário do sistema. Como parte do design de alocação de memória do Android, os serviços do sistema são alguns dos últimos processos a serem eliminados, o que implica na criticidade dos serviços definidos com tal atributo. Para saber mais sobre o design de alocação de memória do Android, consulte Assassino de pouca memória .

  1. Se sim , não coloque na lista de permissões.
  2. Se Não , continue verificando outros componentes.

Por exemplo, o pacote com.android.networkstack.inprocess deve estar na lista de permissões, pois contém RegularMaintenanceJobService , que possui a tag android:process="system" .

Provedor de conteúdo

Para saber mais sobre provedores de conteúdo, consulte Provedores de conteúdo .

f. Verifique se o aplicativo instalado no usuário do sistema depende deste provedor

Verifique se há pacotes permitidos no Nível 1 e de quais provedores eles dependem. Se um aplicativo em execução no usuário do sistema (por exemplo, com.android.car.companiondevicesupport estiver na lista de permissões para execução no usuário do sistema) e depender desse provedor de conteúdo, verifique se esse provedor de conteúdo também está na lista de permissões.

  1. Se sim , coloque na lista de permissões.
  2. Se Não , não coloque na lista de permissões.

Por exemplo, se com.android.car.EXAMPLE contiver provedores singleton ( SystemActionsContentProvider e ManagedProvisioningActionsContentProvider ), ele deverá estar na lista de permissões para o usuário do sistema. Então, se com.android.car.EXAMPLE depender de android.webkit para WebViewFactoryProvider , então, com.android.webview deverá estar na lista de permissões para o usuário do sistema, visto que ele carrega o android.webkit .

Passo a passo do pacote de amostra

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>