Monitorowanie wykorzystania pamięci flash

Watchdog monitoruje wykorzystanie pamięci flash, śledząc łączną liczbę operacji zapisu na dysku wykonywanych przez wszystkie aplikacje i usługi przy użyciu statystyk operacji wejścia/wyjścia na dysku dla UID udostępnianych przez jądro w lokalizacji /proc/uid_io/stats. Gdy aplikacja lub usługa przekroczy próg nadużywania operacji wejścia/wyjścia na dysku, Watchdog podejmuje działania w odniesieniu do tej aplikacji lub usługi. Próg nadużywania operacji wejścia/wyjścia dysku i działanie w przypadku nadużywania są zdefiniowane w konfiguracji nadużywania operacji wejścia/wyjścia dysku.

Progi nadużywania

  • Próg nadużywania we/wy dysku jest egzekwowany codziennie, co oznacza, że wszystkie zapisy dokonane przez aplikację lub usługę są agregowane od początku bieżącego dnia kalendarzowego według uniwersalnego czasu koordynowanego (UTC) i porównywane z wartościami progowymi zdefiniowanymi w konfiguracjach nadużywania.
  • Jeśli pojazd jest uruchamiany wielokrotnie w danym dniu, moduł Watchdog przechowuje statystyki wykorzystania wejść/wyjść na dysku w pamięci flash i zbiera je od początku bieżącego dnia kalendarzowego według czasu UTC.

Nadmierne używanie

Gdy aplikacja wielokrotnie przekracza określone progi nadużywania operacji wejścia/wyjścia na dysku, Watchdog podejmuje działania określone w konfiguracji nadużywania.

  • Wszystkie aplikacje i usługi dostawców są uważane za kluczowe dla ogólnej stabilności systemu, dlatego nie są przerywane z powodu nadmiernego wykorzystania we/wy dysku. Konfiguracja nadużywania może jednak określać listę aplikacji i usług dostawców, które można bezpiecznie zakończyć.
  • Wszystkie aplikacje innych firm można bezpiecznie zakończyć.

Gdy aplikacja lub usługa może zostać bezpiecznie zamknięta, Watchdog wyłącza ją za pomocą stanu komponentu aplikacji PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED .

Konfiguracja nadużywania

Konfiguracja nadużywania zawiera progi i działania dotyczące nadużywania wejść/wyjść dysku. Domyślne konfiguracje nadużywania są definiowane w obrazach systemu i dostawców oraz dostarczane z kompilacją. Dostawcy mogą opcjonalnie dodać konfigurację dostawcy do obrazu dostawcy. Jeśli konfiguracja dostawcy nie została podana, do aplikacji i usług dostawcy jest używana konfiguracja systemu.

Watchdog udostępnia interfejsy API systemu za pomocą CarWatchdogManager, co pozwala dostawcom aktualizować konfigurację w dowolnym momencie.

Definicja konfiguracji nadwyrężenia

Konfiguracja nadużywania jest podzielona według typu komponentu, np. system, dostawca i inne firmy. Producenci OEM muszą zaktualizować tylko konfigurację komponentu dostawcy.

Konfiguracja dostawcy

Konfiguracja dostawcy definiuje progi i działania związane z nadmiernym wykorzystaniem dysków dla wszystkich aplikacji i usług dostawcy oraz wszystkich map i aplikacji multimedialnych. Konfiguracja zawiera te pola konfiguracji.

  • Prefiksy pakietów dostawców. Wszystkie pakiety zainstalowane w partycji dostawcy są uważane za pakiety dostawcy. Oprócz tych pakietów dostawcy mogą klasyfikować wstępnie zainstalowane pakiety jako pakiety dostawcy, dodając prefiksy pakietów do konfiguracji prefiksów pakietów dostawcy. Ta konfiguracja nie akceptuje wyrażeń regularnych.
  • Pakiety, które można bezpiecznie zakończyć. Dostawcy mogą określić, które pakiety dostawcy można bezpiecznie zakończyć, dodając pełne nazwy pakietów do konfiguracji pakietów bezpiecznych do zakończenia.
  • Mapowania kategorii aplikacji. Dostawcy mogą zmapować dowolny pakiet (w tym pakiety innych firm) do jednej z 2 obsługiwanych kategorii aplikacji: Mapy i Media. Mapowanie to ma na celu zapewnienie aplikacjom do map i multimediów wyższych progów nadmiernego użycia wejścia-wyjścia na dysku, ponieważ te aplikacje mają tendencję do pobierania i zapisywania na dysku więcej danych niż inne typy aplikacji.
  • Progi na poziomie komponentu. Definiuje ogólne progi dla wszystkich pakietów dostawców (czyli pakietów, które nie są objęte progami dotyczącymi pakietów ani progami dotyczącymi kategorii aplikacji). Podczas definiowania konfiguracji nadużywania operacji wejścia/wyjścia na dysku dostawcy muszą zdefiniować niezerowane progi na poziomie komponentu.
  • Progi dotyczące poszczególnych pakietów. Dostawcy mogą definiować specjalne progi dla konkretnych pakietów. Mapowania powinny zawierać pełne nazwy pakietów. Próg określony w tej konfiguracji ma pierwszeństwo przed progami określonymi w innych konfiguracjach danego pakietu.
  • Progi w przypadku poszczególnych kategorii aplikacji. Dostawcy mogą określać specjalne progi dla określonych kategorii aplikacji. Kategorie aplikacji muszą należeć do jednej z obsługiwanych kategorii – mapy i multimedia. Prógowe wartości zdefiniowane w tej konfiguracji są mapowane na konkretne pakiety za pomocą mapowania kategorii aplikacji.
  • Progi w całym systemie. Dostawcy nie mogą określać tej konfiguracji.

Przedrostki pakietów dostawcy, pakiety bezpieczne do zakończenia, progi na poziomie komponentów i konfiguracje progów na poziomie pakietu mogą być aktualizowane tylko przez konfigurację dostawcy w przypadku aplikacji i usług dostawcy. Konfiguracja progresji dla poszczególnych kategorii aplikacji może być aktualizowana tylko przez konfigurację dostawcy dla wszystkich map i aplikacji multimedialnych.

Progi nadużywania zawierają liczbę bajtów, które mogą zostać zapisane podczas:

  • tryb aplikacji lub usługi na pierwszym planie a w tle;
  • Tryb garażu systemu

Ta klasyfikacja umożliwia aplikacjom i usługom na pierwszym planie zapisywanie większej ilości danych niż aplikacjom i usługom działającym w tle. W trybie Garaż aplikacje i usługi zwykle pobierają aktualizacje, więc każda z nich wymaga wyższego progu niż aplikacje i usługi działające w innych trybach.

Konfiguracje systemu i rozwiązań innych firm

Producenci OEM nie powinni aktualizować systemu ani konfiguracji innych firm.

  • Konfiguracja systemu określa progi i działania dotyczące nadużywania wejść/wyjść w przypadku aplikacji i usług systemowych.
    • Ta konfiguracja może też zaktualizować mapowania kategorii aplikacji. Dlatego to pole konfiguracji jest wspólne dla konfiguracji systemu i dostawcy.
  • Konfiguracja aplikacji innych firm określa progi dla wszystkich aplikacji innych firm. Wszystkie aplikacje, które nie są zainstalowane fabrycznie w systemie, są aplikacjami innych firm.
    • Wszystkie aplikacje innych firm mają te same wartości progowe (np. żadna aplikacja innej firmy nie ma specjalnych wartości progowych), z wyjątkiem aplikacji do map i multimediów, których wartości progowe są definiowane przez konfigurację dostawcy.
    • Podane poniżej progi nadużywania operacji wejścia/wyjścia na dysku są domyślnymi wartościami progowymi dla aplikacji innych firm. Te progi są dostarczane z obrazem systemu.
      • 3 GB w trybie aplikacji na pierwszym planie.
      • 2 GB w trybie działania w tle aplikacji.
      • 4 GB zapisu w trybie garażu systemu.
    • To są progi podstawowe. Te wartości graniczne są aktualizowane w miarę zdobywania informacji o wykorzystaniu operacji wejścia/wyjścia na dysku.

Format XML konfiguracji nadużywania

Domyślną konfigurację dostawcy można umieścić (jest to opcjonalne) w miejscu /vendor/etc/automotive/watchdog/resource_overuse_configuration.xml w pliku obrazu kompilacji. Jeśli ta konfiguracja nie jest określona, konfiguracja zdefiniowana przez system jest stosowana również w przypadku aplikacji i usług dostawcy.

Plik XML powinien zawierać tylko 1 tag dla każdego pola konfiguracji. Konfiguracja dotycząca nadużywania wejść i wyjść musi być zdefiniowana w pliku XML. Wszystkie wartości progowe należy podać w jednostce MiB.

Poniżej przedstawiamy przykładową konfigurację XML:

<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>

Aktualizowanie konfiguracji nadużywania za pomocą interfejsów systemowych CarWatchdogManager

Powyższą konfigurację XML można podać tylko w pliku obrazu kompilacji. Jeśli po wydaniu wersji kompilacji OEM zdecyduje się zaktualizować konfigurację na urządzeniu, może użyć tych interfejsów API, aby wprowadzić zmiany w konfiguracji na urządzeniu.

  • Przyznaj uprawnienia Car.PERMISSION_CONTROL_CAR_WATCHDOG_CONFIG rozmówcy.
  • Aby zaktualizować i ustawić nowe konfiguracje, musisz użyć istniejących konfiguracji. Użyj interfejsu API CarWatchdogManager.getResourceOveruseConfigurations, aby pobrać istniejące konfiguracje. Jeśli nie użyjesz istniejących konfiguracji, wszystkie konfiguracje (w tym systemowe i konfiguracje innych firm) zostaną zastąpione, co nie jest zalecane.
  • Zaktualizuj istniejące konfiguracje, stosując zmiany delta, i ustaw nowe konfiguracje. Nie aktualizuj konfiguracji systemu i komponentów innych firm.
  • Użyj interfejsu API CarWatchdogManager.setResourceOveruseConfigurations, aby ustawić nowe konfiguracje.
  • Aby pobrać i ustawić konfiguracje nadużywania we/wy dysku, użyj flagi CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO.

Oto przykładowa implementacja, która aktualizuje konfiguracje nadużywania zasobów:

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();
}

Aplikacje monitorujące nadmierne wykorzystanie zasobów

Aplikacje dostawców i aplikacje innych firm mogą odbierać powiadomienia o nadużywaniu zasobów przez aplikację z Watchdoga lub ankietować CarWatchdogManager w celu uzyskania statystyk dotyczących nadużywania zasobów przez aplikację z ostatnich 30 dni.

Odsłuchiwanie powiadomień o nadużywaniu zasobów

Aplikacje mogą stosować odbiornik nadużywania zasobów i rejestrować go w CarWatchdogManager, aby otrzymywać powiadomienia dotyczące aplikacji, gdy przekroczy ona 80% lub 100% progów nadużywania operacji wejścia/wyjścia z dysku. Aplikacje mogą używać tych powiadomień do:

  • rejestrowanie statystyk nadużywania operacji wejścia/wyjścia na dysku do analizy offline; Deweloperzy aplikacji mogą używać tego logowania do debugowania problemu nadużywania operacji wejścia/wyjścia na dysku.
  • Zmniejsz liczbę operacji zapisu na dysku, aż liczniki nadużywania zostaną zresetowane.

Klient Java

  1. Zaimplementuj detektor, dziedzicząc go z poziomu 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. Zarejestruj instancję listenera, wywołując funkcję 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. Zwróć uwagę, że po zakończeniu słuchania przez aplikację:
    private void removeResourceOveruseListener() {
        CarWatchdogManager manager =
                (CarWatchdogManager) car.getCarManager(Car.CAR_WATCHDOG_SERVICE);
        mCarWatchdogManager.removeResourceOveruseListener(
              mListenerImpl);
    }

Klient natywny

  1. Uwzględnij carwatchdog_aidl_interface-ndk_platform w zależności shared_libs reguły kompilacji.

    Android.bp

    cc_binary {
        name: "sample_native_client",
        srcs: [
            "src/*.cpp"
        ],
        shared_libs: [
            "carwatchdog_aidl_interface-ndk_platform",
            "libbinder_ndk",
        ],
        vendor: true,
    }
  2. Dodaj zasadę SELinux, aby domena usługi dostawcy mogła używać bindera (makro binder_user) i dodaj domenę usługi dostawcy do domeny klienta carwatchdog ((carwatchdog_client_domain macro)). Poniżej znajdziesz kod dotyczący funkcji 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. Zaimplementuj listenera nadużywania zasobów, dziedzicząc go z poziomu BnResourceOveruseListener. Zastąpić BnResourceOveruseListener::onOveruse, aby zarządzać powiadomieniami o nadużywaniu zasobów.

    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. Uruchom pulę wątków bindera i zarejestruj listenera nadużywania zasobów na serwerze watchdog. Serwer watchdog jest zarejestrowany pod nazwą usługi 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);
    }

Statystyki nadużywania zasobów

Aplikacje mogą prosić CarWatchdogManagera o statystyki dotyczące nadużywania wejść/wyjść w przypadku danej aplikacji (ATS) z ostatnich 30 dni.

Klient Java

Aby uzyskać statystyki dotyczące nadużywania zasobów, użyj CarWatchdogManager.getResourceOveruseStats. Przekaż flagę CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO, aby uzyskać statystyki nadużywania operacji wejścia-wyjścia na dysku.

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()
}

Klient natywny

Aby uzyskać statystyki dotyczące nadużywania zasobów, użyj CarWatchdogServer.getResourceOveruseStats. Przekaż typ ResourceType.IO, aby pobrać statystyki nadużywania I/O dysku.

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
      }
}

Wrażenia użytkowników w przypadku nadużywania zasobów

W sekcjach poniżej opisujemy działania użytkownika w przypadku nadużywania zasobów.

Ustawienie priorytetu wydajności aplikacji

Na stronie Ustawienia aplikacji znajdują się ustawieniaPrioritize app performance (patrz obrazek poniżej), które pozwalają użytkownikom nadać priorytet wydajności aplikacji nad systemem i długoterminową wydajnością sprzętu. To ustawienie jest dostępne tylko w przypadku aplikacji, które można bezpiecznie zakończyć w przypadku nadużywania zasobów. W przeciwnym razie to ustawienie jest wyłączone. Jeśli to ustawienie jest wyłączone (ustawienie domyślne) dla aplikacji, aplikacja może zostać zamknięta z powodu nadmiernego wykorzystania zasobów. W przeciwnym razie aplikacja nie zostanie zamknięta z powodu nadużywania zasobów.

Gdy użytkownik włączy to ustawienie, pojawi się okno potwierdzenia z opisem konsekwencji włączenia tego ustawienia:

Po 90 dniach to ustawienie zostanie automatycznie przywrócone do wartości domyślnej. Limit dni można zmienić za pomocą aplikacji nakładki RRO za pomocą funkcji watchdogUserPackageSettingsResetDays do maksymalnie 180 dni. Więcej informacji znajdziesz w artykule Zmienianie wartości zasobów aplikacji w czasie wykonywania. W pliku AndroidManifest.xml możesz umieścić ten przykładowy tag nakładki:

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

res/values/config.xml:

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

res/xml/overlays.xml:

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

Ustawienie dotyczące aplikacji wpływających na wydajność

Aplikacja Ustawienia zawiera sekcję Aplikacje wpływające na wydajność (patrz rys. 1). Po jej kliknięciu wyświetli się lista aplikacji, które zostały ograniczone z powodu nadużywania pamięci flash i mają negatywny wpływ na wydajność systemu. Jest to zgodne z wymogiem CDD 3.5.1 [C-1-1].

Aplikacje wpływające na wydajność

Rysunek 1. aplikacje wpływające na wydajność,

Aplikacje zakończone z powodu nadużywania zasobów są wymienione tutaj (patrz rys. 2). Możesz określić kolejność wyświetlania aplikacji. Więcej informacji znajdziesz w sekcji Ustawienie nadawania priorytetu działaniu aplikacji.

Lista aplikacji zakończonych z powodu nadmiernego wykorzystania zasobów

Rysunek 2. Lista aplikacji zakończonych z powodu nadmiernego wykorzystania zasobów.

Powiadomienie użytkownika

Gdy aplikacja lub usługa wielokrotnie nadużywa wejść/wyjść dyskowych (np. zapisuje dane na dysku poza zdefiniowanymi wartościami progowymi) w określonym czasie i można ją bezpiecznie zamknąć z powodu nadużywania zasobów, użytkownik jest powiadamiany, gdy pojazd wejdzie w stan zezwalający na rozproszenie kierowcy.

Pierwsze powiadomienie dla użytkownika (podczas jazdy) jest wyświetlane jako powiadomienie z uprzedzeniem, a pozostałe powiadomienia są wyświetlane w centrum powiadomień.

Jeśli na przykład aplikacja wielokrotnie nadużywa operacji wejścia/wyjścia z dysku, użytkownik otrzymuje takie powiadomienie:

  • Gdy użytkownik kliknie przycisk Daj pierwszeństwo aplikacji, otworzy się strona ustawień aplikacji, na której może włączyć lub wyłączyć ustawienie Daj pierwszeństwo wydajności aplikacji.
  • Gdy użytkownik kliknie przycisk Wyłącz aplikację, aplikacja jest wyłączona, dopóki użytkownik nie uruchomi jej lub nie włączy jej na stronie ustawień.
  • W przypadku aplikacji, które można odinstalować, przycisk Wyłącz aplikację jest zastąpiony przyciskiem Odinstaluj aplikację. Gdy użytkownik kliknie przycisk Odinstaluj aplikację, otworzy się strona Ustawienia aplikacji, na której użytkownik może odinstalować aplikację.

Rekomendacja dotycząca implementacji menu

Gdy aplikacje są wyłączone z powodu nadużywania zasobów, znikają z domyślnego menu aplikacji, ponieważ usługa CarService aktualizuje stan włączenia aplikacji jako PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED. Producenci OEM muszą zaktualizować implementację wbudowanego programu uruchamiającego, aby wyświetlać te aplikacje jako nietypowe, dzięki czemu użytkownicy będą mogli z nich korzystać w razie potrzeby. Zobacz te rekomendacje na podstawie wersji kompilacji.

Wersja 2 Androida SC