O Google está comprometido em promover a equidade racial para as comunidades negras. Veja como.
Esta página foi traduzida pela API Cloud Translation.
Switch to English

Gerenciamento de energia do aplicativo

No Android 9 e superior, a plataforma pode monitorar aplicativos quanto a comportamentos que afetam negativamente a vida útil da bateria dos dispositivos. A plataforma usa e avalia regras de configuração para fornecer um fluxo de UX que oferece aos usuários a opção de restringir aplicativos que violam as regras.

No Android 8.0 e versões inferiores, havia restrições através de recursos como Doze, espera do aplicativo, limites de segundo plano e limites de localização em segundo plano. No entanto, alguns aplicativos continuaram exibindo maus comportamentos, alguns dos quais são descritos nos sinais vitais do Android . O Android 9 introduziu uma infraestrutura de sistema operacional que pode detectar e restringir aplicativos com base em regras de configuração que podem ser atualizadas com o tempo.

Restrições de fundo

Os usuários podem restringir aplicativos ou o sistema pode sugerir que os aplicativos detectados estejam afetando negativamente a saúde do dispositivo.

Aplicativos restritos:

  • Ainda pode ser iniciado pelo usuário.
  • Não é possível executar trabalhos / alarmes ou usar a rede em segundo plano.
  • Não é possível executar serviços em primeiro plano.
  • Pode ser alterado para um aplicativo irrestrito pelo usuário.

Os implementadores de dispositivos podem adicionar restrições adicionais aos aplicativos para:

  • Restrinja o aplicativo a reinicializações automáticas.
  • Restrinja os serviços de serem vinculados (altamente arriscados).

Não é esperado que aplicativos restritos em segundo plano consumam quaisquer recursos do dispositivo, como memória, CPU e bateria. Os aplicativos com restrição de plano de fundo não devem afetar a integridade do dispositivo quando o usuário não estiver usando esses aplicativos ativamente. No entanto, espera-se que os mesmos aplicativos sejam totalmente funcionais quando o usuário iniciar os aplicativos.

Usando implementações personalizadas

Os implementadores de dispositivos podem continuar usando seus métodos personalizados para aplicar restrições aos aplicativos.

Integrando restrições de aplicativos

As seções a seguir descrevem como definir e integrar restrições de aplicativos no seu dispositivo. Se você estiver usando métodos de restrição de aplicativo do Android 8.x ou inferior, consulte as seções a seguir com atenção para alterações no Android 9 e superior.

Definindo o sinalizador AppOpsManager

Quando um aplicativo é restrito, defina o sinalizador apropriado no AppOpsManager . Um exemplo de trecho de código 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);
    }

Garantir retornos isBackgroundRestricted true

Quando um aplicativo é restrito, verifique se ActivityManager.isBackgroundRestricted() retorna true .

Registrando o motivo da restrição

Quando um aplicativo é restrito, registre os motivos da restrição. Um exemplo de trecho de código 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));
  }

Substitua type pelo valor de AnomalyType .

Os implementadores de dispositivos podem usar as constantes definidas em 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;
    }

Quando o usuário ou o sistema remove as restrições de um aplicativo, você deve registrar os motivos para remover as restrições. Um exemplo de trecho de código 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));
    }

Testando restrições de aplicativos

Para testar o comportamento das restrições de aplicativos no Android 9 e superior, use um dos seguintes comandos:

  • Coloque um aplicativo em restrição:
    appops set package-name RUN_ANY_IN_BACKGROUND ignore
  • Tire um aplicativo da restrição e restaure o comportamento padrão:
    appops set package-name RUN_ANY_IN_BACKGROUND allow
  • Faça um aplicativo em segundo plano ficar ocioso imediatamente:
    am make-uid-idle [--user user-id | all | current] package-name 
  • Adicione um pacote ao tempwhitelist por um curto período:
    cmd deviceidle tempwhitelist [-u user ] [-d duration ] [package package-name ]
  • Adicione / remova um pacote da lista de permissões do usuário:
    cmd deviceidle whitelist [+/-] package-name 
  • Verifique o estado interno do jobscheduler de jobscheduler e do gerenciador de alarmes:
     dumpsys jobscheduler
    dumpsys alarm 

App standby

O modo de espera do aplicativo aumenta a vida útil da bateria, adiando a atividade e os trabalhos de rede em segundo plano para aplicativos que o usuário não está usando ativamente.

Ciclo de vida do aplicativo em espera

A plataforma detecta aplicativos inativos e os coloca em espera até que o usuário comece a se envolver ativamente com o aplicativo.

Durante a fase de detecção , a plataforma detecta que um aplicativo está inativo quando o dispositivo não está carregando e o usuário não iniciou o aplicativo direta ou indiretamente por um período específico de tempo, bem como por um tempo específico na tela . (Os lançamentos indiretos ocorrem quando um aplicativo em primeiro plano acessa um serviço em um segundo aplicativo.)

Durante a espera do aplicativo , a plataforma impede que os aplicativos acessem a rede mais de uma vez por dia, adiando a sincronização de aplicativos e outros trabalhos.

A plataforma sai do aplicativo do modo de espera quando:

  • O aplicativo fica ativo.
  • O dispositivo está conectado e carregando.

Os aplicativos ativos não são afetados pelo modo de espera do aplicativo. Um aplicativo está ativo quando possui:

  • Um processo atualmente em primeiro plano (como uma atividade ou serviço em primeiro plano ou em uso por outra atividade ou serviço em primeiro plano), como ouvinte de notificação, serviços de acessibilidade, papel de parede ao vivo etc.
  • Uma notificação visualizada pelo usuário, como na tela de bloqueio ou na bandeja de notificação
  • Foi lançado explicitamente pelo usuário

Um aplicativo fica inativo se nenhuma das atividades acima ocorrer por um período de tempo.

Testando a espera do aplicativo

Você pode testar manualmente a espera do aplicativo usando os seguintes 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