App-Energiesparmodus

Unter Android 9 und höher kann die Plattform Apps auf Verhalten überwachen, beeinträchtigt die Akkulaufzeit der Geräte. Die Plattform nutzt evaluiert Einrichtungsregeln, um einen UX-Flow bereitzustellen, der Nutzenden die Möglichkeit gibt, Apps einschränken, die gegen die Regeln verstoßen.

Unter Android 8.0 und niedriger gab es Einschränkungen durch Funktionen wie Stromsparmodus, App-Standby, Hintergrundbeschränkungen und Standortermittlung im Hintergrund Beschränkungen. Einige Apps zeigten jedoch weiterhin ein schlechtes Verhalten auf, die in Android Vitals beschrieben sind. Mit Android 9 wurde eine Betriebssysteminfrastruktur eingeführt, die Apps basierend auf Einrichtungsregeln, die sich im Laufe der Zeit aktualisieren können.

Hintergrundbeschränkungen

Nutzer können Apps einschränken oder das System schlägt Apps vor, die es die den Zustand des Geräts beeinträchtigen.

Eingeschränkte Apps:

  • Können immer noch vom Nutzer gestartet werden.
  • Kann keine Jobs/Alarme ausführen und das Netzwerk nicht im Hintergrund nutzen.
  • Dienste im Vordergrund können nicht ausgeführt werden.
  • Kann vom Nutzer in eine uneingeschränkte App geändert werden.

Geräte-Implementierer können für Apps zusätzliche Einschränkungen hinzufügen, um:

  • Sie können verhindern, dass sich die App selbst neu startet.
  • Schränken Sie die Bindung von Diensten ein (hohes Risiko).

Es wird nicht erwartet, dass eingeschränkte Apps im Hintergrund Geräteressourcen verbrauchen, z. B. Speicher, CPU und Akku. Apps mit eingeschränktem Hintergrund sollten wenn der Nutzer diese Apps nicht aktiv verwendet. Es wird jedoch erwartet, dass dieselben Apps wenn der Nutzer die Apps startet.

Benutzerdefinierte Implementierungen verwenden

Geräte-Implementierer können weiterhin ihre benutzerdefinierten Methoden verwenden, um Einschränkungen auf die Apps anzuwenden.

App-Einschränkungen einbinden

In den folgenden Abschnitten wird beschrieben, wie eine App definiert und integriert wird. auf Ihrem Gerät. Wenn Sie App-Einschränkungsmethoden verwenden Android 8.x oder niedriger haben, lesen Sie die folgenden Abschnitte sorgfältig durch Änderungen unter Android 9 und höher.

Flag „AppOpsManager“ festlegen

Wenn eine App eingeschränkt ist, setzen Sie das entsprechende Flag in AppOpsManager Ein Beispiel-Code-Snippet aus 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);
    }

Achten Sie darauf, dass isBackgroundRestricted "true" zurückgibt

Achten Sie bei eingeschränkten Apps darauf, ActivityManager.isBackgroundRestricted() gibt true zurück.

Grund für Einschränkung protokollieren

Wenn eine App eingeschränkt ist, protokolliere die Gründe dafür. Eine Beispiel-Code-Snippet für das Logging von 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));
  }

Ersetzen Sie type durch den Wert aus AnomalyType.

Geräte-Implementierer können die Konstanten verwenden, die in 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;
    }

Wenn der Nutzer oder das System die Einschränkungen einer App entfernt, müssen Sie die Gründe für das Entfernen der Einschränkungen protokollieren. Ein Beispiel-Code-Snippet für das Logging von 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));
    }

App-Einschränkungen testen

Um das Verhalten von App-Einschränkungen unter Android 9 und höher zu testen, verwenden Sie eine der folgenden Befehle:

  • So blockieren Sie eine App:
    appops set package-name RUN_ANY_IN_BACKGROUND ignore
  • So kannst du die Beschränkung einer App aufheben und das Standardverhalten wiederherstellen:
    appops set package-name RUN_ANY_IN_BACKGROUND allow
  • So legen Sie eine App im Hintergrund sofort inaktiv:
    am make-uid-idle [--user user-id | all | current] package-name
  • Fügen Sie tempwhitelist für kurze Zeit ein Paket hinzu:
    cmd deviceidle tempwhitelist [-u user] [-d duration] [package package-name]
  • So fügen Sie ein Paket zur weißen Liste der Nutzer hinzu bzw. entfernen es:
    cmd deviceidle whitelist [+/-]package-name
  • Internen Status von jobscheduler und Alarm-Manager prüfen:
    dumpsys jobscheduler
    dumpsys alarm

App-Standby

App-Standby verlängert die Akkulaufzeit, indem das Hintergrundnetzwerk verzögert wird Aktivitäten und Jobs für Apps, die der Nutzer nicht aktiv verwendet.

App-Standby-Lebenszyklus

Die Plattform erkennt inaktive Apps und platziert sie in der App bis der Nutzer aktiv mit der App interagiert.

Während der Erkennungsphase erkennt die Plattform, dass eine App inaktiv ist, wenn das Gerät nicht lädt und der Nutzer die App nicht direkt gestartet hat oder indirekt über eine bestimmte Uhrzeit und eine bestimmte Bildschirmzeit. Ein indirekter Start erfolgt, wenn eine App im Vordergrund auf einen Dienst in einer zweiten App zugreift.

Während des App-Standbys verhindert die Plattform, dass Apps häufiger auf das Netzwerk zugreifen. App-Synchronisierungen und andere Aufträge aussetzen.

Die Plattform beendet die App in den folgenden Fällen aus dem Stand-by-Modus:

  • Die App wird aktiviert.
  • Das Gerät ist angeschlossen und lädt.

Aktive Apps sind vom App-Standby nicht betroffen. Eine App ist aktiv, wenn sie

  • Ein Prozess, der gerade im Vordergrund ausgeführt wird (entweder als Aktivität oder Dienst im Vordergrund oder von einer anderen Aktivität oder einem anderen Dienst im Vordergrund verwendet wird, wie Benachrichtigungs-Listener, Bedienungshilfen, Live-Hintergrund usw.
  • Eine vom Nutzer gesehene Benachrichtigung, z. B. auf dem Sperrbildschirm oder Benachrichtigungsleiste
  • Sie wurden explizit vom Nutzer gestartet.

Eine App ist inaktiv, wenn über einen bestimmten Zeitraum keine der oben genannten Aktivitäten stattgefunden hat. der Zeit.

App-Standby-Modus testen

Mit den folgenden adb können Sie den App-Standby-Modus manuell testen Befehle:

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