إدارة تشغيل التطبيقات

في Android 9 والإصدارات الأحدث، يمكن للنظام الأساسي مراقبة التطبيقات لمعرفة السلوك الذي يؤثر سلبًا على عمر بطارية الأجهزة. تستخدم المنصة تقيّم قواعد الإعداد لتوفير تدفق تجربة المستخدم الذي يمنح المستخدمين خيار فرض قيود على التطبيقات التي تنتهك القواعد.

في الإصدار Android 8.0 والإصدارات الأقدم، كانت هناك قيود متعلقة بالميزات مثل القيلولة، ووضع الاستعداد للتطبيقات، وحدود الخلفية، والموقع في الخلفية الحدود. ومع ذلك، استمرت بعض التطبيقات في إظهار سلوكيات سيئة، ومن الموضحة في مؤشرات Android الحيوية. يوفّر Android 9 بنية أساسية لنظام التشغيل يمكنها رصد المحتوى وتقييده. تطبيقات تستند إلى قواعد الإعداد التي يمكن تعديلها بمرور الوقت.

قيود الخلفية

يمكن للمستخدمين فرض قيود على التطبيقات، أو قد يقترح النظام تطبيقات الجديدة تؤثر سلبًا على سلامة الجهاز.

التطبيقات المحظورة:

  • لا يزال بإمكان المستخدم إطلاقها.
  • يتعذَّر تشغيل المهام/المنبّهات أو استخدام الشبكة في الخلفية.
  • يتعذّر تشغيل الخدمات التي تعمل في المقدّمة.
  • يمكن للمستخدم تغييره إلى تطبيق غير مقيّد.

يمكن للمستخدمين الذين نفّذوا الأجهزة إضافة قيود إضافية على التطبيقات من أجل:

  • منع إعادة تشغيل التطبيق ذاتيًا
  • يجب منع تقييد الخدمات (شديد الخطورة).

من غير المتوقع أن تستهلك التطبيقات المحظورة التي تعمل في الخلفية أي موارد من موارد الجهاز، مثل الذاكرة ووحدة المعالجة المركزية والبطارية. يجب ألا تؤثر التطبيقات المحظورة في الخلفية على سلامة الجهاز في الحالات التالية: عدم استخدام المستخدم لهذه التطبيقات بشكل نشط. ومع ذلك، من المتوقع أن تكون التطبيقات نفسها تعمل بكامل طاقتها عند تشغيل المستخدم للتطبيقات.

استخدام آليات تنفيذ مخصّصة

ويمكن للمستخدمين الذين نفّذوا الأجهزة مواصلة استخدام طرقهم المخصَّصة لتطبيق القيود على التطبيقات.

دمج القيود المفروضة على التطبيقات

توضح الأقسام التالية كيفية تحديد ودمج التطبيق القيود المفروضة على جهازك. في حال استخدام طرق تقييد التطبيقات من نظام التشغيل Android 8.x أو الإصدارات الأقدم، راجع الأقسام التالية بدقة التغييرات في الإصدار 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 يعرض القيمة "صحيح"

عند حظر أحد التطبيقات، عليك التأكّد من تُرجع 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));
    }

اختبار القيود المفروضة على التطبيقات

لاختبار سلوك قيود التطبيقات في الإصدار 9 من نظام Android والإصدارات الأحدث، يمكنك استخدام إحدى الأوامر التالية:

  • فرض قيود على تطبيق:
    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