Loading media/utils/ServiceUtilities.cpp +79 −36 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ namespace android { namespace { constexpr auto PERMISSION_GRANTED = permission::PermissionChecker::PERMISSION_GRANTED; constexpr auto PERMISSION_HARD_DENIED = permission::PermissionChecker::PERMISSION_HARD_DENIED; } Loading Loading @@ -78,19 +79,32 @@ static String16 resolveCallingPackage(PermissionController& permissionController int32_t getOpForSource(audio_source_t source) { switch (source) { case AUDIO_SOURCE_HOTWORD: return AppOpsManager::OP_RECORD_AUDIO_HOTWORD; case AUDIO_SOURCE_FM_TUNER: return AppOpsManager::OP_NONE; case AUDIO_SOURCE_ECHO_REFERENCE: // fallthrough case AUDIO_SOURCE_REMOTE_SUBMIX: return AppOpsManager::OP_RECORD_AUDIO_OUTPUT; case AUDIO_SOURCE_VOICE_DOWNLINK: return AppOpsManager::OP_RECORD_INCOMING_PHONE_AUDIO; case AUDIO_SOURCE_HOTWORD: return AppOpsManager::OP_RECORD_AUDIO_HOTWORD; case AUDIO_SOURCE_DEFAULT: default: return AppOpsManager::OP_RECORD_AUDIO; } } bool isRecordOpRequired(audio_source_t source) { switch (source) { case AUDIO_SOURCE_FM_TUNER: case AUDIO_SOURCE_ECHO_REFERENCE: // fallthrough case AUDIO_SOURCE_REMOTE_SUBMIX: return false; default: return true; } } std::optional<AttributionSourceState> resolveAttributionSource( const AttributionSourceState& callerAttributionSource, const uint32_t virtualDeviceId) { AttributionSourceState nextAttributionSource = callerAttributionSource; Loading Loading @@ -122,6 +136,7 @@ std::optional<AttributionSourceState> resolveAttributionSource( return std::optional<AttributionSourceState>{myAttributionSource}; } static int checkRecordingInternal(const AttributionSourceState &attributionSource, const uint32_t virtualDeviceId, const String16 &msg, bool start, audio_source_t source) { Loading @@ -131,19 +146,19 @@ std::optional<AttributionSourceState> resolveAttributionSource( // user is active, but it is a core system service so let it through. // TODO(b/141210120): UserManager.DISALLOW_RECORD_AUDIO should not affect system user 0 uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)); if (isAudioServerOrMediaServerOrSystemServerOrRootUid(uid)) return true; if (isAudioServerOrMediaServerOrSystemServerOrRootUid(uid)) return PERMISSION_GRANTED; const int32_t attributedOpCode = getOpForSource(source); if (isRecordOpRequired(source)) { // We specify a pid and uid here as mediaserver (aka MediaRecorder or StageFrightRecorder) // may open a record track on behalf of a client. Note that pid may be a tid. // IMPORTANT: DON'T USE PermissionCache - RUNTIME PERMISSIONS CHANGE. std::optional<AttributionSourceState> resolvedAttributionSource = resolveAttributionSource(attributionSource, virtualDeviceId); if (!resolvedAttributionSource.has_value()) { return false; return PERMISSION_HARD_DENIED; } const int32_t attributedOpCode = getOpForSource(source); permission::PermissionChecker permissionChecker; int permitted; if (start) { Loading @@ -157,6 +172,21 @@ std::optional<AttributionSourceState> resolveAttributionSource( } return permitted; } else { if (attributedOpCode == AppOpsManager::OP_NONE) return PERMISSION_GRANTED; // nothing to do AppOpsManager ap{}; PermissionController pc{}; return ap.startOpNoThrow( attributedOpCode, attributionSource.uid, resolveCallingPackage(pc, String16{attributionSource.packageName.value_or("").c_str()}, attributionSource.uid), false, attributionSource.attributionTag.has_value() ? String16{attributionSource.attributionTag.value().c_str()} : String16{}, msg); } } static constexpr int DEVICE_ID_DEFAULT = 0; Loading Loading @@ -188,6 +218,8 @@ void finishRecording(const AttributionSourceState &attributionSource, uint32_t v uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)); if (isAudioServerOrMediaServerOrSystemServerOrRootUid(uid)) return; const int32_t attributedOpCode = getOpForSource(source); if (isRecordOpRequired(source)) { // We specify a pid and uid here as mediaserver (aka MediaRecorder or StageFrightRecorder) // may open a record track on behalf of a client. Note that pid may be a tid. // IMPORTANT: DON'T USE PermissionCache - RUNTIME PERMISSIONS CHANGE. Loading @@ -197,10 +229,21 @@ void finishRecording(const AttributionSourceState &attributionSource, uint32_t v return; } const int32_t attributedOpCode = getOpForSource(source); permission::PermissionChecker permissionChecker; permissionChecker.finishDataDeliveryFromDatasource(attributedOpCode, resolvedAttributionSource.value()); } else { if (attributedOpCode == AppOpsManager::OP_NONE) return; // nothing to do AppOpsManager ap{}; PermissionController pc{}; ap.finishOp(attributedOpCode, attributionSource.uid, resolveCallingPackage( pc, String16{attributionSource.packageName.value_or("").c_str()}, attributionSource.uid), attributionSource.attributionTag.has_value() ? String16{attributionSource.attributionTag.value().c_str()} : String16{}); } } bool captureAudioOutputAllowed(const AttributionSourceState& attributionSource) { Loading media/utils/include/mediautils/ServiceUtilities.h +1 −0 Original line number Diff line number Diff line Loading @@ -118,6 +118,7 @@ bool mustAnonymizeBluetoothAddress( const AttributionSourceState& attributionSource, const String16& caller); void anonymizeBluetoothAddress(char *address); bool isRecordOpRequired(audio_source_t source); int32_t getOpForSource(audio_source_t source); AttributionSourceState getCallingAttributionSource(); Loading services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp +2 −3 Original line number Diff line number Diff line Loading @@ -909,13 +909,12 @@ Status AudioPolicyService::startInput(int32_t portIdAidl) std::stringstream msg; msg << "Audio recording on session " << client->session; const auto permitted = startRecording(client->attributionSource, client->virtualDeviceId, String16(msg.str().c_str()), client->attributes.source); // check calling permissions if (permitted == PERMISSION_HARD_DENIED && client->attributes.source != AUDIO_SOURCE_FM_TUNER && client->attributes.source != AUDIO_SOURCE_REMOTE_SUBMIX && client->attributes.source != AUDIO_SOURCE_ECHO_REFERENCE) { if (permitted == PERMISSION_HARD_DENIED) { ALOGE("%s permission denied: recording not allowed for attribution source %s", __func__, client->attributionSource.toString().c_str()); return binderStatusFromStatusT(PERMISSION_DENIED); Loading services/audiopolicy/service/AudioRecordClient.cpp +8 −3 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include "AudioRecordClient.h" #include "AudioPolicyService.h" #include "binder/AppOpsManager.h" #include "mediautils/ServiceUtilities.h" #include <android_media_audiopolicy.h> #include <algorithm> Loading Loading @@ -118,16 +119,20 @@ OpRecordAudioMonitor::createIfNeeded( } return new OpRecordAudioMonitor(attributionSource, virtualDeviceId, attr, getOpForSource(attr.source), commandThread); getOpForSource(attr.source), isRecordOpRequired(attr.source), commandThread); } OpRecordAudioMonitor::OpRecordAudioMonitor( const AttributionSourceState &attributionSource, const uint32_t virtualDeviceId, const audio_attributes_t &attr, int32_t appOp, bool shouldMonitorRecord, wp<AudioPolicyService::AudioCommandThread> commandThread) : mHasOp(true), mAttributionSource(attributionSource), mVirtualDeviceId(virtualDeviceId), mAttr(attr), mAppOp(appOp), mShouldMonitorRecord(shouldMonitorRecord), mCommandThread(commandThread) { } Loading Loading @@ -160,7 +165,7 @@ void OpRecordAudioMonitor::onFirstRef() }); }; reg(mAppOp); if (mAppOp != AppOpsManager::OP_RECORD_AUDIO) { if (mAppOp != AppOpsManager::OP_RECORD_AUDIO && mShouldMonitorRecord) { reg(AppOpsManager::OP_RECORD_AUDIO); } } Loading @@ -186,7 +191,7 @@ void OpRecordAudioMonitor::checkOp(bool updateUidStates) { }); }; bool hasIt = check(mAppOp); if (mAppOp != AppOpsManager::OP_RECORD_AUDIO) { if (mAppOp != AppOpsManager::OP_RECORD_AUDIO && mShouldMonitorRecord) { hasIt = hasIt && check(AppOpsManager::OP_RECORD_AUDIO); } Loading services/audiopolicy/service/AudioRecordClient.h +2 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ private: uint32_t virtualDeviceId, const audio_attributes_t &attr, int32_t appOp, bool shouldMonitorRecord, wp<AudioPolicyService::AudioCommandThread> commandThread); void onFirstRef() override; Loading Loading @@ -74,6 +75,7 @@ private: const uint32_t mVirtualDeviceId; const audio_attributes_t mAttr; const int32_t mAppOp; const bool mShouldMonitorRecord; wp<AudioPolicyService::AudioCommandThread> mCommandThread; }; Loading Loading
media/utils/ServiceUtilities.cpp +79 −36 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ namespace android { namespace { constexpr auto PERMISSION_GRANTED = permission::PermissionChecker::PERMISSION_GRANTED; constexpr auto PERMISSION_HARD_DENIED = permission::PermissionChecker::PERMISSION_HARD_DENIED; } Loading Loading @@ -78,19 +79,32 @@ static String16 resolveCallingPackage(PermissionController& permissionController int32_t getOpForSource(audio_source_t source) { switch (source) { case AUDIO_SOURCE_HOTWORD: return AppOpsManager::OP_RECORD_AUDIO_HOTWORD; case AUDIO_SOURCE_FM_TUNER: return AppOpsManager::OP_NONE; case AUDIO_SOURCE_ECHO_REFERENCE: // fallthrough case AUDIO_SOURCE_REMOTE_SUBMIX: return AppOpsManager::OP_RECORD_AUDIO_OUTPUT; case AUDIO_SOURCE_VOICE_DOWNLINK: return AppOpsManager::OP_RECORD_INCOMING_PHONE_AUDIO; case AUDIO_SOURCE_HOTWORD: return AppOpsManager::OP_RECORD_AUDIO_HOTWORD; case AUDIO_SOURCE_DEFAULT: default: return AppOpsManager::OP_RECORD_AUDIO; } } bool isRecordOpRequired(audio_source_t source) { switch (source) { case AUDIO_SOURCE_FM_TUNER: case AUDIO_SOURCE_ECHO_REFERENCE: // fallthrough case AUDIO_SOURCE_REMOTE_SUBMIX: return false; default: return true; } } std::optional<AttributionSourceState> resolveAttributionSource( const AttributionSourceState& callerAttributionSource, const uint32_t virtualDeviceId) { AttributionSourceState nextAttributionSource = callerAttributionSource; Loading Loading @@ -122,6 +136,7 @@ std::optional<AttributionSourceState> resolveAttributionSource( return std::optional<AttributionSourceState>{myAttributionSource}; } static int checkRecordingInternal(const AttributionSourceState &attributionSource, const uint32_t virtualDeviceId, const String16 &msg, bool start, audio_source_t source) { Loading @@ -131,19 +146,19 @@ std::optional<AttributionSourceState> resolveAttributionSource( // user is active, but it is a core system service so let it through. // TODO(b/141210120): UserManager.DISALLOW_RECORD_AUDIO should not affect system user 0 uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)); if (isAudioServerOrMediaServerOrSystemServerOrRootUid(uid)) return true; if (isAudioServerOrMediaServerOrSystemServerOrRootUid(uid)) return PERMISSION_GRANTED; const int32_t attributedOpCode = getOpForSource(source); if (isRecordOpRequired(source)) { // We specify a pid and uid here as mediaserver (aka MediaRecorder or StageFrightRecorder) // may open a record track on behalf of a client. Note that pid may be a tid. // IMPORTANT: DON'T USE PermissionCache - RUNTIME PERMISSIONS CHANGE. std::optional<AttributionSourceState> resolvedAttributionSource = resolveAttributionSource(attributionSource, virtualDeviceId); if (!resolvedAttributionSource.has_value()) { return false; return PERMISSION_HARD_DENIED; } const int32_t attributedOpCode = getOpForSource(source); permission::PermissionChecker permissionChecker; int permitted; if (start) { Loading @@ -157,6 +172,21 @@ std::optional<AttributionSourceState> resolveAttributionSource( } return permitted; } else { if (attributedOpCode == AppOpsManager::OP_NONE) return PERMISSION_GRANTED; // nothing to do AppOpsManager ap{}; PermissionController pc{}; return ap.startOpNoThrow( attributedOpCode, attributionSource.uid, resolveCallingPackage(pc, String16{attributionSource.packageName.value_or("").c_str()}, attributionSource.uid), false, attributionSource.attributionTag.has_value() ? String16{attributionSource.attributionTag.value().c_str()} : String16{}, msg); } } static constexpr int DEVICE_ID_DEFAULT = 0; Loading Loading @@ -188,6 +218,8 @@ void finishRecording(const AttributionSourceState &attributionSource, uint32_t v uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)); if (isAudioServerOrMediaServerOrSystemServerOrRootUid(uid)) return; const int32_t attributedOpCode = getOpForSource(source); if (isRecordOpRequired(source)) { // We specify a pid and uid here as mediaserver (aka MediaRecorder or StageFrightRecorder) // may open a record track on behalf of a client. Note that pid may be a tid. // IMPORTANT: DON'T USE PermissionCache - RUNTIME PERMISSIONS CHANGE. Loading @@ -197,10 +229,21 @@ void finishRecording(const AttributionSourceState &attributionSource, uint32_t v return; } const int32_t attributedOpCode = getOpForSource(source); permission::PermissionChecker permissionChecker; permissionChecker.finishDataDeliveryFromDatasource(attributedOpCode, resolvedAttributionSource.value()); } else { if (attributedOpCode == AppOpsManager::OP_NONE) return; // nothing to do AppOpsManager ap{}; PermissionController pc{}; ap.finishOp(attributedOpCode, attributionSource.uid, resolveCallingPackage( pc, String16{attributionSource.packageName.value_or("").c_str()}, attributionSource.uid), attributionSource.attributionTag.has_value() ? String16{attributionSource.attributionTag.value().c_str()} : String16{}); } } bool captureAudioOutputAllowed(const AttributionSourceState& attributionSource) { Loading
media/utils/include/mediautils/ServiceUtilities.h +1 −0 Original line number Diff line number Diff line Loading @@ -118,6 +118,7 @@ bool mustAnonymizeBluetoothAddress( const AttributionSourceState& attributionSource, const String16& caller); void anonymizeBluetoothAddress(char *address); bool isRecordOpRequired(audio_source_t source); int32_t getOpForSource(audio_source_t source); AttributionSourceState getCallingAttributionSource(); Loading
services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp +2 −3 Original line number Diff line number Diff line Loading @@ -909,13 +909,12 @@ Status AudioPolicyService::startInput(int32_t portIdAidl) std::stringstream msg; msg << "Audio recording on session " << client->session; const auto permitted = startRecording(client->attributionSource, client->virtualDeviceId, String16(msg.str().c_str()), client->attributes.source); // check calling permissions if (permitted == PERMISSION_HARD_DENIED && client->attributes.source != AUDIO_SOURCE_FM_TUNER && client->attributes.source != AUDIO_SOURCE_REMOTE_SUBMIX && client->attributes.source != AUDIO_SOURCE_ECHO_REFERENCE) { if (permitted == PERMISSION_HARD_DENIED) { ALOGE("%s permission denied: recording not allowed for attribution source %s", __func__, client->attributionSource.toString().c_str()); return binderStatusFromStatusT(PERMISSION_DENIED); Loading
services/audiopolicy/service/AudioRecordClient.cpp +8 −3 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include "AudioRecordClient.h" #include "AudioPolicyService.h" #include "binder/AppOpsManager.h" #include "mediautils/ServiceUtilities.h" #include <android_media_audiopolicy.h> #include <algorithm> Loading Loading @@ -118,16 +119,20 @@ OpRecordAudioMonitor::createIfNeeded( } return new OpRecordAudioMonitor(attributionSource, virtualDeviceId, attr, getOpForSource(attr.source), commandThread); getOpForSource(attr.source), isRecordOpRequired(attr.source), commandThread); } OpRecordAudioMonitor::OpRecordAudioMonitor( const AttributionSourceState &attributionSource, const uint32_t virtualDeviceId, const audio_attributes_t &attr, int32_t appOp, bool shouldMonitorRecord, wp<AudioPolicyService::AudioCommandThread> commandThread) : mHasOp(true), mAttributionSource(attributionSource), mVirtualDeviceId(virtualDeviceId), mAttr(attr), mAppOp(appOp), mShouldMonitorRecord(shouldMonitorRecord), mCommandThread(commandThread) { } Loading Loading @@ -160,7 +165,7 @@ void OpRecordAudioMonitor::onFirstRef() }); }; reg(mAppOp); if (mAppOp != AppOpsManager::OP_RECORD_AUDIO) { if (mAppOp != AppOpsManager::OP_RECORD_AUDIO && mShouldMonitorRecord) { reg(AppOpsManager::OP_RECORD_AUDIO); } } Loading @@ -186,7 +191,7 @@ void OpRecordAudioMonitor::checkOp(bool updateUidStates) { }); }; bool hasIt = check(mAppOp); if (mAppOp != AppOpsManager::OP_RECORD_AUDIO) { if (mAppOp != AppOpsManager::OP_RECORD_AUDIO && mShouldMonitorRecord) { hasIt = hasIt && check(AppOpsManager::OP_RECORD_AUDIO); } Loading
services/audiopolicy/service/AudioRecordClient.h +2 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ private: uint32_t virtualDeviceId, const audio_attributes_t &attr, int32_t appOp, bool shouldMonitorRecord, wp<AudioPolicyService::AudioCommandThread> commandThread); void onFirstRef() override; Loading Loading @@ -74,6 +75,7 @@ private: const uint32_t mVirtualDeviceId; const audio_attributes_t mAttr; const int32_t mAppOp; const bool mShouldMonitorRecord; wp<AudioPolicyService::AudioCommandThread> mCommandThread; }; Loading