หน้านี้จะอธิบายวิธีปรับปรุงประสิทธิภาพด้วยการระบุและนำแพ็กเกจที่ไม่จำเป็นสำหรับผู้ใช้ระบบออก
ปิดใช้แพ็กเกจที่ไม่จำเป็น
ใน 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
- วางซ้อนการกําหนดค่า
config_systemUserPackagesBlacklistSupported
จากframeworks/base/core/res/res/values/config.xml
และตั้งค่าเป็นtrue
เมื่อเปิดใช้ฟีเจอร์นี้ ระบบจะติดตั้งแพ็กเกจทั้งหมดโดยค่าเริ่มต้นสำหรับทั้งผู้ใช้ระบบและผู้ใช้ที่มีสิทธิ์เต็ม - สร้างไฟล์
config.xml
ที่ระบุแพ็กเกจที่ควรปิดใช้สำหรับผู้ใช้ระบบ เช่น<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
สถานที่ตั้ง
ในการพิจารณาว่าควรติดตั้งแพ็กเกจในผู้ใช้ระบบหรือไม่ ให้ตรวจสอบไฟล์ AndroidManifest.xml
ของแพ็กเกจซึ่งอยู่ที่รูทของแหล่งที่มาของโปรเจ็กต์ รวมถึงแอตทริบิวต์ของแอปและคอมโพเนนต์ของแอป ซึ่งรวมถึงกิจกรรม บริการ ผู้รับออกอากาศ และผู้ให้บริการเนื้อหาทั้งหมด ดูข้อมูลเพิ่มเติมได้ที่ภาพรวมของไฟล์ Manifest
รูปที่ 1 ปิดใช้เวิร์กโฟลว์แพ็กเกจ
ระดับ 1 ระดับแอป
1. ตรวจสอบว่าแอป (หรือคอมโพเนนต์ของแอป) ได้รับการประกาศเป็น Singleton หรือไม่
หากแอปเป็น Singleton ระบบจะสร้างอินสแตนซ์แอปในผู้ใช้ระบบเท่านั้น เป็นไปได้ว่าแอปนี้มีไว้สำหรับผู้ใช้หลายคน ดูข้อมูลเพิ่มเติมเกี่ยวกับแอปที่รองรับผู้ใช้หลายคนได้ที่สร้างแอปที่รองรับผู้ใช้หลายคน
- ตรวจสอบไฟล์ Manifest ของ Android สำหรับ
android:singleUser="true"
- หากเป็น
true
ให้เพิ่มรายการที่อนุญาต ต้องใช้สำหรับผู้ใช้ระบบ - หากเป็น
false
ให้ดำเนินการต่อ โปรดตรวจสอบเกณฑ์อื่นๆ ก่อนนำออก
2. ตรวจสอบว่าแอปต้องการสิทธิ์เข้าถึงพื้นที่เก็บข้อมูลที่มีการป้องกันหรือไม่
บริการการบูตระบบจำนวนมากมักใช้พื้นที่เก็บข้อมูลที่เข้ารหัสอุปกรณ์ (DE) แทนพื้นที่เก็บข้อมูลที่เข้ารหัสข้อมูลเข้าสู่ระบบ (CE) นอกจากนี้ แอประบบที่รับรู้การเปิดเครื่องโดยตรงยังต้องอาศัยพื้นที่เก็บข้อมูลที่เข้ารหัสของอุปกรณ์ด้วย ดูข้อมูลเพิ่มเติมเกี่ยวกับแอปที่รับรู้การเปิดเครื่องโดยตรงได้ที่การรองรับการเปิดเครื่องโดยตรงในแอประบบ
- ตรวจสอบไฟล์ Manifest ของ Android สำหรับ
android:defaultToDeviceProtectedStorage="true"
ซึ่งจำเป็นสำหรับบริการบูตระบบจำนวนมาก - หากเป็น
true
ให้เพิ่มลงในรายการที่อนุญาต - หากเป็น
false
ให้ดำเนินการต่อ
ระดับ 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
อยู่ในรายการที่อนุญาตให้ทำงานในผู้ใช้ระบบ) และใช้ผู้ให้บริการเนื้อหารายนี้ ให้ตรวจสอบว่าผู้ให้บริการเนื้อหารายนี้อยู่ในรายการที่อนุญาตด้วย
- หากใช่ ให้เพิ่มลงในรายการที่อนุญาต
- หากตอบว่าไม่ ก็ไม่ต้องเพิ่มในรายการที่อนุญาต
ตัวอย่างเช่น หาก 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>