مراقبة استخدام ذاكرة الفلاش

يراقب Watchdog استخدام الذاكرة الفلاش من خلال تتبُّع إجمالي عدد عمليات الكتابة للإدخال/الإخراج على القرص التي تجريها جميع التطبيقات والخدمات باستخدام إحصاءات الإدخال/الإخراج على القرص لكل رقم تعريف مستخدم (UID) التي يعرضها النواة في الموقع `/proc/uid_io/stats`. عندما يتجاوز تطبيق أو خدمة الحدّ الأقصى المسموح به لاستخدام الإدخال/الإخراج على القرص، يتّخذ Watchdog إجراءات بشأن الـ تطبيق أو الخدمة. تم تحديد الحدّ الأقصى المسموح به لاستخدام الإدخال/الإخراج على القرص والإجراء الذي يجب اتّخاذه عند تجاوز هذا الحدّ مسبقًا في إعدادات الحدّ الأقصى المسموح به لاستخدام الإدخال/الإخراج على القرص.

الحدود القصوى المسموح بها

  • يتم فرض الحدود القصوى المسموح بها لاستخدام الإدخال/الإخراج على القرص يوميًا، أي يتم تجميع جميع عمليات الكتابة التي يجريها تطبيق أو خدمة منذ بداية اليوم الحالي في التقويم بالتوقيت العالمي المنسَّق (UTC) ومقارنتها بالحدود القصوى المحدّدة في إعدادات الحدّ الأقصى المسموح به.
  • عند تشغيل مركبة عدة مرات في يوم معيّن، تخزِّن وحدة Watchdog إحصاءات استخدام الإدخال/الإخراج على القرص في الذاكرة الفلاش وتجمِّعها منذ بداية اليوم الحالي في التقويم بالتوقيت العالمي المنسَّق.

الإجراءات المتّخذة عند تجاوز الحدّ الأقصى المسموح به

عندما يتجاوز تطبيق بشكل متكرّر الحدود القصوى المحدّدة لاستخدام الإدخال/الإخراج على القرص، يتّخذ Watchdog الإجراءات المحدّدة في إعدادات الحدّ الأقصى المسموح به.

  • تُعدّ جميع تطبيقات وخدمات المورّد ضرورية لاستقرار النظام بشكل عام، لذا لا يتم إنهاؤها عند تجاوز الحدّ الأقصى المسموح به لاستخدام الإدخال/الإخراج على القرص. ومع ذلك، يمكن أن تحدّد إعدادات الحدّ الأقصى المسموح به قائمة بتطبيقات وخدمات المورّد التي يمكن إنهاؤها بأمان.
  • يمكن إنهاء جميع التطبيقات التابعة لجهات خارجية بأمان.

عندما يكون من الآمن إنهاء تطبيق أو خدمة، يوقِف Watchdog التطبيق أو الخدمة باستخدام حالة مكوّن التطبيق PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED .

إعدادات الحدّ الأقصى المسموح به

تحتوي إعدادات الحدّ الأقصى المسموح به على الحدود القصوى المسموح بها لاستخدام الإدخال/الإخراج على القرص والإجراءات المتّخذة عند تجاوز هذه الحدود. تم تحديد إعدادات الحدّ الأقصى المسموح به التلقائية في صور النظام والمورّد، ويتم شحنها مع الإصدار. يمكن للمورّدين اختياريًا تضمين إعدادات المورّد في صورة المورّد. عند عدم توفير إعدادات المورّد، يتم استخدام إعدادات النظام لتطبيقات وخدمات المورّد أيضًا.

يعرض Watchdog واجهات برمجة تطبيقات النظام من خلال CarWatchdogManager، ما يسمح لتطبيقات أو خدمات المورّدين بتعديل إعدادات المورّد في أي وقت.

تعريف إعدادات الحدّ الأقصى المسموح به

يتم تقسيم إعدادات الحدّ الأقصى المسموح به حسب نوع المكوّن، مثلاً النظام والمورّد والجهة الخارجية. على مصنّعي المعدات الأصلية تعديل إعدادات مكوّن المورّد فقط.

إعدادات المورّد

تحدّد إعدادات المورّد الحدود القصوى المسموح بها لاستخدام الإدخال/الإخراج على القرص والإجراءات المتّخذة عند تجاوز هذه الحدود لجميع تطبيقات وخدمات المورّد وجميع تطبيقات الخرائط والوسائط. تحتوي الإعدادات على حقول الإعدادات أدناه.

  • بادئات حِزم المورّد : تُعدّ جميع الحِزم المثبَّتة في الـ قسم المورّد حِزم مورّد. بالإضافة إلى هذه الحِزم، يمكن للمورّدين تصنيف الحِزم المثبَّتة مسبقًا على أنّها حِزم مورّد من خلال إضافة بادئات الحِزم إلى إعدادات بادئات حِزم المورّد. لا تقبل هذه الإعدادات التعبيرات العادية.
  • الحِزم التي يمكن إنهاؤها بأمان : يمكن للمورّدين تحديد حِزم المورّد التي يمكن إنهاؤها بأمان من خلال إضافة أسماء الحِزم الكاملة إلى إعدادات الحِزم التي يمكن إنهاؤها بأمان.
  • عمليات الربط بين فئات التطبيقات : يمكن للمورّدين ربط أي حزمة (بما في ذلك حِزم الجهات الخارجية) بإحدى فئتَي التطبيقات المتوافقتَين ، وهما تطبيقات الخرائط والوسائط. يتم إجراء هذا الربط لتوفير حدود قصوى أعلى لاستخدام الإدخال/الإخراج على القرص لتطبيقات الخرائط والوسائط لأنّ هذه التطبيقات تميل إلى تنزيل المزيد من البيانات وكتابتها على القرص مقارنةً بأنواع التطبيقات الأخرى.
  • الحدود القصوى على مستوى المكوّن : تحدّد هذه الإعدادات الحدود القصوى العامة لجميع حِزم المورّد (أي أنّ الحِزم التي لا تغطيها إعدادات الحدود القصوى الخاصة بالحِزمة أو الحدود القصوى الخاصة بفئة التطبيق تحصل على هذه الحدود القصوى). على المورّدين تحديد حدود قصوى غير صفرية على مستوى المكوّن عند تحديد إعدادات الحدّ الأقصى المسموح به لاستخدام الإدخال/الإخراج على القرص.
  • الحدود القصوى الخاصة بالحِزمة : يمكن للمورّدين تحديد حدود قصوى خاصة بحِزم مورّد معيّنة. يجب أن تحتوي عمليات الربط على الـ أسماء الحِزم الكاملة. يكون للحدود القصوى المحدّدة في هذه الإعدادات الأولوية على الحدود القصوى المحدّدة في الإعدادات الأخرى لحزمة معيّنة.
  • الحدود القصوى الخاصة بفئة التطبيق : يمكن للمورّدين تحديد حدود قصوى خاصة بفئات تطبيقات معيّنة. يجب أن تكون فئات التطبيقات إحدى الفئات المتوافقة، وهما تطبيقات الخرائط والوسائط. يتم ربط الحدود القصوى المحدّدة في هذه الإعدادات بحِزم معيّنة باستخدام عمليات الربط بين فئات التطبيقات.
  • الحدود القصوى على مستوى النظام : على المورّدين عدم تحديد هذه الإعدادات.

لا يمكن تعديل إعدادات بادئات حِزم المورّد والحِزم التي يمكن إنهاؤها بأمان والحدود القصوى على مستوى المكوّن والحدود القصوى الخاصة بالحِزمة إلا من خلال إعدادات المورّد لتطبيقات وخدمات المورّد. لا يمكن تعديل إعدادات الحدود القصوى الخاصة بفئة التطبيق إلا من خلال إعدادات المورّد لجميع تطبيقات الخرائط والوسائط.

تحتوي الحدود القصوى المسموح بها على عدد البايت المسموح بكتابتها خلال:

  • وضع التطبيق أو الخدمة في المقدّمة مقابل وضع التطبيق أو الخدمة في الخلفية
  • وضع المرآب في النظام

يسمح هذا التصنيف للتطبيقات والخدمات التي يراها المستخدم في المقدّمة بكتابة المزيد من البيانات مقارنةً بالتطبيقات والخدمات التي تعمل في الخلفية. في وضع المرآب، تميل التطبيقات والخدمات إلى تنزيل التحديثات، لذا يحتاج كل منها إلى حدّ أقصى أعلى من التطبيقات والخدمات التي تعمل في أوضاع أخرى.

إعدادات النظام والجهات الخارجية

على مصنّعي المعدات الأصلية عدم تعديل إعدادات النظام والجهات الخارجية.

  • تحدّد إعدادات النظام الحدود القصوى المسموح بها لاستخدام الإدخال/الإخراج والإجراءات المتّخذة عند تجاوز هذه الحدود لـ تطبيقات وخدمات النظام.
    • يمكن أن تعدّل هذه الإعدادات أيضًا عمليات الربط بين فئات التطبيقات. وبالتالي، تتم مشاركة حقل الإعدادات هذا بين إعدادات النظام والمورّد.
  • تحدّد إعدادات الجهات الخارجية الحدود القصوى لجميع التطبيقات التابعة لجهات خارجية. تُعدّ جميع التطبيقات التي لم يتم تثبيتها مسبقًا في النظام تطبيقات تابعة لجهات خارجية.
    • تتلقّى جميع التطبيقات التابعة لجهات خارجية الحدود القصوى نفسها (مثلاً، لا يتلقّى أي تطبيق تابع لجهة خارجية حدودًا قصوى خاصة) باستثناء تطبيقات الخرائط والوسائط التي تحدّد إعدادات المورّد حدودها القصوى.
    • الحدود القصوى أدناه لاستخدام الإدخال/الإخراج على القرص هي الحدود القصوى التلقائية للتطبيقات التابعة لجهات خارجية. يتم شحن هذه الحدود القصوى مع صورة النظام.
      • عملية كتابة تبلغ 3 غيغابايت في وضع التطبيق في المقدّمة
      • عملية كتابة تبلغ 2 غيغابايت في وضع التطبيق في الخلفية
      • عملية كتابة تبلغ 4 غيغابايت في وضع المرآب في النظام
    • هذه هي الحدود القصوى الأساسية. يتم تعديل هذه الحدود القصوى كلما توفّرت معلومات إضافية عن استخدام الإدخال/الإخراج على القرص.

تنسيق XML لإعدادات الحدّ الأقصى المسموح به

اختياري: في Android 16 والإصدارات الأحدث، يمكنك وضع إعدادات المورّد التلقائية في /vendor/etc/io-watchdog/resource_overuse_configuration.xml في صورة الإصدار.

في Android 15 والإصدارات الأقدم، يمكنك وضع إعدادات المورّد التلقائية في /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>

تعديل إعدادات الحدّ الأقصى المسموح به من خلال واجهات برمجة تطبيقات النظام في CarWatchdogManager

لا يمكن توفير إعدادات XML أعلاه إلا في صورة الإصدار. إذا اختار أحد المصنّعين الأصليين للأجهزة تعديل الإعدادات على الجهاز فقط بعد إصدار الإصدار، يمكنه استخدام واجهات برمجة التطبيقات التالية لإجراء تغييرات على الإعدادات على الجهاز فقط.

  • امنح الإذن Car.PERMISSION_CONTROL_CAR_WATCHDOG_CONFIG للمتصل.
  • يجب استخدام الإعدادات الحالية لتعديل الإعدادات الجديدة وضبطها. استخدِم واجهة برمجة التطبيقات CarWatchdogManager.getResourceOveruseConfigurations للحصول على الـ إعدادات الحالية. في حال عدم استخدام الإعدادات الحالية، يتم استبدال جميع الإعدادات (بما في ذلك إعدادات النظام والجهات الخارجية)، وهو أمر غير مستحسن.
  • عدِّل الإعدادات الحالية باستخدام التغييرات الجزئية واضبط الإعدادات الجديدة. لا تعدِّل إعدادات مكوّنات النظام والجهات الخارجية.
  • استخدِم واجهة برمجة التطبيقات 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 أو طلب إحصاءات تجاوز الحدّ الأقصى المسموح به لاستخدام الموارد الخاصة بالتطبيق من CarWatchdogManager لمدة تصل إلى آخر 30 يومًا.

الاستماع إلى إشعارات تجاوز الحدّ الأقصى المسموح به لاستخدام الموارد

يمكن للتطبيقات تنفيذ أداة استماع لتجاوز الحدّ الأقصى المسموح به للموارد وتسجيل أداة الاستماع في CarWatchdogManager لتلقّي إشعارات خاصة بالتطبيق عندما تتجاوز 80% أو 100% من الحدود القصوى المسموح بها لاستخدام الإدخال/الإخراج على القرص. يمكن للتطبيقات استخدام هذه الإشعارات في ما يلي:

  • تسجيل إحصاءات تجاوز الحدّ الأقصى المسموح به لاستخدام الإدخال/الإخراج على القرص لإجراء تحليل بلا إنترنت يمكن لمطوّري التطبيقات استخدام هذا التسجيل لتصحيح خطأ تجاوز الحدّ الأقصى المسموح به لاستخدام الإدخال/الإخراج على القرص.
  • تقليل عمليات الكتابة للإدخال/الإخراج على القرص إلى أن تتم إعادة ضبط عدّادات تجاوز الحدّ الأقصى المسموح به

العميل المستند إلى Java

  1. نفِّذ أداة الاستماع من خلال وراثة 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. سجِّل مثيل أداة الاستماع من خلال استدعاء 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_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. ابدأ مجموعة مؤشرات ترابط الرابط وسجِّل أداة الاستماع لتجاوز الحدّ الأقصى المسموح به للموارد في خادم 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` لمدة تصل إلى آخر 30 يومًا.

العميل المستند إلى Java

استخدِم 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 للحصول على إحصاءات تجاوز الحدّ الأقصى المسموح به للموارد. مرِّر تعداد 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 (راجِع الصورة أدناه)، ما يسمح للمستخدمين بمنح الأولوية لأداء تطبيق على أداء النظام و أداء الأجهزة على المدى الطويل. لا يتوفّر هذا الإعداد إلا للتطبيقات التي يمكن إنهاؤها بأمان عند تجاوز الحدّ الأقصى المسموح به للموارد. وإلا، يكون هذا الإعداد غير مفعّل. عند إيقاف هذا الإعداد (الإعداد التلقائي) لتطبيق، يمكن إنهاء التطبيق عند تجاوز الحدّ الأقصى المسموح به للموارد. وإلا، لا يتم إنهاء التطبيق عند تجاوز الحدّ الأقصى المسموح به للموارد.

عندما يفعِّل المستخدم هذا الإعداد، يوضّح مربّع التأكيد التالي الآثار المترتبة على تفعيل الإعداد:

بعد 90 يومًا، تتم إعادة ضبط هذا الإعداد تلقائيًا على الإعداد التلقائي. يمكن تعديل الحدّ الأقصى لعدد الأيام باستخدام تطبيق تراكب RRO باستخدام watchdogUserPackageSettingsResetDays، بحدّ أقصى 180 يومًا. لمزيد من المعلومات، يُرجى الاطّلاع على مقالة تغيير قيمة موارد التطبيق في وقت التشغيل. يمكن تضمين علامة التراكب المثال التالي في 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].

التطبيقات التي تؤثر في الأداء

الشكل 1: التطبيقات التي تؤثر في الأداء

تظهر هنا التطبيقات التي تم إنهاؤها بسبب تجاوز الحدّ الأقصى المسموح به للموارد (راجِع الشكل 2). يمكن منح الأولوية للتطبيقات المدرَجة. لمزيد من المعلومات، يُرجى الاطّلاع على إعدادات منح الأولوية لأداء التطبيق.

قائمة التطبيقات التي تم إنهاؤها بسبب الإفراط في استخدام الموارد

الشكل 2: قائمة بالتطبيقات التي تم إنهاؤها بسبب تجاوز الحدّ الأقصى المسموح به للموارد

إشعار المستخدم

عندما يتجاوز تطبيق أو خدمة بشكل متكرّر الحدّ الأقصى المسموح به لاستخدام الإدخال/الإخراج على القرص (مثلاً، كتابة بيانات على القرص تتجاوز الحدود القصوى المحدّدة) خلال فترة معيّنة ويكون من الآمن إنهاؤه عند تجاوز الحدّ الأقصى المسموح به للموارد، يتم إشعار المستخدم بعد أن تدخل المركبة حالة السماح بتشتيت انتباه السائق.

يتم نشر أول إشعار للمستخدم (أثناء القيادة) كإشعار منبثق، ويتم نشر الإشعارات الأخرى في مركز الإشعارات.

على سبيل المثال، عندما يتجاوز تطبيق بشكل متكرّر الحدّ الأقصى المسموح به لاستخدام الإدخال/الإخراج على القرص، يتلقّى المستخدم الإشعار التالي:

  • عندما ينقر المستخدم على الزر منح الأولوية للتطبيق ، يتم فتح صفحة إعدادات التطبيق، حيث يمكن للمستخدم تفعيل إعدادات منح الأولوية لأداء التطبيق أو إيقافها.
  • عندما ينقر المستخدم على الزر إيقاف التطبيق ، يتم إيقاف التطبيق إلى أن يشغّله المستخدم أو يفعِّله في صفحة إعدادات التطبيق.
  • بالنسبة إلى التطبيقات التي لا يمكن إلغاء تثبيتها، يتم استبدال الزر إيقاف التطبيق بالزر إلغاء تثبيت التطبيق. عندما ينقر المستخدم على الزر إلغاء تثبيت التطبيق ، يتم فتح صفحة إعدادات التطبيق، ومنها يمكن للمستخدم إلغاء تثبيت التطبيق.

اقتراح بشأن تنفيذ مشغّل التطبيقات

عند إيقاف التطبيقات بسبب تجاوز الحدّ الأقصى المسموح به للموارد، تختفي التطبيقات من الـ تطبيق مشغّل التطبيقات التلقائي لأنّ CarService تعدِّل حالة تفعيل التطبيقات إلى PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED. على مصنّعي المعدات الأصلية تعديل تنفيذ مشغّل التطبيقات المضمّن لعرض هذه التطبيقات كالمعتاد، ما يسمح للمستخدمين باستخدامها إذا لزم الأمر. راجِع الاقتراحات التالية استنادًا إلى إصدار الإصدار.

إصدار Android SC V2