Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a64d6281 authored by Ahaan Ugale's avatar Ahaan Ugale
Browse files

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
parent 1028eb2f
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -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) {
+3 −0
Original line number Diff line number Diff line
@@ -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);
+8 −0
Original line number Diff line number Diff line
@@ -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",
+3 −0
Original line number Diff line number Diff line
@@ -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<AudioPort> ports, int[] generation);
+11 −1
Original line number Diff line number Diff line
@@ -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);