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

Commit 45e16b90 authored by Eric Laurent's avatar Eric Laurent
Browse files

audio flinger: match app op monitoring to audio source

When monitoring app op to silence audio recording when app op
is lost, it must be done for the specific app op corresponding
to selected audio source.

Bug: 186582878
Test: music playback to head unit simulator

Change-Id: I86d8b6eecf480d70dc9c0e974a92e6407ee73041
parent 26a0e1a6
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -127,7 +127,7 @@ status_t MediaRecorderClient::setAudioSource(int as)

    if ((as == AUDIO_SOURCE_FM_TUNER
            && !(captureAudioOutputAllowed(mIdentity) || captureTunerAudioInputAllowed(mIdentity)))
            || !recordingAllowed(mIdentity)) {
            || !recordingAllowed(mIdentity, (audio_source_t)as)) {
        return PERMISSION_DENIED;
    }
    Mutex::Autolock lock(mLock);
+3 −3
Original line number Diff line number Diff line
@@ -67,7 +67,7 @@ static String16 resolveCallingPackage(PermissionController& permissionController
    return packages[0];
}

static int32_t getOpForSource(audio_source_t source) {
int32_t getOpForSource(audio_source_t source) {
  switch (source) {
    case AUDIO_SOURCE_HOTWORD:
      return AppOpsManager::OP_RECORD_AUDIO_HOTWORD;
@@ -133,8 +133,8 @@ static bool checkRecordingInternal(const Identity& identity, const String16& msg
    return true;
}

bool recordingAllowed(const Identity& identity) {
    return checkRecordingInternal(identity, String16(), /*start*/ false, AUDIO_SOURCE_DEFAULT);
bool recordingAllowed(const Identity& identity, audio_source_t source) {
    return checkRecordingInternal(identity, String16(), /*start*/ false, source);
}

bool startRecording(const Identity& identity, const String16& msg, audio_source_t source) {
+3 −1
Original line number Diff line number Diff line
@@ -80,7 +80,8 @@ static inline bool isAudioServerOrMediaServerUid(uid_t uid) {
    }
}

bool recordingAllowed(const media::permission::Identity& identity);
bool recordingAllowed(const media::permission::Identity& identity,
        audio_source_t source = AUDIO_SOURCE_DEFAULT);
bool startRecording(const media::permission::Identity& identity,
    const String16& msg, audio_source_t source);
void finishRecording(const media::permission::Identity& identity, audio_source_t source);
@@ -98,6 +99,7 @@ bool dumpAllowed();
bool modifyPhoneStateAllowed(const media::permission::Identity& identity);
bool bypassInterruptionPolicyAllowed(const media::permission::Identity& identity);
void purgePermissionCache();
int32_t getOpForSource(audio_source_t source);

media::permission::Identity getCallingIdentity();

+10 −8
Original line number Diff line number Diff line
@@ -19,17 +19,18 @@
    #error This header file should only be included from AudioFlinger.h
#endif

// Checks and monitors OP_RECORD_AUDIO
// Checks and monitors app ops for audio record
class OpRecordAudioMonitor : public RefBase {
public:
    ~OpRecordAudioMonitor() override;
    bool hasOpRecordAudio() const;
    bool hasOp() const;
    int32_t getOp() const { return mAppOp; }

    static sp<OpRecordAudioMonitor> createIfNeeded
        (const media::permission::Identity& identity, const audio_attributes_t& attr);

private:
    explicit OpRecordAudioMonitor(const media::permission::Identity& identity);
    OpRecordAudioMonitor(const media::permission::Identity& identity, int32_t appOp);
    void onFirstRef() override;

    AppOpsManager mAppOpsManager;
@@ -44,12 +45,13 @@ private:
    };

    sp<RecordAudioOpCallback> mOpCallback;
    // called by RecordAudioOpCallback when OP_RECORD_AUDIO is updated in AppOp callback
    // and in onFirstRef()
    void checkRecordAudio();
    // called by RecordAudioOpCallback when the app op for this OpRecordAudioMonitor is updated
    // in AppOp callback and in onFirstRef()
    void checkOp();

    std::atomic_bool mHasOpRecordAudio;
    std::atomic_bool mHasOp;
    const media::permission::Identity mIdentity;
    const int32_t mAppOp;
};

// record track
@@ -149,7 +151,7 @@ private:

            bool                               mSilenced;

            // used to enforce OP_RECORD_AUDIO
            // used to enforce the audio record app op corresponding to this track's audio source
            sp<OpRecordAudioMonitor>           mOpRecordAudioMonitor;
            std::string                        mSharedAudioPackageName = {};
            int32_t                            mStartFrames = -1;
+22 −22
Original line number Diff line number Diff line
@@ -2215,7 +2215,7 @@ AudioFlinger::RecordThread::OpRecordAudioMonitor::createIfNeeded(
        return nullptr;
    }

    // Capturing from FM TUNER output is not controlled by OP_RECORD_AUDIO
    // Capturing from FM TUNER output is not controlled by an app op
    // because it does not affect users privacy as does capturing from an actual microphone.
    if (attr.source == AUDIO_SOURCE_FM_TUNER) {
        ALOGV("not muting FM TUNER capture for uid %d", identity.uid);
@@ -2227,12 +2227,12 @@ AudioFlinger::RecordThread::OpRecordAudioMonitor::createIfNeeded(
            || checkedIdentity.packageName.value().size() == 0) {
        return nullptr;
    }
    return new OpRecordAudioMonitor(checkedIdentity);
    return new OpRecordAudioMonitor(checkedIdentity, getOpForSource(attr.source));
}

AudioFlinger::RecordThread::OpRecordAudioMonitor::OpRecordAudioMonitor(
        const Identity& identity)
        : mHasOpRecordAudio(true), mIdentity(identity)
        const Identity& identity, int32_t appOp)
        : mHasOp(true), mIdentity(identity), mAppOp(appOp)
{
}

@@ -2246,36 +2246,36 @@ AudioFlinger::RecordThread::OpRecordAudioMonitor::~OpRecordAudioMonitor()

void AudioFlinger::RecordThread::OpRecordAudioMonitor::onFirstRef()
{
    checkRecordAudio();
    checkOp();
    mOpCallback = new RecordAudioOpCallback(this);
    ALOGV("start watching OP_RECORD_AUDIO for %s", mIdentity.toString().c_str());
    mAppOpsManager.startWatchingMode(AppOpsManager::OP_RECORD_AUDIO,
    ALOGV("start watching op %d for %s", mAppOp, mIdentity.toString().c_str());
    mAppOpsManager.startWatchingMode(mAppOp,
        VALUE_OR_FATAL(aidl2legacy_string_view_String16(mIdentity.packageName.value_or(""))),
        mOpCallback);
}

bool AudioFlinger::RecordThread::OpRecordAudioMonitor::hasOpRecordAudio() const {
    return mHasOpRecordAudio.load();
bool AudioFlinger::RecordThread::OpRecordAudioMonitor::hasOp() const {
    return mHasOp.load();
}

// Called by RecordAudioOpCallback when OP_RECORD_AUDIO is updated in AppOp callback
// and in onFirstRef()
// Called by RecordAudioOpCallback when the app op corresponding to this OpRecordAudioMonitor
// is updated in AppOp callback and in onFirstRef()
// Note this method is never called (and never to be) for audio server / root track
// due to the UID in createIfNeeded(). As a result for those record track, it's:
// - not called from constructor,
// - not called from RecordAudioOpCallback because the callback is not installed in this case
void AudioFlinger::RecordThread::OpRecordAudioMonitor::checkRecordAudio()
void AudioFlinger::RecordThread::OpRecordAudioMonitor::checkOp()
{

    const int32_t mode = mAppOpsManager.checkOp(AppOpsManager::OP_RECORD_AUDIO,
    const int32_t mode = mAppOpsManager.checkOp(mAppOp,
            mIdentity.uid, VALUE_OR_FATAL(aidl2legacy_string_view_String16(
                mIdentity.packageName.value_or(""))));
    const bool hasIt =  (mode == AppOpsManager::MODE_ALLOWED);
    // verbose logging only log when appOp changed
    ALOGI_IF(hasIt != mHasOpRecordAudio.load(),
            "OP_RECORD_AUDIO missing, %ssilencing record %s",
            hasIt ? "un" : "", mIdentity.toString().c_str());
    mHasOpRecordAudio.store(hasIt);
    ALOGI_IF(hasIt != mHasOp.load(),
            "App op %d missing, %ssilencing record %s",
            mAppOp, hasIt ? "un" : "", mIdentity.toString().c_str());
    mHasOp.store(hasIt);

}

@@ -2286,12 +2286,12 @@ AudioFlinger::RecordThread::OpRecordAudioMonitor::RecordAudioOpCallback::RecordA
void AudioFlinger::RecordThread::OpRecordAudioMonitor::RecordAudioOpCallback::opChanged(int32_t op,
            const String16& packageName) {
    UNUSED(packageName);
    if (op != AppOpsManager::OP_RECORD_AUDIO) {
        return;
    }
    sp<OpRecordAudioMonitor> monitor = mMonitor.promote();
    if (monitor != NULL) {
        monitor->checkRecordAudio();
        if (op != monitor->getOp()) {
            return;
        }
        monitor->checkOp();
    }
}

@@ -2661,7 +2661,7 @@ bool AudioFlinger::RecordThread::RecordTrack::isSilenced() const {
        return true;
    }
    // The monitor is only created for record tracks that can be silenced.
    return mOpRecordAudioMonitor ? !mOpRecordAudioMonitor->hasOpRecordAudio() : false;
    return mOpRecordAudioMonitor ? !mOpRecordAudioMonitor->hasOp() : false;
}

status_t AudioFlinger::RecordThread::RecordTrack::getActiveMicrophones(
Loading