สถาปัตยกรรมรถยนต์ปัจจุบันจำนวนมากมีหน่วยควบคุมอิเล็กทรอนิกส์หลายหน่วย (ECU) ภายนอกระบบสาระบันเทิงที่ควบคุมหลักการยศาสตร์ เช่น ที่นั่ง การตั้งค่าและการปรับมิเรอร์ อิงตามฮาร์ดแวร์และพลังงานในปัจจุบัน ECU หลายรุ่นมีการทำงานมากขึ้นก่อนระบบสาระบันเทิงที่ใช้ Android เปิดอยู่ ECU เหล่านี้สามารถอินเทอร์เฟซด้วยสาระบันเทิงใน Android ผ่านทาง เลเยอร์แอบสแตรกชันของฮาร์ดแวร์ยานพาหนะ (VHAL)
Android Automotive OS (AAOS) เริ่มตั้งแต่ Android 11 ได้เปิดตัวชุด ใน VHAL สำหรับสร้าง สลับ นำออก และเชื่อมโยง อุปกรณ์เสริมภายนอกที่เพื่อระบุผู้ใช้ ตัวอย่างเช่น พร็อพเพอร์ตี้ใหม่เหล่านี้ช่วยให้ ไดรเวอร์เพื่อจับคู่อุปกรณ์เสริมภายนอก เช่น กุญแจรีโมตกับผู้ใช้ Android จากนั้น เมื่อคนขับเข้าใกล้รถ ECU จะเริ่มทำงานและตรวจพบกุญแจรีโมต ECU นี้จะระบุ HAL ว่าผู้ใช้ Android ใดที่ระบบสาระบันเทิงควร เปิดเครื่อง ซึ่งช่วยลดเวลาที่คนขับต้องรอ Android ผู้ใช้ที่จะโหลด
เปิดใช้ 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 แบบ ได้แก่
เวิร์กโฟลว์ Modern ใช้วิธีการคอมมิตแบบ 2 ระยะเพื่อให้แน่ใจว่า ซิงค์ระบบ Android กับ ECU ภายนอกแล้ว เมื่อ Android เริ่มเปลี่ยน
HAL ควรรอจนกว่าจะถึงวันที่ ตัวอย่าง: ขณะเคลื่อนที่ คนขับจะพยายาม เปลี่ยนผู้ใช้ Android ใน UI สาระบันเทิง แต่เนื่องจากคาร์ซีต ที่เชื่อมโยงกับผู้ใช้ Android ที่นั่งจะย้ายระหว่าง เปลี่ยนผู้ใช้ ดังนั้น ECU ที่ควบคุมที่นั่งจะไม่ยืนยันการเปลี่ยน HAL ตอบสนองด้วยความล้มเหลว และผู้ใช้ Android ไม่ถูกเปลี่ยนผ่าน
เวิร์กโฟลว์แบบเดิมเป็นการโทรทางเดียวที่ส่งหลังจากเปลี่ยนผู้ใช้
(เพื่อไม่ให้ HAL บล็อกสวิตช์) โดยจะเรียกใช้เฉพาะเมื่อเปิดเครื่อง (หลังจาก
การเปลี่ยนผู้ใช้ครั้งแรก) หรือสำหรับแอปที่โทร
ตัวอย่าง: หากแอปใช้
เวิร์กโฟลว์ของยานพาหนะจะเริ่มจาก HAL ไม่ใช่จากระบบ Android
ตัวอย่าง: Bob ใช้กุญแจรีโมตของอลิซเพื่อเปิดรถ
และ HAL ได้ตอบกลับคำขอ |
CREATE_USER (อ่าน/เขียน) |
ระบบ Android จะเรียกพร็อพเพอร์ตี้นี้เมื่อผู้ใช้ Android ใหม่
ที่สร้าง (โดยใช้ API ของ CarUserManager.createUser() )
HAL จะตอบสนองด้วย ตัวอย่าง: คนขับแตะไอคอน UI สาระบันเทิงเพื่อ สร้างผู้ใช้ Android ใหม่ การดำเนินการนี้จะส่งคำขอไปยัง HAL และส่วนที่เหลือ ของระบบย่อยของยานพาหนะ ECU จะแจ้งผู้ใช้ที่สร้างใหม่ อื่นๆ ระบบย่อยและ ECU จะเชื่อมโยงรหัสผู้ใช้ภายในกับ Android User ID |
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 }
เปลี่ยนผู้ใช้
ชื่อจริงของคลาสและพร็อพเพอร์ตี้จะแตกต่างกันเล็กน้อย แต่ เวิร์กโฟลว์โดยรวมจะเหมือนกันตามที่แสดงด้านล่าง
รูปที่ 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 }
นำผู้ใช้ออก
ตัวอย่างคำขอ
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 }