W systemie Android 9 i nowszych platforma może monitorować aplikacje pod kątem zachowania, które negatywnie wpływa na żywotność baterii urządzeń. Platforma wykorzystuje i ocenia reguły konfiguracji, aby zapewnić przepływ UX, który daje użytkownikom możliwość ograniczenia aplikacji, które naruszają reguły.
W systemie Android 8.0 i niższych istniały ograniczenia związane z funkcjami, takimi jak drzemka, tryb gotowości aplikacji, ograniczenia w tle i ograniczenia lokalizacji w tle. Jednak niektóre aplikacje nadal zachowywały się źle, a niektóre z nich opisano w Android Vitals . Android 9 wprowadził infrastrukturę systemu operacyjnego, która może wykrywać i ograniczać aplikacje na podstawie reguł konfiguracji, które można aktualizować w czasie.
Ograniczenia w tle
Użytkownicy mogą ograniczać aplikacje lub system może sugerować, że wykryte aplikacje mają negatywny wpływ na stan urządzenia.
Aplikacje z ograniczeniami:
- Nadal może być uruchomiony przez użytkownika.
- Nie można uruchamiać zadań/alarmu ani korzystać z sieci w tle.
- Nie można uruchomić usług pierwszego planu.
- Może zostać zmieniona na aplikację nieograniczoną przez użytkownika.
Realizatorzy urządzeń mogą dodawać dodatkowe ograniczenia do aplikacji, aby:
- Ogranicz aplikację przed samoczynnym ponownym uruchomieniem.
- Ogranicz usługi przed wiązaniem (wysoce ryzykowne).
Aplikacje z ograniczeniami działające w tle nie powinny zużywać żadnych zasobów urządzenia, takich jak pamięć, procesor i bateria. Aplikacje ograniczone w tle nie powinny wpływać na kondycję urządzenia, gdy użytkownik nie korzysta aktywnie z tych aplikacji. Oczekuje się jednak, że te same aplikacje będą w pełni funkcjonalne, gdy użytkownik uruchomi aplikacje.
Korzystanie z niestandardowych wdrożeń
Realizatorzy urządzeń mogą nadal używać swoich niestandardowych metod do nakładania ograniczeń na aplikacje.
Integracja ograniczeń aplikacji
W poniższych sekcjach opisano, jak zdefiniować i zintegrować ograniczenia aplikacji na urządzeniu. Jeśli korzystasz z metod ograniczania aplikacji z systemu Android 8.x lub starszego, dokładnie zapoznaj się z poniższymi sekcjami pod kątem zmian w systemie Android 9 i nowszym.
Ustawianie flagi AppOpsManager
Gdy aplikacja jest ograniczona, ustaw odpowiednią flagę w AppOpsManager
. Przykładowy fragment kodu z 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); }
Zapewnienie, że isBackgroundRestricted zwraca prawdę
Gdy aplikacja jest ograniczona, upewnij się, że ActivityManager.isBackgroundRestricted()
zwraca true
.
Rejestrowanie powodu ograniczenia
Gdy aplikacja jest ograniczona, zanotuj przyczyny ograniczenia. Przykładowy fragment kodu logowania z 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)); }
Zastąp type
wartością z AnomalyType
.
Realizatorzy urządzeń mogą korzystać ze stałych zdefiniowanych w 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; }
Gdy użytkownik lub system usunie ograniczenia aplikacji, musisz zarejestrować przyczyny usunięcia ograniczeń. Przykładowy fragment kodu logowania z 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)); }
Testowanie ograniczeń aplikacji
Aby przetestować zachowanie ograniczeń aplikacji w systemie Android 9 i nowszych, użyj jednego z następujących poleceń:
- Ogranicz aplikację:
appops set package-name RUN_ANY_IN_BACKGROUND ignore
- Wyjmij aplikację z ograniczeń i przywróć domyślne zachowanie:
appops set package-name RUN_ANY_IN_BACKGROUND allow
- Spraw, aby aplikacja w tle natychmiast przeszła w stan bezczynności:
am make-uid-idle [--user user-id | all | current] package-name
- Dodaj pakiet do
tempwhitelist
na krótki czas:cmd deviceidle tempwhitelist [-u user] [-d duration] [package package-name]
- Dodaj/usuń pakiet z białej listy użytkowników:
cmd deviceidle whitelist [+/-]package-name
- Sprawdź wewnętrzny stan
jobscheduler
i menedżera alarmów:dumpsys jobscheduler
dumpsys alarm
Tryb gotowości aplikacji
Tryb gotowości aplikacji wydłuża czas pracy baterii, opóźniając aktywność sieciową w tle i zadania dla aplikacji, z których użytkownik nie korzysta aktywnie.
Cykl życia aplikacji w trybie gotowości
Platforma wykrywa nieaktywne aplikacje i umieszcza je w trybie gotowości aplikacji, dopóki użytkownik nie zacznie aktywnie korzystać z aplikacji.
W fazie wykrywania platforma wykrywa, że aplikacja jest nieaktywna, gdy urządzenie nie ładuje się , a użytkownik nie uruchomił aplikacji bezpośrednio lub pośrednio przez określony czas zegara oraz określony czas wyświetlania ekranu . (Pośrednie uruchomienia występują, gdy aplikacja na pierwszym planie uzyskuje dostęp do usługi w drugiej aplikacji).
W trybie gotowości aplikacji platforma uniemożliwia aplikacjom dostęp do sieci częściej niż raz dziennie, opóźniając synchronizację aplikacji i inne zadania.
Platforma wychodzi z aplikacji ze stanu czuwania , gdy:
- Aplikacja staje się aktywna.
- Urządzenie jest podłączone i ładuje się.
Tryb gotowości aplikacji nie ma wpływu na aktywne aplikacje. Aplikacja jest aktywna , gdy posiada:
- Proces znajdujący się obecnie na pierwszym planie (jako działanie lub usługa pierwszego planu albo używany przez inne działanie lub usługę pierwszego planu), taki jak odbiornik powiadomień, usługi ułatwień dostępu, animowana tapeta itp.
- Powiadomienie wyświetlane przez użytkownika, na przykład na ekranie blokady lub na pasku powiadomień
- Został jawnie uruchomiony przez użytkownika
Aplikacja jest nieaktywna , jeśli przez pewien czas nie wystąpiła żadna z powyższych czynności.
Testowanie gotowości aplikacji
Możesz ręcznie przetestować tryb gotowości aplikacji za pomocą następujących poleceń 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