Zarządzanie zasilaniem aplikacji

W Androidzie 9 i nowszych platforma może monitorować aplikacje pod kątem negatywnie wpływa na żywotność baterii urządzeń. Platforma wykorzystuje ocenia reguły konfiguracji, aby zapewnić użytkownikowi możliwość ograniczanie dostępu do aplikacji, które naruszają reguły.

W Androidzie 8.0 i starszych wersjach występowały ograniczenia takich jak uśpienie, tryb gotowości aplikacji, limity działania w tle oraz lokalizacja w tle. i ograniczeniach. Jednak niektóre aplikacje nadal wykazują niewłaściwe działanie, które są opisane w Android Vitals. W Androidzie 9 wprowadzono infrastrukturę systemu operacyjnego, która może wykrywać i ograniczać dostęp na podstawie reguł konfiguracji, które z czasem można aktualizować.

Ograniczenia w tle

Użytkownicy mogą ograniczać dostęp do aplikacji lub system może sugerować aplikacje, co ma negatywny wpływ na kondycję urządzenia.

Aplikacje z ograniczeniami:

  • Może nadal być uruchamiany przez użytkownika.
  • Nie można uruchamiać zadań ani alarmów ani używać sieci w tle.
  • Nie można uruchomić usług działających na pierwszym planie.
  • Użytkownik może zmienić ją na aplikację bez ograniczeń.

Narzędzia implementujące na urządzeniach mogą nakładać na aplikacje dodatkowe ograniczenia, aby:

  • Ogranicz możliwość samodzielnego ponownego uruchamiania aplikacji.
  • Ogranicz powiązanie usług (duże ryzyko).

Aplikacje z ograniczeniami w tle nie powinny zużywać zasobów urządzenia takich jak: pamięci, procesora i baterii. Aplikacje z dostępem w tle nie powinny wpływać na stan urządzenia, gdy użytkownik nie korzysta aktywnie z tych aplikacji. Jednak te same aplikacje powinny być w pełni funkcjonalne, gdy użytkownik je uruchomi.

Korzystanie z implementacji niestandardowych

Twórcy implementacji na urządzeniach nadal mogą używać własnych metod, aby nakładać ograniczenia na aplikacje.

Integracja ograniczeń aplikacji

W sekcjach poniżej opisujemy, jak zdefiniować i zintegrować aplikację ograniczenia na Twoim urządzeniu. Jeśli korzystasz z metod ograniczania dostępu do aplikacji na Androidzie 8.x lub starszym, zapoznaj się dokładnie z tymi sekcjami zmian w Androidzie 9 i nowszych.

Ustawianie flagi AppOpsManager

Jeśli dostęp do aplikacji jest ograniczony, 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);
    }

Sprawdź, czy parametr isBackgroundRestricted zwraca wartość „true”

Jeśli dostęp do aplikacji jest ograniczony, upewnij się, że: ActivityManager.isBackgroundRestricted() zwraca wartość true.

Zapisz przyczynę nałożenia ograniczenia

Jeśli dostęp do aplikacji jest ograniczony, zapisz przyczyny tego ograniczenia. An 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.

Implementatory urządzeń mogą używać 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: zapisać 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));
    }

Testuj ograniczenia aplikacji

Aby przetestować działanie ograniczeń aplikacji na Androidzie 9 i nowszych, użyj jednej z metod następujące polecenia:

  • Wprowadzanie aplikacji w ograniczenia:
    appops set package-name RUN_ANY_IN_BACKGROUND ignore
  • Przywróć aplikację z ograniczeń i przywróć jej domyślne działanie:
    appops set package-name RUN_ANY_IN_BACKGROUND allow
  • Aplikacje działające w tle natychmiast staną się bezczynne:
    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]
  • Dodawanie pakietu do białej listy użytkownika lub usuwanie go z niej:
    cmd deviceidle whitelist [+/-]package-name
  • Sprawdź stan wewnętrzny urządzenia jobscheduler i menedżera alarmów:
    dumpsys jobscheduler
    dumpsys alarm

Tryb gotowości aplikacji

Tryb czuwania aplikacji wydłuża czas pracy na baterii, opóźniając działanie sieci w tle w przypadku aplikacji, których użytkownik aktywnie nie używa.

Cykl życia aplikacji w trybie gotowości

Platforma wykrywa nieaktywne aplikacje i umieszcza je w aplikacji w trybie gotowości, dopóki użytkownik nie zacznie aktywnie korzystać z aplikacji.

Na fazie wykrywania platforma wykrywa, że aplikacja jest nieaktywna, gdy urządzenie się nie ładuje a użytkownik nie uruchomił aplikacji bezpośrednio lub pośrednio przez określony czas zegara, jak i czas aktywności ekranu. (Uruchomienia pośrednie mają miejsce, gdy aplikacja na pierwszym planie uzyskuje dostęp do usługi w drugiej aplikacji).

W trybie czuwania aplikacji platforma uniemożliwia aplikacjom większy dostęp do sieci niż raz dziennie, opóźniając synchronizację aplikacji i wykonywanie innych zadań.

Platforma wyjdzie z trybu gotowości, gdy:

  • Aplikacja stanie się aktywna.
  • Urządzenie jest podłączone i się ładuje.

Tryb gotowości aplikacji nie ma wpływu na aktywne aplikacje. Aplikacja jest aktywna, jeśli:

  • Proces na pierwszym planie (jako aktywność lub usługi na pierwszym planie bądź używane przez inną aktywność lub usługę na pierwszym planie); takich jak detektor powiadomień, usługi ułatwień dostępu, animowana tapeta itp.
  • powiadomienie wyświetlone przez użytkownika, na przykład na ekranie blokady lub panel powiadomień
  • być wyraźnie uruchomione przez użytkownika,

Aplikacja jest nieaktywna, jeśli przez okres nie wystąpiła żadna z powyższych aktywności czasu.

Tryb gotowości aplikacji testowej

Możesz ręcznie przetestować tryb gotowości aplikacji za pomocą tego adb polecenia:

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