Eliminación de paquetes para el usuario del sistema

Este artículo describe cómo mejorar el rendimiento identificando y eliminando paquetes que no son necesarios para el usuario del SISTEMA.

Deshabilitar paquetes innecesarios

En Automoción, el Usuario del SISTEMA no tiene cabeza , lo que significa que el Usuario del SISTEMA no está diseñado para que un humano lo utilice ni acceda directamente a él. Como resultado, muchas aplicaciones y servicios no necesitan ejecutarse en el Usuario del SISTEMA y pueden desactivarse para mejorar el rendimiento. Por lo tanto, se proporciona una opción para eliminar aplicaciones innecesarias para el usuario del SISTEMA (Usuario 0).

En este artículo se analizan dos tipos de Usuarios:

  • SISTEMA . Siempre Usuario 0
  • COMPLETO . Usuario destinado a ser utilizado por un humano (un usuario que no sea del SISTEMA), Usuario 10+

androide 11

En Android 11, cambia la configuración, config_userTypePackageWhitelistMode . Las banderas se pueden combinar. En este caso, 5 equivale a 1 más 4 (una combinación de las banderas 1 y 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

Asegúrese de instalar el archivo XML en el directorio sysconfig del dispositivo (este es el mismo directorio que contiene el archivo MAKE (.mk) utilizado para crear la imagen del sistema para el dispositivo). Cuando asigne un nombre al archivo XML, incluya la ubicación en la que se define el paquete en la compilación. Por ejemplo, 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 y Android 10

Para configurar esta función en Android 9 y Android 10:

  1. Superponga la configuración config_systemUserPackagesBlacklistSupported de frameworks/base/core/res/res/values/config.xml y configúrela en true . Cuando la función está activada, de forma predeterminada, todos los paquetes deben instalarse tanto para el usuario del SISTEMA como para el usuario COMPLETO.
  2. Cree un archivo config.xml que enumere qué paquetes deben deshabilitarse para el usuario del SISTEMA. Por ejemplo:
    <config>
        <!-- This package will be uninstalled for the system user -->
        <system-user-blacklisted-app package="com.google.car.calendar" />
    </config>
    
  3. Agregue una línea a device.mk para copiar el archivo a la carpeta de destino del dispositivo system/etc/sysconfig/ . Por ejemplo:
    PRODUCT_COPY_FILES += <full path to the config file>:system/etc/sysconfig/<new denylist config file>.xml
    

Verificar el resultado

Para verificar el resultado, ejecute:

$ 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

Premisa

Para determinar si un paquete debe instalarse en el usuario del SISTEMA, examine el archivo AndroidManifest.xml del paquete ubicado en la raíz del origen del proyecto, incluidos los atributos de la aplicación y los componentes de la aplicación, que incluyen todas las actividades, servicios, receptores de transmisión, y proveedores de contenidos. Para obtener más información, consulte Descripción general del manifiesto de la aplicación .

Deshabilitar el flujo de trabajo de paquetes

Figura 1. Deshabilitar el flujo de trabajo de paquetes

Nivel 1, nivel de aplicación

1. Compruebe si la aplicación (o los componentes de la aplicación) está declarada como singleton

Si la aplicación es un singleton , el sistema creará una instancia de la aplicación solo en el usuario del SISTEMA. Es probable que la aplicación estuviera pensada para ser multiusuario. Para obtener más información sobre aplicaciones multiusuario, consulte Creación de aplicaciones multiusuario .

  1. Verifique el manifiesto de Android para android:singleUser="true" .
  2. Si es verdadero , haga la lista de permitidos. Necesario para el usuario del SISTEMA.
  3. Si es falso , continúa. Verifique otros criterios antes de eliminar.

2. Compruebe si la aplicación requiere acceso al almacenamiento protegido.

Muchos servicios de arranque del sistema a menudo dependen del almacenamiento cifrado del dispositivo (DE) en lugar del almacenamiento cifrado de credenciales (CE). Además, las aplicaciones del sistema que reconocen el arranque directo también dependen del almacenamiento cifrado del dispositivo. Para obtener más información sobre las aplicaciones compatibles con el arranque directo, consulte Compatibilidad con el arranque directo en aplicaciones del sistema .

  1. Verifique el manifiesto de Android para android:defaultToDeviceProtectedStorage="true" , ​​que es necesario para numerosos servicios de arranque del sistema.
  2. Si es verdadero , haga la lista de permitidos.
  3. Si es falso , continúa.

Nivel 2, Componentes de la aplicación

Actividades

Para obtener más información sobre las actividades, consulte Introducción a las actividades .

a. Comprueba si la aplicación solo contiene actividades

Las actividades están orientadas a la interfaz de usuario. Dado que el usuario del SISTEMA no tiene cabeza en Automoción, ningún ser humano debería interactuar con el usuario del SISTEMA. Como resultado, si la aplicación solo contiene actividades, lo más probable es que no sea relevante para el usuario del SISTEMA.

Verifique la prioridad y el privilegio especial.

  1. En caso afirmativo , quizás sea necesario para el usuario del SISTEMA.
  2. En caso negativo , no incluya en la lista de permitidos al usuario del SISTEMA.

Por ejemplo, el conjunto de pruebas de compatibilidad (CTS) ( com.android.cts.priv.ctsshim ) contiene solo actividades, y las actividades se definen para probar los filtros de intención. Sin embargo, dado que tiene un alto privilegio, es necesario instalarlo para el usuario del SISTEMA con fines de prueba.

Servicio

Para obtener más información sobre los servicios, consulte Descripción general de los servicios .

b. Verifique si el servicio está declarado como privado y no se puede acceder desde otras aplicaciones

Si el servicio se declara privado , otros paquetes no utilizarán el servicio. Busque android:exported="false" . Si el servicio se declara como privado o no se puede acceder a él desde otras aplicaciones, entonces no puede estar vinculado por otras aplicaciones. Por lo tanto, los pasos C y D siguientes son irrelevantes. Como resultado, este componente no proporcionaría más pistas sobre si el servicio es necesario o no para el usuario del SISTEMA.

  1. En caso afirmativo , marque el siguiente componente.
  2. En caso negativo , continúe verificando este componente.

C. Compruebe si las aplicaciones instaladas en el usuario del SISTEMA pueden vincularse a este servicio

Verifique los paquetes incluidos en la lista permitida en el Nivel 1 e identifique los servicios a los que están vinculados. Rastree desde el filtro de intención en este servicio y startService en otros paquetes.

Si este servicio está vinculado a aplicaciones instaladas en el usuario del SISTEMA (por ejemplo, com.android.car.companiondevicesupport está en la lista permitida para ejecutarse en el usuario del SISTEMA), entonces incluya el servicio en la lista permitida.

  1. En caso afirmativo , haga la lista de permitidos.
  2. En caso negativo , continúe verificando este componente.

d. Compruebe si el servicio está vinculado desde otras aplicaciones y declarado para ejecutarse en primer plano

Busque startForeground . Esto significa que las personas interactuarían con la aplicación en primer plano. Lo más probable es que este servicio no sea necesario para el usuario del SISTEMA y no sea necesario incluirlo en la lista de permitidos.

  1. En caso afirmativo , no incluir en la lista de permitidos.
  2. En caso negativo , continúe comprobando el siguiente componente.

mi. Compruebe si el servicio está definido para ejecutarse en el proceso del sistema

En AndroidManifest, busque android:process="system" .
Si el servicio se define intencionalmente para ejecutarse en el proceso del sistema, significa que se ejecutará explícitamente en el mismo proceso que el servicio del sistema y debe incluirse en la lista permitida para ejecutarse en el Usuario del SISTEMA. Como parte del diseño de asignación de memoria de Android, los servicios del sistema son algunos de los últimos procesos en ser eliminados, lo que implica la criticidad de los servicios definidos con dicho atributo. Para obtener más información sobre el diseño de asignación de memoria de Android, consulte Asesino de poca memoria .

  1. En caso afirmativo , no incluir en la lista de permitidos.
  2. Si no , continúe revisando otros componentes.

Por ejemplo, el paquete com.android.networkstack.inprocess debe estar incluido en la lista de permitidos, ya que contiene RegularMaintenanceJobService , que tiene la etiqueta android:process="system" .

Proveedor de contenido

Para obtener más información sobre los proveedores de contenido, consulte Proveedores de contenido .

F. Compruebe si la aplicación instalada en el usuario del SISTEMA depende de este proveedor

Verifique los paquetes incluidos en la lista permitida en el Nivel 1 y verifique de qué proveedores dependen. Si una aplicación que se ejecuta en el usuario del SISTEMA (por ejemplo, com.android.car.companiondevicesupport está en la lista permitida para ejecutarse en el usuario del SISTEMA) y depende de este proveedor de contenido, asegúrese de que este proveedor de contenido también esté en la lista de permitidos.

  1. En caso afirmativo , haga la lista de permitidos.
  2. Si no , no incluya en la lista de permitidos.

Por ejemplo, si com.android.car.EXAMPLE contiene proveedores únicos ( SystemActionsContentProvider y ManagedProvisioningActionsContentProvider ), debe estar incluido en la lista permitida para el usuario del SISTEMA. Luego, si com.android.car.EXAMPLE depende de android.webkit para WebViewFactoryProvider , entonces com.android.webview debe estar incluido en la lista permitida para el usuario del SISTEMA dado que carga android.webkit .

Tutorial del paquete de muestra

El siguiente ejemplo muestra cómo evaluar AndroidManifest.xml de un paquete:

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