สถาปัตยกรรมของยานพาหนะในปัจจุบันจำนวนมากมีชุดควบคุมอิเล็กทรอนิกส์ (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 ทราบเกี่ยวกับการนำผู้ใช้ออกเพื่อให้นำรหัสผู้ใช้ภายในออกได้ |
พร็อพเพอร์ตี้เพิ่มเติม
ต่อไปนี้คือพร็อพเพอร์ตี้เพิ่มเติมที่ไม่เกี่ยวข้องกับสถานะวงจรของลูกค้า แต่ละวิธีสามารถติดตั้งใช้งานได้โดยไม่ต้องรองรับ User HAL
พร็อพเพอร์ตี้ HAL | คำอธิบาย |
---|---|
USER_IDENTIFICATION_ASSOCIATION (อ่าน/เขียน) |
ใช้พร็อพเพอร์ตี้นี้เพื่อเชื่อมโยงผู้ใช้ Android กับกลไกการระบุตัวตน เช่น รีโมตล็อกรถยนต์หรือโทรศัพท์ ใช้พร็อพเพอร์ตี้เดียวกันนี้เพื่อเชื่อมโยง get หรือ set
ตัวอย่าง: คนขับแตะไอคอน UI สาระบันเทิงเพื่อเชื่อมโยงโฟลกุญแจที่ใช้เปิดรถ ( |
ไลบรารีตัวช่วย
ออบเจ็กต์ทั้งหมดที่ใช้ในข้อความคำขอและคำตอบ (เช่น UserInfo
, InitialUserInfoRequest
, InitialUSerInfoResponse
และอื่นๆ) มีการแสดงระดับสูงโดยใช้ C++ struct
แต่การนำออกต้องยุบเป็นออบเจ็กต์ VehiclePropValue
มาตรฐาน (ดูตัวอย่างด้านล่าง) เพื่อความสะดวกในการพัฒนา เราจึงจัดเตรียมไลบรารีตัวช่วย C++ ไว้ใน AOSP เพื่อแปลง HAL ของผู้ใช้ structs
เป็น 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 }
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) }
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
ตัวอย่างชุด (กุญแจรีโมตที่เชื่อมโยงกับผู้ใช้ 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 }