ממשק 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 באופן אסינכרוני. התוצאה מועברת באמצעות השיטה 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).

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

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

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

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

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

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

פונקציות 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 או באמצעות כיתת עטיפה שימושית לספרייה ב-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.
}