In genere l'ingresso audio 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 svolgere attività diverse. Ad esempio, alcune app che ricevono audio potrebbero "registrare", come un semplice registratore vocale, mentre altre app potrebbero "per l'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", a prescindere dal fatto che un'app sia in registrazione o semplicemente in ascolto.
Se due o più app vogliono acquisire audio contemporaneamente, potrebbe esserci un problema durante la trasmissione del segnale audio dalla stessa sorgente a tutte. In questa pagina viene descritto in che modo il sistema Android condivide l'input audio tra più app che acquisiscono l'audio.
Comportamento precedente ad Android 10
Prima di Android 10, lo stream audio di input poteva essere acquisito da un'unica app alla
volta. Se un'app stesse già registrando o ascoltando audio, l'app potrebbe creare un oggetto AudioRecord
, ma verrà restituito un errore quando chiami AudioRecord.startRecording()
e la registrazione non viene avviata.
Un'eccezione a questa regola è stata quando un'app con privilegi (come l'Assistente Google o un
servizio di accessibilità) aveva l'autorizzazione
android.permission.CAPTURE_AUDIO_HOTWORD
e utilizzava una sorgente audio di tipo
HOTWORD
. In questo caso, un'altra app potrebbe iniziare a registrare. Quando è successo, l'app con privilegi è stata terminata e la nuova app ha acquisito l'input.
In Android 9 è stata aggiunta un'altra modifica: solo le app eseguite 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 della UI in primo piano ha iniziato ad acquisire, l'app ha continuato a essere eseguita, ma ha ricevuto silenzio, anche se era l'unica app ad acquisire audio in quel momento.
Comportamento di Android 10
Il comportamento precedente ad Android 10 è "primo arrivato, primo servito". Quando un'app inizia ad acquisire l'audio, nessun'altra app può accedere all'input audio finché l'app che acquisisce l'audio non 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 acquisita in precedenza continua a essere eseguita, ma riceve silenzio. In alcuni casi, il sistema può continuare a inviare l'audio a entrambe le app. Di seguito sono illustrati i vari scenari di condivisione.
Questo schema è simile al modo in cui lo stato attivo dell'audio gestisce più app che si contendono l'utilizzo dell'output audio. Tuttavia, l'attenzione relativa all'audio viene gestita dalle richieste di pubblicità programmatica per raggiungere e rilasciare l'attenzione, mentre lo schema di cambio di 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. inclusi l'Assistente Google e tutti i servizi di accessibilità.
Inoltre, un'app viene trattata in modo diverso se utilizza una sorgente audio "sensibile alla privacy":
CAMCORDER
o VOICE_COMMUNICATION
.
Le regole di priorità per l'utilizzo e la condivisione dell'input audio sono le seguenti:
- Le app con privilegi hanno una priorità maggiore rispetto alle app ordinarie.
- 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 che rispetta la privacy hanno una priorità maggiore rispetto alle app che non lo sono.
- Due normali app non sono mai in grado di acquisire l'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 app avviata ha una priorità maggiore.
Scenari di condivisione
Quando due app cercano di acquisire audio, potrebbero essere in grado di ricevere il segnale di ingresso o una di loro potrebbe ricevere il silenzio.
Esistono quattro scenari principali:
- Assistente + app normale
- Servizio di accessibilità + app normale
- Due app ordinarie
- Chiamata vocale + app normale
Assistente + app normale
L'Assistente è un'app con privilegi perché è preinstallato e detiene il ruolo RoleManager.ROLE_ASSISTANT
.
Tutte le altre app preinstallate con questo ruolo vengono trattate in modo simile.
Android condivide l'audio in 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 non sia già in corso l'acquisizione di un'altra app che utilizza una sorgente audio sensibile alla privacy.
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 acquisisce audio da una sorgente audio sensibile alla privacy.
Servizio di accessibilità + app normale
Un AccessibilityService
richiede una dichiarazione rigorosa.
Android condivide l'audio in input in base alle seguenti regole:
Se la UI 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 dell'acquisizione di video con comandi vocali.
Se il servizio non è in primo piano, questo caso viene trattato come la normale richiesta di due app riportata di seguito.
Due app ordinarie
Quando due app vengono acquisite contemporaneamente, solo un'app riceve audio e l'altra si disattiva.
Android condivide l'audio in input in base alle seguenti regole:
- Se nessuna delle due app è sensibile alla privacy, l'app con una UI in alto riceve audio. Se nessuna delle app dispone di una UI, l'app che ha avviato l'acquisizione più di recente riceve audio.
- Se una delle app è sensibile alla privacy, riceve audio e l'altra viene silenziata anche se ha una UI nella parte superiore o se ha iniziato l'acquisizione più di recente.
- Se entrambe le app sono sensibili alla privacy, l'app che ha iniziato ad acquisire più di recente riceve audio e l'altra viene silenziata.
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 in input in base alle seguenti regole:
- La chiamata riceve sempre audio.
- L'app è in grado di acquisire l'audio se si tratta di un servizio di accessibilità.
L'app può acquisire la chiamata vocale se si tratta di un'app con privilegi (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) rispetta lo schema di priorità di Android 10 descritto sopra. Offre inoltre nuovi metodi in AudioRecord
, MediaRecorder
e AAudioStream
che abilitano e disabilitano 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()
Se setPrivacySensitive()
è true
, il caso d'uso dell'acquisizione è privato e neanche un assistente con privilegi non può acquisire immagini contemporaneamente. Questa impostazione sostituisce il
comportamento predefinito che dipende dalla sorgente audio. Ad esempio,
VOICE_COMMUNICATION
è privato per impostazione predefinita, mentre UNPROCESSED
non lo è.
Modifiche alla configurazione
Quando più app acquisiscono l'audio contemporaneamente, solo una o due sono "attive" (ricezione audio), mentre l'audio delle altre viene disattivato (ricezione di silenzio). Quando le app attive cambiano, il framework audio potrebbe riconfigurare i percorsi audio in base a queste regole:
- Il dispositivo di input audio di ogni app attiva potrebbe cambiare (ad esempio, dal microfono integrato alle cuffie Bluetooth collegate).
- La pre-elaborazione associata all'app attiva con priorità più alta viene attivata. 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:
- Acquisisci elementi silenziati o non silenziati
- Dispositivo modificato
- Pre-elaborazione modificata
- Proprietà dello stream modificate (frequenza di campionamento, maschera del canale, formato di esempio)
Devi chiamare
AudioRecord.registerAudioRecordingCallback()
prima di iniziare l'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 dell'acquisizione dell'audio. Per ottenere informazioni sulla modifica, utilizza i seguenti metodi:
isClientSilenced()
- Restituisce true se l'audio restituito al client viene attualmente silenziato a causa del criterio di acquisizione.
getAudioDevice()
- Restituisci il dispositivo audio attivo.
getEffects()
- Restituisci l'effetto di pre-elaborazione attivo. Tieni presente che l'effetto attivo potrebbe non essere uguale a quelli restituiti da
getClientEffects()
se il client non è l'app attiva con priorità più alta. getFormat()
- Restituisci 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 per il ricampionamento, il canale e il formato dal formato utilizzato nell'interfaccia hardware al formato specificato dal client. AudioRecord.getActiveRecordingConfiguration()
.- Restituisci la configurazione di registrazione attiva.
Puoi avere una visione generale di tutte le registrazioni attive sul dispositivo chiamando il numero
AudioManager.getActiveRecordingConfigurations()
.