L'input audio di solito proviene dal microfono integrato, da un microfono esterno o da un'interfaccia audio collegata al dispositivo. L'input audio può provenire anche da una conversazione telefonica.
A volte due o più app potrebbero voler "acquisire" lo stesso input audio. Potrebbero eseguire attività diverse. Ad esempio, alcune app che ricevono audio potrebbero essere in "registrazione", come un semplice registratore vocale, mentre altre app potrebbero essere in "ascolto", come l'Assistente Google o un servizio di accessibilità che risponde ai comandi vocali.
In entrambi i casi, queste app vogliono ricevere input audio. In questa pagina, utilizziamo il termine "acquisizione" indipendentemente dal fatto che un'app stia registrando o semplicemente ascoltando.
Se due o più app vogliono acquisire audio contemporaneamente, potrebbe esserci un problema con la trasmissione del segnale audio dalla stessa origine a tutte le app. Questa pagina descrive in che modo il sistema Android condivide l'input audio tra più app che acquisiscono audio.
Comportamento precedente ad Android 10
Prima di Android 10, lo stream audio di input poteva essere acquisito solo da un'app alla volta. Se un'app stava già registrando o ascoltando l'audio, la tua
app poteva creare un AudioRecord oggetto, ma veniva restituito un errore quando
chiamavi AudioRecord.startRecording()
e la registrazione non veniva avviata.
Un'eccezione a questa regola si verificava quando un'app con privilegi (come l'Assistente Google o
un servizio di accessibilità) aveva l'autorizzazione
android.permission.CAPTURE_AUDIO_HOTWORD e utilizzava un'origine audio di tipo
HOTWORD. In questo caso, un'altra app poteva avviare la registrazione. Quando ciò accadeva, l'app con privilegi veniva terminata e la nuova app acquisiva l'input.
In Android 9 è stata aggiunta un'altra modifica: solo le app in esecuzione in primo piano (o un servizio in primo piano) potevano acquisire l'input audio. Quando un'app senza un servizio in primo piano o un componente UI in primo piano iniziava l'acquisizione, l'app continuava a essere eseguita, ma riceveva silenzio, anche se era l'unica app che acquisiva audio in quel momento.
Comportamento di Android 10
Il comportamento precedente ad Android 10 è "chi prima arriva, meglio alloggia". Una volta che un'app inizia ad acquisire audio, nessun'altra app può accedere all'input audio finché l'app che sta acquisendo audio non si ferma.
Android 10 impone uno schema di priorità che può spostare lo stream audio di input tra le app durante l'esecuzione. Nella maggior parte dei casi, se una nuova app acquisisce l'input audio, l'app che acquisiva in precedenza continua a essere eseguita, ma riceve silenzio. In alcuni casi, il sistema può continuare a fornire audio a entrambe le app. Di seguito sono illustrati i vari scenari di condivisione.
Questo schema è simile al modo in cui il focus audio gestisce più app che competono per l'utilizzo dell'uscita audio. Tuttavia, la messa a fuoco audio viene gestita dalle richieste programmatiche per ottenere e rilasciare la messa a fuoco, mentre lo schema di commutazione dell'input descritto qui si basa su una policy di assegnazione delle priorità che viene applicata automaticamente ogni volta che una nuova app inizia ad acquisire audio.
Ai fini dell'acquisizione audio, Android distingue due tipi di app:
- Le app "normali" vengono installate dall'utente.
- Le app "con privilegi" sono preinstallate sul dispositivo. Queste includono l'Assistente Google e tutti i servizi di accessibilità.
Inoltre, un'app viene trattata in modo diverso se utilizza un'origine audio "sensibile alla privacy"
: CAMCORDER o VOICE_COMMUNICATION.
Le regole di assegnazione delle priorità per l'utilizzo e la condivisione dell'input audio sono le seguenti:
- Le app con privilegi hanno una priorità maggiore rispetto alle app normali.
- Le app con UI in primo piano visibili hanno una priorità maggiore rispetto alle app in background.
- Le app che acquisiscono audio da un'origine sensibile alla privacy hanno una priorità maggiore rispetto alle app che non lo fanno.
- Due app normali non possono mai acquisire audio contemporaneamente.
- In alcune situazioni, un'app con privilegi può condividere l'input audio con un'altra app.
- Se due app in background con la stessa priorità acquisiscono audio, quella avviata per ultima ha una priorità maggiore.
Scenari di condivisione
Quando due app tentano di acquisire audio, entrambe potrebbero essere in grado di ricevere il segnale di input oppure una di esse potrebbe ricevere silenzio.
Esistono quattro scenari principali:
- Assistente + app normale
- Servizio di accessibilità + app normale
- Due app normali
- Chiamata vocale + app normale
Assistente + app normale
L'Assistente è un'app con privilegi perché è preinstallata e ha il
ruolo RoleManager.ROLE_ASSISTANT. Qualsiasi altra app preinstallata con questo ruolo viene trattata in modo simile.
Android condivide l'audio di input in base a queste regole:
L'Assistente può ricevere audio (indipendentemente dal fatto che sia in primo piano o in background) a meno che un'altra app che utilizza un'origine audio sensibile alla privacy non stia già acquisendo.
L'app riceve audio a meno che l'Assistente non abbia un componente UI visibile nella parte superiore dello schermo.
Tieni presente che entrambe le app ricevono audio solo quando l'Assistente è in background e l'altra app non sta acquisendo da un'origine audio sensibile alla privacy.
Servizio di accessibilità + app normale
Un AccessibilityService richiede una rigorosa dichiarazione.
Android condivide l'audio di input in base a queste regole:
Se l'UI del servizio è in primo piano, sia il servizio sia l'app ricevono input audio. Questo comportamento offre funzionalità come il controllo di una chiamata vocale o dell'acquisizione video con i comandi vocali.
Se il servizio non è in primo piano, questo caso viene trattato come il caso di due app normali di seguito.
Due app normali
Quando due app acquisiscono contemporaneamente, solo una riceve audio e l'altra riceve silenzio.
Android condivide l'audio di input in base a queste regole:
- Se nessuna delle due app è sensibile alla privacy, l'app con un'UI in primo piano riceve audio. Se nessuna delle due app ha un'UI, quella che ha iniziato l'acquisizione più di recente riceve audio.
- Se una delle app è sensibile alla privacy, riceve audio e l'altra app riceve silenzio anche se ha un'UI in primo piano o ha iniziato l'acquisizione più di recente.
- Se entrambe le app sono sensibili alla privacy, l'app che ha iniziato l'acquisizione più di recente riceve audio e l'altra riceve silenzio.
Chiamata vocale + app normale
Una chiamata vocale è attiva se la modalità audio restituita da
AudioManager.getMode() è MODE_IN_CALL o
MODE_IN_COMMUNICATION.
Android condivide l'audio di input in base a queste regole:
- La chiamata riceve sempre audio.
- L'app può acquisire audio se è un servizio di accessibilità.
L'app può acquisire la chiamata vocale se è un'app con privilegi (preinstallata) con l'autorizzazione
CAPTURE_AUDIO_OUTPUT.Per acquisire l'uplink (TX), il downlink (RX) o entrambi della chiamata vocale, l'app deve specificare le origini audio
MediaRecorder.AudioSource.VOICE_UPLINKoMediaRecorder.AudioSource.VOICE_DOWNLINKe/o il dispositivoAudioDeviceInfo.TYPE_TELEPHONY.
Comportamento di Android 11
Android 11 (livello API 30) rispetta lo schema di priorità di Android 10 descritto sopra. Fornisce anche nuovi metodi in AudioRecord, MediaRecorder e AAudioStream che consentono di attivare e disattivare la possibilità di acquisire audio contemporaneamente, indipendentemente dal caso d'uso selezionato.
I nuovi metodi sono:
AudioRecord.Builder.setPrivacySensitive()AudioRecord.isPrivacySensitive()MediaRecorder.setPrivacySensitive()MediaRecorder.isPrivacySensitive()AAudioStreamBuilder_setPrivacySensitive()AAudioStream_isPrivacySensitive()
Quando setPrivacySensitive() è true, il caso d'uso di acquisizione è privato e anche un Assistente con privilegi non può acquisire contemporaneamente. Questa impostazione sostituisce il comportamento predefinito che dipende dall'origine audio. Ad esempio, VOICE_COMMUNICATION è privato per impostazione predefinita, ma UNPROCESSED non lo è.
Modifiche alla configurazione
Quando più app acquisiscono audio contemporaneamente, solo una o due sono "attive" (ricevono audio); le altre sono disattivate (ricevono silenzio). Quando le app attive cambiano, il framework audio potrebbe riconfigurare i percorsi audio in base a queste regole:
- Il dispositivo di input audio per ogni app attiva potrebbe cambiare (ad esempio, dal microfono integrato a una cuffia Bluetooth collegata).
- Viene abilitata la pre-elaborazione associata all'app attiva con la priorità più alta. Tutte le altre pre-elaborazioni vengono ignorate.
Poiché un'app attiva potrebbe essere silenziata quando un'app con priorità più alta diventa attiva,
puoi registrare un AudioManager.AudioRecordingCallback sull'oggetto
AudioRecord o MediaRecorder per ricevere una notifica quando la
configurazione cambia. Le possibili modifiche potrebbero essere:
- Acquisizione silenziata o non silenziata
- Dispositivo modificato
- Pre-elaborazione modificata
- Proprietà dello stream modificate (frequenza di campionamento, maschera dei canali, formato del campione)
Devi chiamare AudioRecord.registerAudioRecordingCallback() prima dell'
avvio dell'acquisizione. Il callback viene eseguito solo quando l'app riceve audio e si verifica una modifica.
Il metodo onRecordingConfigChanged() restituisce un
AudioRecordingConfiguration contenente lo stato di acquisizione audio corrente.
Utilizza i seguenti metodi per scoprire la modifica:
isClientSilenced()- Restituisce true se l'audio restituito al client è attualmente silenziato a causa della policy di acquisizione.
getAudioDevice()- Restituisce il dispositivo audio attivo.
getEffects()- Restituisce l'effetto di pre-elaborazione attivo. Tieni presente che l'effetto attivo potrebbe non
essere lo stesso di quelli restituiti da
getClientEffects()se il client non è l'app attiva con la priorità più alta. getFormat()- Restituisce le proprietà dello stream. Tieni presente che i dati audio effettivi ricevuti dal
client rispettano sempre il formato richiesto restituito da
getClientFormat(). Il framework esegue automaticamente la conversione necessaria di ricampionamento, canale e formato dal formato utilizzato nell'interfaccia hardware al formato specificato dal client. AudioRecord.getActiveRecordingConfiguration()- Restituisce la configurazione di registrazione attiva.
Puoi ottenere una visualizzazione generale di tutte le registrazioni attive sul dispositivo chiamando
AudioManager.getActiveRecordingConfigurations().