ऑडियो फ़ोकस

लॉजिकल स्ट्रीम शुरू करने से पहले, ऐप्लिकेशन को ऑडियो फ़ोकस का अनुरोध करना चाहिए. इसके लिए, वही ऑडियो एट्रिब्यूट इस्तेमाल करने चाहिए जिनका इस्तेमाल लॉजिकल स्ट्रीम के लिए किया जाता है. फ़ोकस करने का अनुरोध भेजने का सुझाव दिया जाता है, लेकिन सिस्टम इसे लागू नहीं करता. कुछ ऐप्लिकेशन, खास तरह की कार्रवाइयां करने के लिए अनुरोध भेजने से साफ़ तौर पर बच सकते हैं. उदाहरण के लिए, फ़ोन कॉल के दौरान जान-बूझकर आवाज़ चलाना.

इसलिए, फ़ोकस को ऑडियो कंट्रोल करने के मुख्य तरीके के तौर पर नहीं, बल्कि ऑडियो को अप्रत्यक्ष तौर पर कंट्रोल करने और चलाने में आने वाली समस्याओं को हल करने के तरीके के तौर पर इस्तेमाल करना चाहिए. वाहन को ऑडियो सबसिस्टम के काम करने के लिए, फ़ोकस सिस्टम पर निर्भर नहीं होना चाहिए.

फ़ोकस इंटरैक्शन

AAOS की ज़रूरतों को पूरा करने के लिए, ऑडियो फ़ोकस के अनुरोधों को, अनुरोध के CarAudioContext और फ़िलहाल फ़ोकस में मौजूद ऐप्लिकेशन के बीच पहले से तय इंटरैक्शन के आधार पर मैनेज किया जाता है. इंटरैक्शन तीन तरह के होते हैं: एक्सक्लूज़िव, अस्वीकार, और एक साथ होने वाले.

खास इंटरैक्शन

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

इंटरैक्शन अस्वीकार करना

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

एक साथ कई इंटरैक्शन

AAOS की सबसे खास बात यह है कि इसमें एक साथ कई इंटरैक्शन होते हैं. इससे, कार में ऑडियो फ़ोकस का अनुरोध करने वाले ऐप्लिकेशन को, अन्य ऐप्लिकेशन के साथ फ़ोकस बनाए रखने की सुविधा मिलती है. एक साथ कई इंटरैक्शन होने के लिए, ये शर्तें पूरी होनी चाहिए. ये:

  • फ़ोकस टाइम के लिए किए गए अनुरोध में AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK का अनुरोध करना ज़रूरी है.
  • फ़िलहाल, फ़ोकस किसी दूसरे एलिमेंट पर है.setPauseWhenDucked(true)
  • फ़ोकस में मौजूद मौजूदा उपयोगकर्ता, डक इवेंट पाने के लिए ऑप्ट इन नहीं करता.

अगर ये शर्तें पूरी होती हैं, तो फ़ोकस का अनुरोध AUDIOFOCUS_REQUEST_GRANTED के साथ दिखता है. हालांकि, फ़ोकस के मौजूदा होल्डर के फ़ोकस में कोई बदलाव नहीं होता. हालांकि, अगर फ़ोकस में मौजूद ऐप्लिकेशन, डक इवेंट पाने या डक होने पर रुकने का विकल्प चुनता है, तो फ़ोकस में मौजूद ऐप्लिकेशन का फ़ोकस हट जाता है. यह ठीक वैसा ही होता है जैसे किसी खास इंटरैक्शन के दौरान फ़ोकस हट जाता है.

एक साथ कई डिवाइसों पर स्ट्रीम करने की सुविधा

एक साथ कई इंटरैक्शन के कई काम के ऐप्लिकेशन हैं. हालांकि, OEM को सभी आउटपुट डिवाइसों पर हार्डवेयर लेवल पर, मिक्सिंग और डकिंग का ध्यान रखना चाहिए. इसलिए, हमारा सुझाव है कि CarAudioContext को सिर्फ़ उसी आउटपुट डिवाइस पर भेजा जाए जिस पर CarAudioContext एक साथ नहीं चल सकते. एक साथ चल रही स्ट्रीम के लिए अलग-अलग आउटपुट डिवाइस होने पर, HAL उन स्ट्रीम को एक साथ मिक्स करने से पहले, उनमें से किसी एक स्ट्रीम को कम कर सकता है. इसके अलावा, वाहन में मौजूद अलग-अलग स्पीकर पर फ़िज़िकल स्ट्रीम को रूट किया जा सकता है. अगर Android में लॉजिकल स्ट्रीम को मिलाया जाता है, तो उनके गेन में कोई बदलाव नहीं होता और उन्हें एक ही फ़िज़िकल स्ट्रीम के हिस्से के तौर पर डिलीवर किया जाता है.

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

इंटरैक्शन मैट्रिक्स

नीचे दी गई टेबल में, CarAudioService के हिसाब से इंटरैक्शन मैट्रिक दिखाई गई है. लाइनें, फ़ोकस में मौजूद एलिमेंट के CarAudioContext को दिखाती हैं और कॉलम, आने वाले अनुरोध को दिखाते हैं.

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

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

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

ऑडियो फ़ोकस इंटरैक्शन

पहली इमेज. ऑडियो फ़ोकस इंटरैक्शन

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

ऑडियो फ़ोकस में देरी

Android 11 में, AAOS ने ऑडियो फ़ोकस में देरी करने का अनुरोध करने की सुविधा जोड़ी है. इससे, फ़ोकस के लिए किए गए ऐसे अनुरोधों को स्वीकार करने में देरी की जा सकती है जो लंबे समय तक फ़ोकस में रहते हैं. ऐसा तब किया जाता है, जब फ़िलहाल फ़ोकस में मौजूद लोगों के साथ उनके इंटरैक्शन की वजह से, आम तौर पर उन्हें अस्वीकार कर दिया जाता है. फ़ोकस में बदलाव होने के बाद, जब वह स्थिति आ जाती है जहां देर से किए गए अनुरोध को फ़ोकस मिल सकता है, तो अनुरोध को स्वीकार कर लिया जाता है.

ऑडियो फ़ोकस के लिए देर से किए गए अनुरोधों से जुड़े नियम

  • सिर्फ़ ऐसे अनुरोध जिनमें डेटा लंबे समय तक सेव नहीं रहता - जैसा कि पहले बताया गया है, देर से किए जाने वाले अनुरोध सिर्फ़ ऐसे सोर्स के लिए किए जा सकते हैं जिनमें डेटा लंबे समय तक सेव नहीं रहता. ऐसा इसलिए किया जाता है, ताकि ट्रांज़िशन के दौरान बजने वाला साउंड, ज़रूरत के बाद भी न बजता रहे.
  • एक बार में सिर्फ़ एक अनुरोध को पूरा होने में देरी की जा सकती है - अगर किसी अनुरोध को पूरा होने में देरी करने का अनुरोध करने के बाद, फिर से किसी अनुरोध को पूरा होने में देरी करने का अनुरोध किया जाता है, तो पहले अनुरोध को AUDIOFOCUS_LOSS बदलाव इवेंट मिलता है और नए अनुरोध को AUDIOFOCUS_REQUEST_DELAYED का सिंक्रोनस रिस्पॉन्स मिलता है.
  • जिन अनुरोधों को बाद में पूरा किया जा सकता है उनके लिए OnAudioFocusChangeListener होना ज़रूरी है. अनुरोध पूरा होने में देरी होने पर, अनुरोध करने वाले व्यक्ति को इसकी सूचना देने के लिए, लिसनर का इस्तेमाल किया जाता है. जैसे, अनुरोध स्वीकार होने पर (AUDIOFOCUS_GAIN) या बाद में अस्वीकार होने पर (AUDIOFOCUS_LOSS).

देर से फ़ोकस करने का अनुरोध करना

ऐसा अनुरोध बनाने के लिए जिसे बाद में भेजा जा सकता है, AudioFocusRequest.Builder#setAcceptsDelayedFocusGain का इस्तेमाल करें:

mMediaWithDelayedFocusListener = new MediaWithDelayedFocusListener();

mDelayedFocusRequest = new AudioFocusRequest
     .Builder(AudioManager.AUDIOFOCUS_GAIN)
     .setAudioAttributes(mMusicAudioAttrib)
     .setOnAudioFocusChangeListener(mMediaWithDelayedFocusListener)
     .setForceDucking(false)
     .setWillPauseWhenDucked(false)
     .setAcceptsDelayedFocusGain(true)
     .build();

इसके बाद, अनुरोध करते समय AUDIOFOCUS_REQUEST_DELAYED जवाब को मैनेज करें:

int delayedFocusRequestResults = mAudioManager.requestAudioFocus(mDelayedFocusRequest);
if (delayedFocusRequestResults == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
// start audio playback
return;
}
if (delayedFocusRequestResults == AudioManager.AUDIOFOCUS_REQUEST_DELAYED) {
     // audio playback delayed to audio focus listener
     return;
}

जब अनुरोध में देरी होती है, तो फ़ोकस में हुए बदलावों को मैनेज करने की ज़िम्मेदारी, फ़ोकस लिसनर की होती है:

private final class MediaWithDelayedFocusListener implements
OnAudioFocusChangeListener {
       @Override
       public void onAudioFocusChange(int focusChange) {
           synchronized (mLock) {
               switch (focusChange) {
                   case AudioManager.AUDIOFOCUS_GAIN:
                        // Start focus playback
                   case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
                        // Pause media transiently
                   case AudioManager.AUDIOFOCUS_LOSS:
                        // Stop media

एक से ज़्यादा ज़ोन में फ़ोकस मैनेज करना

जिन वाहनों में एक से ज़्यादा ऑडियो ज़ोन होते हैं उनके लिए, हर ज़ोन के लिए ऑडियो फ़ोकस को अलग से मैनेज किया जाता है. इसलिए, किसी एक ज़ोन के लिए किए गए अनुरोध में, यह नहीं देखा जाता कि दूसरे ज़ोन में क्या फ़ोकस में है. साथ ही, इससे दूसरे ज़ोन में फ़ोकस रखने वाले लोगों का फ़ोकस नहीं हटता. इसकी मदद से, मुख्य केबिन के फ़ोकस को पीछे की सीट के मनोरंजन वाले सिस्टम से अलग से मैनेज किया जा सकता है. इससे, एक ज़ोन में फ़ोकस में बदलाव होने पर, दूसरे ज़ोन में ऑडियो प्लेबैक में रुकावट नहीं आती.

सभी ऐप्लिकेशन के लिए फ़ोकस मैनेजमेंट की सुविधा, CarAudioService अपने-आप काम करती है. फ़ोकस रिक्वेस्ट का ऑडियो ज़ोन, उससे जुड़े UserId या UID के आधार पर तय किया जाता है. ज़्यादा जानकारी के लिए, ऑडियो रूटिंग देखें.

एक साथ कई ज़ोन से ऑडियो का अनुरोध करना

अगर किसी ऐप्लिकेशन को एक साथ कई ज़ोन में ऑडियो चलाना है, तो उसे बंडल में AUDIOFOCUS_EXTRA_REQUEST_ZONE_ID शामिल करके, हर ज़ोन के लिए फ़ोकस का अनुरोध करना होगा:

// Create attribute with bundle and AUDIOFOCUS_EXTRA_REQUEST_ZONE_ID
Bundle bundle = new Bundle();
bundle.putInt(CarAudioManager.AUDIOFOCUS_EXTRA_REQUEST_ZONE_ID,
               zoneId);

AudioAttributes attributesWithZone = new AudioAttributes.Builder()
     .setUsage(AudioAttributes.USAGE_MEDIA)
     .addBundle(bundle)
     .build();

// Create focus request using built attributesWithZone

इस बंडल पैरामीटर की मदद से, अनुरोध करने वाला व्यक्ति ऑडियो ज़ोन की अपने-आप मैप होने की सुविधा को बदल सकता है. इसके बजाय, वह तय किए गए ज़ोन आईडी का इस्तेमाल कर सकता है. इसलिए, इसकी मदद से कोई ऐप्लिकेशन, अलग-अलग ऑडियो ज़ोन के लिए अलग-अलग अनुरोध कर सकता है.

HAL Audio Focus

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

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

इसी तरह, HAL को अब भी ज़रूरत पड़ने पर Android स्ट्रीम को म्यूट करना चाहिए. ऐसा तब करना चाहिए, जब आपातकालीन या सुरक्षा से जुड़ी अहम आवाज़ें बजाई जा रही हों. इससे यह पक्का किया जा सकेगा कि ये आवाज़ें साफ़ सुनाई दें.

AudioControl@2.0

AudioControl HAL के वर्शन 2.0 में कई नए एपीआई जोड़े गए हैं:

एपीआई मकसद
IAudioControl#registerFocusListener AudioControl HAL के साथ IFocusListener का इंस्टेंस रजिस्टर करता है. यह ऑडियो फ़ोकस का अनुरोध करने और उसे छोड़ने के लिए, एचएएल को चालू करता है. उम्मीद है कि एचएआई, ICloseHandle इंस्टेंस उपलब्ध कराएगा, ताकि Android, लिसनर को अनरजिस्टर कर सके.
IAudioControl#onAudioFocusChange IFocusListener के ज़रिए किए गए अनुरोधों पर फ़ोकस करने के लिए, स्टेटस में हुए बदलावों के बारे में एचएएल को सूचना देता है. इसमें फ़ोकस करने के शुरुआती अनुरोधों के जवाब भी शामिल हैं.
IFocusListener#requestAudioFocus ये अनुरोध, HAL की ओर से किसी खास इस्तेमाल, ज़ोन आईडी, और फ़ोकस हासिल करने के तरीके के लिए किए जाते हैं.
IFocusListener#abandonAudioFocus तय किए गए इस्तेमाल और ज़ोन आईडी के लिए, मौजूदा एचएएल फ़ोकस अनुरोधों को छोड़ देता है.

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

registerFocusListener के अलावा, ये सभी अनुरोध oneway हैं. इससे यह पक्का होता है कि फ़ोकस अनुरोध को प्रोसेस करने के दौरान, Android, एचएएल में देरी न करे. सुरक्षा से जुड़ी अहम आवाज़ें चलाने से पहले, एचएएल को फ़ोकस पाने का इंतज़ार नहीं करना चाहिए. HAL के लिए, IAudioControl#onAudioFocusChange के ज़रिए ऑडियो फ़ोकस में होने वाले बदलावों को सुनना और उनका जवाब देना ज़रूरी नहीं है. हालांकि, ज़रूरत पड़ने पर ऐसा करने का सुझाव दिया जाता है.