為系統用戶刪除軟件包

本文介紹如何通過識別和刪除 SYSTEM 用戶不需要的包來提高性能。

禁用不必要的軟件包

在汽車中,系統用戶是無頭的,這意味著系統用戶不打算被人使用或直接訪問。因此,許多應用程序和服務不需要在 SYSTEM 用戶中運行,並且可以禁用以提高性能。因此,提供了一個選項來為 SYSTEM 用戶(用戶 0)刪除不必要的應用程序。

在本文中,討論了兩種類型的用戶:

  • 系統。總是用戶 0
  • 滿。打算供人類使用的用戶(非系統用戶),用戶 10+

安卓 11

在 Android 11 中,您更改配置config_userTypePackageWhitelistMode 。可以組合標誌。在這種情況下, 5等於14 (標誌14的組合)。

  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

確保在設備的sysconfig目錄中安裝 XML 文件(該目錄與包含用於為設備構建系統映像的 makefile (.mk) 的目錄相同)。命名 XML 文件時,請包括在構建中定義包的位置。例如, 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->

安卓 9 和安卓 10

要在 Android 9 和 Android 10 中配置此功能:

  1. 覆蓋frameworks/base/core/res/res/values/config.xml中的config_systemUserPackagesBlacklistSupported配置並將其設置為true 。啟用該功能後,默認情況下,應為 SYSTEM 用戶和 FULL 用戶安裝所有軟件包。
  2. 創建一個config.xml文件,列出應該為 SYSTEM 用戶禁用哪些包。例如:
    <config>
        <!-- This package will be uninstalled for the system user -->
        <system-user-blacklisted-app package="com.google.car.calendar" />
    </config>
    
  3. device.mk中添加一行以將文件複製到設備的目標文件夾system/etc/sysconfig/ 。例如:
    PRODUCT_COPY_FILES += <full path to the config file>:system/etc/sysconfig/<new denylist config file>.xml
    

驗證結果

要驗證結果,請運行:

$ 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

前提

要確定是否應在 SYSTEM 用戶中安裝包,請檢查位於項目源根目錄的包的AndroidManifest.xml文件,包括應用程序的屬性和應用程序的組件,其中包括所有活動、服務、廣播接收器、和內容提供商。要了解更多信息,請參閱應用清單概述

禁用包工作流

圖 1.禁用包工作流程

1級,應用級

1.檢查app(或app組件)是否被聲明為單例

如果應用程序是單例,系統將僅在 SYSTEM 用戶中實例化應用程序。該應用程序很可能旨在成為多用戶感知應用程序。要了解有關多用戶感知應用程序的更多信息,請參閱構建多用戶感知應用程序

  1. 檢查android:singleUser="true"的 Android 清單。
  2. 如果為true ,則列入許可名單。系統用戶需要。
  3. 如果為false ,請繼續。在刪除之前檢查其他條件。

2.檢查應用程序是否需要受保護的存儲訪問

許多系統引導服務通常依賴於設備加密 (DE) 存儲,而不是憑證加密 (CE) 存儲。此外,直接啟動感知的系統應用程序也依賴於設備加密存儲。要了解有關直接啟動感知應用程序的更多信息,請參閱在系統應用程序中支持直接啟動

  1. 檢查 Android 清單中的android:defaultToDeviceProtectedStorage="true" ,這是許多系統啟動服務所必需的。
  2. 如果為true ,則列入許可名單。
  3. 如果為false ,請繼續。

第 2 級,應用程序組件

活動

要了解有關活動的更多信息,請參閱活動簡介

一個。檢查應用程序是否僅包含活動

活動是面向用戶界面的。由於 SYSTEM 用戶在 Automotive 中是無頭的,因此任何人都不應該與 SYSTEM 用戶交互。因此,如果應用程序僅包含活動,則該應用程序很可能與系統用戶無關。

檢查優先級和特殊特權。

  1. 如果,系統用戶可能需要。
  2. 如果,則不要將 SYSTEM 用戶列入白名單。

例如,兼容性測試套件 (CTS) ( com.android.cts.priv.ctsshim ) 僅包含活動,並且活動被定義為測試意圖過濾器。但是,由於它具有很高的權限,因此需要為 SYSTEM 用戶安裝以進行測試。

服務

要了解有關服務的更多信息,請參閱服務概述

灣。檢查服務是否被聲明為私有且不能從其他應用程序訪問

如果服務被聲明為private ,其他包將不會使用該服務。尋找android:exported="false" 。如果該服務被聲明為私有或無法從其他應用程序訪問,則它不能被其他應用程序綁定。因此,下面的步驟 C 和步驟 D 無關緊要。因此,該組件不會提供更多關於系統用戶是否需要該服務的提示。

  1. 如果,請檢查下一個組件。
  2. 如果,則繼續檢查該組件。

C。檢查系統用戶中安裝的應用程序是否可能綁定到此服務

檢查級別 1 中的許可包並確定它們綁定到的服務。跟踪此服務中的意圖過濾器和其他包中的startService

如果此服務綁定到安裝在 SYSTEM 用戶中的應用程序(例如, com.android.car.companiondevicesupport被允許在 SYSTEM 用戶中運行),則將該服務列入白名單。

  1. 如果,則列入許可名單。
  2. 如果,則繼續檢查該組件。

d。檢查服務是否與其他應用程序綁定並聲明在前台運行

尋找startForeground 。這意味著人們將在前台與應用程序進行交互。最有可能的是,SYSTEM 用戶不需要此服務,也不需要列入白名單。

  1. 如果,請勿列入白名單。
  2. 如果,繼續檢查下一個組件。

e.檢查服務是否定義為在系統進程中運行

在 AndroidManifest 中,查找android:process="system"
如果有意將服務定義為在系統進程中運行,那麼這意味著它將顯式地在與系統服務相同的進程中運行,並且應該被允許在 SYSTEM 用戶中運行。作為 Android 內存分配設計的一部分,系統服務是最後被殺死的一些進程,這意味著使用此類屬性定義的服務的重要性。要了解有關 Android 內存分配設計的更多信息,請參閱低內存殺手

  1. 如果,請勿列入白名單。
  2. 如果,繼續檢查其他組件。

例如,包com.android.networkstack.inprocess必須被列入白名單,因為它包含具有android:process="system"標記的RegularMaintenanceJobService

內容提供商

要了解有關內容提供者的更多信息,請參閱內容提供者

F。檢查系統用戶中安裝的應用程序是否依賴於此提供程序

檢查級別 1 中的許可包並檢查它們依賴的提供程序。如果在 SYSTEM 用戶中運行的應用程序(例如, com.android.car.companiondevicesupport被列入允許在 SYSTEM 用戶中運行)並且依賴於該內容提供者,則確保該內容提供者也被列入允許名單。

  1. 如果,則列入許可名單。
  2. 如果,則不要列入白名單。

例如,如果com.android.car.EXAMPLE包含單例提供程序( SystemActionsContentProviderManagedProvisioningActionsContentProvider ),它應該被 SYSTEM 用戶列入白名單。然後,如果com.android.car.EXAMPLE依賴於WebViewFactoryProviderandroid.webkit ,則com.android.webview必須被 SYSTEM 用戶列入白名單,因為它加載了android.webkit

樣品包演練

以下示例顯示如何評估包的AndroidManifest.xml

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