ניהול צריכת החשמל של האפליקציה

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

ב-Android מגרסה 8.0 ומטה היו הגבלות שימוש בתכונות כמו 'נמנום', מצב המתנה של אפליקציה, מגבלות ברקע ומיקום ברקע מגבלות בפועל. למרות זאת, חלק מהאפליקציות המשיכו להציג התנהגות לא תקינה, שמתוארים במאמר תפקוד האפליקציה. ב-Android 9 נוספה תשתית של מערכת הפעלה שיכולה לזהות ולהגביל על סמך כללי הגדרה שעשויים להתעדכן במשך הזמן.

הגבלות רקע

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

אפליקציות מוגבלות:

  • המשתמש עדיין יכול להפעיל אותו.
  • לא ניתן להריץ משימות/התראות או להשתמש ברשת ברקע.
  • אי אפשר להפעיל שירותים שפועלים בחזית.
  • למשתמש יכול להפוך לאפליקציה לא מוגבלת.

מטמיעי מכשירים יכולים להוסיף עוד הגבלות לאפליקציות כדי:

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

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

שימוש בהטמעות מותאמות אישית

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

שילוב הגבלות על אפליקציות

בקטעים הבאים מוסבר איך להגדיר ולשלב אפליקציה הגבלות על המכשיר. אם אתם משתמשים בשיטות להגבלת אפליקציות מ-Android מגרסה 8.x ומטה, צריך לעיין בקפידה בקטעים הבאים ב-Android מגרסה 9 ואילך.

הגדרת הסימון של 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