उपयोगकर्ता की एचएएल प्रॉपर्टी

फ़िलहाल, कई वाहनों के आर्किटेक्चर में, मनोरंजन और जानकारी देने वाले सिस्टम के अलावा कई इलेक्ट्रॉनिक कंट्रोल यूनिट (ईसीयू) होती हैं. ये यूनिट, कार के इस्तेमाल से जुड़ी सुविधाओं को कंट्रोल करती हैं. जैसे, सीट की सेटिंग और मिरर में बदलाव करना. मौजूदा हार्डवेयर और पावर आर्किटेक्चर के आधार पर, कई ईसीयू, Android पर आधारित सूचना और मनोरंजन की सुविधा देने वाले डिवाइस के चालू होने से पहले चालू हो जाते हैं. ये ईसीयू, वाहन के हार्डवेयर एब्स्ट्रैक्शन लेयर (वीएचएएल) के ज़रिए, Android पर आधारित सूचना और मनोरंजन की सुविधा देने वाले डिवाइस के साथ इंटरफ़ेस कर सकते हैं.

Android 11 से, Android Automotive OS (AAOS) ने VHAL पर प्रॉपर्टी का एक नया सेट शुरू किया है. इसकी मदद से, उपयोगकर्ताओं की पहचान करने के लिए बाहरी ऐक्सेसरी बनाई जा सकती हैं, उन पर स्विच किया जा सकता है, उन्हें हटाया जा सकता है, और उनसे जोड़ा जा सकता है. उदाहरण के लिए, इन नई प्रॉपर्टी की मदद से ड्राइवर, अपने Android डिवाइस का इस्तेमाल करने वाले व्यक्ति से किसी बाहरी ऐक्सेसरी, जैसे कि की फ़ोब को जोड़कर रख सकता है. इसके बाद, जब ड्राइवर वाहन के पास पहुंचता है, तो ईसीयू चालू हो जाता है और की फ़ॉब का पता लगाता है. यह ईसीयू, एचएएल को बताता है कि infotainment को किस Android उपयोगकर्ता के लिए बूट अप करना चाहिए. इससे ड्राइवर को अपने Android उपयोगकर्ता के लोड होने का इंतज़ार कम करना पड़ता है.

User HAL चालू करना

उपयोगकर्ता HAL प्रॉपर्टी को साफ़ तौर पर चालू किया जाना चाहिए. इसके लिए, यह पक्का करें कि सिस्टम प्रॉपर्टी android.car.user_hal_enabled को true पर सेट किया गया हो. (car.mk फ़ाइल में जाकर ऐसा किया जा सकता है, ताकि इसे मैन्युअल तरीके से सेट करने की ज़रूरत न पड़े.) UserHalService को डंप करके देखें कि user_hal_enabled=true चालू है या नहीं:

$ adb shell dumpsys car_service --hal UserHalService|grep enabled
user_hal_enabled=true

adb shell getprop android.car.user_hal_enabled या adb logcat CarServiceHelper *:s का इस्तेमाल करके भी, user_hal_enabled की जांच की जा सकती है. अगर प्रॉपर्टी बंद है, तो 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 प्रॉपर्टी

उपयोगकर्ता लाइफ़साइकल प्रॉपर्टी

यहां दी गई प्रॉपर्टी, उपयोगकर्ता के लाइफ़साइकल की स्थितियों के लिए एचएएल की जानकारी देती हैं. इनकी मदद से, Android सिस्टम और बाहरी ईसीयू के बीच उपयोगकर्ता के लाइफ़साइकल को सिंक किया जा सकता है. ये प्रॉपर्टी, अनुरोध और जवाब वाले प्रोटोकॉल का इस्तेमाल करती हैं. इसमें, Android सिस्टम किसी प्रॉपर्टी की वैल्यू सेट करके अनुरोध करता है और HAL, प्रॉपर्टी में हुए बदलाव का इवेंट जारी करके जवाब देता है.

ध्यान दें: जब उपयोगकर्ता के लिए एचएएल काम करता है, तो यहां दी गई सभी प्रॉपर्टी लागू की जानी चाहिए.

HAL प्रॉपर्टी ब्यौरा
INITIAL_USER_INFO
(पढ़ें/लिखें)
Android सिस्टम इस प्रॉपर्टी को कॉल करता है, ताकि यह तय किया जा सके कि डिवाइस के बूट होने या स्लीप मोड (RAM में स्टोर किया गया डेटा) से फिर से चालू होने पर, सिस्टम किस Android उपयोगकर्ता को शुरू करे. कॉल किए जाने पर, एचएएल को इनमें से किसी एक विकल्प के साथ जवाब देना होगा:
  • Android की ओर से सेट किया गया डिफ़ॉल्ट व्यवहार (पिछले इस्तेमाल किए गए उपयोगकर्ता पर स्विच करना या पहली बार बूट होने पर नया उपयोगकर्ता बनाना).
  • मौजूदा उपयोगकर्ता पर स्विच करें.
  • एक नया उपयोगकर्ता बनाएं (नाम, फ़्लैग, सिस्टम की स्थान-भाषा वगैरह जैसी वैकल्पिक प्रॉपर्टी के साथ) और उस नए उपयोगकर्ता पर स्विच करें.

ध्यान दें: अगर एचएएल कोई जवाब नहीं देता है, तो डिफ़ॉल्ट रूप से, टाइम आउट की अवधि (डिफ़ॉल्ट रूप से पांच सेकंड) के बाद इसे लागू किया जाता है. इससे, डिवाइस के बूट होने में देरी होती है. अगर HAL जवाब देता है, लेकिन Android सिस्टम कार्रवाई को पूरा नहीं कर पाता है (उदाहरण के लिए, अगर उपयोगकर्ताओं की संख्या ज़्यादा से ज़्यादा तय सीमा तक पहुंच गई है), तो डिफ़ॉल्ट तरीके का इस्तेमाल किया जाता है.

उदाहरण: डिफ़ॉल्ट रूप से, Android सिस्टम बूट होने पर, आखिरी बार सक्रिय उपयोगकर्ता के तौर पर सेट किए गए उपयोगकर्ता के खाते से शुरू होता है. अगर किसी अन्य उपयोगकर्ता के लिए की फ़ोब का पता चलता है, तो ईसीयू एचएएल प्रॉपर्टी को बदल देता है और शुरू होने के दौरान, Android सिस्टम उस उपयोगकर्ता के लिए स्टार्ट पर स्विच हो जाता है.

SWITCH_USER
(रीड/राइट)
फ़ोरग्राउंड में मौजूद Android उपयोगकर्ता को स्विच करने पर, इस प्रॉपर्टी को कॉल किया जाता है. उपयोगकर्ता स्विच करने का अनुरोध करने के लिए, Android सिस्टम या HAL, दोनों में से किसी एक से प्रॉपर्टी को कॉल किया जा सकता है. ये तीन वर्कफ़्लो हैं:
  • मॉडर्न. CarUserManager से स्विच शुरू हुआ.
  • लेगसी. ActivityManager से स्विच शुरू हुआ.
  • वाहन. उपयोगकर्ता स्विच करने का अनुरोध करने के लिए, HAL इसे कॉल करता है.

मॉडर्न वर्कफ़्लो, दो चरणों में कमिट करने के तरीके का इस्तेमाल करता है. इससे यह पक्का होता है कि Android सिस्टम और बाहरी ईसीयू सिंक हो. Android स्विच करने की प्रोसेस शुरू करने पर:

  1. उपयोगकर्ता को स्विच किया जा सकता है या नहीं, यह पता करने के लिए एचएएल देखें.

    एचएएल, SUCCESS या FAILURE के साथ जवाब देता है, ताकि Android को पता चल सके कि आगे बढ़ना है या नहीं.

  2. Android उपयोगकर्ता खाते को स्विच करने की प्रक्रिया पूरी करें.

    स्विच करने की प्रोसेस पूरी होने या न होने के बारे में बताने के लिए, Android, HAL को ANDROID_POST_SWITCH रिस्पॉन्स भेजता है.

ईसीयू को सिंक करने या अन्य एचएएल प्रॉपर्टी को अपडेट करने के लिए, एचएएल को अपनी स्थिति अपडेट करने के लिए ANDROID_POST_SWITCH के जवाब का इंतज़ार करना चाहिए.

उदाहरण: गाड़ी चलाते समय, ड्राइवर ने infotainment यूज़र इंटरफ़ेस में, Android उपयोगकर्ताओं को स्विच करने की कोशिश की. हालांकि, कार की सीट की सेटिंग, Android डिवाइस के उपयोगकर्ता से जुड़ी होती हैं. इसलिए, उपयोगकर्ता के स्विच करने पर, सीट की सेटिंग भी बदल जाती है. इसलिए, सीटों को कंट्रोल करने वाली ECU की जानकारी, स्विच की पुष्टि नहीं होती. साथ ही, एचएएल खराब जवाब देता है और Android इस्तेमाल करने वाले व्यक्ति को स्विच नहीं किया जाता.

लेगसी वर्कफ़्लो, उपयोगकर्ता के स्विच करने के बाद भेजा जाने वाला एकतरफ़ा कॉल होता है. (इसलिए, एचएएल स्विच को ब्लॉक नहीं कर सकता). इसे सिर्फ़ बूट होने पर (उपयोगकर्ता के डिवाइस को पहली बार चालू करने के बाद) या उन ऐप्लिकेशन के लिए कॉल किया जाता है जो CarUserManager.switchUser() के बजाय ActivityManager.switchUser() को कॉल करते हैं. पहचान फ़ाइल Settings और SystemUI ऐप्लिकेशन पहले से ही बाद वाले ऐप्लिकेशन का इस्तेमाल कर रहे हैं, लेकिन अगर कोई OEM, उपयोगकर्ताओं को स्विच करने के लिए खुद का सेटिंग ऐप्लिकेशन देता है, तो OEM को इस्तेमाल में बदलाव करना चाहिए.

उदाहरण: अगर कोई ऐप्लिकेशन, उपयोगकर्ताओं को एक से दूसरे ऐप्लिकेशन पर स्विच करने के लिए ActivityManager.switchUser() का इस्तेमाल करता है, तो उपयोगकर्ता के स्विच होने की जानकारी देने के लिए, HAL को एकतरफ़ा कॉल भेजा जाता है.

वाहन का वर्कफ़्लो, Android सिस्टम से नहीं, बल्कि HAL से शुरू होता है:

  1. HAL, उपयोगकर्ता को स्विच करने का अनुरोध करता है.
  2. सिस्टम, Android उपयोगकर्ता स्विच की प्रोसेस पूरी करता है.
  3. Android, स्विच के काम करने या न करने के बारे में बताने के लिए, एचएएल को ANDROID_POST_SWITCH रिस्पॉन्स भेजता है.

उदाहरण: बॉब ने कार खोलने के लिए ऐलिस के की फ़ॉब का इस्तेमाल किया और एचएएल ने ऐलिस के यूज़र आईडी के साथ INITIAL_USER_INFO अनुरोध का जवाब दिया. इसके बाद, बायोमेट्रिक सेंसर ईसीयू ने ड्राइवर की पहचान बॉब के तौर पर की, इसलिए उपयोगकर्ता एचएएल ने उपयोगकर्ताओं को स्विच करने के लिए SWITCH_USER अनुरोध भेजा.

CREATE_USER
(पढ़ें/लिखें)
जब कोई नया Android उपयोगकर्ता बनाया जाता है (CarUserManager.createUser() एपीआई का इस्तेमाल करके), तो Android सिस्टम इस प्रॉपर्टी को कॉल करता है.

HAL, SUCCESS या FAILURE के साथ जवाब देता है. अगर HAL, 'कार्रवाई पूरी नहीं हो सकी' मैसेज के साथ जवाब देता है, तो Android सिस्टम उपयोगकर्ता को हटा देता है.

उदाहरण: कोई ड्राइवर, Android का नया उपयोगकर्ता बनाने के लिए, infotainment यूज़र इंटरफ़ेस (यूआई) आइकॉन पर टैप करता है. इससे एचएएल और वाहन के बाकी सबसिस्टम को अनुरोध भेजा जाता है. ईसीयू को नए उपयोगकर्ता के बारे में सूचना दी जाती है. इसके बाद, अन्य सबसिस्टम और ईसीयू अपने इंटरनल यूज़र आईडी को Android यूज़र आईडी से जोड़ देते हैं.

REMOVE_USER
(सिर्फ़ लिखने के लिए)
Android सिस्टम इस प्रॉपर्टी को किसी Android उपयोगकर्ता को हटाए जाने के बाद कॉल करता है (CarUserManager.removeUser() तरीके का इस्तेमाल करके).

यह एकतरफ़ा कॉल है. एचएएल से कोई जवाब मिलने की उम्मीद नहीं है.

उदाहरण के लिए: कोई ड्राइवर, सूचना और मनोरंजन की सुविधा देने वाले डिवाइस के यूज़र इंटरफ़ेस (यूआई) से किसी मौजूदा Android उपयोगकर्ता को हटाने के लिए टैप करता है. उपयोगकर्ता को हटाने के बारे में एचएएल को सूचना दी जाती है. साथ ही, वाहन के अन्य सबसिस्टम और ईसीयू को भी इसकी सूचना दी जाती है, ताकि वे अपने इंटरनल उपयोगकर्ता आईडी को हटा सकें.

अन्य प्रॉपर्टी

यहां कुछ अतिरिक्त प्रॉपर्टी दी गई हैं. ये उपयोगकर्ता के लाइफ़साइकल की स्थितियों से नहीं जुड़ी होती हैं. हर सुविधा को User HAL के बिना लागू किया जा सकता है.

एचएएल प्रॉपर्टी ब्यौरा
USER_IDENTIFICATION_ASSOCIATION
(रीड/राइट)
इस प्रॉपर्टी का इस्तेमाल करके, किसी भी Android उपयोगकर्ता को पहचान करने के तरीके से जोड़ें. जैसे, की फ़ॉब या फ़ोन. get या set असोसिएशन के लिए, इसी प्रॉपर्टी का इस्तेमाल करें.

उदाहरण: ड्राइवर, कार खोलने के लिए इस्तेमाल किए जाने वाले की फ़ॉब (KEY_123) को मौजूदा सक्रिय Android उपयोगकर्ता (USER_11) से जोड़ने के लिए, infotainment यूज़र इंटरफ़ेस (यूआई) आइकॉन पर टैप करता है.

हेल्पर लाइब्रेरी

अनुरोध और जवाब वाले मैसेज में इस्तेमाल किए गए सभी ऑब्जेक्ट (जैसे कि UserInfo, InitialUserInfoRequest, InitialUSerInfoResponse वगैरह) का C++ struct का इस्तेमाल करके, हाई लेवल में दिखाया जाता है. हालांकि, हटाने के लिए, ऑब्जेक्ट को स्टैंडर्ड VehiclePropValue ऑब्जेक्ट में फ़्लैट किया जाना चाहिए. नीचे दिए गए उदाहरण देखें. आसानी से डेवलपमेंट के लिए, एओएसपी में C++ हेल्पर लाइब्रेरी उपलब्ध कराई गई है, ताकि उपयोगकर्ता एचएएल 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

क्लास और प्रॉपर्टी का असल नाम थोड़ा अलग होता है, लेकिन पूरा वर्कफ़्लो एक जैसा होता है. इसकी जानकारी इस इमेज में दी गई है:

वर्कफ़्लो

पहली इमेज. उपयोगकर्ता 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
}