חיבור מכשיר קלט ב-AAOS

אפשר להשתמש במנגנונים האלה כדי להפעיל אודיו ב-Android:

כל מנגנון מאפשר הפעלת אודיו ב-Android. יכול להיות שהאפשרויות האלה לא יספיקו להפעלת רדיו או להפעלה ממכשירי קלט, אבל אפשר לשלב כל אחת מהן עם לכידת אודיו או עם המחלקה MediaRecorder כדי קודם ללכוד את האודיו ואז להפעיל אותו מ-Android. במיוחד באפליקציות של המערכת, אפשר להשתמש במידע הבא כדי לחבר מכשיר קלט למיקסר פלט ב-AAOS.

נגן HwAudioSource

HwAudioSource מחבר את המכשיר שממנו מופעל האודיו ישירות למיקסר של Android.

מניעים

יכולות להיות כמה מגבלות כשמשתמשים בתיקון של אודיו מחומרה או ממכשיר למכשיר ב-Android. כל אחת מהאפשרויות האלה לא יכולה לקבל אירועים של מקשי מדיה כמו PLAY,‏ PAUSE ו-STOP. בנוסף, מכיוון שהן עוקפות את מחסנית האודיו של Android, כל אחת מהן דורשת חומרה כדי לערבב את התיקון עם אודיו אחר מ-Android.

שימוש ב-HwAudioSource

HwAudioSource הוא סוג חדש של נגן שנועד להיות תיקון תוכנה. כך אפליקציות שמשתמשות בנגן הזה יכולות לקבל אירועים של מקשי מדיה, ומערכת Android יכולה לערבב את זרם הפלט ולנתב אותו.

mHwAudioSource = new HwAudioSource.Builder()
                .setAudioDeviceInfo(AudioDeviceInfo: info)
                .setAudioAttributes(new AudioAttributes.Builder()
                        .setUsage(AudioAttributes.USAGE_MEDIA)
                        .build())
                .build();
mHwAudioSource.play();
mHwAudioSource.stop();

שינויים ב-HAL של האודיו

עם הנגן החדש הזה, כדאי לקחת בחשבון את הציפיות הבאות לגבי HAL של אודיו. לדוגמה, device/generic/car/emulator/audio/driver/audio_hw.c.

  • adev_create_audio_patch מצפה שהבקשה תקים תיקון אודיו ממכשיר למיקסר.

  • הערך הצפוי של adev_open_input_stream הוא audio_source, אבל בפועל הוא AUDIO_SOURCE_FM_TUNER.

  • in_read ממלא את מאגר האודיו בנתוני אודיו של רדיו שידור.

מומלץ להגדיר מכשיר כוונון עם סוג AUDIO_DEVICE_IN_FM_TUNER ב-audio_policy_configuration.xml:

<devicePort
    tagName="Tuner_source"
    type="AUDIO_DEVICE_IN_FM_TUNER"
    role="source"
    address="tuner0">
    <profile
        name=""
        format="AUDIO_FORMAT_PCM_16_BIT"
        samplingRates="48000"
        channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
</devicePort>

בעזרת הגדרת המכשיר הזו, אפשר למצוא בקלות את מכשיר הקלט של רדיו FM באמצעות AudioManager.getDevices(AudioManager.GET_DEVICES_INPUTS בשילוב עם AudioDeviceInfo.TYPE_FM_TUNER.

יצירת תיקוני אודיו

אפשר ליצור תיקון אודיו בין שתי יציאות אודיו, יציאת מיקס או יציאת מכשיר. בדרך כלל, תיקון אודיו מיציאת המיקס ליציאת המכשיר מיועד להפעלה, והכיוון ההפוך מיועד ללכידה.

לדוגמה, תיקון אודיו שמנתב דגימות אודיו מFM_TUNER המקור ישירות ל-media sink עוקף את המיקסר של התוכנה. לאחר מכן צריך להשתמש במיקסר חומרה כדי לערבב את דגימות האודיו מ-Android ומ-FM_TUNER עבור יעד הפלט. כשיוצרים תיקון אודיו ישירות מFM_TUNER המקור אל יעד המדיה:

  • השליטה בעוצמת הקול חלה על יעד המדיה וצריכה להשפיע על האודיו ב-Android וב-FM_TUNER.

  • המשתמשים יכולים לעבור בין אודיו ב-Android לבין אודיו ב-FM_TUNER באמצעות מעבר פשוט בין האפליקציות (אין צורך לבחור מקור מדיה ספציפי).

יכול להיות שיישומים לרכב יצטרכו גם ליצור תיקון אודיו בין שני יציאות של מכשיר. כדי לעשות את זה, צריך קודם להצהיר על יציאות המכשיר ועל המסלולים האפשריים ב-audio_policy_configuration.xml, ואז לשייך את יציאות המכשיר ל-mixports.

הגדרה לדוגמה

אפשר לראות את ההגדרה לדוגמה הזו,device/generic/car/emulator/audio/audio_policy_configuration.xml.

<audioPolicyConfiguration>
    <modules>
        <module name="primary" halVersion="3.0">
            <attachedDevices>
                <item>bus0_media_out</item>
                <item>bus1_audio_patch_test_in</item>
            </attachedDevices>
            <mixPorts>
                <mixPort name="mixport_bus0_media_out" role="source"
                        flags="AUDIO_OUTPUT_FLAG_PRIMARY">
                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                            samplingRates="48000"
                            channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
                </mixPort>
                <mixPort name="mixport_audio_patch_in" role="sink">
                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                           samplingRates="48000"
                           channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
                </mixPort>
            </mixPorts>
            <devicePorts>
                <devicePort tagName="bus0_media_out" role="sink" type="AUDIO_DEVICE_OUT_BUS"
                        address="bus0_media_out">
                    <profile balance="" 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>
                <devicePort tagName="bus1_audio_patch_test_in" type="AUDIO_DEVICE_IN_BUS" role="source"
                        address="bus1_audio_patch_test_in">
                    <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
                            samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_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_media_out" sources="mixport_bus0_media_out,bus1_audio_patch_test_in"/>
                <route type="mix" sink="mixport_audio_patch_in" sources="bus1_audio_patch_test_in"/>
            </routes>
        </module>
    </modules>
</audioPolicyConfiguration>

Audio driver API

אפשר להשתמש ב-getExternalSources() כדי לאחזר רשימה של מקורות זמינים (מזוהים לפי כתובת), ואז ליצור תיקוני אודיו בין המקורות האלה לבין יציאות היעד לפי שימושים באודיו. נקודות הכניסה המתאימות ב-Audio HAL מופיעות ב-IDevice.hal:

Interface IDevice {
...
/
*   Creates an audio patch between several source and sink ports.  The handle
*   is allocated by the HAL and must be unique for this audio HAL module.
*
*   @param sources patch sources.
*   @param sinks patch sinks.
*   @return retval operation completion status.
*   @return patch created patch handle.
*/
createAudioPatch(vec<AudioPortConfig> sources, vec<AudioPortConfig> sinks)
       generates (Result retval, AudioPatchHandle patch);

*   Release an audio patch.
*
*   @param patch patch handle.
*   @return retval operation completion status.
*/
releaseAudioPatch(AudioPatchHandle patch) generates (Result retval);
...
}
.

טיונר רדיו

כשמפתחים אפליקציית רדיו, מומלץ להשתמש ב-HwAudioSource כי הוא מטפל גם ביצירת התיקון וגם בסשן מדיה לטיפול באירועים של מקשי מדיה. אפשר ליצור כמה מקורות אודיו לאותו מקור ולאותם מאפייני אודיו. אפשר להגדיר אחד לשימוש רגיל ברדיו ועוד אחד להודעות על עומסי תנועה.

אם מקליטים את FM_TUNER, ב-Android 11 ההרשאה לכך השתנתה ל-android.permission.CAPTURE_AUDIO_OUTPUT. הוא כבר לא עובר את OP_RECORD_AUDIOבדיקת ההרשאות, שחלה רק על מיקרופונים. השינוי הזה לא אמור להשפיע על אפליקציות, כי כבר עכשיו נדרשת הרשאה לגישה ל-FM_TUNER.SYSTEM_API

פרטים על פיתוח אפליקציית רדיו זמינים במאמר בנושא הטמעת רדיו.