ממשק VHAL

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

שיטה
VehiclePropConfigs getAllPropConfigs()
החזרת רשימה של כל הגדרות הנכס שנתמכות על ידי HAL הרכב הזה.
VehiclePropConfigs getPropConfigs(in int[] props)
החזרת רשימה של הגדרות נכס למזהי נכסים נתונים.
void getValues(IVehicleCallback callback, in GetValueRequests requests)
קבלת ערכים של מאפייני רכב באופן אסינכרוני. טיפול באצווה של GetValueRequest באופן אסינכרוני. התוצאה נמסרת באמצעות שיטת הקריאה החוזרת (callback) של 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).

הקריאות החוזרות (callback) מוגדרות ב-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, אירוע בנכס מתרחש כשערך הנכס או סטטוס הנכס משתנים.
SharedMemoryFileCount הוא תמיד 0.
oneway void onPropertySetError(in VehiclePropErrors errors)
קריאה חוזרת (callback) לדיווח על שגיאות בקבוצת נכס אסינכרונית שאין להן בקשה מוגדרת תואמת. אם אנחנו יודעים לאיזו בקשה להגדרה מתייחסת השגיאה, צריך להשתמש ב-onSetValues עם תוצאת שגיאה במקום בקוד הזה.

מידע נוסף זמין בקובצי IVehicle.aidl ו-IVehicleCallback.aidl.

ההטמעה של VHAL מאומתת על ידי VHAL VTS בקובץ VtsHalAutomotiveVehicle_TargetTest.cpp. הבדיקה מאמתת שה-methods הבסיסיות מוטמעות בצורה תקינה ושההגדרות הנתמכות של הנכס נכונות.

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

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

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

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

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

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

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

מגרשים גדולים

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

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

לדוגמה, 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 לא אפס, הוא מכיל קובץ זיכרון משותף שמאחסן את המבנה הסידורי של VehiclePropConfigs. המבנה משתמש בפונקציה writeToParcel כדי לסדר את הנתונים של Parcel.

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

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

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

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

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