สถาปัตยกรรมของยานพาหนะในปัจจุบันจำนวนมากมีหน่วยควบคุมอิเล็กทรอนิกส์ (ECU) หลายหน่วยนอกระบบสาระบันเทิงที่ควบคุมการยศาสตร์ เช่น การตั้งค่าเบาะและการปรับเปลี่ยนกระจก ECU จำนวนมากจะเปิดเครื่องก่อนระบบสาระบันเทิงที่ใช้ Android โดยอิงตามฮาร์ดแวร์และสถาปัตยกรรมการจ่ายไฟในปัจจุบัน ECU เหล่านี้สามารถอินเทอร์เฟซกับระบบสาระบันเทิงที่ใช้ Android ผ่านเลเยอร์การแยกแยะฮาร์ดแวร์ของยานพาหนะ (VHAL)
ใน Android 11 เป็นต้นไป Android Automotive OS (AAOS) ได้เปิดตัวพร็อพเพอร์ตี้ชุดใหม่ใน VHAL เพื่อสร้าง สลับ นำออก และเชื่อมโยงอุปกรณ์เสริมภายนอกเพื่อระบุผู้ใช้ ตัวอย่างเช่น พร็อพเพอร์ตี้ใหม่เหล่านี้ช่วยให้คนขับจับคู่อุปกรณ์เสริมภายนอก เช่น กุญแจรีโมตกับผู้ใช้ Android ได้ จากนั้นเมื่อคนขับเข้าใกล้ยานพาหนะ ECU จะตื่นขึ้นและตรวจหากุญแจรีโมต ECU นี้จะระบุให้ HAL ทราบว่าผู้ใช้ Android คนใดที่ระบบสาระบันเทิงควรเริ่มบูต ซึ่งจะช่วยลดเวลาที่คนขับต้องรอให้ผู้ใช้ Android โหลด
เปิดใช้ User HAL
คุณต้องเปิดใช้พร็อพเพอร์ตี้ 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 สำหรับสถานะวงจรชีวิตของผู้ใช้ ซึ่งช่วยให้ระบบ Android และ ECU ภายนอกซิงค์วงจรชีวิตของผู้ใช้ได้ พร็อพเพอร์ตี้เหล่านี้ใช้โปรโตคอลคำขอและการตอบกลับ ซึ่งระบบ Android จะส่งคำขอโดยการตั้งค่าค่าพร็อพเพอร์ตี้ และ HAL จะตอบกลับด้วยการส่งเหตุการณ์การเปลี่ยนแปลงพร็อพเพอร์ตี้
หมายเหตุ: เมื่อมีการรองรับ HAL ของผู้ใช้ จะต้องติดตั้งใช้งานพร็อพเพอร์ตี้ต่อไปนี้ทั้งหมด
พร็อพเพอร์ตี้ HAL | คำอธิบาย |
---|---|
INITIAL_USER_INFO (อ่าน/เขียน) |
ระบบ Android จะเรียกพร็อพเพอร์ตี้นี้เพื่อระบุผู้ใช้ Android ที่ระบบเริ่มต้นเมื่ออุปกรณ์เปิดเครื่องหรือกลับมาทำงานอีกครั้งจากการระงับไปยัง RAM (STR) เมื่อได้รับแจ้ง HAL จะต้องตอบกลับด้วยตัวเลือกใดตัวเลือกหนึ่งต่อไปนี้
หมายเหตุ: หาก HAL ไม่ตอบสนอง ลักษณะการทำงานเริ่มต้นจะดำเนินการหลังจากหมดเวลา (5 วินาทีโดยค่าเริ่มต้น) ซึ่งจะทำให้การบูตล่าช้า หาก HAL ตอบกลับ แต่ระบบ Android ดำเนินการไม่สำเร็จ (เช่น หากมีผู้ใช้ถึงจำนวนสูงสุดแล้ว) ระบบจะใช้ลักษณะการทำงานเริ่มต้น ตัวอย่าง: โดยค่าเริ่มต้น ระบบ Android จะเริ่มทำงานในผู้ใช้ที่ใช้งานล่าสุดเมื่อบูต หากตรวจพบกุญแจรีโมตของผู้ใช้รายอื่น ECU จะลบล้างพร็อพเพอร์ตี้ HAL และในระหว่างการเริ่มต้นระบบ Android จะเปลี่ยนเป็นเริ่มในผู้ใช้ที่ระบุ |
SWITCH_USER (อ่าน/เขียน) |
ระบบจะเรียกใช้พร็อพเพอร์ตี้นี้เมื่อเปลี่ยนผู้ใช้ Android ที่ใช้งานอยู่เบื้องหน้า
ระบบ Android หรือ HAL สามารถเรียกใช้พร็อพเพอร์ตี้เพื่อขอเปลี่ยนผู้ใช้ เวิร์กโฟลว์ทั้ง 3 รายการ ได้แก่
เวิร์กโฟลว์สมัยใหม่ใช้แนวทางการคอมมิตแบบ 2 เฟสเพื่อให้ระบบ Android และ ECU ภายนอกซิงค์กัน เมื่อ Android เริ่มเปลี่ยน
HAL ควรรอจนกว่า ตัวอย่าง: ขณะขับรถ ผู้ขับขี่พยายามเปลี่ยนผู้ใช้ Android ใน UI ของระบบสาระบันเทิง อย่างไรก็ตาม เนื่องจากการตั้งค่าเบาะรถเชื่อมโยงกับผู้ใช้ Android เบาะจึงขยับไปมาระหว่างที่ผู้ใช้เปลี่ยน ดังนั้น ECU ที่ควบคุมที่นั่งจะไม่ยืนยันการเปลี่ยน HAL จะตอบกลับว่าไม่สำเร็จ และผู้ใช้ Android จะไม่เปลี่ยน
เวิร์กโฟลว์เดิมคือการโทรทางเดียวที่ส่งหลังจากมีการเปลี่ยนผู้ใช้แล้ว (ดังนั้น HAL จึงบล็อกการเปลี่ยนไม่ได้) โดยจะเรียกใช้เฉพาะเมื่อเปิดเครื่อง (หลังจากการเปลี่ยนผู้ใช้ครั้งแรก) หรือสำหรับแอปที่เรียกใช้
ตัวอย่าง: หากแอปใช้ เวิร์กโฟลว์ของยานพาหนะจะเริ่มจาก HAL ไม่ใช่จากระบบ Android
ตัวอย่าง: Bob ใช้กุญแจรีโมตของ Alice เพื่อเปิดรถ และ HAL ตอบกลับคำขอ |
CREATE_USER (อ่าน/เขียน) |
ระบบ Android จะเรียกพร็อพเพอร์ตี้นี้เมื่อมีการสร้างผู้ใช้ Android ใหม่ (โดยใช้ CarUserManager.createUser() API)
HAL จะตอบกลับด้วย ตัวอย่าง: คนขับแตะไอคอน UI สาระบันเทิงเพื่อสร้างผู้ใช้ Android ใหม่ โดยจะส่งคำขอไปยัง HAL และระบบย่อยอื่นๆ ของยานพาหนะ ECU จะได้รับแจ้งเกี่ยวกับผู้ใช้ที่สร้างใหม่ จากนั้นระบบย่อยและ ECU อื่นๆ จะเชื่อมโยงรหัสผู้ใช้ภายในกับรหัสผู้ใช้ Android |
REMOVE_USER (เขียนเท่านั้น) |
ระบบ Android เรียกใช้พร็อพเพอร์ตี้นี้หลังจากผู้ใช้ Android ถูกนำออก (โดยใช้เมธอด CarUserManager.removeUser() )
การเรียกนี้เป็นแบบทางเดียว โดย HAL จะไม่ตอบกลับ ตัวอย่าง: คนขับแตะเพื่อนำผู้ใช้ Android ที่มีอยู่ออกจาก UI สาระบันเทิง ระบบจะแจ้งให้ HAL และระบบย่อยอื่นๆ ของยานพาหนะและ ECU ทราบเกี่ยวกับการนำผู้ใช้ออกเพื่อให้นำรหัสผู้ใช้ภายในออกได้ |
พร็อพเพอร์ตี้เพิ่มเติม
ต่อไปนี้คือพร็อพเพอร์ตี้เพิ่มเติมที่ไม่เกี่ยวข้องกับสถานะวงจรของลูกค้า แต่ละวิธีสามารถติดตั้งใช้งานได้โดยไม่ต้องสนับสนุน HAL ของผู้ใช้
พร็อพเพอร์ตี้ HAL | คำอธิบาย |
---|---|
USER_IDENTIFICATION_ASSOCIATION (อ่าน/เขียน) |
ใช้พร็อพเพอร์ตี้นี้เพื่อเชื่อมโยงผู้ใช้ Android กับกลไกการระบุตัวตน เช่น รีโมตล็อกรถยนต์หรือโทรศัพท์ ใช้พร็อพเพอร์ตี้เดียวกันนี้เพื่อเชื่อมโยง get หรือ set
ตัวอย่าง: คนขับแตะไอคอน UI สาระบันเทิงเพื่อเชื่อมโยงโฟลกุญแจที่ใช้เปิดรถ ( |
ไลบรารีตัวช่วย
ออบเจ็กต์ทั้งหมดที่ใช้ในคำขอและข้อความตอบกลับ (เช่น UserInfo
, InitialUserInfoRequest
, InitialUSerInfoResponse
และอื่นๆ) มีระดับการนำเสนอระดับสูงโดยใช้ C++ struct
แต่การนำออกจะต้องแยกเป็นหลายรายการในออบเจ็กต์ VehiclePropValue
มาตรฐาน (ดูตัวอย่างด้านล่าง) เพื่อความสะดวกในการพัฒนา เราจึงจัดเตรียมไลบรารีตัวช่วย C++ ไว้ใน AOSP เพื่อแปลง HAL ของผู้ใช้ structs
เป็น VehiclePropValue
(และในทางกลับกัน) โดยอัตโนมัติ
ตัวอย่าง
ข้อมูลผู้ใช้เริ่มต้น
ตัวอย่างคำขอ (เมื่อเปิดเครื่องครั้งแรก)
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 }
SWITCH_USER
ชื่อจริงของคลาสและพร็อพเพอร์ตี้จะแตกต่างกันเล็กน้อย แต่เวิร์กโฟลว์โดยรวมจะเหมือนกัน ดังที่แสดงในภาพต่อไปนี้
รูปที่ 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 }
ตัวอย่างคำตอบหลังเปลี่ยนเวิร์กโฟลว์ที่ทันสมัย
โดยปกติแล้ว การตอบกลับนี้จะเกิดขึ้นเมื่อการสลับ Android สำเร็จ
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) }
การตอบกลับหลังเปลี่ยนเวิร์กโฟลว์ที่ทันสมัย
โดยปกติแล้วการตอบกลับนี้จะเกิดขึ้นเมื่อสวิตช์ Android ไม่สําเร็จ
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 }
การตอบกลับเวิร์กโฟลว์เดิมหลังการเปลี่ยน
การตอบสนองนี้มักเกิดขึ้นเมื่อการเปลี่ยน Android สำเร็จ
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 }