From be71aa29a3c86d2e01cd17839d2a72ab09a1bce5 Mon Sep 17 00:00:00 2001 From: Svet Ganov Date: Tue, 28 Apr 2015 12:06:02 -0700 Subject: Respect the record audio app op - media Change-Id: I3a97977b6e9a09355e2008f780d22d480fb7308b --- cmds/stagefright/audioloop.cpp | 5 +- include/media/AudioEffect.h | 13 +++- include/media/AudioRecord.h | 12 +++- include/media/IAudioFlinger.h | 2 + include/media/IMediaPlayerService.h | 6 +- include/media/MediaRecorderBase.h | 7 +- include/media/Visualizer.h | 3 +- include/media/mediarecorder.h | 2 +- include/media/stagefright/AudioSource.h | 1 + media/libmedia/AudioEffect.cpp | 12 ++-- media/libmedia/AudioRecord.cpp | 23 +++--- media/libmedia/IAudioFlinger.cpp | 13 ++-- media/libmedia/IMediaPlayerService.cpp | 14 ++-- media/libmedia/Visualizer.cpp | 5 +- media/libmedia/mediarecorder.cpp | 4 +- media/libmediaplayerservice/MediaPlayerService.cpp | 7 +- media/libmediaplayerservice/MediaPlayerService.h | 6 +- .../libmediaplayerservice/MediaRecorderClient.cpp | 5 +- media/libmediaplayerservice/MediaRecorderClient.h | 3 +- media/libmediaplayerservice/RemoteDisplay.cpp | 3 +- media/libmediaplayerservice/RemoteDisplay.h | 1 + .../libmediaplayerservice/StagefrightRecorder.cpp | 6 +- media/libmediaplayerservice/StagefrightRecorder.h | 2 +- media/libstagefright/AudioSource.cpp | 4 +- .../tests/SurfaceMediaSource_test.cpp | 3 +- .../wifi-display/source/PlaybackSession.cpp | 5 +- .../wifi-display/source/PlaybackSession.h | 5 ++ .../wifi-display/source/WifiDisplaySource.cpp | 6 +- .../wifi-display/source/WifiDisplaySource.h | 5 ++ services/audioflinger/AudioFlinger.cpp | 6 +- services/audioflinger/AudioFlinger.h | 2 + services/audioflinger/ServiceUtilities.cpp | 84 ++++++++++++++++++---- services/audioflinger/ServiceUtilities.h | 3 +- .../audiopolicy/service/AudioPolicyEffects.cpp | 6 +- 34 files changed, 209 insertions(+), 75 deletions(-) diff --git a/cmds/stagefright/audioloop.cpp b/cmds/stagefright/audioloop.cpp index 7b0de24..6e9e6ec 100644 --- a/cmds/stagefright/audioloop.cpp +++ b/cmds/stagefright/audioloop.cpp @@ -18,6 +18,8 @@ #include #include +#include + #include #include #include @@ -34,7 +36,7 @@ using namespace android; static void usage(const char* name) { - fprintf(stderr, "Usage: %s [-d duration] [-m] [-w] []\n", name); + fprintf(stderr, "Usage: %s [-d du.ration] [-m] [-w] []\n", name); fprintf(stderr, "Encodes either a sine wave or microphone input to AMR format\n"); fprintf(stderr, " -d duration in seconds, default 5 seconds\n"); fprintf(stderr, " -m use microphone for input, default sine source\n"); @@ -85,6 +87,7 @@ int main(int argc, char* argv[]) // talk into the appropriate microphone for the duration source = new AudioSource( AUDIO_SOURCE_MIC, + String16(), kSampleRate, channels); } else { diff --git a/include/media/AudioEffect.h b/include/media/AudioEffect.h index 583695d..61da4f2 100644 --- a/include/media/AudioEffect.h +++ b/include/media/AudioEffect.h @@ -201,8 +201,12 @@ public: */ /* Simple Constructor. + * + * Parameters: + * + * opPackageName: The package name used for app op checks. */ - AudioEffect(); + AudioEffect(const String16& opPackageName); /* Constructor. @@ -211,6 +215,7 @@ public: * * type: type of effect created: can be null if uuid is specified. This corresponds to * the OpenSL ES interface implemented by this effect. + * opPackageName: The package name used for app op checks. * uuid: Uuid of effect created: can be null if type is specified. This uuid corresponds to * a particular implementation of an effect type. * priority: requested priority for effect control: the priority level corresponds to the @@ -227,6 +232,7 @@ public: */ AudioEffect(const effect_uuid_t *type, + const String16& opPackageName, const effect_uuid_t *uuid = NULL, int32_t priority = 0, effect_callback_t cbf = NULL, @@ -239,6 +245,7 @@ public: * Same as above but with type and uuid specified by character strings */ AudioEffect(const char *typeStr, + const String16& opPackageName, const char *uuidStr = NULL, int32_t priority = 0, effect_callback_t cbf = NULL, @@ -406,7 +413,9 @@ protected: void* mUserData; // client context for callback function effect_descriptor_t mDescriptor; // effect descriptor int32_t mId; // system wide unique effect engine instance ID - Mutex mLock; // Mutex for mEnabled access + Mutex mLock; // Mutex for mEnabled access + + String16 mOpPackageName; // The package name used for app op checks. // IEffectClient virtual void controlStatusChanged(bool controlGranted); diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h index c24a28d..b743c11 100644 --- a/include/media/AudioRecord.h +++ b/include/media/AudioRecord.h @@ -129,8 +129,12 @@ public: /* Constructs an uninitialized AudioRecord. No connection with * AudioFlinger takes place. Use set() after this. + * + * Parameters: + * + * opPackageName: The package name used for app ops. */ - AudioRecord(); + AudioRecord(const String16& opPackageName); /* Creates an AudioRecord object and registers it with AudioFlinger. * Once created, the track needs to be started before it can be used. @@ -143,6 +147,7 @@ public: * format: Audio format (e.g AUDIO_FORMAT_PCM_16_BIT for signed * 16 bits per sample). * channelMask: Channel mask, such that audio_is_input_channel(channelMask) is true. + * opPackageName: The package name used for app ops. * frameCount: Minimum size of track PCM buffer in frames. This defines the * application's contribution to the * latency of the track. The actual size selected by the AudioRecord could @@ -165,6 +170,7 @@ public: uint32_t sampleRate, audio_format_t format, audio_channel_mask_t channelMask, + const String16& opPackageName, size_t frameCount = 0, callback_t cbf = NULL, void* user = NULL, @@ -483,7 +489,7 @@ private: // caller must hold lock on mLock for all _l methods - status_t openRecord_l(size_t epoch); + status_t openRecord_l(size_t epoch, const String16& opPackageName); // FIXME enum is faster than strcmp() for parameter 'from' status_t restoreRecord_l(const char *from); @@ -520,6 +526,8 @@ private: status_t mStatus; + String16 mOpPackageName; // The package name used for app ops. + size_t mFrameCount; // corresponds to current IAudioRecord, value is // reported back by AudioFlinger to the client size_t mReqFrameCount; // frame count to request the first or next time diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h index f927a80..046345c 100644 --- a/include/media/IAudioFlinger.h +++ b/include/media/IAudioFlinger.h @@ -85,6 +85,7 @@ public: uint32_t sampleRate, audio_format_t format, audio_channel_mask_t channelMask, + const String16& callingPackage, size_t *pFrameCount, track_flags_t *flags, pid_t tid, // -1 means unused, otherwise must be valid non-0 @@ -198,6 +199,7 @@ public: // AudioFlinger doesn't take over handle reference from client audio_io_handle_t output, int sessionId, + const String16& callingPackage, status_t *status, int *id, int *enabled) = 0; diff --git a/include/media/IMediaPlayerService.h b/include/media/IMediaPlayerService.h index 49a3d61..a316ce2 100644 --- a/include/media/IMediaPlayerService.h +++ b/include/media/IMediaPlayerService.h @@ -47,7 +47,7 @@ class IMediaPlayerService: public IInterface public: DECLARE_META_INTERFACE(MediaPlayerService); - virtual sp createMediaRecorder() = 0; + virtual sp createMediaRecorder(const String16 &opPackageName) = 0; virtual sp createMetadataRetriever() = 0; virtual sp create(const sp& client, int audioSessionId = 0) = 0; @@ -65,8 +65,8 @@ public: // display client when display connection, disconnection or errors occur. // The assumption is that at most one remote display will be connected to the // provided interface at a time. - virtual sp listenForRemoteDisplay(const sp& client, - const String8& iface) = 0; + virtual sp listenForRemoteDisplay(const String16 &opPackageName, + const sp& client, const String8& iface) = 0; // codecs and audio devices usage tracking for the battery app enum BatteryDataBits { diff --git a/include/media/MediaRecorderBase.h b/include/media/MediaRecorderBase.h index f55063e..f9feede 100644 --- a/include/media/MediaRecorderBase.h +++ b/include/media/MediaRecorderBase.h @@ -29,7 +29,8 @@ class Surface; class IGraphicBufferProducer; struct MediaRecorderBase { - MediaRecorderBase() {} + MediaRecorderBase(const String16 &opPackageName) + : mOpPackageName(opPackageName) {} virtual ~MediaRecorderBase() {} virtual status_t init() = 0; @@ -57,6 +58,10 @@ struct MediaRecorderBase { virtual status_t dump(int fd, const Vector& args) const = 0; virtual sp querySurfaceMediaSource() const = 0; + +protected: + String16 mOpPackageName; + private: MediaRecorderBase(const MediaRecorderBase &); MediaRecorderBase &operator=(const MediaRecorderBase &); diff --git a/include/media/Visualizer.h b/include/media/Visualizer.h index 6167dd6..b92f816 100644 --- a/include/media/Visualizer.h +++ b/include/media/Visualizer.h @@ -65,7 +65,8 @@ public: /* Constructor. * See AudioEffect constructor for details on parameters. */ - Visualizer(int32_t priority = 0, + Visualizer(const String16& opPackageName, + int32_t priority = 0, effect_callback_t cbf = NULL, void* user = NULL, int sessionId = 0); diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h index 74a6469..8e40c5d 100644 --- a/include/media/mediarecorder.h +++ b/include/media/mediarecorder.h @@ -209,7 +209,7 @@ class MediaRecorder : public BnMediaRecorderClient, public virtual IMediaDeathNotifier { public: - MediaRecorder(); + MediaRecorder(const String16& opPackageName); ~MediaRecorder(); void died(); diff --git a/include/media/stagefright/AudioSource.h b/include/media/stagefright/AudioSource.h index 4c9aaad..50cf371 100644 --- a/include/media/stagefright/AudioSource.h +++ b/include/media/stagefright/AudioSource.h @@ -35,6 +35,7 @@ struct AudioSource : public MediaSource, public MediaBufferObserver { // _not_ a bitmask of audio_channels_t constants. AudioSource( audio_source_t inputSource, + const String16 &opPackageName, uint32_t sampleRate, uint32_t channels = 1); diff --git a/media/libmedia/AudioEffect.cpp b/media/libmedia/AudioEffect.cpp index 7d8222f..bbeb854 100644 --- a/media/libmedia/AudioEffect.cpp +++ b/media/libmedia/AudioEffect.cpp @@ -35,13 +35,14 @@ namespace android { // --------------------------------------------------------------------------- -AudioEffect::AudioEffect() - : mStatus(NO_INIT) +AudioEffect::AudioEffect(const String16& opPackageName) + : mStatus(NO_INIT), mOpPackageName(opPackageName) { } AudioEffect::AudioEffect(const effect_uuid_t *type, + const String16& opPackageName, const effect_uuid_t *uuid, int32_t priority, effect_callback_t cbf, @@ -49,12 +50,13 @@ AudioEffect::AudioEffect(const effect_uuid_t *type, int sessionId, audio_io_handle_t io ) - : mStatus(NO_INIT) + : mStatus(NO_INIT), mOpPackageName(opPackageName) { mStatus = set(type, uuid, priority, cbf, user, sessionId, io); } AudioEffect::AudioEffect(const char *typeStr, + const String16& opPackageName, const char *uuidStr, int32_t priority, effect_callback_t cbf, @@ -62,7 +64,7 @@ AudioEffect::AudioEffect(const char *typeStr, int sessionId, audio_io_handle_t io ) - : mStatus(NO_INIT) + : mStatus(NO_INIT), mOpPackageName(opPackageName) { effect_uuid_t type; effect_uuid_t *pType = NULL; @@ -128,7 +130,7 @@ status_t AudioEffect::set(const effect_uuid_t *type, mIEffectClient = new EffectClient(this); iEffect = audioFlinger->createEffect((effect_descriptor_t *)&mDescriptor, - mIEffectClient, priority, io, mSessionId, &mStatus, &mId, &enabled); + mIEffectClient, priority, io, mSessionId, mOpPackageName, &mStatus, &mId, &enabled); if (iEffect == 0 || (mStatus != NO_ERROR && mStatus != ALREADY_EXISTS)) { ALOGE("set(): AudioFlinger could not create effect, status: %d", mStatus); diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index 9f5c4c5..9a61977 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -65,8 +65,8 @@ status_t AudioRecord::getMinFrameCount( // --------------------------------------------------------------------------- -AudioRecord::AudioRecord() - : mStatus(NO_INIT), mSessionId(AUDIO_SESSION_ALLOCATE), +AudioRecord::AudioRecord(const String16 &opPackageName) + : mStatus(NO_INIT), mOpPackageName(opPackageName), mSessionId(AUDIO_SESSION_ALLOCATE), mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT), mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE) { @@ -77,6 +77,7 @@ AudioRecord::AudioRecord( uint32_t sampleRate, audio_format_t format, audio_channel_mask_t channelMask, + const String16& opPackageName, size_t frameCount, callback_t cbf, void* user, @@ -85,7 +86,9 @@ AudioRecord::AudioRecord( transfer_type transferType, audio_input_flags_t flags, const audio_attributes_t* pAttributes) - : mStatus(NO_INIT), mSessionId(AUDIO_SESSION_ALLOCATE), + : mStatus(NO_INIT), + mOpPackageName(opPackageName), + mSessionId(AUDIO_SESSION_ALLOCATE), mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT), mProxy(NULL), @@ -136,9 +139,9 @@ status_t AudioRecord::set( const audio_attributes_t* pAttributes) { ALOGV("set(): inputSource %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, " - "notificationFrames %u, sessionId %d, transferType %d, flags %#x", + "notificationFrames %u, sessionId %d, transferType %d, flags %#x, opPackageName %s", inputSource, sampleRate, format, channelMask, frameCount, notificationFrames, - sessionId, transferType, flags); + sessionId, transferType, flags, String8(mOpPackageName).string()); switch (transferType) { case TRANSFER_DEFAULT: @@ -235,7 +238,7 @@ status_t AudioRecord::set( } // create the IAudioRecord - status_t status = openRecord_l(0 /*epoch*/); + status_t status = openRecord_l(0 /*epoch*/, mOpPackageName); if (status != NO_ERROR) { if (mAudioRecordThread != 0) { @@ -435,7 +438,7 @@ audio_port_handle_t AudioRecord::getInputDevice() { // ------------------------------------------------------------------------- // must be called with mLock held -status_t AudioRecord::openRecord_l(size_t epoch) +status_t AudioRecord::openRecord_l(size_t epoch, const String16& opPackageName) { const sp& audioFlinger = AudioSystem::get_audio_flinger(); if (audioFlinger == 0) { @@ -502,8 +505,10 @@ status_t AudioRecord::openRecord_l(size_t epoch) sp iMem; // for cblk sp bufferMem; sp record = audioFlinger->openRecord(input, - mSampleRate, mFormat, + mSampleRate, + mFormat, mChannelMask, + opPackageName, &temp, &trackFlags, tid, @@ -1032,7 +1037,7 @@ status_t AudioRecord::restoreRecord_l(const char *from) // It will also delete the strong references on previous IAudioRecord and IMemory size_t position = mProxy->getPosition(); mNewPosition = position + mUpdatePeriod; - status_t result = openRecord_l(position); + status_t result = openRecord_l(position, mOpPackageName); if (result == NO_ERROR) { if (mActive) { // callback thread or sync event hasn't changed diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp index 38055f9..034a3d9 100644 --- a/media/libmedia/IAudioFlinger.cpp +++ b/media/libmedia/IAudioFlinger.cpp @@ -174,6 +174,7 @@ public: uint32_t sampleRate, audio_format_t format, audio_channel_mask_t channelMask, + const String16& opPackageName, size_t *pFrameCount, track_flags_t *flags, pid_t tid, @@ -190,6 +191,7 @@ public: data.writeInt32(sampleRate); data.writeInt32(format); data.writeInt32(channelMask); + data.writeString16(opPackageName) size_t frameCount = pFrameCount != NULL ? *pFrameCount : 0; data.writeInt64(frameCount); track_flags_t lFlags = flags != NULL ? *flags : (track_flags_t) TRACK_DEFAULT; @@ -702,6 +704,7 @@ public: int32_t priority, audio_io_handle_t output, int sessionId, + const String16& opPackageName, status_t *status, int *id, int *enabled) @@ -722,6 +725,7 @@ public: data.writeInt32(priority); data.writeInt32((int32_t) output); data.writeInt32(sessionId); + data.writeString16(opPackageName); status_t lStatus = remote()->transact(CREATE_EFFECT, data, &reply); if (lStatus != NO_ERROR) { @@ -950,6 +954,7 @@ status_t BnAudioFlinger::onTransact( uint32_t sampleRate = data.readInt32(); audio_format_t format = (audio_format_t) data.readInt32(); audio_channel_mask_t channelMask = data.readInt32(); + const String16& opPackageName = data.readString16(); size_t frameCount = data.readInt64(); track_flags_t flags = (track_flags_t) data.readInt32(); pid_t tid = (pid_t) data.readInt32(); @@ -959,9 +964,8 @@ status_t BnAudioFlinger::onTransact( sp buffers; status_t status; sp record = openRecord(input, - sampleRate, format, channelMask, &frameCount, &flags, tid, &sessionId, - ¬ificationFrames, - cblk, buffers, &status); + sampleRate, format, channelMask, opPackageName, &frameCount, &flags, tid, + &sessionId, ¬ificationFrames, cblk, buffers, &status); LOG_ALWAYS_FATAL_IF((record != 0) != (status == NO_ERROR)); reply->writeInt64(frameCount); reply->writeInt32(flags); @@ -1247,12 +1251,13 @@ status_t BnAudioFlinger::onTransact( int32_t priority = data.readInt32(); audio_io_handle_t output = (audio_io_handle_t) data.readInt32(); int sessionId = data.readInt32(); + const String16 opPackageName = data.readString16(); status_t status; int id; int enabled; sp effect = createEffect(&desc, client, priority, output, sessionId, - &status, &id, &enabled); + opPackageName, &status, &id, &enabled); reply->writeInt32(status); reply->writeInt32(id); reply->writeInt32(enabled); diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp index aa7b2e1..05f8670 100644 --- a/media/libmedia/IMediaPlayerService.cpp +++ b/media/libmedia/IMediaPlayerService.cpp @@ -78,10 +78,11 @@ public: return interface_cast(reply.readStrongBinder()); } - virtual sp createMediaRecorder() + virtual sp createMediaRecorder(const String16 &opPackageName) { Parcel data, reply; data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); + data.writeString16(opPackageName); remote()->transact(CREATE_MEDIA_RECORDER, data, &reply); return interface_cast(reply.readStrongBinder()); } @@ -128,11 +129,12 @@ public: return remote()->transact(PULL_BATTERY_DATA, data, reply); } - virtual sp listenForRemoteDisplay(const sp& client, - const String8& iface) + virtual sp listenForRemoteDisplay(const String16 &opPackageName, + const sp& client, const String8& iface) { Parcel data, reply; data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); + data.writeString16(opPackageName); data.writeStrongBinder(IInterface::asBinder(client)); data.writeString8(iface); remote()->transact(LISTEN_FOR_REMOTE_DISPLAY, data, &reply); @@ -166,7 +168,8 @@ status_t BnMediaPlayerService::onTransact( } break; case CREATE_MEDIA_RECORDER: { CHECK_INTERFACE(IMediaPlayerService, data, reply); - sp recorder = createMediaRecorder(); + const String16 opPackageName = data.readString16(); + sp recorder = createMediaRecorder(opPackageName); reply->writeStrongBinder(IInterface::asBinder(recorder)); return NO_ERROR; } break; @@ -214,10 +217,11 @@ status_t BnMediaPlayerService::onTransact( } break; case LISTEN_FOR_REMOTE_DISPLAY: { CHECK_INTERFACE(IMediaPlayerService, data, reply); + const String16 opPackageName = data.readString16(); sp client( interface_cast(data.readStrongBinder())); String8 iface(data.readString8()); - sp display(listenForRemoteDisplay(client, iface)); + sp display(listenForRemoteDisplay(opPackageName, client, iface)); reply->writeStrongBinder(IInterface::asBinder(display)); return NO_ERROR; } break; diff --git a/media/libmedia/Visualizer.cpp b/media/libmedia/Visualizer.cpp index 9d69b6a..dc46038 100644 --- a/media/libmedia/Visualizer.cpp +++ b/media/libmedia/Visualizer.cpp @@ -34,11 +34,12 @@ namespace android { // --------------------------------------------------------------------------- -Visualizer::Visualizer (int32_t priority, +Visualizer::Visualizer (const String16& opPackageName, + int32_t priority, effect_callback_t cbf, void* user, int sessionId) - : AudioEffect(SL_IID_VISUALIZATION, NULL, priority, cbf, user, sessionId), + : AudioEffect(SL_IID_VISUALIZATION, opPackageName, NULL, priority, cbf, user, sessionId), mCaptureRate(CAPTURE_RATE_DEF), mCaptureSize(CAPTURE_SIZE_DEF), mSampleRate(44100000), diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp index a2d6e53..9470936 100644 --- a/media/libmedia/mediarecorder.cpp +++ b/media/libmedia/mediarecorder.cpp @@ -594,13 +594,13 @@ status_t MediaRecorder::release() return INVALID_OPERATION; } -MediaRecorder::MediaRecorder() : mSurfaceMediaSource(NULL) +MediaRecorder::MediaRecorder(const String16& opPackageName) : mSurfaceMediaSource(NULL) { ALOGV("constructor"); const sp& service(getMediaPlayerService()); if (service != NULL) { - mMediaRecorder = service->createMediaRecorder(); + mMediaRecorder = service->createMediaRecorder(opPackageName); } if (mMediaRecorder != NULL) { mCurrentState = MEDIA_RECORDER_IDLE; diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index 3bc763f..9567eff 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -307,10 +307,10 @@ MediaPlayerService::~MediaPlayerService() ALOGV("MediaPlayerService destroyed"); } -sp MediaPlayerService::createMediaRecorder() +sp MediaPlayerService::createMediaRecorder(const String16 &opPackageName) { pid_t pid = IPCThreadState::self()->getCallingPid(); - sp recorder = new MediaRecorderClient(this, pid); + sp recorder = new MediaRecorderClient(this, pid, opPackageName); wp w = recorder; Mutex::Autolock lock(mLock); mMediaRecorderClients.add(w); @@ -381,12 +381,13 @@ sp MediaPlayerService::makeHDCP(bool createEncryptionModule) { } sp MediaPlayerService::listenForRemoteDisplay( + const String16 &opPackageName, const sp& client, const String8& iface) { if (!checkPermission("android.permission.CONTROL_WIFI_DISPLAY")) { return NULL; } - return new RemoteDisplay(client, iface.string()); + return new RemoteDisplay(opPackageName, client, iface.string()); } status_t MediaPlayerService::AudioOutput::dump(int fd, const Vector& args) const diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h index 6ddfe14..1a3ce92 100644 --- a/media/libmediaplayerservice/MediaPlayerService.h +++ b/media/libmediaplayerservice/MediaPlayerService.h @@ -188,7 +188,7 @@ public: static void instantiate(); // IMediaPlayerService interface - virtual sp createMediaRecorder(); + virtual sp createMediaRecorder(const String16 &opPackageName); void removeMediaRecorderClient(wp client); virtual sp createMetadataRetriever(); @@ -200,8 +200,8 @@ public: virtual sp makeDrm(); virtual sp makeHDCP(bool createEncryptionModule); - virtual sp listenForRemoteDisplay(const sp& client, - const String8& iface); + virtual sp listenForRemoteDisplay(const String16 &opPackageName, + const sp& client, const String8& iface); virtual status_t dump(int fd, const Vector& args); void removeClient(wp client); diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp index 319ebb0..40e9d1c 100644 --- a/media/libmediaplayerservice/MediaRecorderClient.cpp +++ b/media/libmediaplayerservice/MediaRecorderClient.cpp @@ -290,11 +290,12 @@ status_t MediaRecorderClient::release() return NO_ERROR; } -MediaRecorderClient::MediaRecorderClient(const sp& service, pid_t pid) +MediaRecorderClient::MediaRecorderClient(const sp& service, pid_t pid, + const String16& opPackageName) { ALOGV("Client constructor"); mPid = pid; - mRecorder = new StagefrightRecorder; + mRecorder = new StagefrightRecorder(opPackageName); mMediaPlayerService = service; } diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h index b45344b..e03ec3f 100644 --- a/media/libmediaplayerservice/MediaRecorderClient.h +++ b/media/libmediaplayerservice/MediaRecorderClient.h @@ -62,7 +62,8 @@ private: MediaRecorderClient( const sp& service, - pid_t pid); + pid_t pid, + const String16& opPackageName); virtual ~MediaRecorderClient(); pid_t mPid; diff --git a/media/libmediaplayerservice/RemoteDisplay.cpp b/media/libmediaplayerservice/RemoteDisplay.cpp index eb959b4..0eb4b5d 100644 --- a/media/libmediaplayerservice/RemoteDisplay.cpp +++ b/media/libmediaplayerservice/RemoteDisplay.cpp @@ -26,13 +26,14 @@ namespace android { RemoteDisplay::RemoteDisplay( + const String16 &opPackageName, const sp &client, const char *iface) : mLooper(new ALooper), mNetSession(new ANetworkSession) { mLooper->setName("wfd_looper"); - mSource = new WifiDisplaySource(mNetSession, client); + mSource = new WifiDisplaySource(opPackageName, mNetSession, client); mLooper->registerHandler(mSource); mNetSession->start(); diff --git a/media/libmediaplayerservice/RemoteDisplay.h b/media/libmediaplayerservice/RemoteDisplay.h index 1a48981..d4573e9 100644 --- a/media/libmediaplayerservice/RemoteDisplay.h +++ b/media/libmediaplayerservice/RemoteDisplay.h @@ -33,6 +33,7 @@ struct WifiDisplaySource; struct RemoteDisplay : public BnRemoteDisplay { RemoteDisplay( + const String16 &opPackageName, const sp &client, const char *iface); diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index 8a0b060..aa19a25 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -69,8 +69,9 @@ static void addBatteryData(uint32_t params) { } -StagefrightRecorder::StagefrightRecorder() - : mWriter(NULL), +StagefrightRecorder::StagefrightRecorder(const String16 &opPackageName) + : MediaRecorderBase(opPackageName), + mWriter(NULL), mOutputFd(-1), mAudioSource(AUDIO_SOURCE_CNT), mVideoSource(VIDEO_SOURCE_LIST_END), @@ -905,6 +906,7 @@ sp StagefrightRecorder::createAudioSource() { sp audioSource = new AudioSource( mAudioSource, + mOpPackageName, mSampleRate, mAudioChannels); diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h index 8fa5bfa..1425f59 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.h +++ b/media/libmediaplayerservice/StagefrightRecorder.h @@ -40,7 +40,7 @@ class SurfaceMediaSource; struct ALooper; struct StagefrightRecorder : public MediaRecorderBase { - StagefrightRecorder(); + StagefrightRecorder(const String16 &opPackageName); virtual ~StagefrightRecorder(); virtual status_t init(); diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp index 804f131..e5a6a9b 100644 --- a/media/libstagefright/AudioSource.cpp +++ b/media/libstagefright/AudioSource.cpp @@ -50,7 +50,8 @@ static void AudioRecordCallbackFunction(int event, void *user, void *info) { } AudioSource::AudioSource( - audio_source_t inputSource, uint32_t sampleRate, uint32_t channelCount) + audio_source_t inputSource, const String16 &opPackageName, uint32_t sampleRate, + uint32_t channelCount) : mStarted(false), mSampleRate(sampleRate), mPrevSampleTimeUs(0), @@ -78,6 +79,7 @@ AudioSource::AudioSource( mRecord = new AudioRecord( inputSource, sampleRate, AUDIO_FORMAT_PCM_16_BIT, audio_channel_in_mask_from_count(channelCount), + opPackageName, (size_t) (bufCount * frameCount), AudioRecordCallbackFunction, this, diff --git a/media/libstagefright/tests/SurfaceMediaSource_test.cpp b/media/libstagefright/tests/SurfaceMediaSource_test.cpp index fd889f9..3860e9b 100644 --- a/media/libstagefright/tests/SurfaceMediaSource_test.cpp +++ b/media/libstagefright/tests/SurfaceMediaSource_test.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -466,7 +467,7 @@ void SurfaceMediaSourceGLTest::oneBufferPassGL(int num) { // Set up the MediaRecorder which runs in the same process as mediaserver sp SurfaceMediaSourceGLTest::setUpMediaRecorder(int fd, int videoSource, int outputFormat, int videoEncoder, int width, int height, int fps) { - sp mr = new MediaRecorder(); + sp mr = new MediaRecorder(String16()); mr->setVideoSource(videoSource); mr->setOutputFormat(outputFormat); mr->setVideoEncoder(videoEncoder); diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.cpp b/media/libstagefright/wifi-display/source/PlaybackSession.cpp index 5e2f0bf..ed5a404 100644 --- a/media/libstagefright/wifi-display/source/PlaybackSession.cpp +++ b/media/libstagefright/wifi-display/source/PlaybackSession.cpp @@ -345,12 +345,14 @@ bool WifiDisplaySource::PlaybackSession::Track::isSuspended() const { //////////////////////////////////////////////////////////////////////////////// WifiDisplaySource::PlaybackSession::PlaybackSession( + const String16 &opPackageName, const sp &netSession, const sp ¬ify, const in_addr &interfaceAddr, const sp &hdcp, const char *path) - : mNetSession(netSession), + : mOpPackageName(opPackageName), + mNetSession(netSession), mNotify(notify), mInterfaceAddr(interfaceAddr), mHDCP(hdcp), @@ -1069,6 +1071,7 @@ status_t WifiDisplaySource::PlaybackSession::addVideoSource( status_t WifiDisplaySource::PlaybackSession::addAudioSource(bool usePCMAudio) { sp audioSource = new AudioSource( AUDIO_SOURCE_REMOTE_SUBMIX, + mOpPackageName, 48000 /* sampleRate */, 2 /* channelCount */); diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.h b/media/libstagefright/wifi-display/source/PlaybackSession.h index 4cd1a75..f6673df 100644 --- a/media/libstagefright/wifi-display/source/PlaybackSession.h +++ b/media/libstagefright/wifi-display/source/PlaybackSession.h @@ -22,6 +22,8 @@ #include "VideoFormats.h" #include "WifiDisplaySource.h" +#include + namespace android { struct ABuffer; @@ -36,6 +38,7 @@ struct NuMediaExtractor; // display. struct WifiDisplaySource::PlaybackSession : public AHandler { PlaybackSession( + const String16 &opPackageName, const sp &netSession, const sp ¬ify, const struct in_addr &interfaceAddr, @@ -96,6 +99,8 @@ private: kWhatPullExtractorSample, }; + String16 mOpPackageName; + sp mNetSession; sp mNotify; in_addr mInterfaceAddr; diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp index 332fe16..e26165e 100644 --- a/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp +++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.cpp @@ -50,10 +50,12 @@ const int64_t WifiDisplaySource::kPlaybackSessionTimeoutUs; const AString WifiDisplaySource::sUserAgent = MakeUserAgent(); WifiDisplaySource::WifiDisplaySource( + const String16 &opPackageName, const sp &netSession, const sp &client, const char *path) - : mState(INITIALIZED), + : mOpPackageName(opPackageName), + mState(INITIALIZED), mNetSession(netSession), mClient(client), mSessionID(0), @@ -1245,7 +1247,7 @@ status_t WifiDisplaySource::onSetupRequest( sp playbackSession = new PlaybackSession( - mNetSession, notify, mInterfaceAddr, mHDCP, mMediaPath.c_str()); + mOpPackageName, mNetSession, notify, mInterfaceAddr, mHDCP, mMediaPath.c_str()); looper()->registerHandler(playbackSession); diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.h b/media/libstagefright/wifi-display/source/WifiDisplaySource.h index c417cf5..c25a675 100644 --- a/media/libstagefright/wifi-display/source/WifiDisplaySource.h +++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.h @@ -25,6 +25,8 @@ #include +#include + namespace android { struct AReplyToken; @@ -38,6 +40,7 @@ struct WifiDisplaySource : public AHandler { static const unsigned kWifiDisplayDefaultPort = 7236; WifiDisplaySource( + const String16 &opPackageName, const sp &netSession, const sp &client, const char *path = NULL); @@ -114,6 +117,8 @@ private: static const AString sUserAgent; + String16 mOpPackageName; + State mState; VideoFormats mSupportedSourceVideoFormats; sp mNetSession; diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 5002099..48f7514 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -1416,6 +1416,7 @@ sp AudioFlinger::openRecord( uint32_t sampleRate, audio_format_t format, audio_channel_mask_t channelMask, + const String16& opPackageName, size_t *frameCount, IAudioFlinger::track_flags_t *flags, pid_t tid, @@ -1435,7 +1436,7 @@ sp AudioFlinger::openRecord( buffers.clear(); // check calling permissions - if (!recordingAllowed()) { + if (!recordingAllowed(opPackageName)) { ALOGE("openRecord() permission denied: recording not allowed"); lStatus = PERMISSION_DENIED; goto Exit; @@ -2447,6 +2448,7 @@ sp AudioFlinger::createEffect( int32_t priority, audio_io_handle_t io, int sessionId, + const String16& opPackageName, status_t *status, int *id, int *enabled) @@ -2543,7 +2545,7 @@ sp AudioFlinger::createEffect( // check recording permission for visualizer if ((memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) && - !recordingAllowed()) { + !recordingAllowed(opPackageName)) { lStatus = PERMISSION_DENIED; goto Exit; } diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index e1ddcbc..3c4517f 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -120,6 +120,7 @@ public: uint32_t sampleRate, audio_format_t format, audio_channel_mask_t channelMask, + const String16& opPackageName, size_t *pFrameCount, IAudioFlinger::track_flags_t *flags, pid_t tid, @@ -216,6 +217,7 @@ public: int32_t priority, audio_io_handle_t io, int sessionId, + const String16& opPackageName, status_t *status /*non-NULL*/, int *id, int *enabled); diff --git a/services/audioflinger/ServiceUtilities.cpp b/services/audioflinger/ServiceUtilities.cpp index 8246fef..0a718fb 100644 --- a/services/audioflinger/ServiceUtilities.cpp +++ b/services/audioflinger/ServiceUtilities.cpp @@ -14,38 +14,97 @@ * limitations under the License. */ +#include #include #include #include #include "ServiceUtilities.h" +/* When performing permission checks we do not use permission cache for + * runtime permissions (protection level dangerous) as they may change at + * runtime. All other permissions (protection level normal and dangerous) + * can be cached as they never change. Of course all permission checked + * here are platform defined. + */ + namespace android { // Not valid until initialized by AudioFlinger constructor. It would have to be // re-initialized if the process containing AudioFlinger service forks (which it doesn't). pid_t getpid_cached; -bool recordingAllowed() { +bool recordingAllowed(const String16& opPackageName) { + // Note: We are getting the UID from the calling IPC thread state because all + // clients that perform recording create AudioRecord in their own processes + // and the system does not create AudioRecord objects on behalf of apps. This + // differs from playback where in some situations the system recreates AudioTrack + // instances associated with a client's MediaPlayer on behalf of this client. + // In the latter case we have to store the client UID and pass in along for + // security checks. + if (getpid_cached == IPCThreadState::self()->getCallingPid()) return true; static const String16 sRecordAudio("android.permission.RECORD_AUDIO"); - // don't use PermissionCache; this is not a system permission - bool ok = checkCallingPermission(sRecordAudio); - if (!ok) ALOGE("Request requires android.permission.RECORD_AUDIO"); - return ok; + + // IMPORTANT: Don't use PermissionCache - a runtime permission and may change. + const bool ok = checkCallingPermission(sRecordAudio); + if (!ok) { + ALOGE("Request requires android.permission.RECORD_AUDIO"); + return false; + } + + const uid_t uid = IPCThreadState::self()->getCallingUid(); + String16 checkedOpPackageName = opPackageName; + + // In some cases the calling code has no access to the package it runs under. + // For example, code using the wilhelm framework's OpenSL-ES APIs. In this + // case we will get the packages for the calling UID and pick the first one + // for attributing the app op. This will work correctly for runtime permissions + // as for legacy apps we will toggle the app op for all packages in the UID. + // The caveat is that the operation may be attributed to the wrong package and + // stats based on app ops may be slightly off. + if (checkedOpPackageName.size() <= 0) { + sp sm = defaultServiceManager(); + sp binder = sm->getService(String16("permission")); + if (binder == 0) { + ALOGE("Cannot get permission service"); + return false; + } + + sp permCtrl = interface_cast(binder); + Vector packages; + + permCtrl->getPackagesForUid(uid, packages); + + if (packages.isEmpty()) { + ALOGE("No packages for calling UID"); + return false; + } + checkedOpPackageName = packages[0]; + } + + AppOpsManager appOps; + if (appOps.noteOp(AppOpsManager::OP_RECORD_AUDIO, uid, opPackageName) + != AppOpsManager::MODE_ALLOWED) { + ALOGE("Request denied by app op OP_RECORD_AUDIO"); + return false; + } + + return true; } bool captureAudioOutputAllowed() { if (getpid_cached == IPCThreadState::self()->getCallingPid()) return true; static const String16 sCaptureAudioOutput("android.permission.CAPTURE_AUDIO_OUTPUT"); - // don't use PermissionCache; this is not a system permission - bool ok = checkCallingPermission(sCaptureAudioOutput); + // IMPORTANT: Use PermissionCache - not a runtime permission and may not change. + bool ok = PermissionCache::checkCallingPermission(sCaptureAudioOutput); if (!ok) ALOGE("Request requires android.permission.CAPTURE_AUDIO_OUTPUT"); return ok; } bool captureHotwordAllowed() { static const String16 sCaptureHotwordAllowed("android.permission.CAPTURE_AUDIO_HOTWORD"); - bool ok = checkCallingPermission(sCaptureHotwordAllowed); + // IMPORTANT: Use PermissionCache - not a runtime permission and may not change. + bool ok = PermissionCache::checkCallingPermission(sCaptureHotwordAllowed); if (!ok) ALOGE("android.permission.CAPTURE_AUDIO_HOTWORD"); return ok; } @@ -53,15 +112,16 @@ bool captureHotwordAllowed() { bool settingsAllowed() { if (getpid_cached == IPCThreadState::self()->getCallingPid()) return true; static const String16 sAudioSettings("android.permission.MODIFY_AUDIO_SETTINGS"); - // don't use PermissionCache; this is not a system permission - bool ok = checkCallingPermission(sAudioSettings); + // IMPORTANT: Use PermissionCache - not a runtime permission and may not change. + bool ok = PermissionCache::checkCallingPermission(sAudioSettings); if (!ok) ALOGE("Request requires android.permission.MODIFY_AUDIO_SETTINGS"); return ok; } bool modifyAudioRoutingAllowed() { static const String16 sModifyAudioRoutingAllowed("android.permission.MODIFY_AUDIO_ROUTING"); - bool ok = checkCallingPermission(sModifyAudioRoutingAllowed); + // IMPORTANT: Use PermissionCache - not a runtime permission and may not change. + bool ok = PermissionCache::checkCallingPermission(sModifyAudioRoutingAllowed); if (!ok) ALOGE("android.permission.MODIFY_AUDIO_ROUTING"); return ok; } @@ -69,7 +129,7 @@ bool modifyAudioRoutingAllowed() { bool dumpAllowed() { // don't optimize for same pid, since mediaserver never dumps itself static const String16 sDump("android.permission.DUMP"); - // OK to use PermissionCache; this is a system permission + // IMPORTANT: Use PermissionCache - not a runtime permission and may not change. bool ok = PermissionCache::checkCallingPermission(sDump); // convention is for caller to dump an error message to fd instead of logging here //if (!ok) ALOGE("Request requires android.permission.DUMP"); diff --git a/services/audioflinger/ServiceUtilities.h b/services/audioflinger/ServiceUtilities.h index df6f6f4..fba6dce 100644 --- a/services/audioflinger/ServiceUtilities.h +++ b/services/audioflinger/ServiceUtilities.h @@ -20,11 +20,10 @@ namespace android { extern pid_t getpid_cached; -bool recordingAllowed(); +bool recordingAllowed(const String16& opPackageName); bool captureAudioOutputAllowed(); bool captureHotwordAllowed(); bool settingsAllowed(); bool modifyAudioRoutingAllowed(); bool dumpAllowed(); - } diff --git a/services/audiopolicy/service/AudioPolicyEffects.cpp b/services/audiopolicy/service/AudioPolicyEffects.cpp index e6ace20..282ddeb 100644 --- a/services/audiopolicy/service/AudioPolicyEffects.cpp +++ b/services/audiopolicy/service/AudioPolicyEffects.cpp @@ -109,8 +109,8 @@ status_t AudioPolicyEffects::addInputEffects(audio_io_handle_t input, Vector effects = mInputSources.valueAt(index)->mEffects; for (size_t i = 0; i < effects.size(); i++) { EffectDesc *effect = effects[i]; - sp fx = new AudioEffect(NULL, &effect->mUuid, -1, 0, 0, - audioSession, input); + sp fx = new AudioEffect(NULL, String16("android"), &effect->mUuid, -1, 0, + 0, audioSession, input); status_t status = fx->initCheck(); if (status != NO_ERROR && status != ALREADY_EXISTS) { ALOGW("addInputEffects(): failed to create Fx %s on source %d", @@ -254,7 +254,7 @@ status_t AudioPolicyEffects::addOutputSessionEffects(audio_io_handle_t output, Vector effects = mOutputStreams.valueAt(index)->mEffects; for (size_t i = 0; i < effects.size(); i++) { EffectDesc *effect = effects[i]; - sp fx = new AudioEffect(NULL, &effect->mUuid, 0, 0, 0, + sp fx = new AudioEffect(NULL, String16("android"), &effect->mUuid, 0, 0, 0, audioSession, output); status_t status = fx->initCheck(); if (status != NO_ERROR && status != ALREADY_EXISTS) { -- cgit v1.1