نظارت بر مصرف فلش مموری

Watchdog با ردیابی کل میزان نوشتن‌های ورودی/خروجی دیسک که توسط همه برنامه‌ها و سرویس‌ها انجام می‌شود، با استفاده از آمار ورودی/خروجی دیسک به ازای هر UID که توسط هسته در مکان `/proc/uid_io/stats` نمایش داده می‌شود، میزان استفاده از حافظه فلش را رصد می‌کند. هنگامی که یک برنامه یا سرویس از آستانه استفاده بیش از حد از ورودی/خروجی دیسک فراتر می‌رود، Watchdog اقداماتی را روی برنامه یا سرویس انجام می‌دهد. آستانه‌های استفاده بیش از حد از ورودی/خروجی دیسک و اقدامی که باید در صورت استفاده بیش از حد انجام شود، در پیکربندی استفاده بیش از حد از ورودی/خروجی دیسک از پیش تعریف شده است.

آستانه‌های استفاده بیش از حد

  • آستانه‌های استفاده بیش از حد از دیسک I/O به صورت روزانه اعمال می‌شوند، یعنی تمام نوشتن‌های انجام شده توسط یک برنامه/سرویس از ابتدای روز تقویمی UTC فعلی جمع‌آوری شده و با آستانه‌های تعریف شده در پیکربندی‌های استفاده بیش از حد بررسی می‌شوند.
  • وقتی یک وسیله نقلیه در یک روز معین چندین بار روشن می‌شود، ماژول Watchdog آمار استفاده از ورودی/خروجی دیسک را در حافظه فلش ذخیره می‌کند و آنها را از ابتدای روز تقویمی UTC فعلی جمع‌آوری می‌کند.

اقدامات بیش از حد استفاده

وقتی یک برنامه به طور مکرر از آستانه‌های تعریف‌شده‌ی استفاده‌ی بیش از حد از دیسک (ورودی/خروجی) عبور می‌کند، Watchdog اقداماتی را که در پیکربندی استفاده‌ی بیش از حد تعریف شده است، انجام می‌دهد.

  • تمام برنامه‌ها و سرویس‌های فروشنده برای پایداری کلی سیستم حیاتی تلقی می‌شوند، بنابراین در صورت استفاده بیش از حد از ورودی/خروجی دیسک خاتمه نمی‌یابند. با این حال، پیکربندی استفاده بیش از حد می‌تواند لیستی از برنامه‌ها و سرویس‌های فروشنده که می‌توان آنها را به طور ایمن خاتمه داد، تعریف کند.
  • همه برنامه‌های شخص ثالث به صورت ایمن قابل فسخ هستند.

وقتی یک برنامه یا سرویس به صورت امن قابل خاتمه دادن باشد، Watchdog برنامه یا سرویس را با حالت مؤلفه برنامه PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED غیرفعال می‌کند.

استفاده بیش از حد از پیکربندی

پیکربندی overuse شامل آستانه‌ها و اقدامات overuse دیسک I/O است. پیکربندی‌های پیش‌فرض overuse در system و vendor image تعریف شده و همراه با build ارائه می‌شوند. فروشندگان می‌توانند به صورت اختیاری پیکربندی vendor را در vendor image قرار دهند. هنگامی که پیکربندی vendor ارائه نشده باشد، پیکربندی سیستم برای برنامه‌ها و سرویس‌های vendor نیز استفاده می‌شود.

Watchdog از طریق CarWatchdogManager رابط‌های برنامه‌نویسی کاربردی (API) سیستم را در معرض نمایش قرار می‌دهد، که به برنامه‌ها یا سرویس‌های فروشندگان اجازه می‌دهد پیکربندی فروشنده را در هر زمان به‌روزرسانی کنند.

تعریف پیکربندی بیش از حد استفاده شده

پیکربندی Overuse بر اساس نوع قطعه، مثلاً سیستم، فروشنده و شخص ثالث، تقسیم‌بندی می‌شود. تولیدکنندگان اصلی تجهیزات (OEM) باید فقط پیکربندی قطعه فروشنده را به‌روزرسانی کنند.

پیکربندی فروشنده

پیکربندی فروشنده، آستانه‌ها و اقدامات مربوط به استفاده بیش از حد از دیسک I/O را برای همه برنامه‌ها و سرویس‌های فروشنده و همه نقشه‌ها و برنامه‌های رسانه‌ای تعریف می‌کند. این پیکربندی شامل فیلدهای پیکربندی زیر است.

  • پیشوندهای بسته فروشنده . تمام بسته‌های نصب شده در پارتیشن فروشنده، به عنوان بسته‌های فروشنده در نظر گرفته می‌شوند. علاوه بر این بسته‌ها، فروشندگان می‌توانند بسته‌های از پیش نصب شده را با اضافه کردن پیشوندهای بسته به پیکربندی پیشوندهای بسته فروشنده ، به عنوان بسته‌های فروشنده طبقه‌بندی کنند. این پیکربندی عبارات منظم را نمی‌پذیرد.
  • بسته‌های امن برای خاتمه دادن . فروشندگان می‌توانند با اضافه کردن نام کامل بسته‌ها به پیکربندی بسته‌های امن برای خاتمه دادن، مشخص کنند که کدام بسته‌های فروشنده برای خاتمه دادن ایمن هستند.
  • نگاشت‌های دسته‌بندی برنامه‌ها . فروشندگان می‌توانند هر بسته‌ای (از جمله بسته‌های شخص ثالث) را به یکی از دو دسته‌بندی پشتیبانی‌شده‌ی برنامه‌ها - برنامه‌های نقشه و رسانه - نگاشت کنند. این نگاشت برای فراهم کردن آستانه‌های بالاتر استفاده‌ی بیش از حد از ورودی/خروجی دیسک برای برنامه‌های نقشه و رسانه انجام می‌شود، زیرا این برنامه‌ها تمایل دارند داده‌های بیشتری را نسبت به سایر انواع برنامه‌ها دانلود و روی دیسک بنویسند.
  • آستانه‌های سطح کامپوننت . آستانه‌های عمومی را برای همه بسته‌های فروشنده تعریف می‌کند (یعنی بسته‌هایی که تحت پوشش آستانه‌های خاص بسته یا آستانه‌های خاص دسته برنامه نیستند، این آستانه‌ها را دریافت می‌کنند). فروشندگان باید هنگام تعریف پیکربندی استفاده بیش از حد از ورودی/خروجی دیسک، آستانه‌های سطح کامپوننت غیر صفر را تعریف کنند.
  • آستانه‌های خاص بسته . فروشندگان می‌توانند آستانه‌های خاصی را برای بسته‌های خاص فروشندگان تعریف کنند. نگاشت‌ها باید شامل نام کامل بسته‌ها باشند. آستانه‌های تعریف شده در این پیکربندی نسبت به آستانه‌های تعریف شده در سایر پیکربندی‌ها برای یک بسته مشخص، اولویت دارند.
  • آستانه‌های خاص دسته برنامه . فروشندگان می‌توانند آستانه‌های خاصی را برای دسته‌های خاص برنامه مشخص کنند. دسته‌های برنامه باید یکی از دسته‌های پشتیبانی شده باشند - برنامه‌های نقشه‌ها و رسانه. آستانه‌های تعریف شده در این پیکربندی با استفاده از نگاشت‌های دسته برنامه به بسته‌های خاص نگاشت می‌شوند.
  • آستانه‌های سراسری سیستم . فروشندگان نباید این پیکربندی را مشخص کنند.

پیشوندهای بسته فروشنده ، بسته‌های امن برای خاتمه ، آستانه‌های سطح کامپوننت و پیکربندی‌های آستانه‌های خاص بسته فقط توسط پیکربندی فروشنده برای برنامه‌ها و سرویس‌های فروشنده قابل به‌روزرسانی هستند. پیکربندی آستانه‌های خاص دسته برنامه فقط توسط پیکربندی فروشنده برای همه نقشه‌ها و برنامه‌های رسانه‌ای قابل به‌روزرسانی است.

آستانه‌های استفاده بیش از حد شامل مقدار بایت‌هایی است که مجاز به نوشتن در طول موارد زیر هستند:

  • حالت پیش‌زمینه یک برنامه یا سرویس در مقابل حالت پس‌زمینه
  • حالت گاراژ سیستم

این طبقه‌بندی به برنامه‌ها و سرویس‌های پیش‌زمینه که کاربر با آنها مواجه است اجازه می‌دهد تا داده‌های بیشتری نسبت به برنامه‌ها و سرویس‌های پس‌زمینه بنویسند. در حالت گاراژ، برنامه‌ها و سرویس‌ها تمایل به دانلود به‌روزرسانی‌ها دارند، بنابراین هر کدام به آستانه بالاتری نسبت به برنامه‌ها و سرویس‌هایی که در حالت‌های دیگر اجرا می‌شوند، نیاز دارند.

پیکربندی‌های سیستم و شخص ثالث

تولیدکنندگان اصلی تجهیزات (OEM) نباید سیستم و پیکربندی‌های شخص ثالث را به‌روزرسانی کنند.

  • پیکربندی سیستم، آستانه‌ها و اقدامات مربوط به استفاده بیش از حد از ورودی/خروجی (I/O) را برای برنامه‌ها و سرویس‌های سیستم تعریف می‌کند.
    • این پیکربندی همچنین می‌تواند نگاشت‌های دسته‌بندی برنامه را به‌روزرسانی کند. بنابراین، این فیلد پیکربندی بین پیکربندی‌های سیستم و فروشنده مشترک است.
  • پیکربندی شخص ثالث، آستانه‌هایی را برای همه برنامه‌های شخص ثالث تعریف می‌کند. همه برنامه‌هایی که از قبل در سیستم نصب نشده‌اند، برنامه‌های شخص ثالث هستند.
    • همه برنامه‌های شخص ثالث آستانه‌های یکسانی دریافت می‌کنند (برای مثال، هیچ برنامه شخص ثالثی آستانه‌های خاصی دریافت نمی‌کند) به جز برنامه‌های نقشه و رسانه که آستانه‌های آنها توسط پیکربندی فروشنده تعریف می‌شود.
    • آستانه‌های استفاده بیش از حد از دیسک I/O که در زیر آمده است، آستانه‌های پیش‌فرض برای برنامه‌های شخص ثالث هستند. این آستانه‌ها همراه با تصویر سیستم ارائه می‌شوند.
      • ۳ گیگابایت نوشتن در حالت پیش‌زمینه برنامه.
      • ۲ گیگابایت نوشتن در حالت پس‌زمینه برنامه.
      • ۴ گیگابایت نوشتن در حالت گاراژ سیستم.
    • اینها آستانه‌های پایه هستند. این آستانه‌ها با کسب اطلاعات بیشتر در مورد میزان استفاده از ورودی/خروجی دیسک، به‌روزرسانی می‌شوند.

استفاده بیش از حد از فرمت XML پیکربندی

اختیاری: در اندروید ۱۶ و بالاتر، می‌توانید پیکربندی پیش‌فرض فروشنده را در /vendor/etc/io-watchdog/resource_overuse_configuration.xml در تصویر ساخت قرار دهید.

در اندروید ۱۵ و پایین‌تر، می‌توانید پیکربندی پیش‌فرض فروشنده را در /vendor/etc/watchdog/resource_overuse_configuration.xml در تصویر ساخت قرار دهید. وقتی این پیکربندی مشخص نشده باشد، پیکربندی تعریف‌شده توسط سیستم برای برنامه‌ها و سرویس‌های فروشنده نیز اعمال می‌شود.

فایل XML باید فقط شامل یک برچسب برای هر فیلد پیکربندی باشد. پیکربندی استفاده بیش از حد از ورودی/خروجی باید در فایل XML تعریف شود. تمام مقادیر آستانه باید در واحد MiB مشخص شوند.

یک نمونه پیکربندی 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>

به‌روزرسانی پیکربندی استفاده بیش از حد از طریق APIهای سیستم CarWatchdogManager

پیکربندی XML فوق فقط می‌تواند در تصویر ساخت ارائه شود. اگر یک تولیدکننده اصلی (OEM) تصمیم بگیرد پیکربندی روی دستگاه را پس از انتشار یک ساخت به‌روزرسانی کند، می‌تواند از APIهای زیر برای ایجاد تغییرات در پیکربندی روی دستگاه استفاده کند.

  • مجوز Car.PERMISSION_CONTROL_CAR_WATCHDOG_CONFIG را به فراخواننده اعطا کنید.
  • برای به‌روزرسانی و تنظیم پیکربندی‌های جدید، باید از پیکربندی‌های موجود استفاده شود. برای دریافت پیکربندی‌های موجود، از API CarWatchdogManager.getResourceOveruseConfigurations استفاده کنید. اگر از پیکربندی‌های موجود استفاده نشود، تمام پیکربندی‌ها (از جمله پیکربندی‌های سیستمی و شخص ثالث) بازنویسی می‌شوند که توصیه نمی‌شود.
  • پیکربندی‌های موجود را با تغییرات دلتا به‌روزرسانی کنید و پیکربندی‌های جدید را تنظیم کنید. پیکربندی‌های سیستم و اجزای شخص ثالث را به‌روزرسانی نکنید .
  • برای تنظیم پیکربندی‌های جدید از API CarWatchdogManager.setResourceOveruseConfigurations استفاده کنید.
  • برای دریافت و تنظیم پیکربندی‌های مربوط به استفاده بیش از حد از ورودی/خروجی دیسک، از پرچم CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO استفاده کنید.

در اینجا یک پیاده‌سازی نمونه که پیکربندی‌های استفاده بیش از حد از منابع را به‌روزرسانی می‌کند، آورده شده است:

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

برنامه‌هایی که مصرف بیش از حد منابع خود را رصد می‌کنند

برنامه‌های فروشنده و شخص ثالث می‌توانند به اعلان‌های استفاده بیش از حد از منابع خاص برنامه از Watchdog گوش دهند یا آمار استفاده بیش از حد از منابع خاص برنامه را تا 30 روز گذشته از CarWatchdogManager نظرسنجی کنند.

به اعلان‌های استفاده بیش از حد از منابع گوش دهید

برنامه‌ها می‌توانند یک شنونده‌ی استفاده‌ی بیش از حد از منابع پیاده‌سازی کنند و شنونده را در CarWatchdogManager ثبت کنند تا وقتی از ۸۰٪ یا ۱۰۰٪ آستانه‌ی استفاده‌ی بیش از حد از ورودی/خروجی دیسک خود فراتر رفتند، اعلان‌های خاص برنامه را دریافت کنند. برنامه‌ها می‌توانند از این اعلان‌ها برای موارد زیر استفاده کنند:

  • آمار استفاده بیش از حد از ورودی/خروجی دیسک را برای تجزیه و تحلیل آفلاین ثبت کنید. توسعه‌دهندگان برنامه می‌توانند از این گزارش برای اشکال‌زدایی مشکل استفاده بیش از حد از ورودی/خروجی دیسک استفاده کنند.
  • نوشتن‌های ورودی/خروجی دیسک را تا زمانی که شمارنده‌های استفاده بیش از حد بازنشانی شوند، کاهش دهید.

کلاینت جاوا

  1. با ارث‌بری از CarWatchdogManager.ResourceOveruseListener شنونده (listener) را پیاده‌سازی کنید:
    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. با فراخوانی 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. وقتی برنامه گوش دادن به موارد زیر را تمام کرد، نمونه شنونده را از حالت ثبت خارج کن:
    private void removeResourceOveruseListener() {
        CarWatchdogManager manager =
                (CarWatchdogManager) car.getCarManager(Car.CAR_WATCHDOG_SERVICE);
        mCarWatchdogManager.removeResourceOveruseListener(
              mListenerImpl);
    }

کلاینت بومی

  1. carwatchdog_aidl_interface-ndk_platform را در وابستگی shared_libs مربوط به قانون ساخت، لحاظ کنید.

    Android.bp

    cc_binary {
        name: "sample_native_client",
        srcs: [
            "src/*.cpp"
        ],
        shared_libs: [
            "carwatchdog_aidl_interface-ndk_platform",
            "libbinder_ndk",
        ],
        vendor: true,
    }
  2. سیاست SELinux را اضافه کنید تا به دامنه سرویس فروشنده اجازه استفاده از binder (ماکرو binder_user ) را بدهید و دامنه سرویس فروشنده را به دامنه کلاینت carwatchdog (carwatchdog_client_domain macro) اضافه کنید. برای sample_client.te و file_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. با ارث‌بری از BnResourceOveruseListener شنونده‌ی استفاده‌ی بیش از حد از منابع را پیاده‌سازی کنید. برای مدیریت اعلان‌های استفاده‌ی بیش از حد از منابع BnResourceOveruseListener::onOveruse را بازنویسی کنید.

    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. یک مخزن نخ binder راه‌اندازی کنید و شنونده‌ی استفاده‌ی بیش از حد از منابع را در سرور watchdog ثبت کنید. سرور watchdog تحت نام سرویس 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);
    }

آمار استفاده بیش از حد از منابع نظرسنجی

برنامه‌ها می‌توانند از CarWatchdogManager برای آمار استفاده بیش از حد ورودی/خروجی مختص برنامه ATS برای 30 روز اخیر نظرسنجی کنند.

کلاینت جاوا

برای دریافت آمار استفاده بیش از حد از منابع، CarWatchdogManager.getResourceOveruseStats استفاده کنید. برای دریافت آمار استفاده بیش از حد از ورودی/خروجی دیسک، از پرچم CarWatchdogManager.FLAG_RESOURCE_OVERUSE_IO استفاده کنید.

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

کلاینت بومی

برای دریافت آمار استفاده بیش از حد از منابع، از CarWatchdogServer.getResourceOveruseStats استفاده کنید. برای دریافت آمار استفاده بیش از حد از ورودی/خروجی دیسک، enum ResourceType.IO را به آن ارسال کنید.

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

تجربه کاربری استفاده بیش از حد از منابع

بخش‌های زیر تجربه کاربر را هنگام استفاده بیش از حد از منابع شرح می‌دهند.

اولویت‌بندی تنظیمات عملکرد برنامه

صفحه تنظیمات برنامه شامل تنظیماتی برای Prioritize app performance است (به تصویر زیر مراجعه کنید)، که به کاربران امکان می‌دهد عملکرد یک برنامه را نسبت به سیستم و عملکرد سخت‌افزاری بلندمدت در اولویت قرار دهند. این تنظیم فقط برای برنامه‌هایی در دسترس است که خاتمه دادن به آنها در صورت استفاده بیش از حد از منابع ایمن است. در غیر این صورت، این تنظیم غیرفعال است. وقتی این تنظیم (تنظیم پیش‌فرض) برای یک برنامه غیرفعال باشد، می‌توان برنامه را در صورت استفاده بیش از حد از منابع خاتمه داد. در غیر این صورت، برنامه در صورت استفاده بیش از حد از منابع خاتمه نمی‌یابد.

وقتی کاربر این تنظیم را فعال می‌کند، کادر تأیید زیر پیامدهای فعال کردن این تنظیم را شرح می‌دهد:

پس از ۹۰ روز، این تنظیم به طور خودکار به مقدار پیش‌فرض بازنشانی می‌شود. محدودیت روز را می‌توان با یک برنامه‌ی RRO overlay با استفاده از watchdogUserPackageSettingsResetDays ، تا حداکثر ۱۸۰ روز تغییر داد. برای کسب اطلاعات بیشتر، به بخش «تغییر مقدار منابع یک برنامه در زمان اجرا» مراجعه کنید. مثال زیر از تگ overlay را می‌توان در AndroidManifest.xml گنجاند:

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

تنظیمات برنامه‌های تأثیرگذار بر عملکرد

برنامه تنظیمات شامل بخشی به نام برنامه‌های تأثیرگذار بر عملکرد است (شکل 1 را ببینید). وقتی روی آن ضربه بزنید، فهرستی از برنامه‌هایی که به دلیل استفاده بیش از حد از حافظه فلش محدود شده‌اند و بر عملکرد سیستم تأثیر منفی می‌گذارند، نمایش داده می‌شود. این مورد از الزامات CDD 3.5.1 [C-1-1] پیروی می‌کند.

برنامه‌های تأثیرگذار بر عملکرد

شکل ۱. برنامه‌های تأثیرگذار بر عملکرد.

برنامه‌هایی که به دلیل استفاده بیش از حد از منابع متوقف شده‌اند، در اینجا فهرست شده‌اند (شکل ۲ را ببینید). برنامه‌های فهرست‌شده را می‌توان اولویت‌بندی کرد. برای کسب اطلاعات بیشتر، به تنظیمات اولویت‌بندی عملکرد برنامه مراجعه کنید.

لیست برنامه‌هایی که به دلیل استفاده بیش از حد از منابع، متوقف شده‌اند

شکل ۲. فهرست برنامه‌هایی که به دلیل استفاده بیش از حد از منابع خاتمه یافته‌اند.

اعلان کاربر

وقتی یک برنامه یا سرویس در یک دوره زمانی مشخص، مکرراً بیش از حد از ورودی/خروجی دیسک استفاده می‌کند (برای مثال، داده‌ها را فراتر از آستانه‌های تعریف‌شده روی دیسک می‌نویسد) و در صورت استفاده بیش از حد از منابع، می‌توان آن را به‌طور ایمن خاتمه داد، پس از ورود وسیله نقلیه به حالت «اجازه حواس‌پرتی راننده» به کاربر اطلاع داده می‌شود.

اولین اعلان کاربر (در حین رانندگی) به عنوان یک اعلان هشدار دهنده ارسال می‌شود و سایر اعلان‌ها در مرکز اعلان‌ها قرار می‌گیرند.

برای مثال، وقتی یک برنامه مکرراً از ورودی/خروجی دیسک بیش از حد استفاده می‌کند، کاربر اعلان زیر را دریافت می‌کند:

  • وقتی کاربر روی دکمه‌ی «اولویت‌بندی برنامه» کلیک می‌کند، صفحه‌ی تنظیمات برنامه باز می‌شود که در آن می‌تواند تنظیمات «اولویت‌بندی عملکرد برنامه» را فعال یا غیرفعال کند.
  • وقتی کاربر روی دکمه غیرفعال کردن برنامه کلیک می‌کند، برنامه غیرفعال می‌شود تا زمانی که کاربر برنامه را اجرا کند یا آن را در صفحه تنظیمات برنامه فعال کند.
  • برای برنامه‌هایی که قابل حذف نصب هستند، دکمه غیرفعال کردن برنامه با دکمه حذف نصب برنامه جایگزین شده است. وقتی کاربر روی دکمه حذف نصب برنامه کلیک می‌کند، صفحه تنظیمات برنامه اجرا می‌شود که از آنجا می‌تواند برنامه را حذف نصب کند.

توصیه برای پیاده‌سازی لانچر

وقتی برنامه‌ها به دلیل استفاده بیش از حد از منابع غیرفعال می‌شوند، برنامه‌ها از برنامه لانچر پیش‌فرض ناپدید می‌شوند زیرا CarService وضعیت فعال برنامه‌ها را به صورت PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED به‌روزرسانی می‌کند. تولیدکنندگان اصلی تجهیزات (OEM) باید پیاده‌سازی لانچر داخلی را به‌روزرسانی کنند تا این برنامه‌ها را طبق معمول نمایش دهند، تا کاربران در صورت نیاز بتوانند از آنها استفاده کنند. به توصیه‌های زیر بر اساس نسخه ساخت مراجعه کنید.

انتشار نسخه دوم اندروید SC