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 do sistema.

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 SYSTEM User e podem ser desabilitados 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 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. Nesse 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 no qual o pacote está definido no arquivo 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 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 SYSTEM User, examine o arquivo AndroidManifest.xml do pacote localizado na raiz da fonte do projeto, incluindo os atributos do aplicativo e os componentes do aplicativo, que incluem todas as atividades, serviços, broadcast receivers, 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 do SISTEMA. É provável que o aplicativo tenha a intenção de ser um aplicativo com reconhecimento de vários usuários. Para saber mais sobre aplicativos com reconhecimento de vários usuários, consulte Criação de aplicativos com reconhecimento de vários usuários.

  1. Verifique o manifesto do Android para android:singleUser="true" .
  2. Se true , 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 ao armazenamento protegido

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 que reconhecem a 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 , 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 .

uma. 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 Automotive, nenhum humano deve estar interagindo 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 se há prioridade e privilégio especial.

  1. Se sim , talvez necessário para o usuário do sistema.
  2. Se Não , não permita a lista de usuários do SISTEMA.

Por exemplo, o Compatibility Test Suite (CTS) ( com.android.cts.priv.ctsshim ) contém apenas Atividades, e as Atividades são definidas para testar filtros de intenção. No entanto, como possui um alto privilégio, 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. Verifique se o serviço é declarado como privado e não pode ser acessado de outros aplicativos

Se o serviço for declarado como private , 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 de 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, esse componente não forneceria mais dicas sobre se o serviço é necessário ou não para o usuário do SISTEMA.

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

c. Verifique se os aplicativos instalados no usuário do SISTEMA 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 a partir do filtro de intenção neste serviço e startService em outros pacotes.

Se esse 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), então coloque o serviço na lista de permissões.

  1. Se sim , lista de permissões.
  2. Se Não , continue a verificar este componente.

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

Procure por startForeground . Isso significa que as pessoas estariam interagindo com o aplicativo em primeiro plano. Muito provavelmente, esse 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 permita a lista.
  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 deve ser permitido 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, consulteLow-memory killer .

  1. Se sim , não permita a lista.
  2. Se Não , continue verificando outros componentes.

Por exemplo, o pacote com.android.networkstack.inprocess deve ser permitido, pois 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. Verifique se o aplicativo instalado no usuário do SISTEMA depende deste provedor

Verifique se há pacotes permitidos no Nível 1 e verifique de quais provedores eles dependem. Se um aplicativo em execução no SYSTEM User (por exemplo, com.android.car.companiondevicesupport estiver na lista de permissões para execução no SYSTEM User) 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 , lista de permissões.
  2. Se Não , não permita a lista.

Por exemplo, se com.android.car.EXAMPLE contiver provedores singleton ( SystemActionsContentProvider e ManagedProvisioningActionsContentProvider ), ele deverá ser permitido para o usuário SYSTEM. Então, se com.android.car.EXAMPLE depender de android.webkit para WebViewFactoryProvider , com.android.webview deve ser permitido para o usuário SYSTEM, uma vez que carrega o android.webkit .

Pacote de amostra 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>