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ò anche provenire 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 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 solo ascoltando.
Se due o più app vogliono acquisire audio contemporaneamente, può verificarsi un problema di invio del segnale audio dalla stessa sorgente a tutte le app. Questa pagina descrive come 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 da un'app alla volta. Se un'altra app stava già registrando o ascoltando l'audio, la tua app potrebbe creare un oggetto AudioRecord
, ma verrà restituito un errore quando chiami AudioRecord.startRecording()
e la registrazione non verrà avviata.
Un'eccezione a questa regola si verificava quando un'app privilegiata (come l'Assistente Google o un servizio di accessibilità) aveva l'autorizzazioneandroid.permission.CAPTURE_AUDIO_HOTWORD
e utilizzava un'origine audio di tipoHOTWORD
. In questo caso, un'altra app potrebbe avviare la registrazione. In questo caso, l'app con privilegi è stata interrotta e la nuova app ha acquisito 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 dell'interfaccia utente in primo piano iniziava a acquisire, l'app continuava a funzionare, ma riceveva silenzio, anche se era l'unica app che acquisiva l'audio in quel momento.
Comportamento di Android 10
Prima di Android 10, il comportamento era "primo arrivato, primo servito". Una volta che un'app inizia ad acquisire l'audio, nessun'altra app può accedere all'input audio finché l'app che acquisisce l'audio non si arresta.
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 funzionare, ma riceve silenzio. In alcuni casi, il sistema può continuare a trasmettere l'audio a entrambe le app. Di seguito sono descritti i vari scenari di condivisione.
Questo schema è simile al modo in cui l'attenzione audio gestisce più app in competizione per l'utilizzo dell'output audio. Tuttavia, l'attenzione audio è gestita da richieste programmatiche per acquisire e rilasciare l'attenzione, mentre lo schema di commutazione dell'input descritto qui si basa su un criterio di priorità che viene applicato automaticamente ogni volta che una nuova app inizia a acquisire audio.
Ai fini dell'acquisizione dell'audio, Android distingue due tipi di app:
- Le app "normali" vengono installate dall'utente.
- Le app "con privilegi" sono preinstallate sul dispositivo. Sono inclusi 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 definizione 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 una fonte sensibile alla privacy hanno una priorità maggiore rispetto alle altre.
- Due app normali non possono mai acquisire audio contemporaneamente.
- In alcuni casi, un'app con privilegi può condividere l'input audio con un'altra app.
- Se due app in background con la stessa priorità acquisiscono l'audio, l'ultima avviata ha la priorità più alta.
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 ordinaria
- Servizio di accessibilità + app ordinaria
- Due app normali
- Chiamata vocale + app ordinaria
Assistente + app ordinaria
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 alle seguenti 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 l'audio, a meno che l'assistente non abbia un componente dell'interfaccia utente visibile nella parte superiore dello schermo.
Tieni presente che entrambe le app ricevono l'audio solo quando l'assistente è in background e l'altra app non acquisisce da una sorgente audio sensibile alla privacy.
Servizio di accessibilità + app ordinaria
Un AccessibilityService
richiede una dichiarazione rigorosa.
Android condivide l'audio di input in base alle seguenti regole:
Se l'interfaccia utente del servizio è in alto, sia il servizio sia l'app ricevono input audio. Questo comportamento offre funzionalità come il controllo di una chiamata vocale o la registrazione video con comandi vocali.
Se il servizio non è in primo piano, questo caso viene trattato come il normale caso di due app riportato di seguito.
Due app normali
Quando due app acquisiscono contemporaneamente, solo una riceve l'audio e l'altra non riceve nulla.
Android condivide l'audio di input in base alle seguenti regole:
- Se nessuna delle app è sensibile alla privacy, l'app con un'interfaccia utente in alto riceve l'audio. Se nessuna delle due app ha un'interfaccia utente, l'audio viene ricevuto dall'app che ha iniziato la registrazione più di recente.
- Se una delle app è sensibile alla privacy, riceve l'audio e l'altra app viene messa a silenziare anche se ha un'interfaccia utente in alto o ha iniziato a acquisire più di recente.
- Se entrambe le app sono sensibili alla privacy, l'app che ha iniziato a acquisire più di recente riceve l'audio e l'altra riceve silenzio.
Chiamata vocale + app ordinaria
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 alle seguenti regole:
- La chiamata riceve sempre audio.
- L'app può acquisire audio se si tratta di un servizio di accessibilità.
L'app può acquisire la chiamata vocale se è un'app privilegiata (preinstallata) con autorizzazione
CAPTURE_AUDIO_OUTPUT
.Per acquisire l'uplink (TX), il downlink (RX) o entrambi della chiamata vocale, l'app deve specificare le sorgenti audio
MediaRecorder.AudioSource.VOICE_UPLINK
oMediaRecorder.AudioSource.VOICE_DOWNLINK
e/o il dispositivoAudioDeviceInfo.TYPE_TELEPHONY
.
Comportamento di Android 11
Android 11 (livello API 30) segue lo schema di priorità di Android 10 описанном выше. Fornisce inoltre nuovi metodi in AudioRecord
, MediaRecorder
e
AAudioStream
che attivano e disattivano 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
no.
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).
- L'elaborazione preliminare associata all'app attiva con la priorità più alta è attivata. Tutta l'altra pre-elaborazione viene ignorata.
Poiché un'app attiva potrebbe essere disattivata quando viene attivata un'app con priorità più alta, puoi registrare un AudioManager.AudioRecordingCallback sull'oggetto AudioRecord
o MediaRecorder
per ricevere una notifica quando la configurazione cambia.
Le possibili modifiche potrebbero essere:
- Acquisisci con l'audio disattivato o riattivato
- Dispositivo modificato
- Pre-elaborazione modificata
- Modifica delle proprietà dello stream (frequenza di campionamento, maschera canale, formato del sample)
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 corrente della registrazione audio. Utilizza i seguenti metodi per conoscere la modifica:
isClientSilenced()
- Restituisce true se l'audio restituito al client è attualmente disattivato a causa del criterio di acquisizione.
getAudioDevice()
- Restituisce il dispositivo audio attivo.
getEffects()
- Restituisce l'effetto di preelaborazione attivo. Tieni presente che l'effetto attivo potrebbe non essere lo stesso di quello restituito 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 campionamento, canale e formato dal formato utilizzato nell'interfaccia hardware al formato specificato dal cliente. AudioRecord.getActiveRecordingConfiguration()
.- Restituisce la configurazione di registrazione attiva.
Puoi avere una visione generale di tutte le registrazioni attive sul dispositivo chiamando
AudioManager.getActiveRecordingConfigurations()
.