Supprimer les packages pour l'utilisateur système

Cet article décrit comment améliorer les performances en identifiant et en supprimant les packages qui ne sont pas nécessaires à l'utilisateur système.

Désactivez les packages inutiles

Dans l'automobile, l'utilisateur système est sans tête , ce qui signifie qu'il n'est pas destiné à être utilisé ou directement accessible par un humain. Par conséquent, de nombreuses applications et services n'ont pas besoin d'être exécutés dans l'utilisateur système et peuvent être désactivés pour améliorer les performances. Par conséquent, une option est fournie pour supprimer les applications inutiles pour l'utilisateur système (utilisateur 0).

Sur cette page, deux types d'utilisateurs sont abordés :

  • SYSTÈME . Toujours utilisateur 0
  • COMPLET . Utilisateur destiné à être utilisé par un humain (un utilisateur non système), utilisateur 10+

Android 11

Sous Android 11, vous modifiez la configuration, config_userTypePackageWhitelistMode . Les drapeaux peuvent être combinés. Dans ce cas, 5 équivaut à 1 plus 4 (une combinaison des drapeaux 1 et 4 ).

Drapeau Description
0 Désactivez la liste verte. Installez tous les packages système ; pas de journalisation.
1 Imposer. Installez les packages système uniquement lorsqu'ils sont sur la liste autorisée.
2 Enregistrez les packages non autorisés.
4 Tout package non mentionné dans le fichier de liste autorisée est implicitement ajouté à la liste autorisée pour tous les utilisateurs.
8 Identique à 4 , pour l'utilisateur système.
16 Ignorez les OTA. N'installez pas de packages système pendant les OTA.
Considérez ces scénarios courants.
  • Pour activer une fonctionnalité pour une liste blanche complète, 1 ( entièrement appliqué )
  • Pour activer une fonctionnalité pour une liste blanche incomplète, 5
  • Pour activer une fonctionnalité permettant à l'utilisateur SYSTEM de faciliter le développement local, 9 ( liste autorisée implicite )
  • Pour désactiver une fonctionnalité comme si elle n'avait jamais été activée, 16
  • Pour désactiver une fonctionnalité et annuler tous les effets précédents, 0

Assurez-vous d'installer le fichier XML dans le répertoire sysconfig du périphérique (il s'agit du même répertoire qui contient le makefile (`.mk`) utilisé pour créer l'image système du périphérique). Lorsque vous nommez le fichier XML, incluez l'emplacement auquel le package est défini dans la build. Par exemple, 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 et Android 10

Pour configurer cette fonctionnalité sous Android 9 et Android 10 :

  1. Superposez la configuration config_systemUserPackagesBlacklistSupported à partir de frameworks/base/core/res/res/values/config.xml et définissez-la sur true . Lorsque la fonctionnalité est activée, par défaut, tous les packages doivent être installés à la fois pour l'utilisateur système et pour l'utilisateur COMPLET.
  2. Créez un fichier config.xml répertoriant les packages qui doivent être désactivés pour l'utilisateur système. Par exemple :
    <config>
        <!-- This package will be uninstalled for the system user -->
        <system-user-blacklisted-app package="com.google.car.calendar" />
    </config>
    
  3. Ajoutez une ligne à device.mk pour copier le fichier dans le dossier cible system/etc/sysconfig/ périphérique. Par exemple :
    PRODUCT_COPY_FILES += <full path to the config file>:system/etc/sysconfig/<new denylist config file>.xml
    

Vérifier le résultat

Pour vérifier le résultat, exécutez :

$ 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

Prémisse

Pour déterminer si un package doit être installé dans l'utilisateur système, examinez le fichier AndroidManifest.xml du package situé à la racine de la source du projet, y compris les attributs de l'application et les composants de l'application, qui incluent toutes les activités, services, récepteurs de diffusion, et les fournisseurs de contenu. Pour en savoir plus, consultez Présentation du manifeste d’application .

Désactiver le workflow des packages

Figure 1. Désactiver le flux de travail des packages

Niveau 1, niveau application

1. Vérifiez si l'application (ou les composants de l'application) est déclarée comme singleton

Si l'application est un singleton , le système instanciera l'application uniquement dans l'utilisateur système. Il est probable que l'application était destinée à être une application multi-utilisateurs. Pour en savoir plus sur les applications multi-utilisateurs, consultez Création d'applications multi-utilisateurs .

  1. Vérifiez le manifeste Android pour android:singleUser="true" .
  2. Si c'est vrai , ajoutez la liste blanche. Nécessaire pour l'utilisateur du système.
  3. Si faux , continuez. Vérifiez les autres critères avant de supprimer.

2. Vérifiez si l'application nécessite un accès au stockage protégé

De nombreux services de démarrage système s'appuient souvent sur un stockage chiffré par périphérique (DE) au lieu d'un stockage chiffré d'informations d'identification (CE). En outre, les applications système compatibles avec le démarrage direct s'appuient également sur le stockage crypté de l'appareil. Pour en savoir plus sur les applications prenant en charge le démarrage direct, consultez Prise en charge du démarrage direct dans les applications système .

  1. Vérifiez le manifeste Android pour android:defaultToDeviceProtectedStorage="true" , ​​qui est nécessaire pour de nombreux services de démarrage du système.
  2. Si c'est vrai , ajoutez la liste blanche.
  3. Si faux , continuez.

Niveau 2, composants de l'application

Activités

Pour en savoir plus sur les activités, voir Introduction aux activités .

un. Vérifiez si l'application contient uniquement des activités

Les activités sont orientées vers l'interface utilisateur. Étant donné que l'utilisateur du système est sans tête dans l'automobile, aucun humain ne doit interagir avec l'utilisateur du système. Par conséquent, si l’application contient uniquement des activités, elle n’est probablement pas pertinente pour l’utilisateur système.

Vérifiez la priorité et le privilège spécial.

  1. Si oui , peut-être nécessaire pour l'utilisateur système.
  2. Si Non , n'ajoutez pas d'autorisation à l'utilisateur système.

Par exemple, la suite de tests de compatibilité (CTS) ( com.android.cts.priv.ctsshim ) contient uniquement des activités et les activités sont définies pour tester les filtres d'intention. Cependant, comme il dispose d'un privilège élevé, il doit être installé pour l'utilisateur système à des fins de test.

Service

Pour en savoir plus sur les services, consultez Présentation des services .

b. Vérifiez si le service est déclaré privé et n'est pas accessible à partir d'autres applications

Si le service est déclaré comme private , les autres packages n'utiliseront pas le service. Recherchez android:exported="false" . Si le service est déclaré privé ou n'est pas accessible à partir d'autres applications, il ne peut pas être lié par d'autres applications. Par conséquent, les étapes C et D ci-dessous ne sont pas pertinentes. Par conséquent, ce composant ne fournirait pas plus d'indications quant à savoir si le service est nécessaire ou non pour l'utilisateur du système.

  1. Si oui , vérifiez le composant suivant.
  2. Si non , continuez à vérifier ce composant.

c. Vérifiez si les applications installées dans l'utilisateur système peuvent se lier à ce service

Recherchez les packages sur liste verte au niveau 1 et identifiez les services auxquels ils sont liés. Suivez le filtre d'intention dans ce service et startService dans d'autres packages.

Si ce service est lié aux applications installées dans l'utilisateur système (par exemple, com.android.car.companiondevicesupport est sur la liste autorisée pour s'exécuter dans l'utilisateur système), ajoutez le service à la liste autorisée.

  1. Si oui , ajoutez la liste blanche.
  2. Si non , continuez à vérifier ce composant.

d. Vérifiez si le service est lié à d'autres applications et déclaré pour s'exécuter au premier plan

Recherchez startForeground . Cela signifie que les gens interagiraient avec l'application au premier plan. Très probablement, ce service ne serait pas nécessaire pour l'utilisateur du système et n'aurait pas besoin d'être ajouté à la liste verte.

  1. Si oui , ne pas autoriser.
  2. Si non , continuez à vérifier le composant suivant.

e. Vérifiez si le service est défini pour s'exécuter dans le processus système

Dans AndroidManifest, recherchez android:process="system" .
Si le service est intentionnellement défini pour s'exécuter dans le processus système, cela signifie qu'il s'exécutera explicitement dans le même processus que le service système et qu'il doit être ajouté à la liste autorisée pour s'exécuter dans l'utilisateur système. Dans le cadre de la conception de l'allocation de mémoire d'Android, les services système font partie des derniers processus à être supprimés, ce qui implique le caractère critique des services définis avec un tel attribut. Pour en savoir plus sur la conception de l'allocation de mémoire d'Android, consultez Low-memory killer .

  1. Si oui , ne pas autoriser.
  2. Si non , continuez à vérifier les autres composants.

Par exemple, le package com.android.networkstack.inprocess doit être ajouté à la liste verte car il contient RegularMaintenanceJobService , qui possède la balise android:process="system" .

Fournisseur de contenu

Pour en savoir plus sur les fournisseurs de contenu, consultez Fournisseurs de contenu .

F. Vérifiez si l'application installée dans l'utilisateur système dépend de ce fournisseur

Recherchez les packages sur liste verte au niveau 1 et vérifiez de quels fournisseurs ils dépendent. Si une application exécutée dans l'utilisateur système (par exemple, com.android.car.companiondevicesupport est sur la liste autorisée pour s'exécuter dans l'utilisateur système) et dépend de ce fournisseur de contenu, assurez-vous que ce fournisseur de contenu est également sur la liste autorisée.

  1. Si oui , ajoutez la liste blanche.
  2. Si non , ne pas ajouter à la liste d'autorisation.

Par exemple, si com.android.car.EXAMPLE contient des fournisseurs singleton ( SystemActionsContentProvider et ManagedProvisioningActionsContentProvider ), il doit être ajouté à la liste verte pour l'utilisateur système. Ensuite, si com.android.car.EXAMPLE dépend de android.webkit pour WebViewFactoryProvider , com.android.webview doit être ajouté à la liste d'autorisation pour l'utilisateur système étant donné qu'il charge le android.webkit .

Exemple de procédure pas à pas pour le package

L'exemple suivant montre comment évaluer le AndroidManifest.xml d'un package :

<?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>