คุณสมบัติผู้ใช้ HAL

สถาปัตยกรรมรถยนต์ในปัจจุบันจำนวนมากมีชุดควบคุมอิเล็กทรอนิกส์ (ECU) หลายชุดที่อยู่นอกระบบสาระบันเทิงที่ควบคุมการยศาสตร์ เช่น การตั้งค่าเบาะนั่งและการปรับกระจก ขึ้นอยู่กับสถาปัตยกรรมฮาร์ดแวร์และพลังงานในปัจจุบัน ECU จำนวนมากทำงานก่อนที่ระบบสาระบันเทิงที่ใช้ Android จะถูกเปิดใช้งาน ECUs เหล่านี้สามารถเชื่อมต่อกับระบบ Infotainment Android ตามผ่าน ชั้นพาหนะฮาร์ดแวร์ Abstraction (VHAL)

เริ่มต้นใน Android 11 Android Automotive OS (AAOS) ได้แนะนำคุณสมบัติชุดใหม่บน VHAL สำหรับการสร้าง การสลับ การถอด และการเชื่อมโยงอุปกรณ์เสริมภายนอกเพื่อระบุผู้ใช้ ยกตัวอย่างเช่นคุณสมบัติใหม่เหล่านี้ช่วยให้คนขับรถที่จะจับคู่ผูกอุปกรณ์ภายนอกเช่นคีย์ fob เพื่อผู้ใช้ 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 เปลือก GetProp android.car.user_hal_enabled หรือ adb logcat CarServiceHelper *:s 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 รายใดที่ระบบจะเริ่มทำงานเมื่ออุปกรณ์บู๊ตหรือกลับมาทำงานต่อจาก Suspend-to-RAM (STR) เมื่อถูกเรียก HAL ต้องตอบสนองด้วยหนึ่งในตัวเลือกเหล่านี้:
  • ลักษณะการทำงานเริ่มต้นที่กำหนดโดย Android (เปลี่ยนเป็นผู้ใช้ที่ใช้ล่าสุดหรือสร้างผู้ใช้ใหม่หากนี่เป็นการบูตครั้งแรก)
  • เปลี่ยนเป็นผู้ใช้ที่มีอยู่
  • สร้างผู้ใช้ใหม่ (พร้อมคุณสมบัติทางเลือกของชื่อ แฟล็ก ตำแหน่งที่ตั้งของระบบ และอื่นๆ) และสลับไปยังผู้ใช้ใหม่นั้น

หมายเหตุ: หากฮาลไม่ตอบสนองพฤติกรรมเริ่มต้นคือการดำเนินการหลังจากที่มีระยะเวลาการหมด (ห้า (5) วินาทีโดยค่าเริ่มต้น) ซึ่งความล่าช้าในการบูต หาก HAL ตอบกลับ แต่ระบบ Android ไม่สามารถดำเนินการได้ (เช่น หากถึงจำนวนผู้ใช้สูงสุด) พฤติกรรมเริ่มต้นจะถูกใช้

ยกตัวอย่างเช่นโดยค่าเริ่มต้นระบบ Android จะเริ่มต้นในผู้ใช้ที่ใช้งานล่าสุดเมื่อบูต หากตรวจพบคีย์ fob สำหรับผู้ใช้รายอื่น ECU จะแทนที่คุณสมบัติ HAL และในระหว่างการเริ่มต้นระบบ Android จะสลับเพื่อเริ่มต้นในผู้ใช้ที่ระบุ

SWITCH_USER
(อ่านเขียน)
คุณสมบัตินี้ถูกเรียกเมื่อสลับผู้ใช้ Android ที่ทำงานอยู่เบื้องหน้า คุณสมบัติสามารถเรียกโดยระบบ Android หรือโดย HAL เพื่อขอเปลี่ยนผู้ใช้ สามเวิร์กโฟลว์คือ:
  • ทันสมัย. Switch เริ่มต้นจาก CarUserManager
  • มรดก Switch เริ่มต้นจาก ActivityManager
  • ยานพาหนะ. เรียกโดย HAL เพื่อขอเปลี่ยนผู้ใช้

เวิร์กโฟลว์สมัยใหม่ใช้แนวทางการคอมมิตแบบสองเฟสเพื่อให้แน่ใจว่าระบบ Android และ ECU ภายนอกได้รับการซิงโครไนซ์ เมื่อ Android เริ่มสวิตช์:

  1. ตรวจสอบ HAL เพื่อดูว่าสามารถเปลี่ยน User ได้หรือไม่

    ตอบสนอง HAL กับ SUCCESS หรือ FAILURE เพื่อให้ Android รู้ว่าจะดำเนินการต่อไปหรือไม่

  2. ทำการสลับผู้ใช้ Android ให้สมบูรณ์

    Android ส่ง ANDROID_POST_SWITCH การตอบสนองต่อ HAL เพื่อบ่งชี้ถึงความสำเร็จหรือความล้มเหลวสวิทช์

ฮาลควรรอจนกว่าจะหลังจากที่ ANDROID_POST_SWITCH ตอบสนองต่อการอัปเดตสถานะของมันในการประสาน ECUs หรือปรับปรุงคุณสมบัติ HAL อื่น ๆ

ยกตัวอย่างเช่นในขณะที่ในการเคลื่อนไหวความพยายามที่จะเปลี่ยนคนขับรถผู้ใช้ Android ใน UI Infotainment อย่างไรก็ตาม เนื่องจากการตั้งค่าเบาะรถยนต์เชื่อมโยงกับผู้ใช้ Android ที่นั่งจะเคลื่อนระหว่างที่สลับผู้ใช้ ดังนั้น ECU ที่ควบคุมที่นั่งจะไม่ยืนยันสวิตช์ HAL ตอบสนองด้วยความล้มเหลวและผู้ใช้ Android จะไม่ถูกเปลี่ยน

เวิร์กโฟลว์ดั้งเดิมคือการโทรแบบทางเดียวที่ส่งหลังจากที่ผู้ใช้ถูกเปลี่ยน (ดังนั้น HAL จึงไม่สามารถบล็อกสวิตช์ได้) มันเรียกว่าเฉพาะในการบูต (หลังสวิทช์ผู้ใช้เริ่มต้น) หรือปพลิเคชันที่เรียก ActivityManager.switchUser() แทน CarUserManager.switchUser() อ้างอิง Settings และ SystemUI ปพลิเคชันแล้วใช้หลัง แต่ถ้า OEM ให้ปพลิเคชันของตัวเองการตั้งค่าผู้ใช้สวิทช์ OEMs ควรเปลี่ยนการใช้งาน

ตัวอย่างเช่นถ้าแอปใช้ ActivityManager.switchUser() ที่ผู้ใช้สวิทช์โทรแล้วได้ทางเดียวถูกส่งไปยัง HAL ให้ทราบว่าผู้ใช้สวิทช์ได้ที่สถานที่

เวิร์กโฟลว์ของยานพาหนะเริ่มต้นจาก HAL ไม่ใช่จากระบบ Android:

  1. HAL ขอเปลี่ยนผู้ใช้
  2. ระบบเสร็จสิ้นการเปลี่ยนผู้ใช้ Android
  3. Android ส่ง ANDROID_POST_SWITCH การตอบสนองต่อ HAL เพื่อบ่งชี้ถึงความสำเร็จหรือความล้มเหลวสวิทช์

ยกตัวอย่างเช่นบ๊อบใช้คีย์ fob ของอลิซจะเปิดตัวรถและระบบ HAL ตอบไป INITIAL_USER_INFO คำขอกับ User ID ของอลิซ ถัดไป ECU เซ็นเซอร์ไบโอเมตริกซ์ระบุคนขับเป็นบ๊อบเพื่อให้ผู้ใช้ HAL ส่ง SWITCH_USER คำขอเพื่อสลับผู้ใช้

CREATE_USER
(อ่านเขียน)
สถานที่แห่งนี้ถูกเรียกโดยระบบ Android เมื่อผู้ใช้ Android ใหม่ถูกสร้างขึ้น (โดยใช้ CarUserManager.createUser() API)

ตอบสนอง HAL กับ SUCCESS หรือ FAILURE หาก HAL ตอบสนองด้วยความล้มเหลว ระบบ Android จะลบผู้ใช้ออก

ตัวอย่างเช่นคนขับก๊อกไอคอน Infotainment ใน UI ที่จะสร้างผู้ใช้ Android ใหม่ การดำเนินการนี้จะส่งคำขอไปยัง HAL และระบบย่อยอื่นๆ ของรถยนต์ ECU จะได้รับแจ้งเกี่ยวกับผู้ใช้ที่สร้างขึ้นใหม่ จากนั้นระบบย่อยและ ECU อื่นๆ จะเชื่อมโยง ID ผู้ใช้ภายในกับ ID ผู้ใช้ Android

REMOVE_USER
(เขียนเท่านั้น)
ระบบ Android เรียกคุณสมบัตินี้หลังจากที่ผู้ใช้ Android จะถูกลบออก (ที่มี CarUserManager.removeUser() API)

นี่คือการโทรทางเดียว — ไม่คาดหวังการตอบกลับจาก HAL

ตัวอย่างเช่นคนขับก๊อกในการลบผู้ใช้ Android ที่มีอยู่ใน UI Infotainment HAL ได้รับแจ้ง และระบบย่อยของยานพาหนะอื่นๆ และ ECU จะได้รับแจ้งถึงการนำผู้ใช้ออก เพื่อให้สามารถลบ ID ผู้ใช้ภายในได้

คุณสมบัติเพิ่มเติม

ต่อไปนี้เป็นพร็อพเพอร์ตี้เพิ่มเติม ซึ่งไม่เกี่ยวข้องกับสถานะของวงจรชีวิตของผู้ใช้ แต่ละรายการสามารถนำไปใช้ได้โดยไม่สนับสนุน HAL ของผู้ใช้

HAL พร็อพเพอร์ตี้ คำอธิบาย
USER_IDENTIFICATION_ASSOCIATION
(อ่านเขียน)
ใช้คุณสมบัตินี้เพื่อเชื่อมโยงผู้ใช้ Android กับกลไกการระบุตัวตน เช่น พวงกุญแจหรือโทรศัพท์ ใช้คุณสมบัติเดียวกันนี้เพื่อ get หรือ set สมาคม

ตัวอย่างเช่นคนขับก๊อกไอคอน Infotainment ใน UI ที่จะเชื่อมโยง FOB สำคัญที่ใช้ในการเปิดคัน (KEY_123) ไปยัง Android ผู้ใช้ที่ใช้งานอยู่ในปัจจุบัน (USER_11)

ห้องสมุดผู้ช่วย

วัตถุทั้งหมดที่ใช้ในการร้องขอและการตอบสนองข้อความ (เช่น 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
}

เปลี่ยนผู้ใช้

ชื่อจริงของคลาสและคุณสมบัติแตกต่างกันเล็กน้อย แต่เวิร์กโฟลว์โดยรวมเหมือนกัน ดังที่แสดงด้านล่าง:

เวิร์กโฟลว์

รูปที่ 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
}