ב-Android 9 ואילך, הפלטפורמה יכולה לעקוב אחרי אפליקציות כדי לזהות התנהגות שמשפיעה לרעה על חיי הסוללה של המכשירים. הפלטפורמה משתמשת בכללי ההגדרה ומעריכה אותם כדי לספק תהליך של חוויית משתמש (UX) שמאפשר למשתמשים להגביל אפליקציות שמפירות את הכללים.
ב-Android מגרסה 8.0 ומטה, היו הגבלות באמצעות תכונות כמו Doze, מצב המתנה של אפליקציות, מגבלות ברקע ומגבלות על מיקום ברקע. עם זאת, אפליקציות מסוימות המשיכו להציג התנהגות לא תקינה, חלק מהן מתוארות בדוח 'תפקוד האפליקציה'. ב-Android 9 הושק תשתית של מערכת הפעלה שיכולה לזהות אפליקציות ולהגביל אותן על סמך כללי הגדרה שאפשר לעדכן לאורך זמן.
הגבלות על פעילות ברקע
המשתמשים יכולים להגביל אפליקציות, או שהמערכת עשויה להציע אפליקציות שהיא מזהה שהן משפיעות לרעה על המצב של המכשיר.
אפליקציות מוגבלות:
- המשתמש עדיין יכול להפעיל אותה.
- לא ניתן להפעיל משימות או התראות או להשתמש ברשת ברקע.
- לא ניתן להפעיל שירותים שפועלים בחזית.
- המשתמש יכול לשנות את האפליקציה לאפליקציה ללא הגבלות.
מפתחי המכשירים יכולים להוסיף הגבלות נוספות לאפליקציות כדי:
- להגביל את האפליקציה כך שלא תופעל מחדש באופן אוטומטי.
- להגביל את האפשרות לשיוך שירותים (סיכון גבוה מאוד).
אפליקציות מוגבלות ברקע לא צפויות לצרוך משאבי מכשיר, כמו זיכרון, מעבד וסוללה. אפליקציות עם הגבלת רקע לא אמורות להשפיע על בריאות המכשיר כשהמשתמש לא משתמש בהן באופן פעיל. עם זאת, אותה אפליקציה אמורה לפעול באופן מלא כשהמשתמש מפעיל אותה.
שימוש בהטמעות בהתאמה אישית
מפתחי המכשירים יכולים להמשיך להשתמש בשיטות בהתאמה אישית שלהם כדי להחיל הגבלות על האפליקציות.
שילוב הגבלות על אפליקציות
בחלקים הבאים מוסבר איך מגדירים ומשתלבים עם הגבלות על אפליקציות במכשיר. אם אתם משתמשים בשיטות הגבלת אפליקציות מגרסה 8.x ואילך של Android, כדאי לעיין בקפידה בקטעים הבאים כדי לבדוק את השינויים בגרסה 9 ואילך של Android.
הגדרת הדגל של AppOpsManager
כשאפליקציה מוגבלת, מגדירים את הדגל המתאים ב-AppOpsManager
. קטע קוד לדוגמה מ-packages/apps/Settings/src/com/android/settings/fuelgauge/BatteryUtils.java
:
public void setForceAppStandby(int uid, String packageName, int mode) { final boolean isPreOApp = isPreOApp(packageName); if (isPreOApp) { // Control whether app could run in the background if it is pre O app mAppOpsManager.setMode(AppOpsManager.OP_RUN_IN_BACKGROUND, uid, packageName, mode); } // Control whether app could run jobs in the background mAppOpsManager.setMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, uid, packageName, mode); }
מוודאים שהפונקציה isBackgroundRestricted מחזירה את הערך true
כשאפליקציה מוגבלת, צריך לוודא שהפונקציה ActivityManager.isBackgroundRestricted()
מחזירה את הערך true
.
רישום ביומן של הסיבה להגבלה
כשאפליקציה מוגבלת, צריך לתעד ביומן את הסיבות להגבלה. קטע קוד לדוגמה של רישום ביומן מ-packages/apps/Settings/src/com/android/settings/fuelgauge/batterytip/actions/RestrictAppAction.java
:
mBatteryUtils.setForceAppStandby(mBatteryUtils.getPackageUid(packageName), packageName,AppOpsManager.MODE_IGNORED); if (CollectionUtils.isEmpty(appInfo.anomalyTypes)) { // Only log context if there is no anomaly type mMetricsFeatureProvider.action(mContext, MetricsProto.MetricsEvent.ACTION_TIP_RESTRICT_APP, packageName, Pair.create(MetricsProto.MetricsEvent.FIELD_CONTEXT,metricsKey)); } else { // Log ALL the anomaly types for (int type : appInfo.anomalyTypes) { mMetricsFeatureProvider.action(mContext, MetricsProto.MetricsEvent.ACTION_TIP_RESTRICT_APP, packageName, Pair.create(MetricsProto.MetricsEvent.FIELD_CONTEXT, metricsKey), Pair.create(MetricsProto.MetricsEvent.FIELD_ANOMALY_TYPE, type)); }
מחליפים את type
בערך מ-AnomalyType
.
מי שמטמיע את המכשיר יכול להשתמש בערכי הקבועים שמוגדרים ב-src/com/android/settings/fuelgauge/batterytip/StatsManagerConfig.java
:
public @interface AnomalyType { // This represents an error condition in the anomaly detection. int NULL = -1; // The anomaly type does not match any other defined type. int UNKNOWN_REASON = 0; // The application held a partial (screen off) wake lock for a period of time that // exceeded the threshold with the screen off when not charging. int EXCESSIVE_WAKELOCK_ALL_SCREEN_OFF = 1; // The application exceeded the maximum number of wakeups while in the background // when not charging. int EXCESSIVE_WAKEUPS_IN_BACKGROUND = 2; // The application did unoptimized Bluetooth scans too frequently when not charging. int EXCESSIVE_UNOPTIMIZED_BLE_SCAN = 3; // The application ran in the background for a period of time that exceeded the // threshold. int EXCESSIVE_BACKGROUND_SERVICE = 4; // The application exceeded the maximum number of wifi scans when not charging. int EXCESSIVE_WIFI_SCAN = 5; // The application exceed the maximum number of flash writes int EXCESSIVE_FLASH_WRITES = 6; // The application used more than the maximum memory, while not spending any time // in the foreground. int EXCESSIVE_MEMORY_IN_BACKGROUND = 7; // The application exceeded the maximum percentage of frames with a render rate of // greater than 700ms. int EXCESSIVE_DAVEY_RATE = 8; // The application exceeded the maximum percentage of frames with a render rate // greater than 16ms. int EXCESSIVE_JANKY_FRAMES = 9; // The application exceeded the maximum cold start time - the app has not been // launched since last system start, died or was killed. int SLOW_COLD_START_TIME = 10; // The application exceeded the maximum hot start time - the app and activity are // already in memory. int SLOW_HOT_START_TIME = 11; // The application exceeded the maximum warm start time - the app was already in // memory but the activity wasn't created yet or was removed from memory. int SLOW_WARM_START_TIME = 12; // The application exceeded the maximum number of syncs while in the background. int EXCESSIVE_BACKGROUND_SYNCS = 13; // The application exceeded the maximum number of gps scans while in the background. int EXCESSIVE_GPS_SCANS_IN_BACKGROUND = 14; // The application scheduled more than the maximum number of jobs while not charging. int EXCESSIVE_JOB_SCHEDULING = 15; // The application exceeded the maximum amount of mobile network traffic while in // the background. int EXCESSIVE_MOBILE_NETWORK_IN_BACKGROUND = 16; // The application held the WiFi lock for more than the maximum amount of time while // not charging. int EXCESSIVE_WIFI_LOCK_TIME = 17; // The application scheduled a job that ran longer than the maximum amount of time. int JOB_TIMED_OUT = 18; // The application did an unoptimized Bluetooth scan that exceeded the maximum // time while in the background. int LONG_UNOPTIMIZED_BLE_SCAN = 19; // The application exceeded the maximum ANR rate while in the background. int BACKGROUND_ANR = 20; // The application exceeded the maximum crash rate while in the background. int BACKGROUND_CRASH_RATE = 21; // The application exceeded the maximum ANR-looping rate. int EXCESSIVE_ANR_LOOPING = 22; // The application exceeded the maximum ANR rate. int EXCESSIVE_ANRS = 23; // The application exceeded the maximum crash rate. int EXCESSIVE_CRASH_RATE = 24; // The application exceeded the maximum crash-looping rate. int EXCESSIVE_CRASH_LOOPING = 25; // The application crashed because no more file descriptors were available. int NUMBER_OF_OPEN_FILES = 26; }
כשהמשתמש או המערכת מסירים את ההגבלות על אפליקציה, עליכם לתעד ביומן את הסיבות להסרת ההגבלות. קטע קוד לדוגמה של רישום ביומן מ-packages/apps/Settings/src/com/android/settings/fuelgauge/batterytip/actions/UnrestrictAppAction.java
:
public void handlePositiveAction(int metricsKey) { final AppInfo appInfo = mUnRestrictAppTip.getUnrestrictAppInfo(); // Clear force app standby, then app can run in the background mBatteryUtils.setForceAppStandby(appInfo.uid, appInfo.packageName, AppOpsManager.MODE_ALLOWED); mMetricsFeatureProvider.action(mContext, MetricsProto.MetricsEvent.ACTION_TIP_UNRESTRICT_APP, appInfo.packageName, Pair.create(MetricsProto.MetricsEvent.FIELD_CONTEXT, metricsKey)); }
בדיקת הגבלות על אפליקציות
כדי לבדוק את ההתנהגות של הגבלות האפליקציות ב-Android 9 ואילך, משתמשים באחת מהפקודות הבאות:
- כדי להגביל אפליקציה:
appops set package-name RUN_ANY_IN_BACKGROUND ignore
- כדי לבטל את ההגבלה על אפליקציה ולשחזר את התנהגות ברירת המחדל:
appops set package-name RUN_ANY_IN_BACKGROUND allow
- איך מעבירים אפליקציה שפועלת ברקע למצב חוסר פעילות באופן מיידי:
am make-uid-idle [--user user-id | all | current] package-name
- הוספת חבילה ל-
tempwhitelist
לתקופה קצרה:cmd deviceidle tempwhitelist [-u user] [-d duration] [package package-name]
- הוספה או הסרה של חבילה מרשימת ההיתרים של המשתמש:
cmd deviceidle whitelist [+/-]package-name
- בודקים את המצב הפנימי של
jobscheduler
ושל מנהל ההתראות:dumpsys jobscheduler
dumpsys alarm
אפליקציה במצב המתנה
התכונה 'מצב המתנה של אפליקציות' מאריכה את חיי הסוללה על ידי דחיית פעילות הרשת והמשימות ברקע של אפליקציות שהמשתמש לא משתמש בהן באופן פעיל.
מחזור החיים של אפליקציה במצב המתנה
הפלטפורמה מזהה אפליקציות לא פעילות ומעבירה אותן למצב המתנה עד שהמשתמש מתחיל להשתמש באפליקציה באופן פעיל.
במהלך שלב הזיהוי, הפלטפורמה מזהה שאפליקציה לא פעילה כשהמכשיר לא נטען וגם כשהמשתמש לא השיק את האפליקציה באופן ישיר או עקיף במשך פרק זמן מסוים לפי שעון, וגם במשך פרק זמן מסוים שהמסך היה דלוק. (הפעלות עקיפות מתרחשות כשאפליקציה בחזית ניגשת לשירות באפליקציה שנייה).
במהלך מצב המתנה של האפליקציות, הפלטפורמה מונעת מהאפליקציות לגשת לרשת יותר מפעם ביום, ומאחרת את סנכרון האפליקציות ומשימות אחרות.
הפלטפורמה מוציאת את האפליקציה ממצב המתנה במקרים הבאים:
- האפליקציה הופכת לפעילה.
- המכשיר מחובר ונמצא בטעינה.
אפליקציות פעילות לא מושפעות ממצב המתנה של האפליקציות. אפליקציה נחשבת פעילה אם:
- תהליך שנמצא כרגע בחזית (כפעילות או שירות בחזית, או בתהליך שימוש של פעילות או שירות אחר בחזית), כמו מאזין התראות, שירותי נגישות, טפטים חיים וכו'.
- התראה שהמשתמש צפה בה, למשל במסך הנעילה או במגש ההתראות
- הופעלו באופן מפורש על ידי המשתמש
אפליקציה נחשבת לא פעילה אם אף אחת מהפעילויות שלמעלה לא התרחשה במשך תקופה מסוימת.
בדיקת מצב המתנה של האפליקציה
אפשר לבדוק באופן ידני את מצב ההמתנה של האפליקציה באמצעות הפקודות הבאות של adb
:
adb shell dumpsys battery unplug
adb shell am set-idle package-name true
adb shell am set-idle package-name false
adb shell am get-idle package-name