Quản lý nguồn ứng dụng

Trong Android 9 trở lên, nền tảng này có thể giám sát các ứng dụng để phát hiện hành vi ảnh hưởng tiêu cực đến thời lượng pin của thiết bị. Nền tảng sử dụng và đánh giá các quy tắc thiết lập để cung cấp luồng UX giúp người dùng có tùy chọn hạn chế các ứng dụng vi phạm quy tắc.

Trong Android 8.0 trở xuống, có các hạn chế thông qua các tính năng như Ngủ sâu, chế độ chờ ứng dụng, giới hạn nền và giới hạn vị trí ở chế độ nền. Tuy nhiên, một số ứng dụng tiếp tục có hành vi xấu, một số hành vi đó được mô tả trong Android Vitals . Android 9 đã giới thiệu cơ sở hạ tầng hệ điều hành có thể phát hiện và hạn chế các ứng dụng dựa trên các quy tắc thiết lập có thể được cập nhật theo thời gian.

Hạn chế nền

Người dùng có thể hạn chế ứng dụng hoặc hệ thống có thể đề xuất các ứng dụng mà hệ thống phát hiện đang ảnh hưởng tiêu cực đến tình trạng của thiết bị.

Ứng dụng bị hạn chế:

  • Người dùng vẫn có thể khởi chạy.
  • Không thể chạy công việc/báo thức hoặc sử dụng mạng ở chế độ nền.
  • Không thể chạy các dịch vụ nền trước.
  • Người dùng có thể thay đổi thành một ứng dụng không bị hạn chế.

Người triển khai thiết bị có thể thêm các hạn chế bổ sung cho ứng dụng để:

  • Hạn chế ứng dụng tự khởi động lại.
  • Hạn chế các dịch vụ bị ràng buộc (rủi ro cao).

Các ứng dụng bị hạn chế ở chế độ nền sẽ không tiêu tốn bất kỳ tài nguyên nào của thiết bị, chẳng hạn như bộ nhớ, CPU và pin. Các ứng dụng bị giới hạn trong nền sẽ không ảnh hưởng đến tình trạng của thiết bị khi người dùng không chủ động sử dụng các ứng dụng đó. Tuy nhiên, các ứng dụng tương tự dự kiến ​​​​sẽ có đầy đủ chức năng khi người dùng khởi chạy ứng dụng.

Sử dụng triển khai tùy chỉnh

Người triển khai thiết bị có thể tiếp tục sử dụng các phương pháp tùy chỉnh của họ để áp dụng các hạn chế trên ứng dụng.

Tích hợp các hạn chế ứng dụng

Các phần sau đây phác thảo cách xác định và tích hợp các hạn chế ứng dụng trên thiết bị của bạn. Nếu bạn đang sử dụng các phương pháp hạn chế ứng dụng từ Android 8.x trở xuống, hãy xem kỹ các phần sau để biết những thay đổi trong Android 9 trở lên.

Đặt cờ AppOpsManager

Khi một ứng dụng bị hạn chế, hãy đặt cờ thích hợp trong AppOpsManager . Một đoạn mã ví dụ từ 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);
    }

Đảm bảo isBackgroundRestricted trả về true

Khi một ứng dụng bị hạn chế, hãy đảm bảo rằng ActivityManager.isBackgroundRestricted() trả về true .

Ghi lại lý do hạn chế

Khi một ứng dụng bị hạn chế, hãy ghi lại lý do hạn chế. Một đoạn mã ví dụ về ghi nhật ký từ 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));
  }

type thế loại bằng giá trị từ AnomalyType .

Người triển khai thiết bị có thể sử dụng các hằng số được xác định trong 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;
    }

Khi người dùng hoặc hệ thống xóa các hạn chế của ứng dụng, bạn phải ghi lại lý do xóa các hạn chế. Một đoạn mã ví dụ về ghi nhật ký từ 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));
    }

Thử nghiệm hạn chế ứng dụng

Để kiểm tra hành vi hạn chế ứng dụng trong Android 9 trở lên, hãy sử dụng một trong các lệnh sau:

  • Đặt ứng dụng vào tình trạng hạn chế:
    appops set package-name RUN_ANY_IN_BACKGROUND ignore
  • Đưa ứng dụng ra khỏi giới hạn và khôi phục hành vi mặc định:
    appops set package-name RUN_ANY_IN_BACKGROUND allow
  • Làm cho một ứng dụng ở chế độ nền không hoạt động ngay lập tức:
    am make-uid-idle [--user user-id | all | current] package-name
  • Thêm gói vào tempwhitelist trong thời gian ngắn:
    cmd deviceidle tempwhitelist [-u user] [-d duration] [package package-name]
  • Thêm/xóa gói khỏi danh sách trắng của người dùng:
    cmd deviceidle whitelist [+/-]package-name
  • Kiểm tra trạng thái nội bộ của jobscheduler và trình quản lý cảnh báo:
    dumpsys jobscheduler
    dumpsys alarm

Chế độ chờ ứng dụng

Chế độ chờ ứng dụng giúp kéo dài thời lượng pin bằng cách trì hoãn hoạt động và công việc mạng nền đối với các ứng dụng mà người dùng không thường xuyên sử dụng.

Vòng đời chờ của ứng dụng

Nền tảng phát hiện các ứng dụng không hoạt động và đặt chúng ở chế độ chờ ứng dụng cho đến khi người dùng bắt đầu tích cực tương tác với ứng dụng.

Trong giai đoạn phát hiện , nền tảng sẽ phát hiện ra rằng ứng dụng không hoạt động khi thiết bị không sạc người dùng chưa khởi chạy ứng dụng một cách trực tiếp hoặc gián tiếp trong một khoảng thời gian đồng hồ cụ thể cũng như một khoảng thời gian bật màn hình cụ thể. . (Việc khởi chạy gián tiếp xảy ra khi ứng dụng trên nền trước truy cập vào dịch vụ trong ứng dụng thứ hai.)

Trong thời gian chờ ứng dụng , nền tảng này ngăn các ứng dụng truy cập mạng nhiều lần trong ngày, trì hoãn việc đồng bộ hóa ứng dụng và các công việc khác.

Nền tảng thoát ứng dụng từ chế độ chờ khi:

  • Ứng dụng sẽ hoạt động.
  • Thiết bị đã được cắm và sạc.

Các ứng dụng đang hoạt động không bị ảnh hưởng bởi chế độ chờ của ứng dụng. Một ứng dụng đang hoạt động khi nó có:

  • Một quy trình hiện đang ở nền trước (dưới dạng hoạt động hoặc dịch vụ trên nền trước hoặc được sử dụng bởi một hoạt động hoặc dịch vụ trên nền trước khác), chẳng hạn như trình nghe thông báo, dịch vụ trợ năng, hình nền động, v.v.
  • Thông báo được người dùng xem, chẳng hạn như trên màn hình khóa hoặc khay thông báo
  • Được người dùng khởi chạy một cách rõ ràng

Ứng dụng sẽ không hoạt động nếu không có hoạt động nào ở trên xảy ra trong một khoảng thời gian.

Kiểm tra chế độ chờ của ứng dụng

Bạn có thể kiểm tra chế độ chờ của ứng dụng theo cách thủ công bằng cách sử dụng các lệnh adb sau:

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