מעקב אחר השימוש בזיכרון ה-Flash

Watchdog עוקב אחר השימוש בזיכרון ה-Flash על ידי מעקב אחר הכמות הכוללת של כתבי קלט/פלט (I/O) שבוצעו על ידי כל האפליקציות והשירותים באמצעות נתוני קלט/פלט של דיסק לפי UID, שנחשפו על ידי הליבה (Kernel) במיקום '/proc/uid_io/stats'. כשאפליקציה או שירות חורגים מסף השימוש יתר בדיסק, Watchdog מבצע פעולות באפליקציה או בשירות. ערכי הסף לשימוש יתר בקלט/פלט בדיסק והפעולה שצריך לבצע במקרה של שימוש יתר מוגדרים מראש בהגדרות של שימוש יתר בקלט/פלט בדיסק.

ערכי סף לשימוש יתר

  • ערכי הסף לשימוש יתר ב-I/O בדיסק נאכפים על בסיס יומי. כלומר, כל פעולות הכתיבה שבוצעו על ידי אפליקציה או שירות נצברות מתחילת היום הקלנדרי הנוכחי לפי שעון UTC, ונבדקות מול ערכי הסף שהוגדרו בהגדרות של שימוש יתר.
  • כשמתניעים רכב כמה פעמים ביום נתון, המודול של הטיימר המפקח (watchdog) מאחסן את נתוני השימוש של הקלט/פלט בדיסק בזיכרון ה-Flash, וצובר אותם מאז תחילת היום הקלנדרי הנוכחי של שעון UTC.

פעולות של שימוש יתר

כשאפליקציה חורגת שוב ושוב מהספים שהוגדרו לשימוש יתר ב-I/O בדיסק, Watchdog מבצע את הפעולות שהוגדרו בהגדרות של שימוש יתר.

  • כל האפליקציות והשירותים של הספקים נחשבים חיוניים ליציבות המערכת הכוללת, ולכן הם לא יופסקו בגלל שימוש מוגזם ב-I/O בדיסק. עם זאת, ההגדרות של שימוש יתר יכולות להגדיר רשימה של אפליקציות ושירותים של ספקים שבטוחים לסיום.
  • אפשר לסגור בבטחה את כל האפליקציות של הצד השלישי.

כשאפשר לסיים את האפליקציה או השירות בבטחה, Watchdog משבית אותם עם מצב הרכיב PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED .

הגדרת שימוש יתר

הגדרת השימוש יתר מכילה את ערכי הסף והפעולות של שימוש יתר ב-I/O בדיסק. הגדרות ברירת המחדל של שימוש יתר מוגדרות בתמונות של המערכת והספק, ונשלחות עם ה-build. ספקים יכולים לכלול את הגדרות הספק בתמונת הספק. אם לא מציינים הגדרות של הספק, המערכת משתמשת בהגדרות שלה גם באפליקציות ובשירותים של הספק.

Watchdog חושף ממשקי API של מערכת דרך CarWatchdogManager, שמאפשרים לאפליקציות או לשירותים של ספקים לעדכן את הגדרות הספק בכל שלב.

הגדרת תצורה של שימוש יתר

ההגדרה של שימוש יתר מחולקת לפי סוג הרכיב, לדוגמה: מערכת, ספק וצד שלישי. יצרני ציוד מקורי צריכים לעדכן רק את ההגדרות של רכיבי הספק.

הגדרות אישיות של ספק

בהגדרות של הספק מוגדרים הסף והפעולות לשימוש יתר ב-I/O בדיסק לכל האפליקציות והשירותים של הספק, וכל האפליקציות של מפות ומדיה. ההגדרה מכילה את שדות ההגדרה הבאים.

  • תחיליות של חבילות של ספקים. כל החבילות שמותקנות במחיצה של הספק נחשבות לחבילות של הספק. בנוסף לחבילות האלה, ספקים יכולים לסווג חבילות מותקנות מראש כחבילות של ספקים על ידי הוספת הקידומות של החבילות להגדרה vendor package prefixes. ההגדרה הזו לא מקבלת ביטויים רגולריים.
  • חבילות בטוחות למחיקה. ספקים יכולים לציין אילו חבילות שלהם בטוחות לסגירה על ידי הוספת שמות החבילות המלאים להגדרה safe-to-terminate packages.
  • מיפויים של קטגוריות אפליקציות. ספקים יכולים למפות כל חבילת אפליקציות (כולל חבילות של צד שלישי) לאחת משתי הקטגוריות הנתמכות של אפליקציות – אפליקציות מפה ואפליקציות מדיה. המיפוי הזה נועד לספק למפות ולאפליקציות מדיה ערכי סף גבוהים יותר של קלט/פלט (I/O) בדיסק, כי האפליקציות האלה נוטות להוריד ולכתוב יותר נתונים לדיסק בהשוואה לסוגים אחרים של אפליקציות.
  • סכומי סף ברמת הרכיב. הגדרת ערכי סף כלליים לכל חבילות הספקים (כלומר, חבילות שלא חלות עליהן ערכי סף ספציפיים לחבילות או ערכי סף ספציפיים לקטגוריות של אפליקציות). ספקים חייבים להגדיר ערכי סף שאינם אפס ברמת הרכיב כשהם מגדירים את ההגדרות של שימוש יתר ב-I/O בדיסק.
  • ערכי סף ספציפיים לחבילה. ספקים יכולים להגדיר ערכי סף מיוחדים לחבילות ספציפיות של ספקים. המיפויים צריכים לכלול את שמות החבילות המלאים. ערכי הסף שמוגדרים בהגדרה הזו מקבלים עדיפות על פני ערכי הסף שמוגדרים בהגדרות אחרות לחבילה מסוימת.
  • סף ספציפי לקטגוריית אפליקציה. ספקים יכולים לציין ערכי סף מיוחדים לקטגוריות ספציפיות של אפליקציות. קטגוריות האפליקציות חייבות להיות אחת מהקטגוריות הנתמכות – אפליקציות מפות ואפליקציות מדיה. ערכי הסף שמוגדרים בהגדרה הזו ממופים לחבילות ספציפיות באמצעות מיפויים של קטגוריות אפליקציות.
  • ערכי סף ברמת המערכת. אסור לספקים לציין את ההגדרה הזו.

אפשר לעדכן את ההגדרות של תחילית החבילה של הספק, חבילות שניתן לסגור בבטחה, סף ברמת הרכיב וסף ספציפי לחבילה רק באמצעות הגדרות הספק לאפליקציות ולשירותים של הספק. אפשר לעדכן את ההגדרה של סף ספציפי לקטגוריית אפליקציה רק באמצעות הגדרת הספק לכל האפליקציות של מפות ומדיה.

ערכי הסף לשימוש יתר מכילים את כמות הבייטים שמותר לכתוב במהלך:

  • מצב חזית לעומת מצב רקע של אפליקציה או שירות
  • מצב החניה של המערכת

הסיווג הזה מאפשר לאפליקציות ולשירותים בחזית המשתמש לכתוב יותר נתונים מאשר לאפליקציות ולשירותים ברקע. במצב Garage, האפליקציות והשירותים נוטים להוריד עדכונים, ולכן לכל אחד מהם נדרש סף גבוה יותר מאשר לאפליקציות ולשירותים שפועלים במצבים אחרים.

הגדרות של מערכת וצד שלישי

יצרני ציוד מקורי לא צריכים לעדכן את ההגדרות של המערכת ושל צד שלישי.

  • בהגדרת המערכת מוגדרות ערכי סף ושימוש יתר של קלט/פלט (I/O) עבור אפליקציות ושירותים של המערכת.
    • ההגדרה הזו יכולה גם לעדכן את המיפויים של קטגוריות האפליקציות. לכן, שדה התצורה הזה משותף בין הגדרות המערכת לבין הגדרות הספק.
  • ההגדרות של צד שלישי מגדירות ערכי סף לכל האפליקציות של צד שלישי. כל האפליקציות שלא מותקנות מראש במערכת הן אפליקציות של צד שלישי.
    • כל האפליקציות של צד שלישי מקבלות את אותם ערכי סף (לדוגמה, אף אפליקציה של צד שלישי לא מקבלת ערכי סף מיוחדים) מלבד אפליקציות של מפות ומדיה, שערכי הסף שלהן מוגדרים על ידי הגדרת הספק.
    • ערכי הסף הבאים לשימוש יתר ב-I/O בדיסק הם ערכי ברירת המחדל לאפליקציות של צד שלישי. ערכי הסף האלה נשלחים עם קובץ האימג' של המערכת.
      • כתיבה בנפח 3 GiB במצב 'חזית' של האפליקציה.
      • כתיבה בנפח 2 GiB במצב הרקע של האפליקציה.
      • כתיבה של 4 GiB במצב 'מחסן המערכת'.
    • אלה ערכי סף בסיסיים. הסף הזה מתעדכן ככל שמתקבל מידע נוסף על השימוש ב-I/O בדיסק.

פורמט XML של הגדרות שימוש יתר

אפשר למקם את תצורת ברירת המחדל של הספק (אופציונלי) במיקום /vendor/etc/automotive/watchdog/resource_overuse_configuration.xml בקובץ האימג' של ה-build. אם לא מציינים את ההגדרה הזו, ההגדרה שמוגדרת במערכת חלה גם על אפליקציות ושירותים של ספקים.

קובץ ה-XML צריך להכיל תג אחד בלבד לכל שדה config. צריך להגדיר את ההגדרות של שימוש יתר ב-I/O בקובץ ה-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 שלמעלה רק בקובץ האימג' של ה-build. אם יצרן ציוד מקורי (OEM) יבחר לעדכן את ההגדרות במכשיר אחרי פרסום ה-build, הוא יוכל להשתמש בממשקי ה-API הבאים כדי לבצע שינויים בהגדרות במכשיר.

  • מעניקים למבצע הקריאה החוזרת את ההרשאה Car.PERMISSION_CONTROL_CAR_WATCHDOG_CONFIG.
  • צריך להשתמש בהגדרות הקיימות כדי לעדכן ולהגדיר את ההגדרות החדשות. משתמשים ב-API‏ CarWatchdogManager.getResourceOveruseConfigurations כדי לקבל את ההגדרות הקיימות. אם לא משתמשים בהגדרות קיימות, כל ההגדרות (כולל הגדרות מערכת והגדרות של צד שלישי) יימחקו, וזו לא המלצה.
  • מעדכנים את ההגדרות הקיימות עם השינויים של דלתא ומגדירים את ההגדרות החדשות. לא מעדכנים את ההגדרות של המערכת ושל רכיבי הצד השלישי.
  • משתמשים ב-API CarWatchdogManager.setResourceOveruseConfigurations כדי להגדיר את ההגדרות החדשות.
  • כדי לקבל ולהגדיר את ההגדרות של שימוש יתר ב-I/O בדיסק, משתמשים בדגל 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% של ערכי הסף שלהן לשימוש יתר ב-I/O בדיסק. אפליקציות יכולות להשתמש בהתראות האלה כדי:

  • רישום ביומן של נתוני הסטטיסטיקה של שימוש יתר ב-I/O בדיסק לצורך ניתוח אופליין. מפתחי האפליקציות יכולים להשתמש ביומן הזה כדי לנפות באגים בבעיה של שימוש יתר ב-I/O בדיסק.
  • מפחיתים את מספר פעולות הכתיבה של קלט/פלט בדיסק עד שמונהני השימוש יאופסו.

לקוח 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. רישום המופע של ה-listener באמצעות קריאה אל 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. ביטול הרישום של מופע ה-listener כשהאפליקציה מסיימת להאזין ל:
    private void removeResourceOveruseListener() {
        CarWatchdogManager manager =
                (CarWatchdogManager) car.getCarManager(Car.CAR_WATCHDOG_SERVICE);
        mCarWatchdogManager.removeResourceOveruseListener(
              mListenerImpl);
    }
    

Native Client

  1. כוללים את carwatchdog_aidl_interface-ndk_platform בתלות shared_libs של כלל ה-build.

    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 ורושמים את ה-listener לשימוש יתר במשאבים אצל השרת 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 הספציפיים לאפליקציה לגבי שימוש יתר ב-I/O ב-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 כדי לאחזר נתונים סטטיסטיים על שימוש יתר ב-I/O בדיסק.

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. רשימת האפליקציות שהושעו בגלל שימוש יתר במשאבים.

הודעה למשתמש

אם אפליקציה או שירות משתמשים באופן חוזר באינטראקציה קלט/פלט (I/O) בדיסק (למשל, כותבים נתונים בדיסק מעבר לסף המוגדר) בפרק זמן מסוים, ואפשר לסגור אותם בבטחה בגלל שימוש יתר במשאבים, המשתמש יקבל הודעה אחרי שהרכב יעבור למצב 'אישור הסחת דעת של הנהג'.

ההתראה הראשונה למשתמש (במהלך נסיעה) מוצגת כהודעה מראש, וההתראות האחרות מוצגות במרכז ההתראות.

לדוגמה, כשאפליקציה משתמשת שוב ושוב בקלט/פלט בדיסק, המשתמש מקבל את ההתראה הבאה:

  • כשהמשתמש לוחץ על הלחצן העדפת האפליקציה, נפתח דף ההגדרות של האפליקציה, שבו המשתמש יכול להפעיל או להשבית את ההגדרה העדפת ביצועי האפליקציה.
  • כשהמשתמש לוחץ על הלחצן Disable app, האפליקציה מושבתת עד שהמשתמש מפעיל אותה או מפעיל אותה בדף ההגדרות של האפליקציה.
  • באפליקציות שניתנות להסרה, הלחצן Disable app מוחלף בלחצן Uninstall app (הסרת האפליקציה). כאשר המשתמש לוחץ על הלחצן Uninstall app (הסרת האפליקציה), נפתח דף ההגדרות של האפליקציה, שממנו המשתמש יכול להסיר את האפליקציה.

המלצה להטמעה של מרכז האפליקציות

כשאפליקציות מושבתות בגלל שימוש יתר במשאבים, הן נעלמות מאפליקציית מרכז האפליקציות שמוגדרת כברירת מחדל, כי CarService מעדכן את מצב ההפעלה של האפליקציות כ-PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED. יצרני ציוד מקורי (OEM) צריכים לעדכן את ההטמעה של מרכז האפליקציות המובנה כדי להציג את האפליקציות האלה כחריגות, כדי שהמשתמשים יוכלו להשתמש בהן במקרה הצורך. תוכלו לראות את ההמלצות הבאות, בהתאם לגרסת ה-build.

Android SC V2 release