Gestión de energía de la aplicación

En Android 9 y versiones posteriores, la plataforma puede monitorear aplicaciones en busca de comportamientos que afecten negativamente la duración de la batería de los dispositivos. La plataforma utiliza y evalúa reglas de configuración para proporcionar un flujo de UX que brinde a los usuarios la opción de restringir las aplicaciones que violan las reglas.

En Android 8.0 y versiones anteriores, había restricciones a través de funciones como Doze, espera de aplicaciones, límites en segundo plano y límites de ubicación en segundo plano. Sin embargo, algunas aplicaciones continuaron mostrando malos comportamientos, algunos de los cuales se describen en Android vitals . Android 9 introdujo una infraestructura de sistema operativo que puede detectar y restringir aplicaciones según reglas de configuración que se pueden actualizar con el tiempo.

Restricciones de fondo

Los usuarios pueden restringir las aplicaciones o el sistema puede sugerir aplicaciones que detecta que están impactando negativamente la salud del dispositivo.

Aplicaciones restringidas:

  • El usuario todavía puede iniciarlo.
  • No se pueden ejecutar trabajos/alarmas ni utilizar la red en segundo plano.
  • No se pueden ejecutar servicios en primer plano.
  • El usuario puede cambiarlo a una aplicación sin restricciones.

Los implementadores de dispositivos pueden agregar restricciones adicionales a las aplicaciones para:

  • Restrinja el reinicio automático de la aplicación.
  • Restringir la vinculación de servicios (alto riesgo).

No se espera que las aplicaciones restringidas en segundo plano consuman recursos del dispositivo, como memoria, CPU y batería. Las aplicaciones restringidas en segundo plano no deberían afectar el estado del dispositivo cuando el usuario no las esté usando activamente. Sin embargo, se espera que las mismas aplicaciones sean completamente funcionales cuando el usuario las inicie.

Utilice implementaciones personalizadas

Los implementadores de dispositivos pueden seguir usando sus métodos personalizados para aplicar restricciones a las aplicaciones.

Integrar restricciones de aplicaciones

Las siguientes secciones describen cómo definir e integrar restricciones de aplicaciones en su dispositivo. Si está utilizando métodos de restricción de aplicaciones desde Android 8.x o versiones anteriores, revise atentamente las siguientes secciones para conocer los cambios en Android 9 y versiones posteriores.

Establecer el indicador AppOpsManager

Cuando una aplicación esté restringida, configure el indicador apropiado en AppOpsManager . Un fragmento de código de ejemplo de 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);
    }

Asegúrese de que isBackgroundRestricted devuelva verdadero

Cuando una aplicación está restringida, asegúrese de que ActivityManager.isBackgroundRestricted() devuelva true .

Registre el motivo de la restricción

Cuando una aplicación está restringida, registre los motivos de la restricción. Un fragmento de código de ejemplo de registro de 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));
  }

Reemplace type con el valor de AnomalyType .

Los implementadores de dispositivos pueden usar las constantes definidas en 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;
    }

Cuando el usuario o el sistema elimina las restricciones de una aplicación, debe registrar los motivos para eliminar las restricciones. Un fragmento de código de ejemplo de registro de 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));
    }

Restricciones de la aplicación de prueba

Para probar el comportamiento de las restricciones de aplicaciones en Android 9 y versiones posteriores, use uno de los siguientes comandos:

  • Poner una aplicación en restricción:
    appops set package-name RUN_ANY_IN_BACKGROUND ignore
  • Saque una aplicación de la restricción y restaure el comportamiento predeterminado:
    appops set package-name RUN_ANY_IN_BACKGROUND allow
  • Hacer que una aplicación en segundo plano quede inactiva inmediatamente:
    am make-uid-idle [--user user-id | all | current] package-name
  • Agregue un paquete a tempwhitelist por un período breve:
    cmd deviceidle tempwhitelist [-u user] [-d duration] [package package-name]
  • Agregar/eliminar un paquete de la lista blanca de usuarios:
    cmd deviceidle whitelist [+/-]package-name
  • Verifique el estado interno del jobscheduler y del administrador de alarmas:
    dumpsys jobscheduler
    dumpsys alarm

Modo de espera de la aplicación

El modo de espera de la aplicación extiende la duración de la batería al diferir la actividad de la red en segundo plano y los trabajos para las aplicaciones que el usuario no está usando activamente.

Ciclo de vida en espera de la aplicación

La plataforma detecta aplicaciones inactivas y las pone en espera hasta que el usuario comienza a interactuar activamente con la aplicación.

Durante la fase de detección , la plataforma detecta que una aplicación está inactiva cuando el dispositivo no se está cargando y el usuario no ha iniciado la aplicación directa o indirectamente durante un período específico de tiempo de reloj, así como un período específico de tiempo de pantalla encendida. . (Los inicios indirectos ocurren cuando una aplicación en primer plano accede a un servicio en una segunda aplicación).

Durante el modo de espera de la aplicación , la plataforma impide que las aplicaciones accedan a la red más de una vez al día, posponiendo las sincronizaciones de aplicaciones y otras tareas.

La plataforma sale de la aplicación del modo de espera cuando:

  • La aplicación se activa.
  • El dispositivo está enchufado y cargándose.

Las aplicaciones activas no se ven afectadas por el modo de espera. Una aplicación está activa cuando tiene:

  • Un proceso actualmente en primer plano (ya sea como una actividad o servicio en primer plano, o en uso por otra actividad o servicio en primer plano), como escucha de notificaciones, servicios de accesibilidad, fondo de pantalla en vivo, etc.
  • Una notificación vista por el usuario, como en la pantalla de bloqueo o en la bandeja de notificaciones.
  • Ha sido lanzado explícitamente por el usuario.

Una aplicación está inactiva si ninguna de las actividades anteriores ha ocurrido durante un período de tiempo.

Prueba de espera de la aplicación

Puedes probar manualmente el modo de espera de la aplicación usando los siguientes comandos 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