Removendo pacotes para o usuário do sistema

Este artigo descreve como melhorar o desempenho identificando e removendo pacotes que não são necessários para o usuário SYSTEM.

Desativando 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).

Neste artigo, 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 ).

  0  - disable whitelist (install all system packages; no logging)
  1  - enforce (only install system packages if they are whitelisted)
  2  - log (log non-whitelisted packages)
  4  - any package not mentioned in the whitelist file is implicitly whitelisted on all users
  8  - same as 4, but just for the SYSTEM user
  16 - ignore OTAs (don't install system packages during OTAs)
  Common scenarios:
  - to enable feature (fully enforced) for a complete allowlist: 1
  - to enable feature for an incomplete allowlist (so use implicit allowlist mode): 5
  - to enable feature but implicitly allowlist for SYSTEM user to ease local development: 9
  - to disable feature completely if it had never been enabled: 16
  - to henceforth disable feature and try to undo its previous effects: 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 SYSTEM quanto para o usuário FULL.
  2. Crie um arquivo config.xml listando quais pacotes devem ser desabilitados para o usuário SYSTEM. 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 SYSTEM, 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 aplicação

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 SYSTEM. É 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 SYSTEM.
  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 SYSTEM.
  2. Se Não , não coloque na lista de permissões o usuário SYSTEM.

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 SYSTEM 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 por 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 SYSTEM podem se vincular 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 intencionalmente definido 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 SYSTEM 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 SYSTEM (por exemplo, com.android.car.companiondevicesupport estiver na lista de permissões para execução no usuário SYSTEM) e depender desse provedor de conteúdo, certifique-se de que esse provedor de conteúdo também esteja 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 SYSTEM. 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 SYSTEM, visto que ele carrega o android.webkit .

Exemplo de pacote passo a passo

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>