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

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

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

ในยานยนต์ ผู้ใช้ระบบ ไม่มีหัว ซึ่งหมายความว่าผู้ใช้ระบบไม่ได้ตั้งใจให้มนุษย์ใช้หรือเข้าถึงโดยตรง ด้วยเหตุนี้ แอปและบริการจำนวนมากจึงไม่จำเป็นต้องทำงานในผู้ใช้ระบบ และสามารถปิดใช้งานได้เพื่อปรับปรุงประสิทธิภาพ ดังนั้นจึงมีตัวเลือกในการลบแอพที่ไม่จำเป็นสำหรับผู้ใช้ระบบ (ผู้ใช้ 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:

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

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

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

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

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

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

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

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

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

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

ระดับ 2 ส่วนประกอบแอป

กิจกรรม

หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับกิจกรรม โปรดดูที่ บทนำสู่กิจกรรม

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

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

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

  1. ถ้า ใช่ อาจจำเป็นสำหรับผู้ใช้ระบบ
  2. หาก ไม่มี ไม่ต้องอนุญาตสำหรับผู้ใช้ระบบ

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

บริการ

หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับบริการ โปรดดูที่ ภาพรวมบริการ

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

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

  1. ถ้า ใช่ ให้ตรวจสอบส่วนประกอบถัดไป
  2. หาก ไม่มี ให้ตรวจสอบส่วนประกอบนี้ต่อไป

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

ตรวจสอบแพ็คเกจที่อนุญาตในระดับ 1 และระบุบริการที่ผูกมัดไว้ ติดตามจากตัวกรองเจตนาในบริการนี้และ startService ในแพ็คเกจอื่น

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

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

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

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

  1. หาก ใช่ ไม่ต้องอนุญาต
  2. หาก ไม่มี ให้ตรวจสอบส่วนประกอบถัดไปต่อไป

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

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

  1. หาก ใช่ ไม่ต้องอนุญาต
  2. หาก ไม่มี ให้ตรวจสอบส่วนประกอบอื่นๆ ต่อไป

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

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

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

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

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

  1. หาก ใช่ รายการที่อนุญาต
  2. หาก ไม่มี ไม่ต้องอนุญาต

ตัวอย่างเช่น หาก 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>