Xoá gói cho người dùng hệ thống

Trang này mô tả cách cải thiện hiệu suất bằng cách xác định và xoá các gói không cần thiết cho người dùng hệ thống.

Tắt các gói không cần thiết

Trong Automotive, người dùng hệ thống ở trạng thái không có giao diện người dùng, nghĩa là người dùng hệ thống không nên để người dùng sử dụng hoặc truy cập trực tiếp. Do đó, nhiều ứng dụng và dịch vụ không cần chạy trong người dùng hệ thống và có thể bị tắt để cải thiện hiệu suất. Do đó, chúng tôi đã cung cấp một tuỳ chọn để xoá các ứng dụng không cần thiết cho người dùng hệ thống (Người dùng 0).

Trên trang này, chúng ta sẽ thảo luận về hai loại người dùng:

  • HỆ THỐNG. Luôn là người dùng 0
  • ĐẦY ĐỦ. Người dùng mà con người dự định sử dụng (người dùng không phải hệ thống), Người dùng 10+

Android 11

Trong Android 11, hãy thay đổi cấu hình config_userTypePackageWhitelistMode. Bạn có thể kết hợp các cờ. Trong trường hợp này, 5 tương đương với 1 cộng với 4 (tổ hợp cờ 14).

Gắn cờ Mô tả
0 Tắt danh sách cho phép. Cài đặt tất cả các gói hệ thống; không ghi nhật ký.
1 Thực thi. Chỉ cài đặt các gói hệ thống khi các gói đó có trong danh sách cho phép.
2 Ghi lại các gói không có trong danh sách cho phép.
4 Mọi gói không được đề cập trong tệp danh sách cho phép đều được ngầm đưa vào danh sách cho phép đối với tất cả người dùng.
8 Giống như 4 cho người dùng hệ thống.
16 Bỏ qua OTA. Không cài đặt các gói hệ thống trong quá trình OTA.

Hãy xem xét các trường hợp phổ biến sau:

  • Để bật một tính năng cho danh sách cho phép đầy đủ, hãy 1 (thực thi đầy đủ)
  • Để bật một tính năng cho danh sách cho phép chưa hoàn chỉnh, 5
  • Để bật một tính năng cho người dùng SYSTEM nhằm dễ dàng phát triển cục bộ, hãy 9 (danh sách cho phép ngầm)
  • Để tắt một tính năng như thể chưa bao giờ bật, 16
  • Để tắt một tính năng và huỷ tất cả hiệu ứng trước đó, hãy 0

Cài đặt tệp XML trong thư mục sysconfig cho thiết bị (đây là cùng một thư mục chứa tệp makefile (.mk) dùng để tạo hình ảnh hệ thống cho thiết bị). Khi đặt tên cho tệp XML, hãy thêm vị trí gói được xác định trong bản dựng, ví dụ: 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 và Android 10

Cách định cấu hình tính năng này trong Android 9 và Android 10:

  1. Lớp phủ cấu hình config_systemUserPackagesBlacklistSupported từ frameworks/base/core/res/res/values/config.xml và đặt cấu hình đó thành true. Theo mặc định, khi tính năng này được bật, bạn phải cài đặt tất cả các gói cho cả người dùng hệ thống và người dùng FULL.
  2. Tạo tệp config.xml liệt kê các gói cần tắt cho người dùng hệ thống, ví dụ:
    <config>
        <!-- This package will be uninstalled for the system user -->
        <system-user-blacklisted-app package="com.google.car.calendar" />
    </config>
  3. Thêm một dòng vào device.mk để sao chép tệp vào thư mục mục tiêu system/etc/sysconfig/ của thiết bị, ví dụ:
    PRODUCT_COPY_FILES += <full path to the config file>:system/etc/sysconfig/<new denylist config file>.xml

Xác minh kết quả

Để xác minh kết quả, hãy chạy:

$ 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

Văn phòng

Để xác định xem một gói có được cài đặt trong người dùng hệ thống hay không, hãy kiểm tra tệp AndroidManifest.xml của gói nằm ở gốc nguồn dự án, bao gồm cả các thuộc tính của ứng dụng và thành phần của ứng dụng, bao gồm tất cả các hoạt động, dịch vụ, broadcast receiver và nhà cung cấp nội dung. Để tìm hiểu thêm, hãy xem bài viết Tổng quan về tệp kê khai ứng dụng.

Tắt quy trình làm việc của gói

Hình 1. Tắt quy trình công việc của gói.

Cấp 1, cấp ứng dụng

1. Kiểm tra xem ứng dụng (hoặc các thành phần ứng dụng) có được khai báo là singleton hay không

Nếu ứng dụng là singleton, hệ thống sẽ chỉ tạo thực thể cho ứng dụng đó trong người dùng hệ thống. Có thể ứng dụng này được thiết kế để nhận biết nhiều người dùng. Để tìm hiểu thêm về ứng dụng nhận biết nhiều người dùng, hãy xem phần Tạo ứng dụng nhận biết nhiều người dùng.

  1. Kiểm tra tệp kê khai Android để tìm android:singleUser="true".
  2. Nếu là true, hãy thêm vào danh sách cho phép. Cần thiết cho người dùng hệ thống.
  3. Nếu là false, hãy tiếp tục. Hãy kiểm tra các tiêu chí khác trước khi xoá.

2. Kiểm tra xem ứng dụng có yêu cầu quyền truy cập vào bộ nhớ được bảo vệ hay không

Nhiều dịch vụ khởi động hệ thống thường dựa vào bộ nhớ được mã hoá thiết bị (DE) thay vì bộ nhớ được mã hoá thông tin xác thực (CE). Ngoài ra, các ứng dụng hệ thống có khả năng nhận biết khởi động trực tiếp cũng dựa vào bộ nhớ được mã hoá của thiết bị. Để tìm hiểu thêm về các ứng dụng nhận biết tính năng khởi động trực tiếp, hãy xem phần Hỗ trợ tính năng Khởi động trực tiếp trong ứng dụng hệ thống.

  1. Kiểm tra tệp kê khai Android để biết android:defaultToDeviceProtectedStorage="true", cần thiết cho nhiều dịch vụ khởi động hệ thống.
  2. Nếu là true, hãy thêm vào danh sách cho phép.
  3. Nếu giá trị là false, hãy tiếp tục.

Cấp 2, thành phần ứng dụng

Hoạt động

Để tìm hiểu thêm về hoạt động, hãy xem phần Giới thiệu về hoạt động.

a. Kiểm tra xem ứng dụng có chỉ chứa hoạt động hay không

Hoạt động được định hướng giao diện người dùng. Vì người dùng hệ thống không có giao diện người dùng trong Automotive nên sẽ không có người nào tương tác với người dùng hệ thống. Do đó, nếu chỉ chứa các hoạt động, thì ứng dụng có nhiều khả năng không liên quan đến người dùng hệ thống.

Kiểm tra mức độ ưu tiên và đặc quyền:

  1. Nếu , có thể cần thiết cho người dùng hệ thống.
  2. Nếu Không, đừng đưa người dùng hệ thống vào danh sách cho phép.

Ví dụ: Bộ kiểm tra tính tương thích (CTS) (com.android.cts.priv.ctsshim) chỉ chứa các hoạt động và các hoạt động được xác định để kiểm thử bộ lọc ý định. Tuy nhiên, vì CTS có đặc quyền cao nên cần được cài đặt cho người dùng hệ thống để phục vụ mục đích kiểm thử.

Dịch vụ

Để tìm hiểu thêm về các dịch vụ, hãy xem bài viết Tổng quan về dịch vụ.

b. Kiểm tra xem dịch vụ có được khai báo là riêng tư và không thể truy cập được từ các ứng dụng khác hay không

Nếu dịch vụ được khai báo là riêng tư, các gói khác sẽ không sử dụng dịch vụ đó. Tìm android:exported="false". Nếu dịch vụ được khai báo là riêng tư hoặc không thể truy cập được qua các ứng dụng khác, thì các ứng dụng khác sẽ không thể liên kết dịch vụ đó. Do đó, Bước c và Bước d bên dưới không liên quan. Do đó, thành phần này sẽ không cung cấp thêm gợi ý về việc người dùng hệ thống có cần dịch vụ hay không.

  • Nếu , hãy kiểm tra thành phần tiếp theo.
  • Nếu Không, hãy tiếp tục kiểm tra thành phần này.

c. Kiểm tra xem các ứng dụng được cài đặt trong người dùng hệ thống có thể liên kết với dịch vụ này hay không

Kiểm tra các gói có trong danh sách cho phép ở Cấp 1 và xác định dịch vụ liên kết với các gói đó. Theo dõi từ bộ lọc ý định trong dịch vụ này và startService trong các gói khác.

Nếu dịch vụ này được liên kết với các ứng dụng được cài đặt của người dùng hệ thống (ví dụ: com.android.car.companiondevicesupport được đưa vào danh sách cho phép để chạy trong người dùng hệ thống), hãy thêm dịch vụ vào danh sách cho phép:

  • Nếu , hãy thêm vào danh sách cho phép.
  • Nếu Không, hãy tiếp tục kiểm tra thành phần này.

d. Kiểm tra xem dịch vụ có được liên kết từ các ứng dụng khác và được khai báo để chạy trên nền trước hay không

Tìm startForeground. Điều này có nghĩa là mọi người sẽ tương tác với ứng dụng ở nền trước. Rất có thể, người dùng hệ thống sẽ không cần đến dịch vụ này và không cần đưa vào danh sách cho phép:

  • Nếu , đừng thêm vào danh sách cho phép.
  • Nếu No (Không), hãy tiếp tục kiểm tra thành phần tiếp theo.

e. Kiểm tra xem dịch vụ có được xác định là chạy trong quy trình hệ thống hay không

Trong tệp AndroidManifest, hãy tìm android:process="system". Nếu dịch vụ được xác định một cách có chủ ý để chạy trong quy trình hệ thống, thì dịch vụ đó sẽ chạy trong cùng một quy trình với dịch vụ hệ thống và phải được đưa vào danh sách cho phép để chạy trong người dùng hệ thống. Theo thiết kế phân bổ bộ nhớ của Android, dịch vụ hệ thống là một số quy trình cuối cùng bị loại bỏ. Điều này cho thấy tầm quan trọng của các dịch vụ được xác định bằng thuộc tính như vậy. Để tìm hiểu thêm về thiết kế phân bổ bộ nhớ của Android, hãy xem phần Low-memory killer (đóng các mô-đun bộ nhớ thấp).

  • Nếu , thì đừng đưa vào danh sách cho phép.
  • Nếu Không, hãy tiếp tục kiểm tra các thành phần khác.

Ví dụ: gói com.android.networkstack.inprocess phải được đưa vào danh sách cho phép vì gói này chứa RegularMaintenanceJobService có thẻ android:process="system".

Trình cung cấp nội dung

Để tìm hiểu thêm về trình cung cấp nội dung, hãy xem bài viết Trình cung cấp nội dung.

th Kiểm tra xem ứng dụng được cài đặt trong người dùng hệ thống có phụ thuộc vào nhà cung cấp này hay không

Kiểm tra các gói trong danh sách cho phép ở Cấp 1 và kiểm tra xem các gói đó phụ thuộc vào nhà cung cấp nào. Nếu một ứng dụng chạy trong người dùng hệ thống (ví dụ: com.android.car.companiondevicesupport có trong danh sách cho phép để chạy trong người dùng hệ thống) và phụ thuộc vào nhà cung cấp nội dung này, hãy đảm bảo rằng nhà cung cấp nội dung này cũng có trong danh sách cho phép.

  1. Nếu , hãy thêm vào danh sách cho phép.
  2. Nếu Không, đừng thêm vào danh sách cho phép.

Ví dụ: nếu com.android.car.EXAMPLE chứa các trình cung cấp singleton (SystemActionsContentProviderManagedProvisioningActionsContentProvider), thì trình cung cấp đó phải được đưa vào danh sách cho phép đối với người dùng hệ thống. Sau đó, nếu com.android.car.EXAMPLE phụ thuộc vào android.webkit cho WebViewFactoryProvider, thì com.android.webview phải được đưa vào danh sách cho phép cho người dùng hệ thống vì nó tải android.webkit.

Hướng dẫn từng bước về gói mẫu

Ví dụ sau đây cho thấy cách đánh giá AndroidManifest.xml của một gói:

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