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

Commit d17c8502 authored by Eric Laurent's avatar Eric Laurent
Browse files

Add explicit private audio recording request

Add the possibility for apps to indicate that their
capture use case is private and that a privileged Assistant
should not be able to capture concurrently.
This allows to override the default behavior tied to the audio
source (e.g VOICE_COMMUNICATION is private by default but
UNPROCESSED is not).

- Add AAudio API to set and get privacy sensitive mode on input stream
- Add MediaRecorder API to set and get privacy sensitive mode
- Modify AudioSource constructor to accept audio attributes instead of an
audio source to specify the use case.
- Modify audio policy concurrent capture logic to use audio attributes
flag instead of audio source to decide of a capture client has
requested privacy mode or not.

Bug: 137850106
Test: CTS AudioRecordTest and MediaRecorderTest, manual audio smoke tests

Change-Id: I250ea5da4c1da809ceac0da22ae9bee15b937001
parent d203cb92
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -107,8 +107,11 @@ int main(int argc, char* argv[])

    if (useMic) {
        // talk into the appropriate microphone for the duration
        audio_attributes_t attr = AUDIO_ATTRIBUTES_INITIALIZER;
        attr.source = AUDIO_SOURCE_MIC;

        source = new AudioSource(
                AUDIO_SOURCE_MIC,
                &attr,
                String16(),
                sampleRate,
                channels);
+52 −4
Original line number Diff line number Diff line
@@ -38,12 +38,15 @@ static void (*s_setInputPreset)(AAudioStreamBuilder* builder,
                                aaudio_input_preset_t inputPreset) = nullptr;
static void (*s_setAllowedCapturePolicy)(AAudioStreamBuilder* builder,
                                          aaudio_allowed_capture_policy_t usage) = nullptr;
static void (*s_setPrivacySensitive)(AAudioStreamBuilder* builder,
                                          bool privacySensitive) = nullptr;

static bool s_loadAttempted = false;
static aaudio_usage_t (*s_getUsage)(AAudioStream *stream) = nullptr;
static aaudio_content_type_t (*s_getContentType)(AAudioStream *stream) = nullptr;
static aaudio_input_preset_t (*s_getInputPreset)(AAudioStream *stream) = nullptr;
static aaudio_allowed_capture_policy_t (*s_getAllowedCapturePolicy)(AAudioStream *stream) = nullptr;
static bool (*s_isPrivacySensitive)(AAudioStream *stream) = nullptr;

// Link to test functions in shared library.
static void loadFutureFunctions() {
@@ -68,6 +71,10 @@ static void loadFutureFunctions() {
                dlsym(handle, "AAudioStreamBuilder_setAllowedCapturePolicy");
        if (s_setAllowedCapturePolicy == nullptr) goto error;

        s_setPrivacySensitive = (void (*)(AAudioStreamBuilder *, bool))
                dlsym(handle, "AAudioStreamBuilder_setPrivacySensitive");
        if (s_setPrivacySensitive == nullptr) goto error;

        s_getUsage = (aaudio_usage_t (*)(AAudioStream *))
                dlsym(handle, "AAudioStream_getUsage");
        if (s_getUsage == nullptr) goto error;
@@ -83,6 +90,10 @@ static void loadFutureFunctions() {
        s_getAllowedCapturePolicy = (aaudio_input_preset_t (*)(AAudioStream *))
                dlsym(handle, "AAudioStream_getAllowedCapturePolicy");
        if (s_getAllowedCapturePolicy == nullptr) goto error;

        s_isPrivacySensitive = (bool (*)(AAudioStream *))
                dlsym(handle, "AAudioStream_isPrivacySensitive");
        if (s_isPrivacySensitive == nullptr) goto error;
    }
    return;

@@ -91,9 +102,11 @@ error:
    s_setUsage = nullptr;
    s_setContentType = nullptr;
    s_setInputPreset = nullptr;
    s_setPrivacySensitive = nullptr;
    s_getUsage = nullptr;
    s_getContentType = nullptr;
    s_getInputPreset = nullptr;
    s_isPrivacySensitive = nullptr;
    dlclose(handle);
    return;
}
@@ -211,6 +224,14 @@ public:
        mFramesPerCallback = size;
    }

    int32_t isPrivacySensitive() const {
        return mPrivacySensitive;
    }

    void setPrivacySensitive(int32_t privacySensitive) {
        mPrivacySensitive = privacySensitive;
    }

    /**
     * Apply these parameters to a stream builder.
     * @param builder
@@ -234,12 +255,12 @@ public:
        }
        if (s_setContentType != nullptr) {
            s_setContentType(builder, mContentType);
        } else if (mUsage != AAUDIO_UNSPECIFIED){
        } else if (mContentType != AAUDIO_UNSPECIFIED){
            printf("WARNING: setContentType not supported");
        }
        if (s_setInputPreset != nullptr) {
            s_setInputPreset(builder, mInputPreset);
        } else if (mUsage != AAUDIO_UNSPECIFIED){
        } else if (mInputPreset != AAUDIO_UNSPECIFIED){
            printf("WARNING: setInputPreset not supported");
        }

@@ -249,6 +270,15 @@ public:
        } else if (mAllowedCapturePolicy != AAUDIO_UNSPECIFIED){
            printf("WARNING: setAllowedCapturePolicy not supported");
        }

        if (mPrivacySensitive != PRIVACY_SENSITIVE_DEFAULT) {
            if (s_setPrivacySensitive != nullptr) {
                s_setPrivacySensitive(builder,
                    mPrivacySensitive == PRIVACY_SENSITIVE_ENABLED);
            } else {
                printf("WARNING: setPrivacySensitive not supported");
            }
        }
    }

    static constexpr int32_t   kDefaultNumberOfBursts = 2;
@@ -270,6 +300,13 @@ private:

    int32_t                    mNumberOfBursts  = kDefaultNumberOfBursts;
    int32_t                    mFramesPerCallback = AAUDIO_UNSPECIFIED;

    enum {
        PRIVACY_SENSITIVE_DEFAULT = -1,
        PRIVACY_SENSITIVE_DISABLED = 0,
        PRIVACY_SENSITIVE_ENABLED = 1,
    };
    int32_t                    mPrivacySensitive = PRIVACY_SENSITIVE_DEFAULT;
};

class AAudioArgsParser : public AAudioParameters {
@@ -341,6 +378,9 @@ public:
                case 'z':
                    setFramesPerCallback(atoi(&arg[2]));
                    break;
                case 'S':
                    setPrivacySensitive(atoi(&arg[2]));
                    break;
                default:
                    unrecognized = true;
                    break;
@@ -399,6 +439,9 @@ public:
        printf("      -x to use EXCLUSIVE mode\n");
        printf("      -y{contentType} eg. 1 for AAUDIO_CONTENT_TYPE_SPEECH\n");
        printf("      -z{callbackSize} or block size, in frames, default = 0\n");
        printf("      -S{0|1} set privacy Sensitive enabled or disabled\n");
        printf("          0 = disabled\n");
        printf("          1 = enabled\n");
    }

    static aaudio_performance_mode_t parseAllowedCapturePolicy(char c) {
@@ -506,11 +549,16 @@ public:
                   getContentType(), s_getContentType(stream));
        }

        if (AAudioStream_getDirection(stream) == AAUDIO_DIRECTION_INPUT
            && s_getInputPreset != nullptr) {
        if (AAudioStream_getDirection(stream) == AAUDIO_DIRECTION_INPUT) {
            if (s_getInputPreset != nullptr) {
                printf("  InputPreset:  requested = %d, actual = %d\n",
                       getInputPreset(), s_getInputPreset(stream));
            }
            if (s_isPrivacySensitive != nullptr) {
                printf("  Privacy Sensitive:  requested = %d, actual = %d\n",
                       isPrivacySensitive(), s_isPrivacySensitive(stream));
            }
        }

        printf("  Is MMAP used? %s\n", AAudioStream_isMMapUsed(stream)
               ? "yes" : "no");
+36 −0
Original line number Diff line number Diff line
@@ -759,6 +759,28 @@ AAUDIO_API void AAudioStreamBuilder_setAllowedCapturePolicy(AAudioStreamBuilder*
AAUDIO_API void AAudioStreamBuilder_setSessionId(AAudioStreamBuilder* builder,
        aaudio_session_id_t sessionId) __INTRODUCED_IN(28);


/** Indicates whether this input stream must be marked as privacy sensitive or not.
 *
 * When true, this input stream is privacy sensitive and any concurrent capture
 * is not permitted.
 *
 * This is off (false) by default except when the input preset is {@link #AAUDIO_INPUT_PRESET_VOICE_COMMUNICATION}
 * or {@link #AAUDIO_INPUT_PRESET_CAMCORDER}.
 *
 * Always takes precedence over default from input preset when set explicitly.
 *
 * Only relevant if the stream direction is {@link #AAUDIO_DIRECTION_INPUT}.
 *
 * Added in API level 30.
 *
 * @param builder reference provided by AAudio_createStreamBuilder()
 * @param privacySensitive true if capture from this stream must be marked as privacy sensitive,
 * false otherwise.
 */
AAUDIO_API void AAudioStreamBuilder_setPrivacySensitive(AAudioStreamBuilder* builder,
        bool privacySensitive) __INTRODUCED_IN(30);

/**
 * Return one of these values from the data callback function.
 */
@@ -1444,6 +1466,20 @@ AAUDIO_API aaudio_input_preset_t AAudioStream_getInputPreset(AAudioStream* strea
AAUDIO_API aaudio_allowed_capture_policy_t AAudioStream_getAllowedCapturePolicy(
        AAudioStream* stream) __INTRODUCED_IN(29);


/**
 * Return whether this input stream is marked as privacy sensitive or not.
 *
 * See {@link #AAudioStreamBuilder_setPrivacySensitive()}.
 *
 * Added in API level 30.
 *
 * @param stream reference provided by AAudioStreamBuilder_openStream()
 * @return true if privacy sensitive, false otherwise
 */
AAUDIO_API bool AAudioStream_isPrivacySensitive(AAudioStream* stream)
        __INTRODUCED_IN(30);

#ifdef __cplusplus
}
#endif
+5 −1
Original line number Diff line number Diff line
@@ -66,6 +66,8 @@ status_t AAudioStreamConfiguration::writeToParcel(Parcel* parcel) const {
    if (status != NO_ERROR) goto error;
    status = parcel->writeInt32(getSessionId());
    if (status != NO_ERROR) goto error;
    status = parcel->writeInt32(isPrivacySensitive() ? 1 : 0);
    if (status != NO_ERROR) goto error;
    return NO_ERROR;
error:
    ALOGE("%s(): write failed = %d", __func__, status);
@@ -111,7 +113,9 @@ status_t AAudioStreamConfiguration::readFromParcel(const Parcel* parcel) {
    status = parcel->readInt32(&value);
    if (status != NO_ERROR) goto error;
    setSessionId(value);

    status = parcel->readInt32(&value);
    if (status != NO_ERROR) goto error;
    setPrivacySensitive(value == 1);
    return NO_ERROR;
error:
    ALOGE("%s(): read failed = %d", __func__, status);
+1 −0
Original line number Diff line number Diff line
@@ -116,6 +116,7 @@ aaudio_result_t AudioStreamInternal::open(const AudioStreamBuilder &builder) {
    request.getConfiguration().setUsage(getUsage());
    request.getConfiguration().setContentType(getContentType());
    request.getConfiguration().setInputPreset(getInputPreset());
    request.getConfiguration().setPrivacySensitive(isPrivacySensitive());

    request.getConfiguration().setBufferCapacity(builder.getBufferCapacity());

Loading