本文介紹如何通過識別和刪除 SYSTEM 用戶不需要的包來提高性能。
禁用不必要的軟件包
在汽車中,系統用戶是無頭的,這意味著系統用戶不打算被人使用或直接訪問。因此,許多應用程序和服務不需要在 SYSTEM 用戶中運行,並且可以禁用以提高性能。因此,提供了一個選項來為 SYSTEM 用戶(用戶 0)刪除不必要的應用程序。
在本文中,討論了兩種類型的用戶:
- 系統。總是用戶 0
- 滿。打算供人類使用的用戶(非系統用戶),用戶 10+
安卓 11
在 Android 11 中,您更改配置config_userTypePackageWhitelistMode
。可以組合標誌。在這種情況下, 5
等於1
加4
(標誌1
和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
確保在設備的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 中配置此功能:
- 覆蓋
frameworks/base/core/res/res/values/config.xml
中的config_systemUserPackagesBlacklistSupported
配置並將其設置為true
。啟用該功能後,默認情況下,應為 SYSTEM 用戶和 FULL 用戶安裝所有軟件包。 - 創建一個
config.xml
文件,列出應該為 SYSTEM 用戶禁用哪些包。例如:<config> <!-- This package will be uninstalled for the system user --> <system-user-blacklisted-app package="com.google.car.calendar" /> </config>
- 在
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 用戶中實例化應用程序。該應用程序很可能旨在成為多用戶感知應用程序。要了解有關多用戶感知應用程序的更多信息,請參閱構建多用戶感知應用程序。
- 檢查
android:singleUser="true"
的 Android 清單。 - 如果為true ,則列入許可名單。系統用戶需要。
- 如果為false ,請繼續。在刪除之前檢查其他條件。
2.檢查應用程序是否需要受保護的存儲訪問
許多系統引導服務通常依賴於設備加密 (DE) 存儲,而不是憑證加密 (CE) 存儲。此外,直接啟動感知的系統應用程序也依賴於設備加密存儲。要了解有關直接啟動感知應用程序的更多信息,請參閱在系統應用程序中支持直接啟動。
- 檢查 Android 清單中的
android:defaultToDeviceProtectedStorage="true"
,這是許多系統啟動服務所必需的。 - 如果為true ,則列入許可名單。
- 如果為false ,請繼續。
第 2 級,應用程序組件
活動
要了解有關活動的更多信息,請參閱活動簡介。
一個。檢查應用程序是否僅包含活動
活動是面向用戶界面的。由於 SYSTEM 用戶在 Automotive 中是無頭的,因此任何人都不應該與 SYSTEM 用戶交互。因此,如果應用程序僅包含活動,則該應用程序很可能與系統用戶無關。
檢查優先級和特殊特權。
- 如果是,系統用戶可能需要。
- 如果否,則不要將 SYSTEM 用戶列入白名單。
例如,兼容性測試套件 (CTS) ( com.android.cts.priv.ctsshim
) 僅包含活動,並且活動被定義為測試意圖過濾器。但是,由於它具有很高的權限,因此需要為 SYSTEM 用戶安裝以進行測試。
服務
要了解有關服務的更多信息,請參閱服務概述。
灣。檢查服務是否被聲明為私有且不能從其他應用程序訪問
如果服務被聲明為private ,其他包將不會使用該服務。尋找android:exported="false"
。如果該服務被聲明為私有或無法從其他應用程序訪問,則它不能被其他應用程序綁定。因此,下面的步驟 C 和步驟 D 無關緊要。因此,該組件不會提供更多關於系統用戶是否需要該服務的提示。
- 如果是,請檢查下一個組件。
- 如果否,則繼續檢查該組件。
C。檢查系統用戶中安裝的應用程序是否可能綁定到此服務
檢查級別 1 中的許可包並確定它們綁定到的服務。跟踪此服務中的意圖過濾器和其他包中的startService
。
如果此服務綁定到安裝在 SYSTEM 用戶中的應用程序(例如, com.android.car.companiondevicesupport
被允許在 SYSTEM 用戶中運行),則將該服務列入白名單。
- 如果是,則列入許可名單。
- 如果否,則繼續檢查該組件。
d。檢查服務是否與其他應用程序綁定並聲明在前台運行
尋找startForeground
。這意味著人們將在前台與應用程序進行交互。最有可能的是,SYSTEM 用戶不需要此服務,也不需要列入白名單。
- 如果是,請勿列入白名單。
- 如果否,繼續檢查下一個組件。
e.檢查服務是否定義為在系統進程中運行
在 AndroidManifest 中,查找android:process="system"
。
如果有意將服務定義為在系統進程中運行,那麼這意味著它將顯式地在與系統服務相同的進程中運行,並且應該被允許在 SYSTEM 用戶中運行。作為 Android 內存分配設計的一部分,系統服務是最後被殺死的一些進程,這意味著使用此類屬性定義的服務的重要性。要了解有關 Android 內存分配設計的更多信息,請參閱低內存殺手。
- 如果是,請勿列入白名單。
- 如果否,繼續檢查其他組件。
例如,包com.android.networkstack.inprocess
必須被列入白名單,因為它包含具有android:process="system"
標記的RegularMaintenanceJobService
。
內容提供商
要了解有關內容提供者的更多信息,請參閱內容提供者。
F。檢查系統用戶中安裝的應用程序是否依賴於此提供程序
檢查級別 1 中的許可包並檢查它們依賴的提供程序。如果在 SYSTEM 用戶中運行的應用程序(例如, com.android.car.companiondevicesupport
被列入允許在 SYSTEM 用戶中運行)並且依賴於該內容提供者,則確保該內容提供者也被列入允許名單。
- 如果是,則列入許可名單。
- 如果否,則不要列入白名單。
例如,如果com.android.car.EXAMPLE
包含單例提供程序( SystemActionsContentProvider
和ManagedProvisioningActionsContentProvider
),它應該被 SYSTEM 用戶列入白名單。然後,如果com.android.car.EXAMPLE
依賴於WebViewFactoryProvider
的android.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>