Google は、黒人コミュニティに対する人種平等の促進に取り組んでいます。取り組みを見る

アプリケーションの電力管理

Android 9 以降では、Android でデバイスの電池寿命を低下させるアプリの動作をモニターできます。Android では、設定ルールを使用して評価し、ルールに違反するアプリを制限するためのユーザー エクスペリエンス フローをユーザーに提供します。

Android 8.0 以前では、Doze、アプリ スタンバイ、バックグラウンドでの実行の制限、バックグラウンドでの位置情報取得の制限などの機能によりアプリを制限していました。しかし、一部のアプリは、Android vitals に記述されている好ましくない動作を続けていました。Android 9 では、設定ルールに基づいてアプリを検出、制限できる OS インフラストラクチャが組み込まれています。この設定ルールは時間の経過とともに更新されます。

バックグラウンド制限

ユーザーが制限するアプリを選択できます。また、デバイスの状態に悪影響を与えるアプリをシステムが検出して提案します。

制限されたアプリでは次の条件が適用されます。

  • ユーザーが起動できます。
  • ジョブやアラームを実行したり、バックグラウンドでネットワークを使用することはできません。
  • フォアグラウンド サービスを実行できません。
  • ユーザーがアプリの制限を解除できます。

デバイスの実装者は、アプリに以下の制限を追加できます。

  • アプリの自己再起動を制限する。
  • サービスに対する制限を禁止する(高リスク)。

制限されたアプリでは、メモリ、CPU、電池などのデバイス リソースをバックグラウンドで使用することはできません。バックグラウンドで制限されたアプリは、ユーザーがアプリを積極的に使用していない限り、デバイスの状態に影響しません。ただし、制限されたアプリをユーザーが起動した場合は、そのアプリは完全に機能します。

カスタム実装を使用する

デバイスの実装者は、現在もカスタム メソッドを使用してアプリに制限を適用できます。

アプリの制限を統合する

以下のセクションでは、デバイスでのアプリの制限を定義して統合する方法を説明します。Android 8.x 以前のアプリ制限メソッドを使用している場合は、以下のセクションで Android 9 の変更点をご確認ください。

AppOpsManager フラグを設定する

アプリが制限されている場合は、AppOpsManager で適切なフラグを設定します。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);
        }
    

isBackgroundRestricted が確実に true を返すようにする

アプリが制限されている場合は、ActivityManager.isBackgroundRestricted() が確実に true を返すようにします。

制限の理由をロギングする

アプリが制限されている場合は、制限の理由をロギングします。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));
      }
    

typeAnomalyType の値に置き換える必要があります。

デバイス実装者は、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;
        }
    

ユーザーまたはシステムがアプリの制限を解除した場合、制限の解除の理由をロギングする必要があります。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));
        }
    

アプリの制限をテストする

Android 9.x 以降でアプリ制限の動作をテストするには、次のいずれかのコマンドを使用します。

  • アプリをアプリ制限に設定するには、以下のコマンドを実行します。
    appops set package-name RUN_ANY_IN_BACKGROUND ignore
  • 制限を解除してデフォルトの動作に戻すには、以下のコマンドを実行します。
    appops set package-name RUN_ANY_IN_BACKGROUND allow
  • バックグラウンドでアプリを即座にアイドル状態にするには、以下のコマンドを実行します。
    am make-uid-idle [--user user-id | all | current] package-name
  • 短期間 tempwhitelist にパッケージを追加するには、以下のコマンドを実行します。
    cmd deviceidle tempwhitelist [-u user] [-d duration] [package package-name]
  • ユーザーのホワイトリストからパッケージを追加または削除するには、以下のコマンドを実行します。
    cmd deviceidle whitelist [+/-]package-name
  • ジョブ スケジューラとアラーム マネージャの内部状態を確認するには、以下のコマンドを実行します。
    dumpsys jobscheduler
        dumpsys alarm

アプリ スタンバイ

アプリ スタンバイでは、ユーザーが実際に使用していないアプリによるバックグラウンドでのネットワーク アクティビティとジョブを保留して、電池寿命を延長します。

アプリ スタンバイのライフサイクル

Android はアクティブではないアプリケーションを検出して、ユーザーがそのアプリケーションを使用し始めるまで、アプリ スタンバイの状態にします。

検出 アプリ スタンバイ中 終了

デバイスが充電されておらず、さらにユーザーが特定の期間(画面オン時間も含む)アプリケーションを直接的または間接的に起動していないとき、アプリケーションがアクティブではないことを Android が検出します(フォアグラウンド アプリが 2 つ目のアプリのサービスにアクセスしたときに、間接的にアプリが起動することがあります)。

Android は、アプリ スタンバイ状態のアプリケーションが 1 日に 1 回以上ネットワークにアクセスすることを防ぎ、アプリケーションの同期などのジョブを保留します。

次の場合、Android はアプリ スタンバイ状態を解除します。

  • アプリケーションがアクティブになったとき
  • デバイスが電源に接続され、充電中になったとき

アクティブなアプリケーションはアプリ スタンバイの影響を受けません。アプリケーションは次の場合にアクティブになります。

  • 通知リスナー、ユーザー補助サービス、ライブ壁紙など、フォアグラウンドにアプリケーションのプロセスが現在存在する(アクティビティまたはフォアグラウンド サービスとして、または別のアクティビティまたはフォアグラウンドで使用中のどちらか)
  • ロック画面や通知トレイなどでユーザーがアプリケーションの通知を表示している
  • ユーザーによって明示的にアプリケーションを開始している

上記のいずれのアクティビティも一定期間発生しなかった場合、アプリケーションは非アクティブになります。

アプリ スタンバイのテスト

アプリ スタンバイは次の 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