เครื่องเสียงรถยนต์

Android Automotive OS (AAOS) สร้างขึ้นจากสแต็กเสียงหลักของ Android เพื่อรองรับกรณีการใช้งานสำหรับระบบสาระบันเทิงในรถยนต์ AAOS มีหน้าที่รับผิดชอบต่อเสียงสาระบันเทิง (นั่นคือ สื่อ การนำทาง และการสื่อสาร) แต่จะไม่รับผิดชอบโดยตรงต่อเสียงกริ่งและคำเตือนที่มีข้อกำหนดด้านความพร้อมใช้งานและเวลาอย่างเข้มงวด แม้ว่า AAOS จะมีสัญญาณและกลไกที่ช่วยให้ยานพาหนะจัดการเสียงได้ แต่สุดท้ายแล้ว ยานพาหนะจะต้องตัดสินใจว่าควรเล่นเสียงใดให้ผู้ขับขี่และผู้โดยสารฟัง เพื่อให้มั่นใจว่าเสียงที่สำคัญต่อความปลอดภัยและเสียงตามข้อกำหนดจะได้ยินอย่างถูกต้องโดยไม่ขาดตอน

เนื่องจาก Android จัดการประสบการณ์การใช้งานสื่อของยานพาหนะ แหล่งที่มาของสื่อภายนอก เช่น เครื่องรับวิทยุ ควรแสดงโดยแอปที่จัดการโฟกัสเสียงและเหตุการณ์สำคัญเกี่ยวกับสื่อสำหรับแหล่งที่มาได้

Android 11 มีการเปลี่ยนแปลงต่อไปนี้เกี่ยวกับการรองรับเสียงที่เกี่ยวข้องกับยานยนต์

เสียงและสตรีมของ Android

ระบบเสียงยานยนต์จัดการเสียงและสตรีมต่อไปนี้

แผนภาพสถาปัตยกรรมที่เน้นสตรีม

รูปที่ 1 แผนภาพสถาปัตยกรรมที่เน้นสตรีม

Android จะจัดการเสียงที่มาจากแอป Android, ควบคุมแอปเหล่านั้น และกำหนดเส้นทางเสียงไปยังอุปกรณ์เอาต์พุตที่ HAL โดยอิงตามประเภทเสียง ดังนี้

  • สตรีมเชิงตรรกะหรือที่เรียกว่าแหล่งที่มาในคําศัพท์หลักของเสียงจะมีการติดแท็กแอตทริบิวต์เสียง
  • สตรีมจริงหรือที่เรียกว่าอุปกรณ์ในคําศัพท์ของเสียงหลักจะไม่มีข้อมูลบริบทหลังจากมิกซ์

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

การใช้งาน HAL และมิกเซอร์ภายนอกมีหน้าที่รับผิดชอบในการตรวจสอบว่าได้ยินเสียงภายนอกที่สำคัญต่อความปลอดภัย รวมถึงผสมในสตรีมที่ Android มีให้และส่งไปยังลำโพงที่เหมาะสม

เสียงของ Android

แอปอาจมีโปรแกรมเล่นอย่างน้อย 1 รายการที่โต้ตอบผ่าน Android API มาตรฐาน (เช่น AudioManager สำหรับการควบคุมโฟกัสหรือ MediaPlayer สำหรับสตรีมมิง) เพื่อส่งสตรีมข้อมูลเสียงเชิงตรรกะอย่างน้อย 1 รายการ ข้อมูลนี้อาจเป็นโมโนแบบช่องเดียวหรือเซอร์ราวด์ 7.1 แต่ระบบจะกำหนดเส้นทางและถือว่าเป็นแหล่งที่มาเดียว สตรีมแอปจะเชื่อมโยงกับ AudioAttributes ที่บอกระบบเกี่ยวกับวิธีแสดงเสียง

ระบบจะส่งสตรีมเชิงตรรกะผ่าน AudioService และกำหนดเส้นทางไปยังสตรีมเอาต์พุตจริงที่มีอยู่ 1 (รายการเดียว) ซึ่งแต่ละรายการเป็นเอาต์พุตของมิกเซอร์ภายใน AudioFlinger หลังจากมิกซ์แอตทริบิวต์เสียงลงเป็นสตรีมจริงแล้ว แอตทริบิวต์ดังกล่าวจะใช้งานไม่ได้อีกต่อไป

จากนั้นระบบจะส่งสตรีมจริงแต่ละรายการไปยัง Audio HAL เพื่อแสดงผลบนฮาร์ดแวร์ ในแอปยานยนต์ ฮาร์ดแวร์การแสดงผลอาจเป็นตัวแปลงรหัสในเครื่อง (คล้ายกับอุปกรณ์เคลื่อนที่) หรือตัวประมวลผลระยะไกลในเครือข่ายจริงของยานพาหนะ ไม่ว่าจะด้วยวิธีใด การติดตั้งใช้งาน Audio HAL มีหน้าที่ส่งข้อมูลตัวอย่างจริงและทำให้เสียงดังขึ้น

สตรีมภายนอก

สตรีมเสียงที่ไม่ควรส่งผ่าน Android (เพื่อเหตุผลด้านเวลาหรือการรับรอง) อาจส่งไปยังมิกเซอร์ภายนอกโดยตรง ตั้งแต่ Android 11 เป็นต้นไป HAL สามารถขอโฟกัสสำหรับเสียงภายนอกเหล่านี้เพื่อแจ้งให้ Android ทราบได้ เพื่อให้ดำเนินการที่เหมาะสม เช่น หยุดสื่อชั่วคราวหรือป้องกันไม่ให้เสียงอื่นๆ ได้รับโฟกัส

หากสตรีมภายนอกเป็นแหล่งที่มาของสื่อที่ควรโต้ตอบกับสภาพแวดล้อมเสียงที่ Android สร้างขึ้น (เช่น หยุดการเล่น MP3 เมื่อเปิดเครื่องรับสัญญาณภายนอก) สตรีมภายนอกเหล่านั้นควรแสดงโดยแอป Android แอปดังกล่าวจะขอโฟกัสเสียงในนามของแหล่งที่มาของสื่อแทน HAL และจะตอบสนองต่อการแจ้งเตือนโฟกัสด้วยการเปิด/หยุดแหล่งที่มาภายนอกตามที่จำเป็นเพื่อให้สอดคล้องกับนโยบายโฟกัสของ Android แอปมีหน้าที่จัดการเหตุการณ์สําคัญของสื่อด้วย เช่น เล่น/หยุดชั่วคราว กลไกที่แนะนำในการควบคุมอุปกรณ์ภายนอกดังกล่าวคือ HwAudioSource

อุปกรณ์เอาต์พุต

ที่ระดับ Audio HAL ประเภทอุปกรณ์ AUDIO_DEVICE_OUT_BUS จะมีอุปกรณ์เอาต์พุตทั่วไปสำหรับใช้ในระบบเสียงของยานพาหนะ อุปกรณ์บัสรองรับพอร์ตที่ระบุตำแหน่งได้ (โดยที่พอร์ตแต่ละพอร์ตเป็นปลายทางสําหรับสตรีมจริง) และคาดว่าจะเป็นอุปกรณ์เอาต์พุตประเภทเดียวที่รองรับในยานพาหนะ

การติดตั้งใช้งานระบบสามารถใช้พอร์ตบัส 1 พอร์ตสำหรับเสียงทั้งหมดของ Android ได้ ซึ่งในกรณีนี้ Android จะผสมเสียงทั้งหมดเข้าด้วยกันและส่งเป็น 1 สตรีม หรือ HAL อาจจัดเตรียมพอร์ตบัส 1 พอร์ตสำหรับ CarAudioContext แต่ละรายการเพื่อให้ส่งเสียงประเภทใดก็ได้พร้อมกัน วิธีนี้ช่วยให้การติดตั้งใช้งาน HAL สามารถผสมและลดเสียงต่างๆ ได้ตามต้องการ

การกำหนดบริบทเสียงให้กับอุปกรณ์เอาต์พุตทำได้ผ่าน car_audio_configuration.xml

อินพุตไมโครโฟน

เมื่อบันทึกเสียง HAL เสียงจะได้รับการเรียก openInputStream ที่มีอาร์กิวเมนต์ AudioSource ซึ่งระบุวิธีประมวลผลอินพุตไมโครโฟน

แหล่งที่มา VOICE_RECOGNITION (โดยเฉพาะ Google Assistant) ต้องการสตรีมไมโครโฟนสเตอริโอที่มีเอฟเฟกต์การตัดเสียงสะท้อน (หากมี) แต่ไม่มีการประมวลผลอื่นๆ คาดว่า Assistant จะเป็นผู้ดำเนินการจัดระเบียบสัญญาณ

อินพุตไมโครโฟนหลายช่อง

หากต้องการบันทึกเสียงจากอุปกรณ์ที่มีมากกว่า 2 ช่อง (สเตอริโอ) ให้ใช้มาสก์ดัชนีช่องแทนมาสก์ดัชนีตำแหน่ง (เช่น CHANNEL_IN_LEFT) ตัวอย่างเช่น

final AudioFormat audioFormat = new AudioFormat.Builder()
    .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
    .setSampleRate(44100)
    .setChannelIndexMask(0xf /* 4 channels, 0..3 */)
    .build();
final AudioRecord audioRecord = new AudioRecord.Builder()
    .setAudioFormat(audioFormat)
    .build();
audioRecord.setPreferredDevice(someAudioDeviceInfo);

เมื่อตั้งค่าทั้ง setChannelMask และ setChannelIndexMask แล้ว AudioRecord จะใช้เฉพาะค่าที่ setChannelMask กำหนด (สูงสุด 2 ช่องทาง)

การจับภาพพร้อมกัน

ตั้งแต่ Android 10 เฟรมเวิร์ก Android รองรับการบันทึกอินพุตพร้อมกัน แต่มีข้อจํากัดเพื่อปกป้องความเป็นส่วนตัวของผู้ใช้ แหล่งที่มาเสมือน เช่น AUDIO_SOURCE_FM_TUNER จะถูกละเว้นตามข้อจำกัดเหล่านี้ และระบบจึงอนุญาตให้บันทึกพร้อมกันกับอินพุตปกติ (เช่น ไมโครโฟน) HwAudioSources ยังไม่ถือว่าเป็นส่วนหนึ่งของข้อจำกัดการบันทึกพร้อมกัน

แอปที่ออกแบบมาให้ทำงานกับอุปกรณ์ AUDIO_DEVICE_IN_BUS หรืออุปกรณ์ AUDIO_DEVICE_IN_FM_TUNER รองต้องอาศัยการระบุอุปกรณ์เหล่านั้นอย่างชัดเจนและใช้ AudioRecord.setPreferredDevice() เพื่อข้ามตรรกะการเลือกแหล่งที่มาเริ่มต้นของ Android

การใช้เสียง

AAOS จะใช้ AudioAttributes.AttributeUsages เป็นหลักในการกำหนดเส้นทาง การปรับระดับเสียง และการจัดการโฟกัส การใช้งานแสดงถึง "เหตุผล" ที่เล่นสตรีม ดังนั้น สตรีมทั้งหมดและคำขอโฟกัสเสียงควรระบุการใช้งานสำหรับการเล่นเสียง หากไม่ได้ตั้งค่าไว้โดยเฉพาะเมื่อสร้างออบเจ็กต์ AudioAttributes ระบบจะใช้ค่าเริ่มต้นเป็น USAGE_UNKNOWN แม้ว่าปัจจุบันระบบจะถือว่าค่านี้เหมือนกับ USAGE_MEDIA แต่คุณไม่ควรใช้ลักษณะการทำงานนี้สำหรับการเล่นสื่อ

การใช้งานระบบ

ใน Android 11 มีการเปิดตัวการใช้งานระบบ การใช้งานเหล่านี้มีลักษณะการทำงานคล้ายกับการใช้งานที่สร้างขึ้นก่อนหน้านี้ ยกเว้นว่าต้องใช้ API ของระบบด้วยเช่นกัน รวมถึง android.permission.MODIFY_AUDIO_ROUTING การใช้งานระบบใหม่มีดังนี้

  • USAGE_EMERGENCY
  • USAGE_SAFETY
  • USAGE_VEHICLE_STATUS
  • USAGE_ANNOUNCEMENT

หากต้องการสร้าง AudioAttributes ที่มีการใช้งานระบบ ให้ใช้ AudioAttributes.Builder#setSystemUsage แทน setUsage การเรียกใช้เมธอดนี้ด้วยการใช้งานที่ไม่ใช่ระบบจะส่งผลให้ระบบแสดง IllegalArgumentException นอกจากนี้ หากตั้งค่าทั้งการใช้งานระบบและการใช้งานในบิลเดอร์ ระบบจะแสดงIllegalArgumentExceptionเมื่อสร้าง

หากต้องการตรวจสอบการใช้งานที่เชื่อมโยงกับอินสแตนซ์ AudioAttributes ให้เรียกใช้ AudioAttributes#getSystemUsage ซึ่งจะแสดงการใช้งานหรือการใช้งานระบบที่เชื่อมโยง

บริบทเสียง

เราได้จัดกลุ่มการใช้งานที่คล้ายกันไว้ใน CarAudioContext เพื่อลดความซับซ้อนในการกําหนดค่าเสียง AAOS บริบทเสียงเหล่านี้ใช้ใน CarAudioService ตลอดเพื่อกำหนดการกำหนดเส้นทาง กลุ่มระดับเสียง และการจัดการโฟกัสเสียง

บริบทเสียงใน Android 11 มีดังนี้

CarAudioContext AttributeUsages ที่เชื่อมโยง
MUSIC UNKNOWN, GAME, MEDIA
NAVIGATION ASSISTANCE_NAVIGATION_GUIDANCE
VOICE_COMMAND ASSISTANT, ASSISTANCE_ACCESSIBILITY
CALL_RING NOTIFICATION_RINGTONE
CALL VOICE_COMMUNICATION, VOICE_COMMUNICATION_SIGNALING
ALARM ALARM
NOTIFICATION NOTIFICATION, NOTIFICATION_*
SYSTEM_SOUND ASSISTANCE_SONIFICATION
EMERGENCY EMERGENCY
SAFETY SAFETY
VEHICLE_STATUS VEHICLE_STATUS
ANNOUNCEMENT ANNOUNCEMENT

การแมประหว่างบริบทและการใช้งานเสียง แถวที่ไฮไลต์มีไว้สำหรับการใช้งานระบบใหม่

เสียงแบบหลายโซน

ยานยนต์มีชุด Use Case ใหม่เกี่ยวกับผู้ใช้ที่โต้ตอบกับแพลตฟอร์มพร้อมกันและต้องการบริโภคสื่อแยกกัน เช่น คนขับสามารถเปิดเพลงในห้องโดยสารขณะที่ผู้โดยสารเบาะหลังกำลังดูวิดีโอ YouTube บนจอแสดงผลด้านหลัง เสียงหลายโซนช่วยให้การดำเนินการนี้เป็นไปได้ด้วยการอนุญาตให้แหล่งที่มาของเสียงต่างๆ เล่นพร้อมกันผ่านพื้นที่ต่างๆ ของยานพาหนะ

เสียงหลายโซนที่เริ่มตั้งแต่ Android 10 ช่วยให้ OEM กำหนดค่าเสียงเป็นโซนแยกกันได้ แต่ละโซนคือกลุ่มอุปกรณ์ภายในยานพาหนะที่มีกลุ่มระดับเสียง การกำหนดค่าการกำหนดเส้นทางสำหรับบริบท และการจัดการโฟกัสของตนเอง วิธีนี้ช่วยให้สามารถกำหนดค่าห้องโดยสารหลักเป็นโซนเสียงโซนหนึ่ง ส่วนแจ็คหูฟังของจอแสดงผลด้านหลังจะกำหนดค่าเป็นโซนที่ 2

เขตเหล่านี้ได้รับการกําหนดเป็นส่วนหนึ่งของ car_audio_configuration.xml จากนั้น CarAudioService จะอ่านการกำหนดค่าและช่วย AudioService กำหนดเส้นทางสตรีมเสียงตามโซนที่เชื่อมโยง แต่ละโซนจะยังคงกำหนดกฎสำหรับการกําหนดเส้นทางตามบริบทและ uid ของแอปพลิเคชัน เมื่อสร้างเพลเยอร์แล้ว CarAudioService จะกำหนดว่าเพลเยอร์เชื่อมโยงกับโซนใด จากนั้นจะกำหนดว่า AudioFlinger ควรส่งเสียงไปยังอุปกรณ์ใดโดยอิงตามการใช้งาน

นอกจากนี้ โฟกัสจะได้รับการคงไว้แยกกันสำหรับโซนเสียงแต่ละโซน วิธีนี้ช่วยให้แอปพลิเคชันในโซนต่างๆ ผลิตเสียงได้อย่างอิสระโดยไม่รบกวนกันเอง ขณะที่แอปพลิเคชันยังคงคำนึงถึงการเปลี่ยนแปลงโฟกัสภายในโซนของตน CarZonesAudioFocus ภายใน CarAudioService มีหน้าที่จัดการโฟกัสสำหรับแต่ละโซน

กำหนดค่าเสียงหลายโซน

รูปที่ 2 กำหนดค่าเสียงหลายโซน

HAL เสียง

การติดตั้งใช้งานเสียงสำหรับยานยนต์จะอาศัย HAL เสียงมาตรฐานของ Android ซึ่งประกอบด้วยรายการต่อไปนี้

  • IDevice.hal. สร้างสตรีมอินพุตและเอาต์พุต, จัดการระดับเสียงหลักและการปิดเสียง และใช้สิ่งต่อไปนี้
    • createAudioPatch. เพื่อสร้างแพตช์ภายนอก-ภายนอกระหว่างอุปกรณ์
    • IDevice.setAudioPortConfig() เพื่อระบุระดับเสียงสำหรับสตรีมเวอร์ชันที่ใช้งานจริงแต่ละรายการ
  • IStream.hal จัดการสตรีมมิงของตัวอย่างเสียงไปยังและจากฮาร์ดแวร์ควบคู่ไปกับตัวแปรอินพุตและเอาต์พุต

ประเภทอุปกรณ์ยานยนต์

ประเภทอุปกรณ์ต่อไปนี้เกี่ยวข้องกับแพลตฟอร์มยานยนต์

ประเภทอุปกรณ์ คำอธิบาย
AUDIO_DEVICE_OUT_BUS เอาต์พุตหลักจาก Android (นี่คือวิธีที่ระบบส่งเสียงทั้งหมดจาก Android ไปยังรถ) ใช้สำหรับระบุที่อยู่เพื่อแยกแยะสตรีมสำหรับบริบทแต่ละรายการ
AUDIO_DEVICE_OUT_TELEPHONY_TX ใช้สำหรับเสียงที่ส่งไปยังวิทยุมือถือเพื่อรับส่ง
AUDIO_DEVICE_IN_BUS ใช้กับอินพุตที่ไม่ได้จัดประเภทไว้
AUDIO_DEVICE_IN_FM_TUNER ใช้กับอินพุตวิทยุกระจายเสียงเท่านั้น
AUDIO_DEVICE_IN_TV_TUNER ใช้สำหรับอุปกรณ์ทีวี (หากมี)
AUDIO_DEVICE_IN_LINE ใช้สำหรับแจ็คอินพุต AUX
AUDIO_DEVICE_IN_BLUETOOTH_A2DP เพลงที่ได้รับผ่านบลูทูธ
AUDIO_DEVICE_IN_TELEPHONY_RX ใช้สำหรับเสียงที่ได้รับจากสัญญาณโทรศัพท์มือถือที่เชื่อมโยงกับการโทร

การกำหนดค่าอุปกรณ์เสียง

อุปกรณ์เสียงที่ Android เห็นต้องกำหนดไว้ใน /audio_policy_configuration.xml ซึ่งมีคอมโพเนนต์ต่อไปนี้

  • ชื่อโมดูล รองรับ "primary" (ใช้สำหรับกรณีการใช้งานยานยนต์), "A2DP", "remote_submix" และ "USB" ชื่อโมดูลและไดรเวอร์เสียงที่เกี่ยวข้องควรคอมไพล์เป็น audio.primary.$(variant).so
  • devicePorts มีรายการตัวระบุอุปกรณ์สำหรับอุปกรณ์อินพุตและเอาต์พุตทั้งหมด (รวมถึงอุปกรณ์ที่ต่อเชื่อมอย่างถาวรและอุปกรณ์แบบถอดออกได้) ที่เข้าถึงได้จากโมดูลนี้
    • สําหรับอุปกรณ์เอาต์พุตแต่ละเครื่อง คุณสามารถกําหนดการควบคุมระดับสัญญาณที่ประกอบด้วยค่าขั้นต่ำ/สูงสุด/ค่าเริ่มต้น/ระยะห่างเป็นมิลลิเบล (1 มิลลิเบล = 1/100 dB = 1/1000 เบล)
    • คุณสามารถใช้แอตทริบิวต์ที่อยู่บนอินสแตนซ์ devicePort เพื่อค้นหาอุปกรณ์ได้ แม้ว่าจะมีอุปกรณ์หลายเครื่องที่มีประเภทอุปกรณ์เดียวกับ AUDIO_DEVICE_OUT_BUS ก็ตาม
  • mixPorts มีรายการสตรีมเอาต์พุตและสตรีมอินพุตทั้งหมดที่ HAL เสียงแสดง อินสแตนซ์ mixPort แต่ละรายการจะถือเป็นสตรีมจริงไปยัง Android AudioService
  • เส้นทาง กำหนดรายการการเชื่อมต่อที่เป็นไปได้ระหว่างอุปกรณ์อินพุตและเอาต์พุต หรือระหว่างสตรีมและอุปกรณ์

ตัวอย่างต่อไปนี้จะกำหนดอุปกรณ์เอาต์พุต bus0_phone_out ซึ่งระบบจะผสมสตรีมเสียง Android ทั้งหมดโดย mixer_bus0_phone_out เส้นทางจะนำสตรีมเอาต์พุตของ mixer_bus0_phone_out ไปยังอุปกรณ์ bus0_phone_out

<audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
    <modules>
        <module name="primary" halVersion="3.0">
            <attachedDevices>
                <item>bus0_phone_out</item>
<defaultOutputDevice>bus0_phone_out</defaultOutputDevice>
            <mixPorts>
                <mixPort name="mixport_bus0_phone_out"
                         role="source"
                         flags="AUDIO_OUTPUT_FLAG_PRIMARY">
                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                            samplingRates="48000"
                            channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
                </mixPort>
            </mixPorts>
            <devicePorts>
                <devicePort tagName="bus0_phone_out"
                            role="sink"
                            type="AUDIO_DEVICE_OUT_BUS"
                            address="BUS00_PHONE">
                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                            samplingRates="48000"
                            channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
                    <gains>
                        <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
                                minValueMB="-8400"
                                maxValueMB="4000"
                                defaultValueMB="0"
                                stepValueMB="100"/>
                    </gains>
                </devicePort>
            </devicePorts>
            <routes>
                <route type="mix" sink="bus0_phone_out"
                       sources="mixport_bus0_phone_out"/>
            </routes>
        </module>
    </modules>
</audioPolicyConfiguration>