นำแพ็กเกจสำหรับผู้ใช้ระบบออก

หน้านี้อธิบายวิธีปรับปรุงประสิทธิภาพโดยการระบุและนำแพ็กเกจที่ไม่จำเป็นสำหรับผู้ใช้ระบบออก

ปิดใช้แพ็กเกจที่ไม่จำเป็น

ในยานยนต์ ผู้ใช้ระบบจะไม่มีการแสดงผล ซึ่งหมายความว่าผู้ใช้ระบบไม่ได้มีไว้เพื่อให้มนุษย์ใช้งานหรือเข้าถึงโดยตรง ด้วยเหตุนี้ แอปและบริการจำนวนมากจึงไม่จำเป็นต้องทำงานในบัญชีผู้ใช้ระบบและสามารถปิดใช้ได้เพื่อเพิ่มประสิทธิภาพ ดังนั้นจึงมีตัวเลือกให้นำแอปที่ไม่จำเป็นออกสำหรับผู้ใช้ระบบ (ผู้ใช้ 0)

ในหน้านี้ เราจะพูดถึงผู้ใช้ 2 ประเภท ได้แก่

  • SYSTEM ผู้ใช้ 0 เสมอ
  • FULL ผู้ใช้ที่มีไว้สำหรับมนุษย์ (ผู้ใช้ที่ไม่ใช่ระบบ) ผู้ใช้ 10 คนขึ้นไป

Android 11

ใน Android 11 ให้เปลี่ยนการกําหนดค่า config_userTypePackageWhitelistMode คุณรวมการแจ้งว่าไม่เหมาะสมได้ ในกรณีนี้ 5 เท่ากับ 1บวก 4 (การรวม Flag 1 และ 4)

ตั้งค่าสถานะ คำอธิบาย
0 ปิดใช้รายการที่อนุญาต ติดตั้งแพ็กเกจระบบทั้งหมด ไม่มีการบันทึก
1 บังคับใช้ ติดตั้งแพ็กเกจระบบเฉพาะเมื่ออยู่ในรายการที่อนุญาตเท่านั้น
2 บันทึกแพ็กเกจที่ไม่ได้รับอนุญาต
4 ระบบจะถือว่าแพ็กเกจที่ไม่ได้กล่าวถึงในไฟล์รายการที่อนุญาตอยู่ในรายการที่อนุญาตโดยปริยายสำหรับผู้ใช้ทุกคน
8 เหมือนกับ 4 สำหรับผู้ใช้ระบบ
16 ละเว้น OTA อย่าติดตั้งแพ็กเกจระบบระหว่าง OTA

พิจารณาสถานการณ์ทั่วไปต่อไปนี้

  • หากต้องการเปิดใช้ฟีเจอร์สําหรับรายการที่อนุญาตทั้งหมด ให้ใช้ 1 (บังคับใช้อย่างเต็มรูปแบบ)
  • หากต้องการเปิดใช้ฟีเจอร์สำหรับรายการที่อนุญาตที่ไม่สมบูรณ์ ให้ทำดังนี้ 5
  • หากต้องการเปิดใช้ฟีเจอร์สำหรับผู้ใช้ SYSTEM เพื่อพัฒนาแอปในเครื่องได้ง่ายขึ้น ให้ทำดังนี้ 9 (รายการที่อนุญาตโดยนัย)
  • หากต้องการปิดใช้ฟีเจอร์ราวกับว่าไม่เคยเปิดใช้มาก่อน ให้กด 16
  • หากต้องการปิดใช้ฟีเจอร์และเลิกทำเอฟเฟกต์ก่อนหน้าทั้งหมด ให้กด 0

ติดตั้งไฟล์ XML ในไดเรกทอรี sysconfig สำหรับอุปกรณ์ (ซึ่งเป็นไดเรกทอรีเดียวกับที่มีไฟล์ make (.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->

Android 9 และ Android 10

วิธีกำหนดค่าฟีเจอร์นี้ใน Android 9 และ Android 10

  1. วางซ้อนการกําหนดค่า config_systemUserPackagesBlacklistSupported จาก frameworks/base/core/res/res/values/config.xml และตั้งค่าเป็น true เมื่อเปิดใช้ฟีเจอร์นี้ ระบบจะติดตั้งแพ็กเกจทั้งหมดโดยค่าเริ่มต้นสำหรับทั้งผู้ใช้ระบบและผู้ใช้ที่มีสิทธิ์เต็ม
  2. สร้างไฟล์ config.xml ที่แสดงรายการแพ็กเกจที่ควรปิดใช้สำหรับผู้ใช้ระบบ เช่น
    <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

สถานที่ตั้ง

หากต้องการตรวจสอบว่าควรติดตั้งแพ็กเกจในผู้ใช้ระบบหรือไม่ ให้ตรวจสอบไฟล์ AndroidManifest.xml ของแพ็กเกจซึ่งอยู่ที่รูทของแหล่งที่มาของโปรเจ็กต์ รวมถึงแอตทริบิวต์ของแอปและคอมโพเนนต์ของแอป ซึ่งรวมถึงกิจกรรม บริการ ตัวรับสัญญาณการออกอากาศ และผู้ให้บริการเนื้อหาทั้งหมด ดูข้อมูลเพิ่มเติมได้ที่ภาพรวมของไฟล์ Manifest

ปิดใช้เวิร์กโฟลว์แพ็กเกจ

รูปที่ 1 ปิดใช้เวิร์กโฟลว์แพ็กเกจ

ระดับ 1 ระดับแอป

1. ตรวจสอบว่าแอป (หรือคอมโพเนนต์ของแอป) ได้รับการประกาศเป็น Singleton หรือไม่

หากแอปเป็น Singleton ระบบจะสร้างอินสแตนซ์แอปในผู้ใช้ระบบเท่านั้น เป็นไปได้ว่าแอปนี้มีไว้สำหรับผู้ใช้หลายคน ดูข้อมูลเพิ่มเติมเกี่ยวกับแอปที่รองรับผู้ใช้หลายคนได้ที่สร้างแอปที่รองรับผู้ใช้หลายคน

  1. ตรวจสอบไฟล์ Manifest ของ Android สำหรับ android:singleUser="true"
  2. หากเป็น true ให้เพิ่มลงในรายการที่อนุญาต จำเป็นสำหรับผู้ใช้ระบบ
  3. หากเป็น false ให้ดำเนินการต่อ โปรดตรวจสอบเกณฑ์อื่นๆ ก่อนนำออก

2. ตรวจสอบว่าแอปกำหนดให้ต้องเข้าถึงพื้นที่เก็บข้อมูลที่ปลอดภัยหรือไม่

บริการบูตระบบหลายอย่างมักใช้พื้นที่เก็บข้อมูลที่เข้ารหัสอุปกรณ์ (DE) แทนพื้นที่เก็บข้อมูลที่เข้ารหัสข้อมูลเข้าสู่ระบบ (CE) นอกจากนี้ แอประบบที่ทราบเกี่ยวกับการบูตโดยตรงยังใช้พื้นที่เก็บข้อมูลที่เข้ารหัสของอุปกรณ์ด้วย ดูข้อมูลเพิ่มเติมเกี่ยวกับแอปที่รองรับ Direct Boot ได้ที่การรองรับ Direct Boot ในแอประบบ

  1. ตรวจสอบไฟล์ Manifest ของ Android สำหรับ android:defaultToDeviceProtectedStorage="true" ซึ่งจำเป็นสำหรับบริการบูตระบบจำนวนมาก
  2. หากเป็น true ให้เพิ่มลงในรายการที่อนุญาต
  3. หากเป็น false ให้ดำเนินการต่อ

ระดับ 2 คอมโพเนนต์ของแอป

กิจกรรม

ดูข้อมูลเพิ่มเติมเกี่ยวกับกิจกรรมได้ที่ข้อมูลเบื้องต้นเกี่ยวกับกิจกรรม

ก. ตรวจสอบว่าแอปมีเฉพาะกิจกรรม

กิจกรรมมีจุดมุ่งหมายเพื่ออินเทอร์เฟซผู้ใช้ เนื่องจากผู้ใช้ระบบเป็นแบบ headless ในยานยนต์ ไม่ควรมีมนุษย์โต้ตอบกับผู้ใช้ระบบ ดังนั้น หากแอปมีกิจกรรมเท่านั้น แสดงว่าแอปนั้นไม่เกี่ยวข้องกับผู้ใช้ระบบ

ตรวจสอบลำดับความสำคัญและสิทธิ์พิเศษ

  1. หากเลือกใช่ ผู้ใช้ระบบอาจต้องใช้
  2. หากเป็นไม่ อย่าเพิ่มผู้ใช้ระบบในรายการที่อนุญาต

เช่น ชุดเครื่องมือทดสอบความเข้ากันได้ (CTS) (com.android.cts.priv.ctsshim) มีเฉพาะกิจกรรม และกิจกรรมได้รับการกําหนดให้ทดสอบตัวกรอง Intent อย่างไรก็ตาม เนื่องจาก CTS มีสิทธิ์ในระดับสูง จึงต้องติดตั้ง CTS ให้กับผู้ใช้ระบบเพื่อวัตถุประสงค์ในการทดสอบ

บริการ

ดูข้อมูลเพิ่มเติมเกี่ยวกับบริการได้ที่ภาพรวมบริการ

ข. ตรวจสอบว่าบริการได้รับการประกาศว่าเป็นแบบส่วนตัวและเข้าถึงจากแอปอื่นๆ ไม่ได้หรือไม่

หากประกาศบริการเป็นส่วนตัว แพ็กเกจอื่นๆ จะไม่ใช้บริการดังกล่าว มองหา android:exported="false" หากมีการประกาศบริการว่าเป็นแบบส่วนตัวหรือเข้าถึงจากแอปอื่นๆ ไม่ได้ แอปอื่นๆ จะไม่สามารถเชื่อมโยงกับบริการดังกล่าวได้ ดังนั้น ขั้นตอน c และ d ด้านล่างจึงไม่มีความหมาย ด้วยเหตุนี้ คอมโพเนนต์นี้จึงไม่ได้ให้คำแนะนำเพิ่มเติมว่าผู้ใช้ระบบจำเป็นต้องใช้บริการหรือไม่

  • หากตอบว่าใช่ ให้ตรวจสอบคอมโพเนนต์ถัดไป
  • หากไม่ ให้ตรวจสอบส่วนประกอบนี้ต่อไป

ค. ตรวจสอบว่าแอปที่ติดตั้งในผู้ใช้ระบบอาจเชื่อมโยงกับบริการนี้หรือไม่

ตรวจสอบแพ็กเกจในรายการที่อนุญาตที่ระดับ 1 และระบุบริการที่เชื่อมโยงกับแพ็กเกจ ติดตามจากตัวกรอง Intent ในบริการนี้และ startService ในแพ็กเกจอื่นๆ

หากบริการนี้เชื่อมโยงกับแอปที่ติดตั้งในผู้ใช้ระบบ (เช่น com.android.car.companiondevicesupport อยู่ในรายการที่อนุญาตให้ทำงานในผู้ใช้ระบบ) ให้เพิ่มบริการนั้นลงในรายการที่อนุญาต ดังนี้

  • หากใช่ ให้เพิ่มลงในรายการที่อนุญาต
  • หากไม่ ให้ตรวจสอบส่วนประกอบนี้ต่อไป

ง. ตรวจสอบว่าบริการมีการเชื่อมโยงจากแอปอื่นๆ และประกาศให้ทำงานอยู่เบื้องหน้าหรือไม่

มองหา startForeground ซึ่งหมายความว่าผู้ใช้จะโต้ตอบกับแอปในเบื้องหน้า ผู้ใช้ระบบส่วนใหญ่ไม่จําเป็นต้องใช้บริการนี้และไม่จำเป็นต้องอยู่ในรายการที่อนุญาต

  • หากตอบว่าใช่ ก็ไม่ต้องเพิ่มในรายการที่อนุญาต
  • หากไม่ ให้ตรวจสอบคอมโพเนนต์ถัดไป

จ. ตรวจสอบว่ามีการกําหนดบริการให้ทํางานในกระบวนการของระบบหรือไม่

ในไฟล์ AndroidManifest ให้มองหา android:process="system" หากมีการกําหนดบริการให้ทํางานในกระบวนการของระบบโดยเจตนา บริการจะทํางานในกระบวนการเดียวกับบริการของระบบและควรอยู่ในรายการที่อนุญาตให้ทํางานในผู้ใช้ระบบ บริการของระบบเป็นหนึ่งในกระบวนการสุดท้ายที่จะถูกสิ้นสุดการทำงานตามการออกแบบการจัดสรรหน่วยความจำของ Android ซึ่งบ่งบอกถึงความสำคัญของบริการที่กําหนดด้วยแอตทริบิวต์ดังกล่าว ดูข้อมูลเพิ่มเติมเกี่ยวกับการออกแบบการจัดสรรหน่วยความจำของ Android ได้ที่โปรแกรมที่ปิดอยู่เนื่องจากหน่วยความจำต่ำ

  • หากตอบว่าใช่ ก็ไม่ต้องเพิ่มในรายการที่อนุญาต
  • หากไม่ ให้ตรวจสอบส่วนประกอบอื่นๆ ต่อ

เช่น แพ็กเกจ com.android.networkstack.inprocess ต้องอยู่ในรายการที่อนุญาตเนื่องจากมี RegularMaintenanceJobService ซึ่งมีแท็ก android:process="system"

ผู้ให้บริการเนื้อหา

ดูข้อมูลเพิ่มเติมเกี่ยวกับผู้ให้บริการเนื้อหาได้ที่หัวข้อผู้ให้บริการเนื้อหา

ฉ. ตรวจสอบว่าแอปที่ติดตั้งในผู้ใช้ระบบต้องอาศัยผู้ให้บริการรายนี้หรือไม่

ตรวจสอบแพ็กเกจในรายการที่อนุญาตในเลเวล 1 และตรวจสอบผู้ให้บริการที่ใช้แพ็กเกจดังกล่าว หากแอปที่ทำงานในผู้ใช้ระบบ (เช่น com.android.car.companiondevicesupport อยู่ในรายการที่อนุญาตให้ทำงานในผู้ใช้ระบบ) และใช้ผู้ให้บริการเนื้อหารายนี้ ให้ตรวจสอบว่าผู้ให้บริการเนื้อหารายนี้อยู่ในรายการที่อนุญาตด้วย

  1. หากใช่ ให้เพิ่มลงในรายการที่อนุญาต
  2. หากตอบว่าไม่ ก็ไม่ต้องเพิ่มในรายการที่อนุญาต

ตัวอย่างเช่น หาก com.android.car.EXAMPLE มีผู้ให้บริการแบบเดี่ยว (SystemActionsContentProvider และ ManagedProvisioningActionsContentProvider) ก็ควรอยู่ในรายการที่อนุญาตสําหรับผู้ใช้ระบบ จากนั้น หาก com.android.car.EXAMPLE ขึ้นอยู่กับ android.webkit สําหรับ WebViewFactoryProvider com.android.webview จะต้องอยู่ในรายการที่อนุญาตสําหรับผู้ใช้ระบบ เนื่องจากโหลด 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>