สถาปัตยกรรมรถยนต์ในปัจจุบันจำนวนมากมีชุดควบคุมอิเล็กทรอนิกส์ (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 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 จะต้องใช้งานคุณสมบัติต่อไปนี้ ทั้งหมด
HAL พร็อพเพอร์ตี้ | คำอธิบาย |
---|---|
INITIAL_USER_INFO (อ่านเขียน) | คุณสมบัตินี้เรียกโดยระบบ Android เพื่อกำหนดว่าผู้ใช้ Android รายใดที่ระบบจะเริ่มทำงานเมื่ออุปกรณ์บู๊ตหรือกลับมาทำงานต่อจาก Suspend-to-RAM (STR) เมื่อถูกเรียก HAL ต้องตอบสนองด้วยหนึ่งในตัวเลือกเหล่านี้:
หมายเหตุ: หาก HAL ไม่ตอบสนอง ลักษณะการทำงานเริ่มต้นคือดำเนินการหลังจากช่วงหมดเวลา (ห้า (5) วินาทีโดยค่าเริ่มต้น) ซึ่งจะทำให้การบูตล่าช้า หาก HAL ตอบกลับ แต่ระบบ Android ไม่สามารถดำเนินการได้ (เช่น หากถึงจำนวนผู้ใช้สูงสุด) พฤติกรรมเริ่มต้นจะถูกใช้ ตัวอย่างเช่น ตามค่าเริ่มต้น ระบบ Android จะเริ่มทำงานในผู้ใช้ที่ใช้งานล่าสุดเมื่อเปิดเครื่อง หากตรวจพบคีย์ fob สำหรับผู้ใช้รายอื่น 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() API)นี่คือการโทรทางเดียว — ไม่คาดหวังการตอบกลับจาก HAL ตัวอย่างเช่น คนขับแตะเพื่อลบผู้ใช้ Android ที่มีอยู่ใน UI สาระบันเทิง HAL ได้รับแจ้ง และระบบย่อยของยานพาหนะอื่นๆ และ ECU จะได้รับแจ้งถึงการนำผู้ใช้ออก เพื่อให้สามารถลบ ID ผู้ใช้ภายในได้ |
คุณสมบัติเพิ่มเติม
ต่อไปนี้เป็นพร็อพเพอร์ตี้เพิ่มเติม ซึ่งไม่เกี่ยวข้องกับสถานะของวงจรชีวิตของผู้ใช้ แต่ละรายการสามารถนำไปใช้ได้โดยไม่สนับสนุน HAL ของผู้ใช้
HAL พร็อพเพอร์ตี้ | คำอธิบาย |
---|---|
USER_IDENTIFICATION_ASSOCIATION (อ่านเขียน) | ใช้คุณสมบัตินี้เพื่อเชื่อมโยงผู้ใช้ Android กับกลไกการระบุตัวตน เช่น พวงกุญแจหรือโทรศัพท์ ใช้คุณสมบัติเดียวกันนี้เพื่อ get หรือ set เชื่อมโยงตัวอย่างเช่น คนขับแตะไอคอน UI สาระบันเทิงเพื่อเชื่อมโยงคีย์ fob ที่ใช้ในการเปิดรถ (KEY_123) กับผู้ใช้ Android ที่ใช้งานอยู่ในปัจจุบัน (USER_11) |
ห้องสมุดผู้ช่วย
ออบเจ็กต์ทั้งหมดที่ใช้ในข้อความคำขอและข้อความตอบกลับ (เช่น UserInfo
, InitialUserInfoRequest
, InitialUSerInfoResponse
เป็นต้น) มีการแสดงระดับสูงโดยใช้ C++ struct
แต่การลบจะต้อง ทำให้แบน เป็นอ็อบเจ็กต์ VehiclePropValue
มาตรฐาน (ดูตัวอย่างด้านล่าง) เพื่อความสะดวกในการพัฒนา ไลบรารีตัวช่วย C++ มีให้ใน AOSP เพื่อแปลง VehiclePropValue
structs
และในทางกลับกัน) โดยอัตโนมัติ
ตัวอย่าง
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
ตั้งค่าตัวอย่าง (คีย์ fob ที่เกี่ยวข้องกับผู้ใช้ 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 }