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

Cơ quan giám sát giám sát việc sử dụng bộ nhớ flash bằng cách theo dõi tổng lượng ghi I/O vào đĩa được thực hiện bởi tất cả các ứng dụng và dịch vụ bằng cách sử dụng số liệu thống kê I/O của mỗi đĩa 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 của ổ đĩ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 lạm dụng I/O của đĩa và hành động xử lý việc sử dụng quá mức được xác định trước trong cấu hình lạm dụng I/O của đĩa.

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

  • Ngưỡng sử dụng quá mức I/O ổ đĩa được thực thi hàng ngày, nghĩa là tất cả các thao tác ghi do ứng dụng/dịch vụ thực hiện đều được tổng hợp kể từ đầu ngày theo lịch UTC hiện tại và được kiểm tra theo các ngưỡng được xác định trong cấu hình sử dụng quá mức.
  • Khi một chiếc xe được 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ê mức sử dụng I/O của đĩa trên bộ nhớ flash và tổng hợp chúng kể từ đầu ngày theo lịch UTC hiện tại.

Hành động lạm dụng

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

  • 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 sự ổn định chung của hệ thống, do đó chúng không bị chấm dứt khi sử dụng quá mức I/O trên ổ đĩa. Tuy nhiên, cấu hình lạm dụng có thể xác định danh sách các ứng dụng và dịch vụ của nhà cung cấp có thể chấm dứt an toàn.
  • Tất cả các ứng dụng của bên thứ ba đều có thể chấm dứt an toàn.

Khi một ứng dụng hoặc dịch vụ ở trạng thái chấm dứt an toàn, Watchdog sẽ vô hiệu hóa ứng dụng hoặc dịch vụ đó với trạng thái thành phần ứng dụng PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED .

Cấu hình lạm dụng

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

Cơ quan giám sát hiển thị 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 kỳ lúc nào.

Định nghĩa cấu hình lạm dụng

Cấu hình sử dụng quá mức được phân 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 cập nhật cấu hình thành phần của nhà cung cấp.

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

Cấu hình của nhà cung cấp xác định các 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à phương tiện. Cấu hình chứa các trường cấu hình bên dưới.

  • Vendor package prefixes . 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 của 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 thành 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 vendor package prefixes . Cấu hình này không chấp nhận biểu thức thông thường.
  • Safe-to-terminate packages . Nhà cung cấp có thể chỉ định gói nhà cung cấp nào an toàn để chấm dứt bằng cách thêm tên gói đầy đủ vào cấu hình safe-to-terminate packages .
  • Application category mappings . Nhà cung cấp có thể ánh xạ bất kỳ gói nào (bao gồm cả gói của bên thứ ba) tới một trong hai danh mục ứng dụng được hỗ trợ - ứng dụng Bản đồ và Phương tiện. Việc ánh xạ này được thực hiện để cung cấp cho bản đồ và ứng dụng đa phương tiện ngưỡng sử dụng quá mức I/O đĩ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 vào đĩa hơn các loại ứng dụng khác.
  • Component level thresholds . Xác định các ngưỡng chung cho tất cả các gói của nhà cung cấp (nghĩa là các gói không nằm trong Package specific thresholds hoặc Application category specific thresholds 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 lạm dụng I/O đĩa.
  • Package specific thresholds . Nhà cung cấp có thể xác định ngưỡng đặc biệt cho các gói của nhà cung cấp cụ thể. 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 đượ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.
  • Application category specific thresholds . Nhà cung cấp có thể chỉ định ngưỡng đặc biệt cho các 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à Phương tiện. Các ngưỡng được xác định trong cấu hình này được ánh xạ tới các gói cụ thể bằng cách sử dụng Application category mappings .
  • System-wide thresholds . Nhà cung cấp không được chỉ định cấu hình này.

Vendor package prefixes , Safe-to-terminate packages , Component level thresholds và cấu hình Package specific thresholds chỉ có thể được cập nhật theo cấu hình của nhà cung cấp cho các ứng dụng và dịch vụ của nhà cung cấp. Cấu hình Application category specific thresholds chỉ có thể được cập nhật bởi cấu hình của nhà cung cấp cho tất cả các ứng dụng bản đồ và phương tiện.

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

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

Phân loại này cho phép người dùng đối mặt với các ứng dụng/dịch vụ nền trước ghi nhiều dữ liệu hơn các ứng dụng/dịch vụ nền. Trong chế độ Garage, các ứng dụng và dịch vụ có xu hướng tải xuống các bản cập nhật, do đó, mỗi ứng dụng và dịch vụ đều cần 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à bên thứ ba

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

  • Cấu hình hệ thống xác định các ngưỡng và hành động sử dụng quá mức I/O cho 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 Application category mappings . 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 của bên thứ ba xác định ngưỡng cho tất cả các ứng dụng của bên thứ ba. Tất cả các ứng dụng không được cài đặt sẵn trong hệ thống đều là ứng dụng của bên thứ ba.
    • Tất cả các ứng dụng của bên thứ ba đều nhận được các ngưỡng giống nhau (ví dụ: không có ứng dụng bên thứ ba nào nhận được các ngưỡng đặc biệt) ngoại trừ các ứng dụng bản đồ và phương tiện có ngưỡng được xác định bởi cấu hình của nhà cung cấp.
    • Ngưỡng lạm dụng I/O đĩa bên dưới là ngưỡng mặc định cho các ứng dụng của bên thứ ba. Các ngưỡng này được gửi cùng với hình ảnh hệ thống.
      • 3 GiB ghi ở chế độ nền trước của ứng dụng.
      • 2 GiB ghi ở chế độ nền ứng dụng.
      • 4 GiB ghi ở chế độ gara hệ thống.
    • Đây là những ngưỡng cơ bản. Các ngưỡng này được cập nhật khi chúng tôi hiểu rõ hơn về mức sử dụng I/O của ổ đĩa.

Lạm dụng định dạng XML cấu hình

Cấu hình nhà cung cấp mặc định có thể được đặt (đây là tùy chọn ) tại vị trí /vendor/etc/automotive/watchdog/resource_overuse_configuration.xml trong hình ảnh bản dựng. Khi cấu hình này không được chỉ định, cấu hình do hệ thống xác định cũng đượ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. Cấu hình lạm dụng I/O phải được xác định trong tệp XML. Tất cả các giá trị ngưỡng phải được chỉ định trong đơn vị MiB.

Cấu hình XML mẫu được cung cấp bên dưới:

<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 lạm dụng thông qua API hệ thống CarWatchdogManager

Cấu hình XML ở trên chỉ có thể được cung cấp trong hình ảnh bản dựng. Nếu OEM chọn cập nhật cấu hình trên thiết bị sau khi bản dựng được phát hành thì họ có thể sử dụng các API sau để thực hiện các thay đổi đối vớ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ấu hình hiện có để cập nhật và thiết lập cấu hình mới. Sử dụng API CarWatchdogManager.getResourceOveruseConfigurations để lấy cấu hình hiện có. Nếu các cấu hình hiện có không được sử dụng, tất cả các cấu hình (bao gồm cả cấu hình hệ thống và bên thứ ba) sẽ bị ghi đè, điều này không được khuyến khích.
  • Cập nhật các cấu hình hiện có với những thay đổi về delta và đặt cấu hình mới. Không cập nhật cấu hình hệ thống và thành phần của 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 lạm dụng I/O đĩa, hãy sử dụng cờ CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO .

Sau đây là cách triển khai mẫu cập nhật cấu hình lạm dụng 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 việc sử dụng quá mức tài nguyên của họ

Các ứng dụng của nhà cung cấp và bên thứ ba có thể nghe thông báo lạm dụng tài nguyên cụ thể của ứng dụng từ Watchdog hoặc thăm dò ý kiến CarWatchdogManager để biết số liệu thống kê về việc sử dụng quá mức tài nguyên cụ thể của ứng dụng trong tối đa 30 ngày qua.

Nghe thông báo lạm dụng tài nguyên

Các ứng dụng có thể triển khai trình xử lý lạm dụng tài nguyên và đăng ký trình nghe với CarWatchdogManager để nhận thông báo cụ thể của ứng dụng khi chúng vượt quá 80% hoặc 100% ngưỡng sử dụng quá mức I/O ổ đĩa của chúng. Ứng dụng có thể sử dụng những thông báo này để:

  • Ghi lại số liệu thống kê lạm dụng I/O của đĩa để phân tích ngoại tuyến. Các 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 đề lạm dụng I/O ổ đĩa.
  • Giảm số lần ghi I/O vào đĩa cho đến khi bộ đếm mức sử dụng quá mức được đặt lại.

Máy khách 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ý phiên bản 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. Hủy đăng ký phiên bản trình nghe khi ứng dụng đã nghe xong:
    private void removeResourceOveruseListener() {
        CarWatchdogManager manager =
                (CarWatchdogManager) car.getCarManager(Car.CAR_WATCHDOG_SERVICE);
        mCarWatchdogManager.removeResourceOveruseListener(
              mListenerImpl);
    }
    

Khách hàng địa phương

  1. Đưa 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 chất kết dính ( macro binder_user ) và thêm miền dịch vụ của nhà cung cấp vào miền khách hàng carwatchdog (carwatchdog_client_domain macro) . 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 xử lý lạm dụng tài nguyên bằng cách kế thừa BnResourceOveruseListener . Ghi đè BnResourceOveruseListener::onOveruse để xử lý các thông báo lạm dụng 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. Bắt đầu một nhóm luồng liên kết và đăng ký trình xử lý lạm dụng tài nguyên với máy chủ cơ quan giám sát. Máy chủ Watchdog được đăng ký dưới 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);
    }
    

Thống kê lạm dụng tài nguyên thăm dò ý kiến

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

Máy khách Java

Sử dụng CarWatchdogManager.getResourceOveruseStats để nhận số liệu thống kê về việc sử dụng quá mức tài nguyên. Chuyển cờ CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO để nhận số liệu thống kê về mức sử dụng quá mức I/O của đĩ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()
}

Khách hàng địa phương

Sử dụng CarWatchdogServer.getResourceOveruseStats để nhận số liệu thống kê về việc 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ê lạm dụng I/O của đĩ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
      }
}

UX lạm dụng tài nguyên

Ưu tiên cài đặt hiệu suất ứng dụng

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

Khi người dùng bật cài đặt này, hộp thoại xác nhận sau sẽ mô tả ý nghĩa của việc bật cài đặt này.

Sau 90 ngày, cài đặt này sẽ tự động được đặt lại về mặc định. Giới hạn ngày có thể được sửa đổi bằng ứng dụng lớp phủ RRO sử dụng watchdogUserPackageSettingsResetDays , tối đa là 180 ngày. Để tìm hiểu thêm, hãy xem Thay đổi giá trị tài nguyên của ứng dụng khi chạy . Thẻ lớp phủ mẫu sau có thể được đưa 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>

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

Khi một ứng dụng hoặc dịch vụ liên tục sử dụng quá mức I/O đĩ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 an toàn do sử dụng quá mức tài nguyên, người dùng sẽ được thông báo sau khi phương tiện đi vào trình điều khiển cho phép -trạng thái phân tâm.

Thông báo đầu tiên của người dùng (trong khi lái xe) được đăng dưới dạng thông báo quan trọng và các thông báo khác được đăng 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á mức I/O ổ đĩ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ẽ được khởi chạy, nơi người dùng có thể bật hoặc tắt 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 khởi 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 có thể gỡ cài đặt, nút Tắt ứng dụng đượ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ẽ được khởi chạy, từ đó người dùng có thể gỡ cài đặt ứng dụng.

Đề xuất triển khai trình khởi chạy

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

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