הסר חבילות עבור משתמש המערכת

מאמר זה מתאר כיצד לשפר את הביצועים על ידי זיהוי והסרה של חבילות שאינן נחוצות עבור משתמש המערכת.

השבת חבילות מיותרות

במכוניות, משתמש המערכת הוא חסר ראש , כלומר משתמש המערכת אינו מיועד לשימוש או גישה ישירה לאדם. כתוצאה מכך, אפליקציות ושירותים רבים אינם צריכים לפעול במשתמש המערכת וניתן להשבית אותם כדי לשפר את הביצועים. לכן, ניתנת אפשרות להסיר אפליקציות מיותרות עבור משתמש המערכת (משתמש 0).

בדף זה נדונים שני סוגי משתמשים:

  • מערכת . תמיד משתמש 0
  • מלא . משתמש שמיועד לשימוש על ידי אדם (לא משתמש מערכת), משתמש 10+

אנדרואיד 11

ב-Android 11, אתה משנה את התצורה, config_userTypePackageWhitelistMode . ניתן לשלב דגלים. במקרה זה, 5 שווה ל 1 ועוד 4 (שילוב של דגלים 1 ו 4 ).

דֶגֶל תיאור
0 השבת את רשימת ההיתרים. התקן את כל חבילות המערכת; ללא רישום.
1 לֶאֱכוֹף. התקן חבילות מערכת רק כשהן רשומות.
2 רישום חבילות שאינן מורשות.
4 כל חבילה שאינה מוזכרת בקובץ רשימת ההיתרים מורשית באופן מרומז עבור כל המשתמשים.
8 זהה ל 4 , עבור משתמש המערכת.
16 התעלם מ-OTAs. אל תתקין חבילות מערכת במהלך OTAs.
שקול את התרחישים הנפוצים הללו.
  • כדי להפעיל תכונה עבור רשימת היתרים מלאה, 1 ( נאכף במלואו )
  • כדי להפעיל תכונה עבור רשימת היתרים חלקית, 5
  • כדי לאפשר תכונה עבור משתמש SYSTEM כדי להקל על הפיתוח המקומי, 9 ( רשימת היתרים מרומזת )
  • כדי להשבית תכונה כאילו היא מעולם לא הופעלה, 16
  • כדי להשבית תכונה ולבטל את כל האפקטים הקודמים, 0

הקפידו להתקין את קובץ ה-XML בספריית sysconfig עבור המכשיר (זו אותה ספרייה המכילה את הקובץ makefile (`.mk`) המשמש לבניית תמונת המערכת עבור המכשיר). כאשר אתה שם לקובץ ה-XML, כלול את המיקום שבו החבילה מוגדרת ב-build. לדוגמה, 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->

אנדרואיד 9 ואנדרואיד 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. בדוק אם האפליקציה (או רכיבי האפליקציה) מוכרזת כיחידה

אם האפליקציה היא יחידה , המערכת תפעיל את האפליקציה במשתמש המערכת בלבד. סביר להניח שהאפליקציה נועדה להיות אפליקציה מודעת לרב משתמשים. למידע נוסף על אפליקציות מרובות משתמשים, ראה בניית אפליקציות מרובות משתמשים .

  1. בדוק את המניפסט של Android עבור android:singleUser="true" .
  2. אם זה נכון , רשימת ההיתרים. דרוש למשתמש המערכת.
  3. אם לא נכון , המשך. בדוק קריטריונים אחרים לפני ההסרה.

2. בדוק אם האפליקציה דורשת גישה מוגנת לאחסון

שירותי אתחול מערכת רבים מסתמכים לרוב על אחסון מוצפן בהתקן (DE) במקום אחסון מוצפן אישורים (CE). כמו כן, אפליקציות מערכת שמודעת לאתחול ישיר מסתמכות גם על אחסון מוצפן במכשיר. למידע נוסף על אפליקציות המודעות לאתחול ישיר, ראה תמיכה באתחול ישיר ביישומי מערכת .

  1. בדוק את מניפסט אנדרואיד עבור android:defaultToDeviceProtectedStorage="true" , ​​הדרוש עבור שירותי אתחול מערכת רבים.
  2. אם זה נכון , רשימת ההיתרים.
  3. אם לא נכון , המשך.

רמה 2, רכיבי אפליקציה

פעילויות

למידע נוסף על פעילויות, ראה מבוא לפעילויות .

א. בדוק אם האפליקציה מכילה רק פעילויות

הפעילויות מוכוונות לממשק משתמש. מאחר שמשתמש המערכת חסר ראש ברכב, אף אדם לא אמור לקיים אינטראקציה עם משתמש המערכת. כתוצאה מכך, אם האפליקציה מכילה פעילויות בלבד, סביר להניח שהאפליקציה אינה רלוונטית למשתמש המערכת.

בדוק עדיפות והרשאה מיוחדת.

  1. אם כן , אולי נחוץ עבור משתמש המערכת.
  2. אם לא , אל תרשום את רשימת ההיתרים עבור משתמש המערכת.

לדוגמה, חבילת בדיקת התאימות (CTS) ( com.android.cts.priv.ctsshim ) מכילה רק פעילויות, ופעילויות מוגדרות לבדיקת מסנני כוונות. עם זאת, מכיוון שיש לו הרשאה גבוהה, יש להתקין אותו עבור משתמש המערכת למטרות בדיקה.

שֵׁרוּת

למידע נוסף על שירותים, ראה סקירת שירותים .

ב. בדוק אם השירות הוכרז כפרטי ולא ניתן לגשת אליו מאפליקציות אחרות

אם השירות הוכרז כפרטי , חבילות אחרות לא ישתמשו בשירות. חפש את android:exported="false" . אם השירות הוכרז כפרטי או שלא ניתן לגשת אליו מאפליקציות אחרות, לא ניתן לכבול אותו לאפליקציות אחרות. לכן, שלב ג' ושלב ד' להלן אינם רלוונטיים. כתוצאה מכך, רכיב זה לא יספק עוד רמזים לגבי האם השירות נחוץ או לא עבור משתמש המערכת.

  1. אם כן , בדוק את הרכיב הבא.
  2. אם לא , המשך לבדוק את הרכיב הזה.

ג. בדוק אם אפליקציות המותקנות ב-System User עשויות להיקשר לשירות זה

בדוק אם יש חבילות ברשימת ההיתרים ברמה 1 וזהה את השירותים אליהם הם קשורים. עקבו ממסנן הכוונות בשירות זה והתחל startService בחבילות אחרות.

אם שירות זה קשור לאפליקציות המותקנות במשתמש המערכת (לדוגמה, com.android.car.companiondevicesupport מורשה לפעול במשתמש המערכת), אז רשום את השירות.

  1. אם כן , רשימת ההיתרים.
  2. אם לא , המשך לבדוק רכיב זה.

ד. בדוק אם השירות מאוגד מאפליקציות אחרות ומוכרז לפעול בחזית

חפש את startForeground . המשמעות היא שאנשים יקיימו אינטראקציה עם האפליקציה בחזית. סביר להניח, שירות זה לא יהיה נחוץ עבור משתמש המערכת ואין צורך לרשום אותו.

  1. אם כן , אל תרשום.
  2. אם לא , המשך לבדוק את הרכיב הבא.

ה. בדוק אם השירות מוגדר לפעול בתהליך המערכת

ב-AndroidManifest, חפש את android:process="system" .
אם השירות מוגדר בכוונה לפעול בתהליך המערכת, פירוש הדבר שהוא יפעל באופן מפורש באותו תהליך כמו שירות המערכת ויש לרשום אותו ברשימת ההיתרים להפעלה במשתמש המערכת. כחלק מתכנון הקצאת הזיכרון של אנדרואיד, שירותי מערכת הם חלק מהתהליכים האחרונים שהומתו, מה שמרמז על הקריטיות של שירותים המוגדרים עם תכונה כזו. למידע נוסף על עיצוב הקצאת הזיכרון של אנדרואיד, ראה רוצח זיכרון נמוך .

  1. אם כן , אל תרשום.
  2. אם לא , המשך לבדוק רכיבים אחרים.

לדוגמה, החבילה com.android.networkstack.inprocess חייבת להיות ברשימה הרשמית מאחר שהיא מכילה RegularMaintenanceJobService , בעל התג android:process="system" .

מספק תוכן

למידע נוסף על ספקי תוכן, ראה ספקי תוכן .

ו. בדוק אם האפליקציה המותקנת ב-System User תלויה בספק זה

בדוק אם יש חבילות ברשימת ההיתרים ברמה 1 ובדוק באילו ספקים הם תלויים. אם אפליקציה שפועלת ב-System User (לדוגמה, com.android.car.companiondevicesupport מורשית לפעול ב-System User) ותלויה בספק תוכן זה, ודא שגם ספק תוכן זה רשום.

  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>