Unter Android 9 und höher kann die Plattform Apps auf Verhaltensweisen prüfen, die sich negativ auf die Akkulaufzeit von Geräten auswirken. Die Plattform verwendet und bewertet Einrichtungsregeln, um einen UX-Flow bereitzustellen, mit dem Nutzer Apps einschränken können, die gegen die Regeln verstoßen.
Unter Android 8.0 und niedriger gab es Einschränkungen durch Funktionen wie Doze, App-Standby, Hintergrundlimits und Hintergrundstandortlimits. Einige Apps zeigten jedoch weiterhin unerwünschtes Verhalten, von dem einige in Android Vitals beschrieben werden. Mit Android 9 wurde eine Betriebssysteminfrastruktur eingeführt, mit der Apps anhand von Einrichtungsregeln erkannt und eingeschränkt werden können, die im Laufe der Zeit aktualisiert werden können.
Einschränkungen im Hintergrund
Nutzer können Apps einschränken oder das System schlägt Apps vor, die sich negativ auf die Gesundheit des Geräts auswirken.
Eingeschränkte Apps:
- Kann weiterhin vom Nutzer gestartet werden.
- Es ist nicht möglich, Jobs/Wecker auszuführen oder das Netzwerk im Hintergrund zu verwenden.
- Dienste im Vordergrund können nicht ausgeführt werden.
- Kann vom Nutzer in eine App ohne Einschränkungen geändert werden.
Geräteimplementierer können Apps zusätzliche Einschränkungen hinzufügen, um:
- Verhindern, dass die App automatisch neu gestartet wird.
- Dienste daran hindern, gebunden zu werden (sehr riskant)
Eingeschränkte Apps im Hintergrund sollten keine Geräteressourcen wie Arbeitsspeicher, CPU und Akku beanspruchen. Apps, die im Hintergrund eingeschränkt sind, sollten sich nicht auf die Geräteintegrität auswirken, wenn der Nutzer diese Apps nicht aktiv nutzt. Dieselben Apps sollten jedoch voll funktionsfähig sein, wenn der Nutzer sie startet.
Benutzerdefinierte Implementierungen verwenden
Geräteimplementierer können weiterhin ihre benutzerdefinierten Methoden verwenden, um Einschränkungen für die Apps anzuwenden.
App-Einschränkungen einbinden
In den folgenden Abschnitten wird beschrieben, wie Sie App-Einschränkungen auf Ihrem Gerät definieren und einbinden. Wenn Sie Methoden zur App-Einschränkung von Android 8.x oder niedriger verwenden, lesen Sie die folgenden Abschnitte sorgfältig durch, um sich über die Änderungen in Android 9 und höher zu informieren.
AppOpsManager-Flag setzen
Wenn eine App eingeschränkt ist, setzen Sie das entsprechende Flag in AppOpsManager
. Beispiel für ein 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“ den Wert „true“ zurückgibt.
Wenn eine App eingeschränkt ist, muss ActivityManager.isBackgroundRestricted()
true
zurückgeben.
Grund für die Einschränkung protokollieren
Wenn eine App eingeschränkt ist, loggen Sie die Gründe für die Einschränkung. Beispiel für ein Code-Snippet für Protokolle 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äteimplementierer können die in src/com/android/settings/fuelgauge/batterytip/StatsManagerConfig.java
definierten Konstanten verwenden:
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 die Entfernung der Einschränkungen protokollieren. Beispiel für ein Code-Snippet für 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)); }
Einschränkungen für Test-Apps
Verwenden Sie einen der folgenden Befehle, um das Verhalten von App-Einschränkungen unter Android 9 und höher zu testen:
- So legen Sie eine Einschränkung für eine App fest:
appops set package-name RUN_ANY_IN_BACKGROUND ignore
- So heben Sie die Einschränkung für eine App auf und stellen das Standardverhalten wieder her:
appops set package-name RUN_ANY_IN_BACKGROUND allow
- So legen Sie eine App im Hintergrund sofort in den Ruhemodus:
am make-uid-idle [--user user-id | all | current] package-name
- So fügen Sie
tempwhitelist
für eine kurze Zeit ein Paket hinzu:cmd deviceidle tempwhitelist [-u user] [-d duration] [package package-name]
- So fügen Sie ein Paket zur Zulassungsliste der Nutzer hinzu oder entfernen es daraus:
cmd deviceidle whitelist [+/-]package-name
- Prüfen Sie den internen Status von
jobscheduler
und dem Alarmmanager:dumpsys jobscheduler
dumpsys alarm
App-Standby
Der App-Standbymodus verlängert die Akkulaufzeit, indem Netzwerkaktivitäten und Aufgaben für Apps, die der Nutzer nicht aktiv nutzt, verschoben werden.
App-Standby-Lebenszyklus
Die Plattform erkennt inaktive Apps und versetzt sie in den App-Standby-Modus, bis der Nutzer die App aktiv nutzt.
Während der Erkennungsphase erkennt die Plattform, dass eine App inaktiv ist, wenn das Gerät nicht geladen wird und der Nutzer die App nicht direkt oder indirekt für eine bestimmte Zeit gestartet hat. Indirekte Starts erfolgen, wenn eine App im Vordergrund auf einen Dienst in einer zweiten App zugreift.
Während des App-Standbys verhindert die Plattform, dass Apps mehrmals täglich auf das Netzwerk zugreifen. App-Synchronisierungen und andere Aufgaben werden verschoben.
Die Plattform beendet den Standby-Modus der App in folgenden Fällen:
- Die App wird aktiv.
- Das Gerät ist angeschlossen und wird geladen.
Aktive Apps sind vom App-Standby nicht betroffen. Eine App ist aktiv, wenn folgende Voraussetzungen erfüllt sind:
- Ein Prozess, der sich derzeit im Vordergrund befindet (entweder als Aktivität oder Dienst im Vordergrund oder von einer anderen Aktivität oder einem anderen Dienst im Vordergrund verwendet wird), z. B. Benachrichtigungslistener, Bedienungshilfen oder Live-Hintergrundbilder.
- Eine vom Nutzer aufgerufene Benachrichtigung, z. B. auf dem Sperrbildschirm oder in der Benachrichtigungsleiste
- vom Nutzer explizit gestartet wurde
Eine App ist inaktiv, wenn über einen bestimmten Zeitraum keine der oben genannten Aktivitäten stattgefunden hat.
App-Standby testen
Sie können den App-Standby mit den folgenden adb
-Befehlen manuell testen:
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