Giám sát mức sử dụng bộ nhớ flash

Watchdog giám sát mức sử dụng bộ nhớ flash bằng cách theo dõi tổng lượng hoạt động ghi I/O trên đĩa do tất cả các ứng dụng và dịch vụ thực hiện bằng cách sử dụng số liệu thống kê I/O trên đĩa cho mỗi UID do Kernel hiển thị tại vị trí "/proc/uid_io/stats". Khi một ứng dụng hoặc dịch vụ vượt quá ngưỡng sử dụng quá mức I/O trên đĩa, Watchdog sẽ thực hiện các hành động đối với ứng dụng hoặc dịch vụ đó. Ngưỡng sử dụng quá mức I/O trên ổ đĩa và hành động cần thực hiện khi sử dụng quá mức được xác định trước trong cấu hình sử dụng quá mức I/O trên ổ đĩa.

Ngưỡng sử dụng quá mức

  • Các ngưỡng sử dụng quá mức hoạt động I/O trên đĩa được thực thi hằng ngày, tức là tất cả các hoạt động ghi do một ứng dụng/dịch vụ thực hiện đều được tổng hợp kể từ đầu ngày dương lịch hiện tại theo giờ UTC và được kiểm tra dựa trên các ngưỡng được xác định trong cấu hình sử dụng quá mức.
  • Khi xe khởi động nhiều lần trong một ngày nhất định, mô-đun Watchdog sẽ lưu trữ số liệu thống kê về mức sử dụng I/O của ổ đĩa trên bộ nhớ flash và tổng hợp các số liệu đó kể từ đầu ngày dương lịch hiện tại theo giờ UTC.

Thao tác dùng khớp quá nhiều

Khi một ứng dụng liên tục vượt quá ngưỡng sử dụng quá mức hoạt động I/O trên đĩa đã xác định, Watchdog sẽ thực hiện các hành động được xác định trong cấu hình sử dụng quá mức.

  • Tất cả các ứng dụng và dịch vụ của nhà cung cấp đều được coi là quan trọng đối với độ ổn định tổng thể của hệ thống, vì vậy, chúng không bị chấm dứt khi sử dụng quá nhiều hoạt động đầu vào/đầu ra trên ổ đĩa. Tuy nhiên, cấu hình sử dụng quá mức có thể xác định danh sách các ứng dụng và dịch vụ của nhà cung cấp an toàn để chấm dứt.
  • Tất cả ứng dụng bên thứ ba đều an toàn để chấm dứt.

Khi một ứng dụng hoặc dịch vụ có thể chấm dứt một cách an toàn, Watchdog sẽ tắt ứng dụng hoặc dịch vụ đó bằng trạng thái thành phần ứng dụng PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED .

Cấu hình sử dụng quá nhiều

Cấu hình sử dụng quá mức chứa các ngưỡng và hành động sử dụng quá mức I/O của đĩa. Cấu hình sử dụng quá mức mặc định được xác định trong hình ảnh hệ thống và nhà cung cấp, đồng thời được vận chuyển cùng với bản dựng. Nhà cung cấp có thể tuỳ ý thêm cấu hình nhà cung cấp vào hình ảnh nhà cung cấp. Khi không có cấu hình của nhà cung cấp, cấu hình hệ thống cũng sẽ được dùng cho các ứng dụng và dịch vụ của nhà cung cấp.

Watchdog cung cấp các API hệ thống thông qua CarWatchdogManager, cho phép các ứng dụng hoặc dịch vụ của nhà cung cấp cập nhật cấu hình của nhà cung cấp bất cứ lúc nào.

Định nghĩa cấu hình sử dụng quá nhiều

Cấu hình sử dụng quá mức được chia theo loại thành phần, ví dụ: hệ thống, nhà cung cấp và bên thứ ba. OEM chỉ được phép cập nhật cấu hình thành phần nhà cung cấp.

Cấu hình của nhà cung cấp

Cấu hình nhà cung cấp xác định ngưỡng và hành động sử dụng quá mức I/O của đĩa cho tất cả các ứng dụng và dịch vụ của nhà cung cấp, cũng như tất cả các ứng dụng bản đồ và ứng dụng đa phương tiện. Cấu hình này chứa các trường cấu hình bên dưới.

  • Tiền tố gói của nhà cung cấp. Tất cả các gói được cài đặt trong phân vùng nhà cung cấp đều được coi là gói nhà cung cấp. Ngoài các gói này, nhà cung cấp có thể phân loại các gói được cài đặt sẵn là gói của nhà cung cấp bằng cách thêm tiền tố gói vào cấu hình tiền tố gói của nhà cung cấp. Cấu hình này không chấp nhận biểu thức chính quy.
  • Gói có thể chấm dứt. Nhà cung cấp có thể chỉ định những gói nhà cung cấp nào được phép chấm dứt bằng cách thêm tên gói đầy đủ vào cấu hình các gói được phép chấm dứt.
  • Ánh xạ danh mục ứng dụng. Nhà cung cấp có thể liên kết mọi gói (kể cả gói của bên thứ ba) với một trong hai danh mục ứng dụng được hỗ trợ – Ứng dụng Bản đồ và Ứng dụng Đa phương tiện. Quy trình ánh xạ này được thực hiện để cung cấp cho các ứng dụng bản đồ và ứng dụng đa phương tiện ngưỡng sử dụng quá mức hoạt động đầu vào/đầu ra trên đĩa cao hơn vì những ứng dụng này có xu hướng tải xuống và ghi nhiều dữ liệu hơn vào đĩa so với các loại ứng dụng khác.
  • Ngưỡng cấp thành phần. Xác định các ngưỡng chung cho tất cả các gói của nhà cung cấp (tức là các gói không thuộc Ngưỡng cụ thể theo gói hoặc Ngưỡng cụ thể theo danh mục ứng dụng sẽ nhận được các ngưỡng này). Nhà cung cấp phải xác định các ngưỡng cấp thành phần khác 0 khi xác định cấu hình sử dụng quá mức hoạt động đầu vào/đầu ra của đĩa.
  • Ngưỡng cụ thể theo gói. Nhà cung cấp có thể xác định các ngưỡng đặc biệt cho các gói cụ thể của nhà cung cấp. Các ánh xạ phải chứa tên gói đầy đủ. Các ngưỡng được xác định trong cấu hình này sẽ được ưu tiên hơn các ngưỡng được xác định trong các cấu hình khác cho một gói nhất định.
  • Ngưỡng dành riêng cho danh mục ứng dụng. Nhà cung cấp có thể chỉ định các ngưỡng đặc biệt cho một số danh mục ứng dụng cụ thể. Danh mục ứng dụng phải là một trong những danh mục được hỗ trợ – Ứng dụng Bản đồ và Ứng dụng Đa phương tiện. Các ngưỡng được xác định trong cấu hình này được liên kết với các gói cụ thể bằng cách sử dụng Mối liên kết danh mục ứng dụng.
  • Ngưỡng trên toàn hệ thống. Nhà cung cấp không được chỉ định cấu hình này.

Tiền tố gói của nhà cung cấp, Các gói an toàn để chấm dứt, Ngưỡng cấp thành phầnNgưỡng dành riêng cho gói chỉ có thể được nhà cung cấp định cấu hình cho các ứng dụng và dịch vụ của nhà cung cấp. Chỉ có thể cập nhật cấu hình ngưỡng cụ thể theo danh mục ứng dụng bằng cấu hình của nhà cung cấp cho tất cả các ứng dụng bản đồ và ứng dụng đa phương tiện.

Ngưỡng sử dụng quá mức chứa số lượng byte được phép ghi trong:

  • Chế độ nền trước so với chế độ nền của ứng dụng hoặc dịch vụ
  • Chế độ gara của hệ thống

Việc phân loại này cho phép các ứng dụng và dịch vụ trên nền trước mà người dùng nhìn thấy ghi nhiều dữ liệu hơn so với các ứng dụng và dịch vụ chạy ở chế độ nền. Ở chế độ Garage, các ứng dụng và dịch vụ thường tải nội dung cập nhật xuống, vì vậy, mỗi ứng dụng và dịch vụ cần có ngưỡng cao hơn so với các ứng dụng và dịch vụ chạy ở các chế độ khác.

Cấu hình hệ thống và cấu hình của bên thứ ba

Các OEM không nên cập nhật cấu hình hệ thống và cấu hình bên thứ ba.

  • Cấu hình hệ thống xác định các ngưỡng sử dụng quá mức I/O và các hành động đối với các ứng dụng và dịch vụ hệ thống.
    • Cấu hình này cũng có thể cập nhật các mối liên kết Danh mục ứng dụng. Do đó, trường cấu hình này được chia sẻ giữa cấu hình hệ thống và nhà cung cấp.
  • Cấu hình bên thứ ba xác định các ngưỡng cho tất cả ứng dụng bên thứ ba. Tất cả ứng dụng không được cài đặt sẵn trong hệ thống đều là ứng dụng bên thứ ba.
    • Tất cả ứng dụng bên thứ ba đều nhận được cùng một ngưỡng (ví dụ: không có ứng dụng bên thứ ba nào nhận được ngưỡng đặc biệt) ngoại trừ ứng dụng bản đồ và ứng dụng đa phương tiện. Ngưỡng của các ứng dụng này do cấu hình của nhà cung cấp xác định.
    • Các ngưỡng sử dụng quá mức I/O ổ đĩa bên dưới là ngưỡng mặc định cho các ứng dụng bên thứ ba. Các ngưỡng này được cung cấp cùng với hình ảnh hệ thống.
      • Ghi 3 GiB ở chế độ nền trước của ứng dụng.
      • Ghi 2 GiB ở chế độ nền của ứng dụng.
      • Ghi 4 GiB ở chế độ nhà để xe của hệ thống.
    • Đây là các ngưỡng cơ bản. Các ngưỡng này được cập nhật khi chúng tôi tìm hiểu thêm về mức sử dụng I/O của ổ đĩa.

Định dạng XML cấu hình sử dụng quá mức

Bạn có thể đặt cấu hình mặc định của nhà cung cấp (không bắt buộc) tại vị trí /vendor/etc/automotive/watchdog/resource_overuse_configuration.xml trong hình ảnh bản dựng. Khi bạn không chỉ định cấu hình này, cấu hình do hệ thống xác định cũng sẽ được áp dụng cho các ứng dụng và dịch vụ của nhà cung cấp.

Tệp XML chỉ được chứa một thẻ cho mỗi trường cấu hình. Bạn phải xác định cấu hình sử dụng quá nhiều I/O trong tệp XML. Bạn phải chỉ định tất cả các giá trị ngưỡng bằng đơn vị MiB.

Dưới đây là một cấu hình XML mẫu:

<resourceOveruseConfiguration version="1.0">
      <componentType>VENDOR</componentType>

      <!-- List of safe to kill vendor packages. -->
      <safeToKillPackages>
            <package>com.vendor.package.A</package>
            <package>com.vendor.package.B</package>
      </safeToKillPackages>

      <!-- List of vendor package prefixes. -->
      <vendorPackagePrefixes>
            <packagePrefix>com.vendor.package</packagePrefix>
      </vendorPackagePrefixes>

      <!-- List of unique package names to app category mappings. -->
      <packagesToAppCategoryTypes>
            <packageAppCategory type="MEDIA">com.vendor.package.A</packageAppCategory>
            <packageAppCategory type="MAPS">com.google.package.B</packageAppCategory>
            <packageAppCategory type="MEDIA">com.third.party.package.C</packageAppCategory>
      </packagesToAppCategoryTypes>

      <ioOveruseConfiguration>
        <!-- Thresholds in MiB for all vendor packages that don't have package specific thresholds. -->
            <componentLevelThresholds>
                  <state id="foreground_mode">1024</state>
                  <state id="background_mode">512</state>
                  <state id="garage_mode">3072</state>
            </componentLevelThresholds>

            <packageSpecificThresholds>
                  <!-- IDs must be unique -->
                  <perStateThreshold id="com.vendor.package.C">
                    <state id="foreground_mode">400</state>
                    <state id="background_mode">100</state>
                    <state id="garage_mode">200</state>
                  </perStateThreshold>

                  <perStateThreshold id="com.vendor.package.D">
                    <state id="foreground_mode">1024</state>
                    <state id="background_mode">500</state>
                    <state id="garage_mode">2048</state>
                  </perStateThreshold>
            </packageSpecificThresholds>

            <!-- Application category specific thresholds. -->
            <appCategorySpecificThresholds>
                  <!-- One entry per supported application category -->
                  <perStateThreshold id="MEDIA">
                    <state id="foreground_mode">600</state>
                    <state id="background_mode">700</state>
                    <state id="garage_mode">1024</state>
                  </perStateThreshold>

                  <perStateThreshold id="MAPS">
                    <state id="foreground_mode">800</state>
                    <state id="background_mode">900</state>
                    <state id="garage_mode">2048</state>
                  </perStateThreshold>
            </appCategorySpecificThresholds>
      </ioOveruseConfiguration>
</resourceOveruseConfiguration>

Cập nhật cấu hình sử dụng quá mức thông qua các API hệ thống CarWatchdogManager

Bạn chỉ có thể cung cấp cấu hình XML ở trên trong hình ảnh bản dựng. Nếu chọn cập nhật cấu hình trên thiết bị sau khi phát hành bản dựng, thì OEM có thể dùng các API sau để thay đổi cấu hình trên thiết bị.

  • Cấp quyền Car.PERMISSION_CONTROL_CAR_WATCHDOG_CONFIG cho người gọi.
  • Phải sử dụng các cấu hình hiện có để cập nhật và đặt cấu hình mới. Sử dụng API CarWatchdogManager.getResourceOveruseConfigurations để nhận các cấu hình hiện có. Nếu không sử dụng các cấu hình hiện có, tất cả cấu hình (bao gồm cả cấu hình hệ thống và cấu hình bên thứ ba) sẽ bị ghi đè. Bạn không nên làm như vậy.
  • Cập nhật các cấu hình hiện có bằng những thay đổi gia tăng và đặt cấu hình mới. Không cập nhật cấu hình hệ thống và cấu hình thành phần bên thứ ba.
  • Sử dụng API CarWatchdogManager.setResourceOveruseConfigurations để đặt cấu hình mới.
  • Để nhận và đặt cấu hình sử dụng quá mức I/O của ổ đĩa, hãy dùng cờ CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO.

Dưới đây là một ví dụ về cách triển khai giúp cập nhật cấu hình sử dụng quá nhiều tài nguyên:

void updateResourceOveruseConfigurations() {
    CarWatchdogManager manager =
        (CarWatchdogManager) car.getCarManager(Car.CAR_WATCHDOG_SERVICE);

    List<ResourceOveruseConfiguration> resourceOveruseConfigurations =
        manager.getResourceOveruseConfigurations(
            CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO);

    List<ResourceOveruseConfiguration> newResourceOveruseConfigurations =
            new List<>();
    ResourceOveruseConfiguration vendorConfiguration;
    for(ResourceOveruseConfiguration config : resourceOveruseConfigurations) {
        // Do not update the configurations of the system and third-party component types.
        if (config.getComponentType()
            != ResourceOveruseConfiguration.COMPONENT_TYPE_VENDOR) {
            newResourceOveruseConfigurations.add(config);
            continue;
        }
        vendorConfiguration = config;
    }

    if (vendorConfiguration == null) {
        ResourceOveruseConfiguration.Builder vendorConfigBuilder =
            new ResourceOveruseConfiguration.Builder();
        initializeConfig(vendorConfigBuilder);
        newResourceOveruseConfigurations.add(vendorConfigBuilder.build());
    } else {
        ResourceOveruseConfiguration newVendorConfig =
            updateConfig(vendorConfiguration);
        newResourceOveruseConfigurations.add(newVendorConfig);
    }
    int result = manager.setResourceOveruseConfigurations(
        newResourceOveruseConfigurations,

    if (result != CarWatchdogManager.RETURN_CODE_SUCCESS) {
        // Failed to set the resource overuse configurations.
    }
}

/** Sets the delta between the old configuration and the new configuration. */
ResourceOveruseConfiguration updateConfig(
    ResourceOveruseConfiguration oldConfiguration) {
    // Replace com.vendor.package.A with com.vendor.package.B in the safe-to-kill list.
    List<String> safeToKillPackages = oldConfiguration.getSafeToKillPackages();
    safeToKillPackages.remove("com.vendor.package.A");
    safeToKillPackages.add("com.vendor.package.B");

    ResourceOveruseConfiguration.Builder configBuilder =
        new ResourceOveruseConfiguration.Builder(
            oldConfiguration.getComponentType(),
            safeToKillPackages,
            oldConfiguration.getVendorPackagePrefixes(),
            oldConfiguration.getPackagesToAppCategoryTypes());

    configBuilder.addVendorPackagePrefixes("com.vendor.");
    configBuilder.addPackagesToAppCategoryTypes("com.vendor.package.B",
        ResourceOveruseConfiguration.APPLICATION_CATEGORY_TYPE_MAPS);

    IoOveruseConfiguration oldIoConfiguration = oldConfiguration.getIoOveruseConfiguration();
    IoOveruseConfiguration.Builder ioConfigBuilder =
        new IoOveruseConfiguration.Builder(
            oldIoConfiguration.getComponentLevelThresholds(),
            oldIoConfiguration.getPackageSpecificThresholds(),
            oldIoConfiguration.getAppCategorySpecificThresholds(),
            oldIoConfiguration.getSystemWideThresholds());

    // Define the amount of bytes based on the flash memory specification, expected lifetime,
    // and estimated average amount of bytes written by a package during different modes.
    ioConfigBuilder.addPackageSpecificThresholds("com.vendor.package.B",
        new PerStateBytes(/* foregroundModeBytes= */ 2 * 1024 * 1024 * 1024,
                          /* backgroundModeBytes= */ 500 * 1024 * 1024,
                          /* garageModeBytes= */ 3 * 1024 * 1024 * 1024));


    return configBuilder.setIoOveruseConfiguration(ioConfigBuilder.build()).build();
}

Ứng dụng giám sát tình trạng sử dụng quá nhiều tài nguyên

Nhà cung cấp và các ứng dụng bên thứ ba có thể theo dõi các thông báo về tình trạng sử dụng quá mức tài nguyên dành riêng cho ứng dụng từ Watchdog hoặc thăm dò CarWatchdogManager để biết số liệu thống kê về tình trạng sử dụng quá mức tài nguyên dành riêng cho ứng dụng trong tối đa 30 ngày qua.

Lắng nghe thông báo về việc sử dụng quá nhiều tài nguyên

Các ứng dụng có thể triển khai một trình nghe sử dụng quá nhiều tài nguyên và đăng ký trình nghe này bằng CarWatchdogManager để nhận thông báo cụ thể của ứng dụng khi các ứng dụng vượt quá 80% hoặc 100% ngưỡng sử dụng quá nhiều I/O trên đĩa. Các ứng dụng có thể dùng những thông báo này để:

  • Ghi lại số liệu thống kê về việc sử dụng quá nhiều dung lượng lưu trữ I/O để phân tích khi không có mạng. Nhà phát triển ứng dụng có thể sử dụng tính năng ghi nhật ký này để gỡ lỗi vấn đề sử dụng quá nhiều hoạt động đầu vào/đầu ra trên đĩa.
  • Giảm số lượt ghi I/O trên ổ đĩa cho đến khi các bộ đếm sử dụng quá mức được đặt lại.

Ứng dụng Java

  1. Triển khai trình nghe bằng cách kế thừa CarWatchdogManager.ResourceOveruseListener:
    class ResourceOveruseListenerImpl implements
          CarWatchdogManager.ResourceOveruseListener {
                @Override
                public void onOveruse(
                      @NonNull ResourceOveruseStats resourceOveruseStats) {
                      // 1. Log/Upload resource overuse metrics.
                      // 2. Reduce writes until the counters reset.
    
                      IoOveruseStats ioOveruseStats = resourceOveruseStats.getIoOveruseStats();
                      // Stats period - [ioOveruseStats.getStartTime(), ioOveruseStats.getStartTime()
                      //   + ioOveruseStats.getDurationInSeconds()]
                      // Total I/O overuses - ioOveruseStats.getTotalOveruses()
                      // Total bytes written - ioOveruseStats.getTotalBytesWritten()
                      // Remaining write bytes for the current UTC calendar day -
                      //    ioOveruseStats.getRemainingWriteBytes()
                }
          }
    }
  2. Đăng ký thực thể trình nghe bằng cách gọi CarWatchdogManager.addResourceOveruseListener
    private void addResourceOveruseListener() {
          CarWatchdogManager manager =
                (CarWatchdogManager) car.getCarManager(Car.CAR_WATCHDOG_SERVICE);
          // Choose a proper executor to handle resource overuse notifications.
          Executor executor = mContext.getMainExecutor();
          manager.addResourceOveruseListener(
                executor, CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO,
                mListenerImpl);
    }
  3. Huỷ đăng ký phiên bản trình nghe khi ứng dụng đã hoàn tất việc nghe:
    private void removeResourceOveruseListener() {
        CarWatchdogManager manager =
                (CarWatchdogManager) car.getCarManager(Car.CAR_WATCHDOG_SERVICE);
        mCarWatchdogManager.removeResourceOveruseListener(
              mListenerImpl);
    }

Native Client

  1. Thêm carwatchdog_aidl_interface-ndk_platform vào phần phụ thuộc shared_libs của quy tắc xây dựng.

    Android.bp

    cc_binary {
        name: "sample_native_client",
        srcs: [
            "src/*.cpp"
        ],
        shared_libs: [
            "carwatchdog_aidl_interface-ndk_platform",
            "libbinder_ndk",
        ],
        vendor: true,
    }
  2. Thêm chính sách SELinux để cho phép miền dịch vụ của nhà cung cấp sử dụng trình liên kết (macro binder_user) và thêm miền dịch vụ của nhà cung cấp vào miền ứng dụng carwatchdog (carwatchdog_client_domain macro). Hãy xem mã bên dưới để biết sample_client.tefile_contexts.

    sample_client.te

    type sample_client, domain;
    type sample_client_exec, exec_type, file_type, vendor_file_type;
    
    carwatchdog_client_domain(sample_client)
    
    init_daemon_domain(sample_client)
    binder_use(sample_client)

    file_contexts

    /vendor/bin/sample_native_client  u:object_r:sample_client_exec:s0
  3. Triển khai trình nghe sử dụng quá nhiều tài nguyên bằng cách kế thừa BnResourceOveruseListener. Ghi đè BnResourceOveruseListener::onOveruse để xử lý các thông báo về việc sử dụng quá nhiều tài nguyên.

    ResourceOveruseListenerImpl.h

    class ResourceOveruseListenerImpl : public BnResourceOveruseListener {
    public:
        ndk::ScopedAStatus onOveruse(
            ResourceOveruseStats resourceOveruseStats) override;
    
    private:
        void initialize();
        void terminate();
    
        std::shared_ptr<ICarWatchdog> mWatchdogServer;
        std::shared_ptr<IResourceOveruseListener> mListener;
    }

    ResourceOveruseListenerImpl.cpp

    ndk::ScopedAStatus ResourceOveruseListenerImpl::onOveruse(
          ResourceOveruseStats resourceOveruseStats) {
    
          // 1. Log/Upload resource overuse metrics.
          // 2. Reduce writes until the counters reset.
    
          if (stats.getTag() != ResourceOveruseStats::ioOveruseStats) {
                // Received resourceOveruseStats doesn't contain I/O overuse stats.
          }
    
          const IoOveruseStats& ioOveruseStats = stats.get();
          // Stats period - [ioOveruseStats.startTime,
          //   ioOveruseStats.startTime + ioOveruseStats.durationInSeconds]
          // Total I/O overuses - ioOveruseStats.totalOveruses
          // Total bytes written - ioOveruseStats.writtenBytes
          // Remaining write bytes for the current UTC calendar day -
          //    ioOveruseStats.remainingWriteBytes
    
          return ndk::ScopedAStatus::ok();
    }
  4. Khởi động một nhóm luồng liên kết và đăng ký trình nghe sử dụng quá nhiều tài nguyên với máy chủ giám sát. Máy chủ giám sát được đăng ký theo tên dịch vụ android.automotive.watchdog.ICarWatchdog/default.

    main.cpp

    int main(int argc, char** argv) {
        ABinderProcess_setThreadPoolMaxThreadCount(1);
        ABinderProcess_startThreadPool();
        std::shared_ptr<ResourceOveruseListenerImpl> listener =
            ndk::SharedRefBase::make<ResourceOveruseListenerImpl>();
    
        // The listener is added in initialize().
        listener->initialize();
    
        ... Run service ...
    
        // The listener is removed in terminate().
        listener->terminate();
    }

    ResourceOveruseListenerImpl.cpp

    void ResourceOveruseListener::initialize() {
        ndk::SpAIBinder binder(AServiceManager_getService(
                "android.automotive.watchdog.ICarWatchdog/default"));
        std::shared_ptr<ICarWatchdog> server = ICarWatchdog::fromBinder(binder);
        mWatchdogServer = server;
    
        std::shared_ptr<IResourceOveruseListener> listener =
            IResourceOveruseListener::fromBinder(this->asBinder());
        mWatchdogServer->addResourceOveruseListener(
          std::vector<int>{ResourceType.IO}, listener);
        mListener = listener;
    }
    
    void ResourceOveruseListener::terminate() {
        mWatchdogServer->removeResourceOveruseListener(mListener);
    }

Lấy số liệu thống kê về việc sử dụng quá nhiều tài nguyên

Các ứng dụng có thể thăm dò CarWatchdogManager để biết số liệu thống kê ATS về tình trạng sử dụng quá mức I/O dành riêng cho ứng dụng trong 30 ngày gần đây nhất.

Ứng dụng Java

Sử dụng CarWatchdogManager.getResourceOveruseStats để nhận số liệu thống kê về tình trạng sử dụng quá mức tài nguyên. Truyền cờ CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO để nhận số liệu thống kê về việc sử dụng quá mức I/O trên ổ đĩa.

private void getResourceOveruseStats() {
      CarWatchdogManager manager =
            (CarWatchdogManager) car.getCarManager(Car.CAR_WATCHDOG_SERVICE);

      // Returns resource overuse stats with I/O overuse stats for the past
      // 7 days. Stats are available for up to the past 30 days.
      ResourceOveruseStats resourceOveruseStats =
            mCarWatchdogManager.getResourceOveruseStats(
                  CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO,
                  CarWatchdogManager.STATS_PERIOD_PAST_7_DAYS);

      IoOveruseStats ioOveruseStats = resourceOveruseStats.getIoOveruseStats();
      // Stats period - [ioOveruseStats.getStartTime(), ioOveruseStats.getStartTime()
      //   + ioOveruseStats.getDurationInSeconds()]
      // Total I/O overuses - ioOveruseStats.getTotalOveruses()
      // Total bytes written - ioOveruseStats.getTotalBytesWritten()
      // Remaining write bytes for the UTC calendar day -
      //    ioOveruseStats.getRemainingWriteBytes()
}

Native Client

Sử dụng CarWatchdogServer.getResourceOveruseStats để nhận số liệu thống kê về tình trạng sử dụng quá mức tài nguyên. Truyền enum ResourceType.IO để tìm nạp số liệu thống kê về việc sử dụng quá mức I/O trên ổ đĩa.

void getResourceOveruseStats() {
      ndk::SpAIBinder binder(AServiceManager_getService(
            "android.automotive.watchdog.ICarWatchdog/default"));
      std::shared_ptr<ICarWatchdog> server = ICarWatchdog::fromBinder(binder);
      // Returns the stats only for the current UTC calendar day.
      const std::vector<ResourceOveruseStats> resourceOveruseStats;
      ndk::ScopedAStatus status = server.getResourceOveruseStats(
            std::vector<int>{ResourceType.IO}, &resourceOveruseStats);
      if (!status.isOk()) {
            // Failed to get the resource overuse stats.
            return;
      }

      for (const auto& stats : resourceOveruseStats) {
            if (stats.getTag() != ResourceOveruseStats::ioOveruseStats) {
                  continue;
            }
            const IoOveruseStats& ioOveruseStats = stats.get();
            // Stats period - [ioOveruseStats.startTime,
            //   ioOveruseStats.startTime + ioOveruseStats.durationInSeconds]
            // Total I/O overuses - ioOveruseStats.totalOveruses
            // Total bytes written - ioOveruseStats.writtenBytes
            // Remaining write bytes for the current UTC calendar day -
            //   ioOveruseStats.remainingWriteBytes
      }
}

Trải nghiệm người dùng khi sử dụng quá nhiều tài nguyên

Các phần sau đây mô tả trải nghiệm người dùng khi xảy ra tình trạng sử dụng quá nhiều tài nguyên.

Chế độ cài đặt ưu tiên hiệu suất ứng dụng

Trang Cài đặt của ứng dụng chứa các chế độ cài đặt cho Prioritize app performance (xem hình bên dưới), cho phép người dùng ưu tiên hiệu suất của ứng dụng hơn hiệu suất hệ thống và phần cứng trong thời gian dài. Chế độ cài đặt này chỉ dành cho những ứng dụng có thể bị chấm dứt một cách an toàn khi sử dụng quá nhiều tài nguyên. Nếu không, chế độ cài đặt này sẽ bị vô hiệu hoá. Khi chế độ cài đặt này bị tắt (chế độ cài đặt mặc định) đối với một ứng dụng, ứng dụng đó có thể bị chấm dứt do sử dụng quá nhiều tài nguyên. Nếu không, ứng dụng sẽ không bị chấm dứt khi sử dụng quá nhiều tài nguyên.

Khi người dùng bật chế độ cài đặt này, hộp thoại xác nhận sau đây sẽ mô tả những hệ quả của việc bật chế độ cài đặt này:

Sau 90 ngày, chế độ cài đặt này sẽ tự động được đặt lại về mặc định. Bạn có thể sửa đổi giới hạn ngày bằng ứng dụng lớp phủ RRO bằng cách sử dụng watchdogUserPackageSettingsResetDays, tối đa 180 ngày. Để tìm hiểu thêm, hãy xem bài viết Thay đổi giá trị của tài nguyên ứng dụng trong thời gian chạy. Bạn có thể thêm thẻ lớp phủ ví dụ sau đây vào AndroidManifest.xml:

<overlay android:priority="<insert-value>"
      android:targetPackage="com.android.car.updatable"
      android:targetName="CarServiceCustomization"
      android:resourcesMap="@xml/overlays" />

Trong res/values/config.xml:

<resources>
  <integer name="watchdogUserPackageSettingsResetDays">value</integer>
</resources>

Trong res/xml/overlays.xml:

<overlay>
  <item target="integer/watchdogUserPackageSettingsResetDays" value="@integer/watchdogUserPackageSettingsResetDays" />
</overlay>

Chế độ cài đặt ứng dụng ảnh hưởng đến hiệu suất

Ứng dụng Cài đặt có một phần Ứng dụng ảnh hưởng đến hiệu suất (xem Hình 1). Khi bạn nhấn vào, một danh sách các ứng dụng bị hạn chế do sử dụng quá nhiều bộ nhớ flash và ảnh hưởng tiêu cực đến hiệu suất hệ thống sẽ xuất hiện. Điều này tuân theo yêu cầu CDD 3.5.1 [C-1-1].

Ứng dụng ảnh hưởng đến hiệu suất

Hình 1. Ứng dụng ảnh hưởng đến hiệu suất.

Những ứng dụng bị chấm dứt do sử dụng quá nhiều tài nguyên sẽ xuất hiện ở đây (xem Hình 2). Bạn có thể ưu tiên các ứng dụng trong danh sách. Để tìm hiểu thêm, hãy xem phần Chế độ cài đặt ưu tiên hiệu suất ứng dụng.

Danh sách các ứng dụng bị chấm dứt do sử dụng quá nhiều tài nguyên

Hình 2. Danh sách các ứng dụng bị chấm dứt do sử dụng quá nhiều tài nguyên.

Thông báo cho người dùng

Khi một ứng dụng hoặc dịch vụ liên tục sử dụng quá nhiều hoạt động đầu vào/đầu ra trên ổ đĩa (ví dụ: ghi dữ liệu vào ổ đĩa vượt quá ngưỡng xác định) trong một khoảng thời gian nhất định và có thể chấm dứt một cách an toàn khi sử dụng quá nhiều tài nguyên, người dùng sẽ nhận được thông báo sau khi xe chuyển sang trạng thái cho phép người lái mất tập trung.

Thông báo đầu tiên cho người dùng (trong khi lái xe) sẽ xuất hiện dưới dạng thông báo quan trọng và các thông báo khác sẽ xuất hiện trên trung tâm thông báo.

Ví dụ: khi một ứng dụng liên tục sử dụng quá nhiều hoạt động đầu vào/đầu ra trên đĩa, người dùng sẽ nhận được thông báo sau:

  • Khi người dùng nhấp vào nút Ưu tiên ứng dụng, trang cài đặt của ứng dụng sẽ khởi chạy. Tại đây, người dùng có thể bật hoặc tắt chế độ cài đặt Ưu tiên hiệu suất ứng dụng.
  • Khi người dùng nhấp vào nút Tắt ứng dụng, ứng dụng sẽ bị tắt cho đến khi người dùng chạy ứng dụng hoặc bật ứng dụng trên trang cài đặt của ứng dụng.
  • Đối với các ứng dụng không gỡ cài đặt được, nút Tắt ứng dụng sẽ được thay thế bằng nút Gỡ cài đặt ứng dụng. Khi người dùng nhấp vào nút Gỡ cài đặt ứng dụng, trang Cài đặt của ứng dụng sẽ khởi chạy, từ đó người dùng có thể gỡ cài đặt ứng dụng.

Đề xuất về cách triển khai trình chạy

Khi các ứng dụng bị tắt do sử dụng quá nhiều tài nguyên, các ứng dụng đó sẽ biến mất khỏi ứng dụng trình chạy mặc định vì CarService cập nhật trạng thái đã bật của các ứng dụng thành PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED. Các OEM phải cập nhật việc triển khai trình chạy tích hợp để hiển thị các ứng dụng này như bình thường, để người dùng có thể sử dụng nếu cần. Hãy xem các đề xuất sau đây dựa trên bản phát hành bản dựng.

Bản phát hành Android SC V2