บทความนี้อธิบายวิธีการปรับปรุงประสิทธิภาพโดยการระบุและการลบแพ็คเกจที่ไม่จำเป็นสำหรับผู้ใช้ระบบ
ปิดการใช้งานแพ็คเกจที่ไม่จำเป็น
ในยานยนต์ ผู้ใช้ระบบ ไม่มีหัว ซึ่งหมายความว่าผู้ใช้ระบบไม่ได้ตั้งใจให้มนุษย์ใช้หรือเข้าถึงโดยตรง ด้วยเหตุนี้ แอปและบริการจำนวนมากจึงไม่จำเป็นต้องทำงานในผู้ใช้ระบบ และสามารถปิดใช้งานได้เพื่อปรับปรุงประสิทธิภาพ ดังนั้นจึงมีตัวเลือกในการลบแอพที่ไม่จำเป็นสำหรับผู้ใช้ระบบ (ผู้ใช้ 0)
ในหน้านี้ มีการพูดคุยถึงผู้ใช้สองประเภท:
- ระบบ . ผู้ใช้ 0 เสมอ
- เต็ม . ผู้ใช้ที่มุ่งหมายให้มนุษย์ใช้งาน (ผู้ใช้ที่ไม่ใช่ระบบ) ผู้ใช้อายุ 10 ปีขึ้นไป
แอนดรอยด์ 11
ใน Android 11 คุณเปลี่ยนการกำหนดค่า config_userTypePackageWhitelistMode
สามารถรวมธงได้ ในกรณีนี้ 5
เท่ากับ 1
บวก 4
(การรวมกันของแฟล็ก 1
และ 4
)
ธง | คำอธิบาย |
---|---|
0 | ปิดการใช้งานรายการที่อนุญาต ติดตั้งแพ็คเกจระบบทั้งหมด ไม่มีการบันทึก |
1 | บังคับใช้ ติดตั้งแพ็คเกจระบบเฉพาะเมื่ออยู่ในรายการที่อนุญาตเท่านั้น |
2 | บันทึกแพ็คเกจที่ไม่อนุญาต |
4 | แพ็กเกจใดๆ ที่ไม่ได้กล่าวถึงในไฟล์รายการที่อนุญาตจะถือเป็นรายการที่อนุญาตโดยปริยายสำหรับผู้ใช้ทุกคน |
8 | เช่นเดียวกับ 4 สำหรับผู้ใช้ระบบ |
16 | ละเว้น OTA อย่าติดตั้งแพ็คเกจระบบระหว่าง OTA |
- หากต้องการเปิดใช้ฟีเจอร์สำหรับรายการที่อนุญาตทั้งหมด
1
( บังคับใช้อย่างสมบูรณ์ ) - หากต้องการเปิดใช้ฟีเจอร์สำหรับรายการที่อนุญาตที่ไม่สมบูรณ์
5
- เพื่อเปิดใช้งานคุณสมบัติสำหรับผู้ใช้
SYSTEM
เพื่อความสะดวกในการพัฒนาท้องถิ่น9
( รายการที่อนุญาตโดยนัย ) - หากต้องการปิดใช้งานคุณลักษณะเหมือนกับไม่เคยเปิดใช้งานมาก่อน
16
- หากต้องการปิดใช้งานคุณสมบัติและเลิกทำเอฟเฟกต์ก่อนหน้าทั้งหมด
0
อย่าลืมติดตั้งไฟล์ XML ในไดเร็กทอรี sysconfig
สำหรับอุปกรณ์ (นี่คือไดเร็กทอรีเดียวกับที่มี 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->
ระบบปฏิบัติการ 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
ของแพ็คเกจที่อยู่ที่รากของแหล่งที่มาของโปรเจ็กต์ รวมถึงแอตทริบิวต์ของแอพและส่วนประกอบของแอพ ซึ่งรวมถึงกิจกรรม บริการ เครื่องรับการออกอากาศทั้งหมด และผู้ให้บริการเนื้อหา หากต้องการเรียนรู้เพิ่มเติม โปรดดูที่ ภาพรวมรายการแอป
รูปที่ 1. ปิดใช้งานเวิร์กโฟลว์แพ็คเกจ
ระดับ 1 ระดับแอป
1. ตรวจสอบว่าแอป (หรือส่วนประกอบของแอป) ได้รับการประกาศเป็นซิงเกิลตันหรือไม่
หากแอปเป็น แบบซิงเกิลตัน ระบบจะสร้างแอปใน System User เท่านั้น เป็นไปได้ว่าแอปนี้ตั้งใจให้เป็นแอปที่คำนึงถึงผู้ใช้หลายคน หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับแอปที่รับรู้ถึงผู้ใช้หลายราย โปรดดูที่ การสร้างแอปที่รับรู้ถึงผู้ใช้หลายคน
- ตรวจสอบรายการ Android สำหรับ
android:singleUser="true"
- หาก เป็นจริง รายการที่อนุญาต จำเป็นสำหรับผู้ใช้ระบบ
- หากเป็น เท็จ ให้ดำเนินการต่อ ตรวจสอบเกณฑ์อื่นๆ ก่อนนำออก
2. ตรวจสอบว่าแอปต้องการการเข้าถึงที่เก็บข้อมูลที่มีการป้องกันหรือไม่
บริการบูตระบบจำนวนมากมักจะอาศัยพื้นที่เก็บข้อมูลที่เข้ารหัสอุปกรณ์ (DE) แทนพื้นที่เก็บข้อมูลที่เข้ารหัสข้อมูลรับรอง (CE) นอกจากนี้ แอประบบที่รับรู้ถึงการบูตโดยตรงยังต้องอาศัยพื้นที่จัดเก็บข้อมูลที่เข้ารหัสของอุปกรณ์อีกด้วย หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับแอปที่รับรู้การบูตโดยตรง โปรดดูที่ การสนับสนุนการบูตโดยตรงในแอประบบ
- ตรวจสอบรายการ Android สำหรับ
android:defaultToDeviceProtectedStorage="true"
ซึ่งจำเป็นสำหรับบริการบูตระบบจำนวนมาก - หาก เป็นจริง รายการที่อนุญาต
- หากเป็น เท็จ ให้ดำเนินการต่อ
ระดับ 2 ส่วนประกอบแอป
กิจกรรม
หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับกิจกรรม โปรดดูที่ บทนำสู่กิจกรรม
ก. ตรวจสอบว่าแอปมีเฉพาะกิจกรรมหรือไม่
กิจกรรมต่างๆ เน้นที่ส่วนต่อประสานกับผู้ใช้ เนื่องจากผู้ใช้ระบบไม่มีหัวในยานยนต์ จึงไม่ควรมีมนุษย์โต้ตอบกับผู้ใช้ระบบ ด้วยเหตุนี้ หากแอปมีเฉพาะกิจกรรม แอปก็มีแนวโน้มว่าจะไม่เกี่ยวข้องกับผู้ใช้ระบบ
ตรวจสอบลำดับความสำคัญและสิทธิพิเศษ
- ถ้า ใช่ อาจจำเป็นสำหรับผู้ใช้ระบบ
- หาก ไม่มี ไม่ต้องอนุญาตสำหรับผู้ใช้ระบบ
ตัวอย่างเช่น ชุดทดสอบความเข้ากันได้ (CTS) ( com.android.cts.priv.ctsshim
) มีเฉพาะกิจกรรม และกิจกรรมถูกกำหนดไว้เพื่อทดสอบตัวกรองเจตนา อย่างไรก็ตาม เนื่องจากมีสิทธิ์สูง จึงจำเป็นต้องติดตั้งสำหรับผู้ใช้ระบบเพื่อการทดสอบ
บริการ
หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับบริการ โปรดดูที่ ภาพรวมบริการ
ข. ตรวจสอบว่าบริการได้รับการประกาศให้เป็นส่วนตัวและไม่สามารถเข้าถึงได้จากแอปอื่นหรือไม่
หากบริการถูกประกาศเป็น private แพ็คเกจอื่น ๆ จะไม่ใช้บริการ มองหา android:exported="false"
หากบริการได้รับการประกาศให้เป็นส่วนตัวหรือไม่สามารถเข้าถึงได้จากแอปอื่น ก็จะไม่สามารถผูกมัดโดยแอปอื่นได้ ดังนั้นขั้นตอน C และขั้นตอน D ด้านล่างจึงไม่เกี่ยวข้อง ด้วยเหตุนี้ ส่วนประกอบนี้จึงไม่ได้ให้คำแนะนำเพิ่มเติมว่าผู้ใช้ระบบจำเป็นต้องมีบริการหรือไม่
- ถ้า ใช่ ให้ตรวจสอบส่วนประกอบถัดไป
- หาก ไม่มี ให้ตรวจสอบส่วนประกอบนี้ต่อไป
ค. ตรวจสอบว่าแอพที่ติดตั้งในผู้ใช้ระบบอาจเชื่อมโยงกับบริการนี้หรือไม่
ตรวจสอบแพ็คเกจที่อนุญาตในระดับ 1 และระบุบริการที่ผูกมัดไว้ ติดตามจากตัวกรองเจตนาในบริการนี้และ startService
ในแพ็คเกจอื่น
หากบริการนี้เชื่อมโยงกับแอพที่ติดตั้งในผู้ใช้ระบบ (เช่น com.android.car.companiondevicesupport
อยู่ในรายการที่อนุญาตให้เรียกใช้ในผู้ใช้ระบบ) แสดงว่าบริการนั้นอยู่ในรายการที่อนุญาต
- หาก ใช่ รายการที่อนุญาต
- หาก ไม่มี ให้ตรวจสอบส่วนประกอบนี้ต่อไป
ง. ตรวจสอบว่าบริการเชื่อมโยงกับแอปอื่นและประกาศว่าทำงานเบื้องหน้าหรือไม่
มองหา startForeground
ซึ่งหมายความว่าผู้คนจะโต้ตอบกับแอปในเบื้องหน้า เป็นไปได้มากว่าบริการนี้ไม่จำเป็นสำหรับผู้ใช้ระบบ และไม่จำเป็นต้องอยู่ในรายการที่อนุญาต
- หาก ใช่ ไม่ต้องอนุญาต
- หาก ไม่มี ให้ตรวจสอบส่วนประกอบถัดไปต่อไป
จ. ตรวจสอบว่าบริการถูกกำหนดให้ทำงานในกระบวนการของระบบหรือไม่
ใน AndroidManifest ให้มองหา android:process="system"
หากบริการถูกกำหนดโดยเจตนาให้ทำงานในกระบวนการของระบบ นั่นหมายความว่าบริการจะทำงานในกระบวนการเดียวกับบริการของระบบอย่างชัดเจน และควรได้รับอนุญาตให้ทำงานในผู้ใช้ระบบ ในฐานะที่เป็นส่วนหนึ่งของการออกแบบการจัดสรรหน่วยความจำของ Android บริการของระบบคือกระบวนการสุดท้ายบางส่วนที่จะถูกทำลาย ซึ่งบ่งบอกถึงความวิกฤตของบริการที่กำหนดด้วยคุณลักษณะดังกล่าว หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับการออกแบบการจัดสรรหน่วยความจำของ Android โปรดดู Low-memory killer
- หาก ใช่ ไม่ต้องอนุญาต
- หาก ไม่มี ให้ตรวจสอบส่วนประกอบอื่นๆ ต่อไป
ตัวอย่างเช่น แพ็คเกจ com.android.networkstack.inprocess
จะต้องอยู่ในรายการที่อนุญาตเนื่องจากมี RegularMaintenanceJobService
ซึ่งมีแท็ก android:process="system"
ผู้ให้บริการเนื้อหา
หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับผู้ให้บริการเนื้อหา โปรดดูที่ ผู้ให้บริการเนื้อหา
ฉ. ตรวจสอบว่าแอพที่ติดตั้งในผู้ใช้ระบบขึ้นอยู่กับผู้ให้บริการรายนี้หรือไม่
ตรวจสอบแพ็คเกจที่อนุญาตในระดับ 1 และตรวจสอบว่าแพ็คเกจนั้นขึ้นอยู่กับผู้ให้บริการรายใด หากแอปที่ทำงานอยู่ในผู้ใช้ระบบ (เช่น com.android.car.companiondevicesupport
อยู่ในรายการที่อนุญาตให้ทำงานในผู้ใช้ระบบ) และขึ้นอยู่กับผู้ให้บริการเนื้อหารายนี้ ให้ตรวจสอบให้แน่ใจว่าผู้ให้บริการเนื้อหารายนี้อยู่ในรายการที่อนุญาตด้วย
- หาก ใช่ รายการที่อนุญาต
- หาก ไม่มี ไม่ต้องอนุญาต
ตัวอย่างเช่น หาก com.android.car.EXAMPLE
มี singleton provider ( 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>