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