From a64d628182dc3e5cf3bceec52d7f5aa53e268216 Mon Sep 17 00:00:00 2001 From: Ahaan Ugale Date: Fri, 21 May 2021 02:18:45 -0700 Subject: [PATCH] Allow HotwordDetectionService access to audioflinger. HotwordDetectionService is an isolated service which ordinarily cannot access audioflinger due to selinux restrictions on isolated processes. To bypass those restrictions, the audioflinger binder is passed from the system server to the HotwordDetectionService. This follows the existing pattern of providing access to the ContentCapture service. In T we *may* instead solve this at the selinux layer. For now, this simpler approach is used. Bug: 190011174 Test: manual - sample app can read audio (with a few other wip changes) Test: atest CtsVoiceInteractionTestCases Change-Id: I5493a5c3addf68f2ae80d64b6971a8576484eb8e --- .../service/voice/HotwordDetectionService.java | 6 ++++++ .../service/voice/IHotwordDetectionService.aidl | 3 +++ core/jni/android_media_AudioSystem.cpp | 8 ++++++++ media/java/android/media/AudioSystem.java | 3 +++ .../voiceinteraction/HotwordDetectionConnection.java | 12 +++++++++++- 5 files changed, 31 insertions(+), 1 deletion(-) diff --git a/core/java/android/service/voice/HotwordDetectionService.java b/core/java/android/service/voice/HotwordDetectionService.java index deb6c01a30881..b66d93d6316e7 100644 --- a/core/java/android/service/voice/HotwordDetectionService.java +++ b/core/java/android/service/voice/HotwordDetectionService.java @@ -31,6 +31,7 @@ import android.content.Context; import android.content.Intent; import android.hardware.soundtrigger.SoundTrigger; import android.media.AudioFormat; +import android.media.AudioSystem; import android.os.Bundle; import android.os.IBinder; import android.os.IRemoteCallback; @@ -186,6 +187,11 @@ public abstract class HotwordDetectionService extends Service { } } + @Override + public void updateAudioFlinger(IBinder audioFlinger) { + AudioSystem.setAudioFlingerBinder(audioFlinger); + } + @Override public void updateContentCaptureManager(IContentCaptureManager manager, ContentCaptureOptions options) { diff --git a/core/java/android/service/voice/IHotwordDetectionService.aidl b/core/java/android/service/voice/IHotwordDetectionService.aidl index 72dd45aeeb0ff..d7ed67812e877 100644 --- a/core/java/android/service/voice/IHotwordDetectionService.aidl +++ b/core/java/android/service/voice/IHotwordDetectionService.aidl @@ -19,6 +19,7 @@ package android.service.voice; import android.content.ContentCaptureOptions; import android.hardware.soundtrigger.SoundTrigger; import android.media.AudioFormat; +import android.os.IBinder; import android.os.IRemoteCallback; import android.os.ParcelFileDescriptor; import android.os.PersistableBundle; @@ -50,6 +51,8 @@ oneway interface IHotwordDetectionService { in SharedMemory sharedMemory, in IRemoteCallback callback); + void updateAudioFlinger(in IBinder audioFlinger); + void updateContentCaptureManager( in IContentCaptureManager contentCaptureManager, in ContentCaptureOptions options); diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index 56814c7eb774f..4c3488e4d6edc 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -42,6 +42,7 @@ #include "android_media_AudioFormat.h" #include "android_media_AudioProfile.h" #include "android_media_MicrophoneInfo.h" +#include "android_util_Binder.h" // ---------------------------------------------------------------------------- @@ -850,6 +851,11 @@ android_media_AudioSystem_checkAudioFlinger(JNIEnv *env, jobject clazz) return (jint) check_AudioSystem_Command(AudioSystem::checkAudioFlinger()); } +static void android_media_AudioSystem_setAudioFlingerBinder(JNIEnv *env, jobject clazz, + jobject audioFlinger) { + AudioSystem::setAudioFlingerBinder(android::ibinderForJavaObject(env, audioFlinger)); +} + static void convertAudioGainConfigToNative(JNIEnv *env, struct audio_gain_config *nAudioGainConfig, const jobject jAudioGainConfig, @@ -2728,6 +2734,8 @@ static const JNINativeMethod gMethods[] = {"getOutputLatency", "(I)I", (void *)android_media_AudioSystem_getOutputLatency}, {"setLowRamDevice", "(ZJ)I", (void *)android_media_AudioSystem_setLowRamDevice}, {"checkAudioFlinger", "()I", (void *)android_media_AudioSystem_checkAudioFlinger}, + {"setAudioFlingerBinder", "(Landroid/os/IBinder;)V", + (void *)android_media_AudioSystem_setAudioFlingerBinder}, {"listAudioPorts", "(Ljava/util/ArrayList;[I)I", (void *)android_media_AudioSystem_listAudioPorts}, {"createAudioPatch", diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index 5f6fc17c38cb6..8012f03d84b37 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -27,6 +27,7 @@ import android.content.pm.PackageManager; import android.media.audiofx.AudioEffect; import android.media.audiopolicy.AudioMix; import android.os.Build; +import android.os.IBinder; import android.os.Vibrator; import android.telephony.TelephonyManager; import android.util.Log; @@ -1655,6 +1656,8 @@ public class AudioSystem /** @hide */ @UnsupportedAppUsage public static native int checkAudioFlinger(); + /** @hide */ + public static native void setAudioFlingerBinder(IBinder audioFlinger); /** @hide */ public static native int listAudioPorts(ArrayList ports, int[] generation); diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java index 0bb09a9de07f8..6f4e9735346ce 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java @@ -137,8 +137,9 @@ final class HotwordDetectionConnection { updateStateLocked(options, sharedMemory); return; } - updateStateWithCallbackLocked(options, sharedMemory, callback); + updateAudioFlinger(); updateContentCaptureManager(); + updateStateWithCallbackLocked(options, sharedMemory, callback); } private void updateStateWithCallbackLocked(PersistableBundle options, @@ -202,6 +203,15 @@ final class HotwordDetectionConnection { }); } + private void updateAudioFlinger() { + // TODO: Consider using a proxy that limits the exposed API surface. + IBinder audioFlinger = ServiceManager.getService("media.audio_flinger"); + if (audioFlinger == null) { + throw new IllegalStateException("Service media.audio_flinger wasn't found."); + } + mRemoteHotwordDetectionService.post(service -> service.updateAudioFlinger(audioFlinger)); + } + private void updateContentCaptureManager() { IBinder b = ServiceManager .getService(Context.CONTENT_CAPTURE_MANAGER_SERVICE);