В Android 9 и выше платформа может отслеживать приложения на предмет поведения, которое отрицательно влияет на время автономной работы устройств. Платформа использует и оценивает правила настройки, чтобы обеспечить поток UX, который дает пользователям возможность ограничивать приложения, которые нарушают правила.
В Android 8.0 и ниже были ограничения, связанные с такими функциями, как Doze, режим ожидания приложений, фоновые ограничения и ограничения фонового местоположения. Однако некоторые приложения продолжали демонстрировать плохое поведение, некоторые из которых описаны в Android Vitals . Android 9 представил инфраструктуру ОС, которая может обнаруживать и ограничивать приложения на основе правил настройки, которые могут обновляться с течением времени.
Фоновые ограничения
Пользователи могут ограничивать приложения, или система может предлагать приложения, которые, как она обнаруживает, негативно влияют на работоспособность устройства.
Запрещенные приложения:
- Все еще может быть запущен пользователем.
- Невозможно запускать задания / сигналы тревоги или использовать сеть в фоновом режиме.
- Невозможно запустить службы переднего плана.
- Может быть изменено пользователем на неограниченное приложение.
Разработчики устройств могут добавить к приложениям дополнительные ограничения:
- Запретить приложению перезапускаться самостоятельно.
- Запретить привязку сервисов (очень рискованно).
Ожидается, что приложения с ограниченным доступом в фоновом режиме будут потреблять какие-либо ресурсы устройства, такие как память, ЦП и аккумулятор. Приложения с ограничением в фоновом режиме не должны влиять на работоспособность устройства, если пользователь не использует эти приложения активно. Однако ожидается, что одни и те же приложения будут полностью функциональными, когда пользователь их запустит.
Использование пользовательских реализаций
Разработчики устройств могут продолжать использовать свои собственные методы для применения ограничений к приложениям.
Интеграция ограничений приложения
В следующих разделах описывается, как определять и интегрировать ограничения приложений на вашем устройстве. Если вы используете методы ограничения приложений из 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
устройств могут использовать константы, определенные в 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