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

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

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

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

ในหน้านี้ เราจะกล่าวถึงผู้ใช้ 2 ประเภท ดังนี้

  • ระบบ ผู้ใช้ 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) นอกจากนี้ แอประบบที่รับรู้การเปิดเครื่องโดยตรงยังต้องอาศัยพื้นที่เก็บข้อมูลที่เข้ารหัสของอุปกรณ์ด้วย ดูข้อมูลเพิ่มเติมเกี่ยวกับแอปที่รับรู้การเปิดเครื่องโดยตรงได้ที่การรองรับการเปิดเครื่องโดยตรงในแอประบบ

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

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

กิจกรรม

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

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

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

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

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

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

บริการ

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

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

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

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

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

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

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

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

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

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

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

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

ให้มองหา android:process="system" ในไฟล์ AndroidManifest หากตั้งใจกำหนดให้บริการทำงานในกระบวนการของระบบ บริการดังกล่าวจะทำงานในกระบวนการเดียวกันกับบริการของระบบและควรอยู่ในรายการที่อนุญาตให้ทำงานในผู้ใช้ระบบ บริการของระบบเป็นหนึ่งในกระบวนการสุดท้ายที่จะถูกสิ้นสุดการทำงานตามการออกแบบการจัดสรรหน่วยความจำของ 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>