Condivisione input audio

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 "catturare" 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 nel fornire a tutte il segnale audio dalla stessa sorgente. 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 una sola app alla volta. Se un'altra app stava già registrando o ascoltando l'audio, la tua app poteva creare un oggetto AudioRecord, ma veniva restituito un errore quando chiamavi AudioRecord.startRecording() e la registrazione non si avviava.

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 iniziare a registrare. 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 non riceveva alcun audio, 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 fino a quando l'app che acquisisce l'audio si interrompe.

Android 10 impone uno schema di priorità che può cambiare lo stream audio di input tra le app mentre sono in esecuzione. Nella maggior parte dei casi, se una nuova app acquisisce l'input audio, l'app di acquisizione precedente continua a essere eseguita, 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, il focus audio è gestito dalle richieste programmatiche per acquisire e rilasciare il focus, mentre lo schema di cambio degli input descritto qui si basa su un criterio di priorità che viene applicato automaticamente ogni volta che una nuova app inizia ad acquisire audio.

Per acquisire l'audio, Android distingue due tipi di app:

  • Le app "ordinarie" 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 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 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 comune
  • 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. Tutte le altre app preinstallate con questo ruolo vengono trattate in modo simile.

Android condivide l'audio di input in base a queste regole:

  • L'assistente può ricevere audio (indipendentemente dal fatto che siano in primo piano o in background), a meno che non sia già in corso l'acquisizione di un'altra app che utilizza una sorgente audio sensibile alla privacy.

  • 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 a queste 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 a queste 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:

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 l'audio contemporaneamente, indipendentemente dal caso d'uso selezionato.

I nuovi metodi sono:

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. Tutte le altre pre-elaborazioni vengono ignorate.

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 di avviare l'acquisizione. Il callback viene eseguito soltanto 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 scoprire di più sul cambiamento:

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().