ממשק VHAL

ה-VHAL של AIDL מוגדר בקובץ android.hardware.automotive.vehicle namespace. ממשק VHAL מוגדר ב-IVehicle.aidl. אלא אם צוין אחרת, צריך להטמיע את כל השיטות לגרסה ספציפית של VHAL.

גרסאות

גרסת Android הגרסה העדכנית ביותר של VHAL הגרסה האחרונה של מאפיין VHAL הגרסה המינימלית התואמת של VHAL
Android 16 V4 V4 גרסה 1
Android 15 V3 V3 גרסה 1
Android 14 V2 V2 גרסה 1
Android 13 גרסה 1 (ממשק הנכס VHAL לא מפוצל) גרסה 1

מומלץ להטמיע את הגרסה העדכנית ביותר של VHAL לגרסה ספציפית של Android.

פונקציות וקריאות חוזרות

הפונקציות של VHAL מוגדרות ב-IVehicle.aidl.

שיטה
VehiclePropConfigs getAllPropConfigs()
החזרת רשימה של כל הגדרות הנכסים שנתמכות על ידי HAL הרכב הזה.
VehiclePropConfigs getPropConfigs(in int[] props)
החזרת רשימה של הגדרות נכס למזהי נכסים נתונים.
void getValues(IVehicleCallback callback, in GetValueRequests requests)
אחזור ערכים של מאפייני רכב באופן אסינכרוני. טיפול באוסף של GetValueRequest באופן אסינכרוני. התוצאה מועברת באמצעות השיטה onGetValues של קריאה חוזרת.
void setValues(IVehicleCallback callback, in SetValueRequests requests)
הגדרה אסינכררונית של ערכי מאפייני הרכב. טיפול באוסף של SetValueRequest באופן אסינכרוני. התוצאה מועברת באמצעות השיטה onSetValues של קריאה חוזרת.
void subscribe(in IVehicleCallback callback, in SubscribeOptions[] options, int maxSharedMemoryFileCount)
הרשמה לאירועים בנכס עם האפשרויות שצוינו. אפשרויות ההרשמה כוללות את מזהה הנכס, מזהה אזור הנכס וקצב דגימה ב-Hz (לנכס רציף). לא נעשה שימוש ב-maxSharedMemoryFileCount.
void unsubscribe(in IVehicleCallback callback, in int[] propIds)
ביטול ההרשמה לאירועים של נכסים שנרשמו בעבר בנכסים שצוינו.
returnSharedMemory(in IVehicleCallback callback, long sharedMemoryId)
לא בשימוש וניתן להטמיע אותו כפעולה ללא תוצאה (no-op).
(חדש ב-Android 16)
SupportedValuesListResults getSupportedValuesLists(in List propIdAreaIds)
החזרת רשימות הערכים הנתמכים לזוגות של מזהה הנכס ומזהה האזור שצוינו.
הופיע לראשונה ב-VHAL V4.
(חדש ב-Android 16)
MinMaxSupportedValueResults getMinMaxSupportedValue(in List propIdAreaIds)
החזרת הערכים המינימלי והמקסימלי הנתמכים לזוגות של מזהה הנכס ומזהה האזור שצוינו.
הופיע לראשונה ב-VHAL V4.
void registerSupportedValueChangeCallback(in IVehicleCallback callback, in List propIdAreaIds)
רישום קריאה חוזרת (callback) שתתבצע כשהערכים הנתמכים ישתנו.
הופיע לראשונה ב-VHAL V4.
void unregisterSupportedValueChangeCallback(in IVehicleCallback callback, in List propIdAreaIds)
ביטול הרישום של הקריאה החוזרת (callback) לשינוי הערך הנתמך.
הופיע לראשונה ב-VHAL V4.

פונקציות ה-callbacks מוגדרות ב-IVehicleCallback.aidl, והן מכילות את השיטות האלה.

שיטה
oneway void onGetValues(in GetValueResults responses)
פונקציית קריאה חוזרת לפונקציה getValues כדי לספק את תוצאות קבלת הערך. הקריאה מתבצעת כשחלק מהערכים לאחזור מוכנים.
oneway void onSetValues(in SetValueResults responses)
פונקציית קריאה חוזרת (callback) לפונקציה setValues כדי לספק תוצאות של ערכי הגדרה. הקריאה מתבצעת כש-VHAL מסיים לטפל בחלק מהבקשות של קבוצות הנכסים.
oneway void onPropertyEvent(in VehiclePropValues propValues, int sharedMemoryFileCount)
קריאה חוזרת (callback) לדיווח על אירועי עדכון של נכס.
נכס
CONTINUOUS, אירוע נכס מתרחש על סמך קצב דגימה של הרשמה ב-Hz או תדירות ההודעות של צ'יפ הרכב. אירוע בנכס יכול להתרחש גם אם הסטטוס של הנכס משתנה. לדוגמה, מ'לא זמין' ל'זמין'.
במאפיין ON_CHANGE, אירוע נכס מתרחש כשהערך של נכס כלשהו משתנה או כשהסטטוס של נכס כלשהו משתנה.
יש להשתמש באירוע הזה גם כדי לשלוח אירועים של שינוי סטטוס של נכס. לדוגמה, כשהנכס הופך ללא זמין או כשיש שגיאה בקריאה שלו, צריך לשלוח אירוע VehiclePropValue עם סטטוס 'לא זמין' או 'שגיאה' וערך ריק.
SharedMemoryFileCount תמיד שווה ל-0.
oneway void onPropertySetError(in VehiclePropErrors errors)
פונקציית קריאה חוזרת (callback) לדיווח על שגיאות אסינכררוניות של קבוצות נכסים שאין להן בקשת הגדרה תואמת. אם אנחנו יודעים לאיזו בקשה להגדרה מתייחסת השגיאה, צריך להשתמש ב-onSetValues עם תוצאת שגיאה במקום בקוד הזה.
oneway void onSupportedValueChange(in List propIdAreaIds)
קריאה חוזרת (callback) לדיווח על ערך מינימלי וערך מקסימלי נתמכים או על שינויים ברשימת הערכים הנתמכים. מבצע הקריאה אמור להתקשר ל-getMinMaxSupportedValue או ל-getSupportedValuesLists כדי לקבל את הערכים המעודכנים.

הטמעת VHAL מאומתת על ידי VHAL VTS בכתובת VtsHalAutomotiveVehicle_TargetTest.cpp.

הבדיקה מוודאת שהשיטות הבסיסיות מיושמות בצורה נכונה ושההגדרות של הנכסים הנתמכים נכונות. הבדיקה פועלת בכל המכונות של VHAL במכשיר, אבל מערכת AAOS משתמשת רק במכונה שמוגדרת כברירת מחדל (android.hardware.automotive.vehicle.IVehicle/default).

ערך מאפיין הרכב

משתמשים במבנה VehiclePropValue כדי לתאר את הערך של כל מאפיין, שכולל את השדות הבאים:

שדה תיאור
timestamp חותמת הזמן שמייצגת את השעה שבה האירוע התרחש ומתואמת עם השעון של SystemClock.elapsedRealtimeNano().
prop מזהה הנכס של הערך הזה.
areaid מזהה האזור של הערך הזה. האזור חייב להיות אחד מהאזורים הנתמכים שמפורטים בהגדרה של מזהה האזור, או 0 לנכסים גלובליים.
value מבנה נתונים שמכיל את ערך הנכס בפועל. בהתאם לסוג הנכס, שדה אחד או יותר בתוך השדה הזה משמשים לאחסון הערך בפועל. לדוגמה, הרכיב הראשון ב-value.int32Values משמש למאפיינים מסוג Int32. פרטים נוספים זמינים במאמר הגדרות של נכסים.
status הסטטוס של הנכס לקריאה. בנכס לקריאה/כתיבה, האפשרות הזו עשויה לחול גם על כתיבה, אבל היא לא מובטחת. לדוגמה, יכול להיות שהנכס יהיה זמין לקריאה אבל לא לכתיבה. במקרה כזה, הסטטוס הוא AVAILABLE ושדה הערך מכיל מידע תקין. הסטטוסים האפשריים מפורטים במאמר VehiclePropertyStatus.

פונקציות getValues ו-setValues אסינכרוניות

הפעולות getValues ו-setValues מתבצעות באופן אסינכרוני, כלומר יכול להיות שהפונקציה תחזיר תשובה לפני שהפעולה בפועל של אחזור או הגדרה תושלם. תוצאות הפעולה (לדוגמה, ערך המאפיין של getValues וסטטוס ההצלחה או השגיאה של setValues) מועברות דרך פונקציות ה-callbacks שמועברות כארגומנטים.

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

איור 1. תהליך אסינכרוני.

רכיבי parcelable גדולים

כל המבנים שנקראים XXXs, כמו VehiclePropConfigs,‏ SetValueRequests ו-VehiclePropValues, נקראים LargeParcelable (או StableLargeParcelable). כל אחד מהם מייצג רשימה של ערכים שמשמשים להעברת נתונים גדולים שעשויים לחרוג מהמגבלות של ה-binder (4KB בהטמעה של הספרייה LargeParcelable) מעבר לגבולות ה-binder. לכל אחד מהם יש הגדרת מבנה דומה שמכילה את השדות הבאים.

הדרכה תיאור
payloads רשימת ערכים כשגודל הערך מתאים למגבלת הזיכרון של ה-binder, או רשימה ריקה.
sharedMemoryFd מתאר קובץ שאפשר לאפס, שמצביע לקובץ זיכרון משותף שמאחסן את עומסי העבודה בסריאליזציה אם רשימת הערכים גדולה מדי.

לדוגמה, VehiclePropConfigs מוגדר בתור:

parcelable VehiclePropConfigs {
    // The list of vehicle property configs if they fit the binder memory
    // limitation.
    VehiclePropConfig[] payloads;
    // Shared memory file to store configs if they exceed binder memory
    // limitation. Created by VHAL, readable only at client. Client could keep
    // the fd opened or keep the FD mapped to access configs.
    @nullable ParcelFileDescriptor sharedMemoryFd;
}

VehiclePropConfigs מכיל עומסי נתונים לא ריקים או את הערך sharedMemoryFd שאינו null.

  • אם השדה payloads לא ריק, הוא מאחסן רשימה של הנתונים בפועל, שהם הגדרות הנכס.
  • אם הערך של sharedMemoryFd הוא לא null, הוא מכיל קובץ של זיכרון משותף שמאחסן את המבנה המסודר של VehiclePropConfigs. המבנה משתמש בפונקציה writeToParcel כדי לסדר את הנתונים של Parcel.

כלקוח Java ל-VHAL, Car Service מטפל בסריאליזציה ובדה-סריאליזציה של LargeParcelable. להטמעות VHAL וללקוחות מקומיים, צריך לבצע סריאליזציה ופעולה הפוכה של LargeParcelable באמצעות הספרייה LargeParcelable או באמצעות כיתת wrapper שימושית לספרייה ב-ParcelableUtils.h.

לדוגמה, לקוח מקומי שמנתח בקשות ל-getValues שקיבלו מ-binder:

// 'requests' are from the binder.
GetValueRequests requests;
expected<LargeParcelableBase::BorrowedOwnedObject, ScopedAStatus> deserializedResults = fromStableLargeParcelable(requests);
if (deserializedResults.ok()) {
    const std::vector& getValueRequests = deserializedResults.value().getObject()->payloads;
    // Use the getValueRequests.
  } else {
    // handle error.
}

בהמשך מוצגת דוגמה להטמעת VHAL ששולחת תוצאות של getValues דרך ה-binder:

std::vector results = getResults();
GetValueResults parcelableResults;
ScopedAStatus status = vectorToStableLargeParcelable(std::move(results), &parcelableResults);
if (status.isOk()) {
    // Send parcelableResults through callback.
} else {
    // Handle error.
}