מאפייני HAL משתמש

ארכיטקטורות רכב נוכחיות רבות מכילות מספר יחידות בקרה אלקטרוניות (ECU) מחוץ למערכת המידע והבידור השולטות בארגונומיה, כגון הגדרות מושבים והתאמת מראה. בהתבסס על ארכיטקטורות החומרה והכוח הנוכחיות, ECUs רבים מופעלים לפני הפעלת מערכת המידע והבידור המבוססת על אנדרואיד. ECUs אלה יכולים להתממשק עם מערכת מידע בידור מבוססת אנדרואיד דרך שכבת חומרת ההפשטה של ​​הרכב (VHAL) .

החל מ-Android 11, Android Automotive OS (AAOS) הציגה קבוצה חדשה של מאפיינים ב-VHAL ליצירה, החלפה, הסרה ושיוך אביזרים חיצוניים לזיהוי משתמשים. לדוגמה, מאפיינים חדשים אלה מאפשרים לנהג לקשור אביזר חיצוני, כגון שלט מפתח, למשתמש האנדרואיד שלו. לאחר מכן, כאשר הנהג מתקרב לרכב, ECU מתעורר ומזהה את שלט המפתח. ECU זה מציין ל-HAL איזה משתמש אנדרואיד צריך להתחיל אתחול המידע-בידור, מה שמפחית את הזמן שנהג ממתין לטעינת משתמש האנדרואיד שלו.

הפעל את המשתמש HAL

יש להפעיל במפורש את מאפייני User HAL על ידי הבטחת מאפיין המערכת android.car.user_hal_enabled מוגדר כ- true . (ניתן לעשות זאת גם בקובץ car.mk , כך שאין צורך להגדיר אותו ידנית.) בדוק ש- user_hal_enabled=true מופעל על ידי השלכת ה- UserHalService :

$ adb shell dumpsys car_service --hal UserHalService|grep enabled
user_hal_enabled=true

אתה יכול גם לבדוק user_hal_enabled באמצעות adb shell getprop android.car.user_hal_enabled או adb logcat CarServiceHelper *:s . אם המאפיין מושבת, הודעה כמו הבאה מוצגת כאשר system_server מופעל:

I CarServiceHelper: Not using User HAL

כדי להפעיל את user_hal_enabled באופן ידני, הגדר את מאפיין המערכת android.car.user_hal_enabled והפעל מחדש system_server :

$ adb shell setprop android.car.user_hal_enabled true
$ adb shell stop && adb shell start

הפלט logcat מופיע באופן הבא:

I CarServiceHelper: User HAL enabled with timeout of 5000ms
D CarServiceHelper: Got result from HAL: OK
I CarServiceHelper: User HAL returned DEFAULT behavior

מאפייני HAL של משתמש

מאפייני מחזור חיים של משתמש

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

הערה: כאשר User HAL נתמך, יש ליישם את כל המאפיינים הבאים.

נכס HAL תיאור
INITIAL_USER_INFO
(קרוא וכתוב)
מאפיין זה נקרא על ידי מערכת אנדרואיד כדי לקבוע באיזה משתמש אנדרואיד המערכת תפעיל כאשר המכשיר יאתחל או יתחדש מ-Suspend-to-RAM (STR). כאשר נקרא, ה-HAL חייב להגיב באחת מהאפשרויות הבאות:
  • התנהגות ברירת המחדל שהוגדרה על ידי אנדרואיד (מעבר למשתמש האחרון בשימוש או יצירת משתמש חדש אם זה האתחול הראשון).
  • עבור למשתמש קיים.
  • צור משתמש חדש (עם המאפיינים האופציונליים של שם, דגלים, אזור מערכת וכן הלאה) ועבור למשתמש החדש הזה.

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

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

SWITCH_USER
(קרוא וכתוב)
מאפיין זה נקרא בעת החלפת משתמש אנדרואיד פעיל בחזית. ניתן להתקשר לנכס על ידי מערכת אנדרואיד או על ידי HAL כדי לבקש החלפת משתמש. שלושת זרימות העבודה הן:
  • מוֹדֶרנִי. המעבר התחיל מ- CarUserManager .
  • מוֹרֶשֶׁת. המעבר התחיל מ- ActivityManager .
  • רכב. נקרא על ידי ה-HAL לבקש החלפת משתמש.

זרימת העבודה המודרנית משתמשת בגישת התחייבות דו-שלבית כדי להבטיח שמערכת אנדרואיד וה-ECU החיצוני מסונכרנים. כאשר אנדרואיד יוזם את המעבר:

  1. בדוק את ה-HAL כדי לקבוע אם ניתן להחליף משתמש.

    ה-HAL מגיב ב- SUCCESS או FAILURE , כך ש-Android יודע אם להמשיך או לא.

  2. השלם את המעבר למשתמש אנדרואיד.

    אנדרואיד שולח תגובת ANDROID_POST_SWITCH ל-HAL כדי לציין הצלחה או כישלון במעבר.

ה-HAL צריך להמתין עד לאחר תגובת ANDROID_POST_SWITCH כדי לעדכן את מצבו לסנכרון ECUs או לעדכן מאפייני HAL אחרים.

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

זרימת העבודה מדור קודם היא שיחה חד-כיוונית הנשלחת לאחר החלפת המשתמש (כך שה-HAL לא יכול לחסום את המתג). זה נקרא רק באתחול (לאחר המעבר למשתמש הראשוני) או עבור אפליקציות שקוראות ל- ActivityManager.switchUser() במקום CarUserManager.switchUser() . אפליקציות ההתייחסות Settings ו- SystemUI כבר משתמשות באחרון, אך אם יצרן OEM מספק אפליקציות הגדרות משלהם כדי להחליף משתמשים, יצרני OEM צריכים לשנות את השימוש.

לדוגמה, אם אפליקציה משתמשת ActivityManager.switchUser() כדי להחליף משתמשים, אזי נשלחת שיחה חד-כיוונית ל-HAL כדי ליידע שהחלפת משתמש בוצעה.

זרימת העבודה של הרכב מקורה ב-HAL, לא ממערכת אנדרואיד:

  1. ה-HAL מבקש מתג משתמש.
  2. המערכת משלימה את מעבר משתמש אנדרואיד.
  3. אנדרואיד שולח תגובת ANDROID_POST_SWITCH ל-HAL כדי לציין הצלחה או כישלון במעבר.

לדוגמה , בוב השתמש בשלט המפתח של אליס כדי לפתוח את המכונית וה-HAL השיב לבקשת INITIAL_USER_INFO עם מזהה המשתמש של אליס. לאחר מכן, חיישן ביומטרי ECU זיהה את הנהג כ-Bob, כך שהמשתמש HAL שלח בקשה של SWITCH_USER להחליף משתמשים.

CREATE_USER
(קרוא וכתוב)
מאפיין זה נקרא על ידי מערכת אנדרואיד כאשר נוצר משתמש אנדרואיד חדש (באמצעות ה-API של CarUserManager.createUser() ).

ה-HAL מגיב עם SUCCESS או FAILURE . אם ה-HAL מגיב בכשל, מערכת אנדרואיד מסירה את המשתמש.

לדוגמה, נהג מקיש על סמל ממשק המשתמש של מידע בידור כדי ליצור משתמש אנדרואיד חדש. זה שולח בקשה ל-HAL ולשאר תתי-מערכות הרכב. ECUs מודיעים על המשתמש החדש שנוצר. מערכות משנה ו-ECU אחרים משייכים את מזהה המשתמש הפנימי שלהם למזהה המשתמש של Android.

REMOVE_USER
(כתוב בלבד)
מערכת אנדרואיד קוראת למאפיין זה לאחר הסרת משתמש אנדרואיד (עם ה-API של CarUserManager.removeUser() ).

מדובר בשיחה חד-כיוונית - לא צפויה תגובה מה-HAL.

לדוגמה, נהג מקיש כדי להסיר משתמש אנדרואיד קיים בממשק המשתמש של המידע והבידור. ה-HAL מודיע ותת-מערכות רכב אחרות ו-ECU מודיעים על הסרת המשתמש כדי שיוכלו להסיר את מזהה המשתמש הפנימי שלהם.

נכסים נוספים

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

נכס HAL תיאור
USER_IDENTIFICATION_ASSOCIATION
(קרוא וכתוב)
השתמש במאפיין זה כדי לשייך כל משתמש אנדרואיד למנגנון זיהוי, כגון שלט מפתח או טלפון. השתמש באותו מאפיין כדי get או set אסוציאציות.

לדוגמה, נהג מקיש על סמל ממשק המשתמש של מידע בידור כדי לשייך את השלט המשמש לפתיחת הרכב (KEY_123) למשתמש הפעיל הנוכחי של Android (USER_11).

ספריות עוזרים

לכל האובייקטים המשמשים בהודעות הבקשה והתגובה (כגון UserInfo , InitialUserInfoRequest , InitialUSerInfoResponse וכן הלאה) יש ייצוג ברמה גבוהה באמצעות C++ struct , אך יש לשטח את ההסרה לאובייקטים סטנדרטיים VehiclePropValue (ראה הדוגמאות למטה). כדי להקל על הפיתוח, ספריית C++ מסייעת מסופקת ב-AOSP כדי להמיר אוטומטית structs HAL של משתמש ל- VehiclePropValue (ולהיפך).

דוגמאות

INITIAL_USER_INFO

בקשה לדוגמא (באתחול ראשון)

VehiclePropValue { // flattened from InitialUserInfoRequest
prop: 299896583 // INITIAL_USER_INFO
prop.values.int32Values:
 [0] = 1 // Request ID
 [1] = 1 // InitialUserInfoRequestType.FIRST_BOOT
 [2] = 0 // user id of current user
 [3] = 1 // flags of current user (SYSTEM)
 [4] = 1 // number of existing users
 [5] = 0 // existingUser[0].id
 [6] = 1 // existingUser[0].flags
}

דוגמה לתגובה (צור משתמש מנהל)

VehiclePropValue { // flattened from InitialUserInfoResponse
prop: 299896583 // INITIAL_USER_INFO
prop.values.int32Values:
  [0] = 1      // Request ID (must match request)
  [1] = 2      // InitialUserInfoResponseAction.CREATE
  [2] = -10000 // user id (not used on CREATE)
  [3] = 8      // user flags (ADMIN)
prop.values.stringValue: "en-US||Car Owner" // User locale and User name
}

החלף משתמש

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

זרימת עבודה

איור 1. זרימת עבודה של מאפייני HAL של משתמש

דוגמה לבקשת זרימת עבודה מודרנית

VehiclePropValue { // flattened from SwitchUserRequest
prop: 299896585 // SWITCH_USER
prop.values.int32Values:
 [0]     = 42    // Request ID
 [1]     = 2     // SwitchUserMessageType::ANDROID_SWITCH ("modern")
 [2,3]   = 11,0  // target user id (11) and flags (none in this case)
 [4,5]   = 10,8  // current user id (10) and flags (ADMIN)
 [6]     = 3     // number of existing users (0, 10, 11)
 [7,8]   = 0,1   // existingUser[0] (id=0, flags=SYSTEM)
 [9,10]  = 10,8  // existingUser[1] (id=10, flags=ADMIN)
 [11,12] = 11,0  // existingUser[2] (id=11, flags=NONE)
}

דוגמה לתגובת זרימת עבודה מודרנית

VehiclePropValue { // flattened from SwitchUserResponse
prop: 299896584 // SWITCH_USER
prop.values.int32Values:
 [0] = 42        // Request ID (must match request)
 [1] = 3         // SwitchUserMessageType::VEHICLE_RESPONSE
 [2] = 1         // SwitchUserStatus::SUCCESS
}

דוגמה לתגובת זרימת עבודה מודרנית לאחר המעבר

תגובה זו מתרחשת בדרך כלל כאשר מתג אנדרואיד מצליח:

VehiclePropValue { // flattened from SwitchUserRequest
prop: 299896584 // SWITCH_USER
prop.values.int32Values:
 [0]     = 42    // Request ID (must match "pre"-SWITCH_USER request )
 [1]     = 5     // SwitchUserMessageType::ANDROID_POST_SWITCH
 [2,3]   = 11,0  // target user id (11) and flags (none in this case)
 [4,5]   = 11,0  // current user id (11) and flags (none in this case)
 [6]     = 3     // number of existing users (0, 10, 11)
 [7,8]   = 0,1   // existingUser[0] (id=0, flags=SYSTEM)
 [9,10]  = 10,8  // existingUser[1] (id=10, flags=ADMIN)
 [11,12] = 11,0  // existingUser[2] (id=11, flags=NONE)
}

תגובה מודרנית של זרימת עבודה לאחר המעבר

תגובה זו מתרחשת בדרך כלל כאשר מתג אנדרואיד נכשל:

VehiclePropValue { // flattened from SwitchUserRequest
prop: 299896584 // SWITCH_USER
prop.values.int32Values:
 [0]     = 42    // Request ID (must match "pre"-SWITCH_USER request )
 [1]     = 5     // SwitchUserMessageType::ANDROID_POST_SWITCH
 [2,3]   = 11,0  // target user id (11) and flags (none in this case)
 [4,5]   = 10,8  // current user id (10) and flags (ADMIN)
 [6]     = 3     // number of existing users (0, 10, 11)
 [7,8]   = 0,1   // existingUser[0] (id=0, flags=SYSTEM)
 [9,10]  = 10,8  // existingUser[1] (id=10, flags=ADMIN)
 [11,12] = 11,0  // existingUser[2] (id=11, flags=NONE)
}

דוגמה לבקשת זרימת עבודה מדור קודם

VehiclePropValue { // flattened from SwitchUserRequest
prop: 299896584 // SWITCH_USER
prop.values.int32Values:
 [0]     = 2     // Request ID
 [1]     = 1     // SwitchUserMessageType::LEGACY_ANDROID_SWITCH
 [2,3]   = 10,8  // target user id (10) and flags (ADMIN)
 [4,5]   = 0,1   // current user id (0) and flags (SYSTEM)
 [6]     = 3     // number of existing users (0, 10, 11)
 [7,8]   = 0,1   // existingUser[0] (id=0, flags=SYSTEM)
 [9,10]  = 10,8  // existingUser[1] (id=10, flags=ADMIN)
 [11,12] = 11,0  // existingUser[2] (id=11, flags=NONE)
}

דוגמה לבקשת זרימת עבודה של רכב

VehiclePropValue { // flattened from SwitchUserRequest
prop: 299896584 // SWITCH_USER
prop.values.int32Values:
 [0]     = -108  // Request ID (must be negative)
 [1]     = 4     // SwitchUserMessageType::VEHICLE_REQUEST
 [2]     = 11    // target user id
}

תגובה מדור קודם של זרימת עבודה לאחר המעבר

תגובה זו מתרחשת בדרך כלל כאשר מתג אנדרואיד מצליח:

VehiclePropValue { // flattened from SwitchUserRequest
prop: 299896584 // SWITCH_USER
prop.values.int32Values:
 [0]     = -108  // Request ID (must match from vehicle request )
 [1]     = 5     // SwitchUserMessageType::ANDROID_POST_SWITCH
 [2,3]   = 11,0  // target user id (11) and flags (none in this case)
 [4,5]   = 11,0  // current user id (11) and flags (none in this case)
 [6]     = 3     // number of existing users (0, 10, 11)
 [7,8]   = 0,1   // existingUser[0] (id=0, flags=SYSTEM)
 [9,10]  = 10,8  // existingUser[1] (id=10, flags=ADMIN)
 [11,12] = 11,0  // existingUser[2] (id=11, flags=NONE)
}

צור משתמש

בקשה לדוגמא

VehiclePropValue { // flattened from CreateUserRequest
prop: 299896585 // CREATE_USER
prop.values.int32Values:
 [0]      = 42  // Request ID
 [1,2]    = 11,6     // Android id of the created user and flags (id=11, flags=GUEST, EPHEMERAL)
 [3,4]    = 10,0  // current user id (10) and flags (none in this case)
 [5]      = 3  // number of existing users (0, 10, 11)
 [6,7]    = 0,1   // existingUser[0] (id=0, flags=SYSTEM)
 [8,9]    = 10,8  // existingUser[1] (id=10, flags=ADMIN)
 [10,11] = 11,6 // newUser[2] (id=11, flags=GUEST,EPHEMERAL)
}

דוגמה לתגובה

VehiclePropValue { // flattened from CreateUserResponse
prop: 299896585 // CREATE_USER
prop.values.int32Values:
 [0] = 42        // Request ID (must match request)
 [1] = 3         // CreateUserStatus::SUCCESS
}

REMOVE_USER

בקשה לדוגמא

VehiclePropValue { // flattened from RemoveUserRequest
prop: 299896586 // REMOVE_USER
prop.values.int32Values:
 [0]      = 42  // Request ID
 [1,2]    = 11,0     // Android id of the removed user and flags (none in this case)
 [3,4]    = 10,0  // current user id (10) and flags (none in this case)
 [5]      = 2  // number of existing users (0, 10)
 [6,7]    = 0,1   // existingUser[0] (id=0, flags=SYSTEM)
 [8,9]    = 10,8  // existingUser[1] (id=10, flags=ADMIN)
}

USER_IDENTIFICATION_ASSOCIATION

הגדר דוגמה (שלט מפתח המשויך למשתמש 10)

VehiclePropValue { // flattened from UserIdentificationSetRequest
prop: 299896587 // USER_IDENTIFICATION_ASSOCIATION
prop.values.int32Values:
 [0]      = 43  // Request ID
 [1,2]    = 10,0     // Android id (10) and flags (none in this case)
 [3]    = 1  // number of associations being set
 [4]      = 1  // 1st type: UserIdentificationAssociationType::KEY_FOB
 [5]    = 1   // 1st value: UserIdentificationAssociationSetValue::ASSOCIATE_CURRENT_USER
}