diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp index 26a320cb46..2432cacb6e 100644 --- a/media/libaudioclient/AudioRecord.cpp +++ b/media/libaudioclient/AudioRecord.cpp @@ -89,7 +89,8 @@ AudioRecord::AudioRecord( audio_input_flags_t flags, uid_t uid, pid_t pid, - const audio_attributes_t* pAttributes) + const audio_attributes_t* pAttributes, + audio_port_handle_t selectedDeviceId) : mActive(false), mStatus(NO_INIT), mOpPackageName(opPackageName), @@ -97,12 +98,11 @@ AudioRecord::AudioRecord( mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT), mProxy(NULL), - mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE), mPortId(AUDIO_PORT_HANDLE_NONE) { mStatus = set(inputSource, sampleRate, format, channelMask, frameCount, cbf, user, notificationFrames, false /*threadCanCallJava*/, sessionId, transferType, flags, - uid, pid, pAttributes); + uid, pid, pAttributes, selectedDeviceId); } AudioRecord::~AudioRecord() @@ -148,7 +148,8 @@ status_t AudioRecord::set( audio_input_flags_t flags, uid_t uid, pid_t pid, - const audio_attributes_t* pAttributes) + const audio_attributes_t* pAttributes, + audio_port_handle_t selectedDeviceId) { ALOGV("set(): inputSource %d, sampleRate %u, format %#x, channelMask %#x, frameCount %zu, " "notificationFrames %u, sessionId %d, transferType %d, flags %#x, opPackageName %s " @@ -156,6 +157,8 @@ status_t AudioRecord::set( inputSource, sampleRate, format, channelMask, frameCount, notificationFrames, sessionId, transferType, flags, String8(mOpPackageName).string(), uid, pid); + mSelectedDeviceId = selectedDeviceId; + switch (transferType) { case TRANSFER_DEFAULT: if (cbf == NULL || threadCanCallJava) { @@ -489,6 +492,7 @@ status_t AudioRecord::setInputDevice(audio_port_handle_t deviceId) { mAudioRecord->stop(); } android_atomic_or(CBLK_INVALID, &mCblk->mFlags); + mProxy->interrupt(); } } return NO_ERROR; diff --git a/media/libaudioclient/include/media/AudioRecord.h b/media/libaudioclient/include/media/AudioRecord.h index c6ad1b5b4d..51596a21a6 100644 --- a/media/libaudioclient/include/media/AudioRecord.h +++ b/media/libaudioclient/include/media/AudioRecord.h @@ -185,7 +185,8 @@ public: audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE, uid_t uid = AUDIO_UID_INVALID, pid_t pid = -1, - const audio_attributes_t* pAttributes = NULL); + const audio_attributes_t* pAttributes = NULL, + audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE); /* Terminates the AudioRecord and unregisters it from AudioFlinger. * Also destroys all resources associated with the AudioRecord. @@ -223,7 +224,8 @@ public: audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE, uid_t uid = AUDIO_UID_INVALID, pid_t pid = -1, - const audio_attributes_t* pAttributes = NULL); + const audio_attributes_t* pAttributes = NULL, + audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE); /* Result of constructing the AudioRecord. This must be checked for successful initialization * before using any AudioRecord API (except for set()), because using diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp index 5282352a82..72f5f585e5 100644 --- a/media/libmedia/IMediaRecorder.cpp +++ b/media/libmedia/IMediaRecorder.cpp @@ -61,6 +61,9 @@ enum { PAUSE, RESUME, GET_METRICS, + SET_INPUT_DEVICE, + GET_ROUTED_DEVICE_ID, + ENABLE_AUDIO_DEVICE_CALLBACK, }; @@ -337,6 +340,57 @@ public: remote()->transact(RELEASE, data, &reply); return reply.readInt32(); } + + status_t setInputDevice(audio_port_handle_t deviceId) + { + ALOGV("setInputDevice"); + Parcel data, reply; + data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); + data.writeInt32(deviceId); + + status_t status = remote()->transact(SET_INPUT_DEVICE, data, &reply); + if (status != OK) { + ALOGE("setInputDevice binder call failed: %d", status); + return status; + } + return reply.readInt32();; + } + + audio_port_handle_t getRoutedDeviceId(audio_port_handle_t *deviceId) + { + ALOGV("getRoutedDeviceId"); + Parcel data, reply; + data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); + + status_t status = remote()->transact(GET_ROUTED_DEVICE_ID, data, &reply); + if (status != OK) { + ALOGE("getRoutedDeviceid binder call failed: %d", status); + *deviceId = AUDIO_PORT_HANDLE_NONE; + return status; + } + + status = reply.readInt32(); + if (status != NO_ERROR) { + *deviceId = AUDIO_PORT_HANDLE_NONE; + } else { + *deviceId = reply.readInt32(); + } + return status; + } + + status_t enableAudioDeviceCallback(bool enabled) + { + ALOGV("enableAudioDeviceCallback"); + Parcel data, reply; + data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor()); + data.writeBool(enabled); + status_t status = remote()->transact(ENABLE_AUDIO_DEVICE_CALLBACK, data, &reply); + if (status != OK) { + ALOGE("enableAudioDeviceCallback binder call failed: %d, %d", enabled, status); + return status; + } + return reply.readInt32(); + } }; IMPLEMENT_META_INTERFACE(MediaRecorder, "android.media.IMediaRecorder"); @@ -543,6 +597,41 @@ status_t BnMediaRecorder::onTransact( } return NO_ERROR; } break; + case SET_INPUT_DEVICE: { + ALOGV("SET_INPUT_DEVICE"); + CHECK_INTERFACE(IMediaRecorder, data, reply); + audio_port_handle_t deviceId; + status_t status = data.readInt32(&deviceId); + if (status == NO_ERROR) { + reply->writeInt32(setInputDevice(deviceId)); + } else { + reply->writeInt32(BAD_VALUE); + } + return NO_ERROR; + } break; + case GET_ROUTED_DEVICE_ID: { + ALOGV("GET_ROUTED_DEVICE_ID"); + CHECK_INTERFACE(IMediaRecorder, data, reply); + audio_port_handle_t deviceId; + status_t status = getRoutedDeviceId(&deviceId); + reply->writeInt32(status); + if (status == NO_ERROR) { + reply->writeInt32(deviceId); + } + return NO_ERROR; + } break; + case ENABLE_AUDIO_DEVICE_CALLBACK: { + ALOGV("ENABLE_AUDIO_DEVICE_CALLBACK"); + CHECK_INTERFACE(IMediaRecorder, data, reply); + bool enabled; + status_t status = data.readBool(&enabled); + if (status == NO_ERROR) { + reply->writeInt32(enableAudioDeviceCallback(enabled)); + } else { + reply->writeInt32(BAD_VALUE); + } + return NO_ERROR; + } default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/media/libmedia/include/media/IMediaRecorder.h b/media/libmedia/include/media/IMediaRecorder.h index 9d0341a2b0..3cef3298c2 100644 --- a/media/libmedia/include/media/IMediaRecorder.h +++ b/media/libmedia/include/media/IMediaRecorder.h @@ -19,6 +19,7 @@ #define ANDROID_IMEDIARECORDER_H #include +#include namespace android { @@ -64,6 +65,10 @@ public: virtual status_t release() = 0; virtual status_t setInputSurface(const sp& surface) = 0; virtual sp querySurfaceMediaSource() = 0; + + virtual status_t setInputDevice(audio_port_handle_t deviceId) = 0; + virtual status_t getRoutedDeviceId(audio_port_handle_t *deviceId) = 0; + virtual status_t enableAudioDeviceCallback(bool enabled) = 0; }; // ---------------------------------------------------------------------------- diff --git a/media/libmedia/include/media/MediaRecorderBase.h b/media/libmedia/include/media/MediaRecorderBase.h index 40dd9f9a12..748153c414 100644 --- a/media/libmedia/include/media/MediaRecorderBase.h +++ b/media/libmedia/include/media/MediaRecorderBase.h @@ -18,6 +18,7 @@ #define MEDIA_RECORDER_BASE_H_ +#include #include #include @@ -62,6 +63,10 @@ struct MediaRecorderBase { virtual status_t dump(int fd, const Vector& args) const = 0; virtual status_t setInputSurface(const sp& surface) = 0; virtual sp querySurfaceMediaSource() const = 0; + virtual status_t setInputDevice(audio_port_handle_t deviceId) = 0; + virtual status_t getRoutedDeviceId(audio_port_handle_t* deviceId) = 0; + virtual void setAudioDeviceCallback(const sp& callback) = 0; + virtual status_t enableAudioDeviceCallback(bool enabled) = 0; protected: diff --git a/media/libmedia/include/media/mediarecorder.h b/media/libmedia/include/media/mediarecorder.h index b9717eaf83..5f2a6fe67b 100644 --- a/media/libmedia/include/media/mediarecorder.h +++ b/media/libmedia/include/media/mediarecorder.h @@ -141,6 +141,8 @@ enum media_recorder_event_type { MEDIA_RECORDER_TRACK_EVENT_ERROR = 100, MEDIA_RECORDER_TRACK_EVENT_INFO = 101, MEDIA_RECORDER_TRACK_EVENT_LIST_END = 1000, + + MEDIA_RECORDER_AUDIO_ROUTING_CHANGED = 10000, }; /* @@ -253,6 +255,9 @@ public: status_t setInputSurface(const sp& surface); sp querySurfaceMediaSourceFromMediaServer(); status_t getMetrics(Parcel *reply); + status_t setInputDevice(audio_port_handle_t deviceId); + status_t getRoutedDeviceId(audio_port_handle_t *deviceId); + status_t enableAudioDeviceCallback(bool enabled); private: void doCleanUp(); diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp index 4405930c9f..aab845b9a6 100644 --- a/media/libmedia/mediarecorder.cpp +++ b/media/libmedia/mediarecorder.cpp @@ -792,4 +792,41 @@ void MediaRecorder::died() notify(MEDIA_RECORDER_EVENT_ERROR, MEDIA_ERROR_SERVER_DIED, 0); } +status_t MediaRecorder::setInputDevice(audio_port_handle_t deviceId) +{ + ALOGV("setInputDevice"); + + if (mMediaRecorder == NULL) { + ALOGE("media recorder is not initialized yet"); + return INVALID_OPERATION; + } + return mMediaRecorder->setInputDevice(deviceId); +} + +status_t MediaRecorder::getRoutedDeviceId(audio_port_handle_t* deviceId) +{ + ALOGV("getRoutedDeviceId"); + + if (mMediaRecorder == NULL) { + ALOGE("media recorder is not initialized yet"); + return INVALID_OPERATION; + } + status_t status = mMediaRecorder->getRoutedDeviceId(deviceId); + if (status != NO_ERROR) { + *deviceId = AUDIO_PORT_HANDLE_NONE; + } + return status; +} + +status_t MediaRecorder::enableAudioDeviceCallback(bool enabled) +{ + ALOGV("enableAudioDeviceCallback"); + + if (mMediaRecorder == NULL) { + ALOGE("media recorder is not initialized yet"); + return INVALID_OPERATION; + } + return mMediaRecorder->enableAudioDeviceCallback(enabled); +} + } // namespace android diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp index a423feee49..dcd393b6e7 100644 --- a/media/libmediaplayerservice/MediaRecorderClient.cpp +++ b/media/libmediaplayerservice/MediaRecorderClient.cpp @@ -411,6 +411,25 @@ void MediaRecorderClient::ServiceDeathNotifier::unlinkToDeath() { } } +MediaRecorderClient::AudioDeviceUpdatedNotifier::AudioDeviceUpdatedNotifier( + const sp& listener) { + mListener = listener; +} + +MediaRecorderClient::AudioDeviceUpdatedNotifier::~AudioDeviceUpdatedNotifier() { +} + +void MediaRecorderClient::AudioDeviceUpdatedNotifier::onAudioDeviceUpdate( + audio_io_handle_t audioIo, + audio_port_handle_t deviceId) { + sp listener = mListener.promote(); + if (listener != NULL) { + listener->notify(MEDIA_RECORDER_AUDIO_ROUTING_CHANGED, audioIo, deviceId); + } else { + ALOGW("listener for process %d death is gone", MEDIA_RECORDER_AUDIO_ROUTING_CHANGED); + } +} + void MediaRecorderClient::clearDeathNotifiers_l() { if (mCameraDeathListener != nullptr) { mCameraDeathListener->unlinkToDeath(); @@ -459,6 +478,9 @@ status_t MediaRecorderClient::setListener(const sp& listen MediaPlayerService::MEDIACODEC_PROCESS_DEATH); omx->linkToDeath(mCodecDeathListener, 0); + mAudioDeviceUpdatedNotifier = new AudioDeviceUpdatedNotifier(listener); + mRecorder->setAudioDeviceCallback(mAudioDeviceUpdatedNotifier); + return OK; } @@ -479,4 +501,30 @@ status_t MediaRecorderClient::dump(int fd, const Vector& args) { return OK; } +status_t MediaRecorderClient::setInputDevice(audio_port_handle_t deviceId) { + ALOGV("setInputDevice(%d)", deviceId); + Mutex::Autolock lock(mLock); + if (mRecorder != NULL) { + return mRecorder->setInputDevice(deviceId); + } + return NO_INIT; +} + +status_t MediaRecorderClient::getRoutedDeviceId(audio_port_handle_t* deviceId) { + ALOGV("getRoutedDeviceId"); + Mutex::Autolock lock(mLock); + if (mRecorder != NULL) { + return mRecorder->getRoutedDeviceId(deviceId); + } + return NO_INIT; +} + +status_t MediaRecorderClient::enableAudioDeviceCallback(bool enabled) { + ALOGV("enableDeviceCallback: %d", enabled); + Mutex::Autolock lock(mLock); + if (mRecorder != NULL) { + return mRecorder->enableAudioDeviceCallback(enabled); + } + return NO_INIT; +} }; // namespace android diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h index 711db2c4d6..538b46192c 100644 --- a/media/libmediaplayerservice/MediaRecorderClient.h +++ b/media/libmediaplayerservice/MediaRecorderClient.h @@ -18,6 +18,7 @@ #ifndef ANDROID_MEDIARECORDERCLIENT_H #define ANDROID_MEDIARECORDERCLIENT_H +#include #include #include @@ -58,6 +59,18 @@ class MediaRecorderClient : public BnMediaRecorder wp mListener; }; + class AudioDeviceUpdatedNotifier: public AudioSystem::AudioDeviceCallback + { + public: + AudioDeviceUpdatedNotifier(const sp& listener); + virtual ~AudioDeviceUpdatedNotifier(); + virtual void onAudioDeviceUpdate( + audio_io_handle_t audioIo, + audio_port_handle_t deviceId); + private: + wp mListener; + }; + void clearDeathNotifiers_l(); public: @@ -91,6 +104,9 @@ public: virtual status_t dump(int fd, const Vector& args); virtual status_t setInputSurface(const sp& surface); virtual sp querySurfaceMediaSource(); + virtual status_t setInputDevice(audio_port_handle_t deviceId); + virtual status_t getRoutedDeviceId(audio_port_handle_t* deviceId); + virtual status_t enableAudioDeviceCallback(bool enabled); private: friend class MediaPlayerService; // for accessing private constructor @@ -103,6 +119,7 @@ private: sp mCameraDeathListener; sp mCodecDeathListener; + sp mAudioDeviceUpdatedNotifier; pid_t mPid; Mutex mLock; diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index 89354d6d09..77eaefeb86 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -103,7 +103,9 @@ StagefrightRecorder::StagefrightRecorder(const String16 &opPackageName) mOutputFd(-1), mAudioSource(AUDIO_SOURCE_CNT), mVideoSource(VIDEO_SOURCE_LIST_END), - mStarted(false) { + mStarted(false), + mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE), + mDeviceCallbackEnabled(false) { ALOGV("Constructor"); @@ -204,7 +206,7 @@ status_t StagefrightRecorder::init() { return OK; } -// The client side of mediaserver asks it to creat a SurfaceMediaSource +// The client side of mediaserver asks it to create a SurfaceMediaSource // and return a interface reference. The client side will use that // while encoding GL Frames sp StagefrightRecorder::querySurfaceMediaSource() const { @@ -1069,7 +1071,8 @@ sp StagefrightRecorder::createAudioSource() { mAudioChannels, mSampleRate, mClientUid, - mClientPid); + mClientPid, + mSelectedDeviceId); status_t err = audioSource->initCheck(); @@ -1120,6 +1123,10 @@ sp StagefrightRecorder::createAudioSource() { sp audioEncoder = MediaCodecSource::Create(mLooper, format, audioSource); + sp callback = mAudioDeviceCallback.promote(); + if (mDeviceCallbackEnabled && callback != 0) { + audioSource->addAudioDeviceCallback(callback); + } mAudioSourceNode = audioSource; if (audioEncoder == NULL) { @@ -2116,6 +2123,46 @@ status_t StagefrightRecorder::getMetrics(Parcel *reply) { return OK; } +status_t StagefrightRecorder::setInputDevice(audio_port_handle_t deviceId) { + ALOGV("setInputDevice"); + + if (mSelectedDeviceId != deviceId) { + mSelectedDeviceId = deviceId; + if (mAudioSourceNode != 0) { + return mAudioSourceNode->setInputDevice(deviceId); + } + } + return NO_ERROR; +} + +status_t StagefrightRecorder::getRoutedDeviceId(audio_port_handle_t* deviceId) { + ALOGV("getRoutedDeviceId"); + + if (mAudioSourceNode != 0) { + status_t status = mAudioSourceNode->getRoutedDeviceId(deviceId); + return status; + } + return NO_INIT; +} + +void StagefrightRecorder::setAudioDeviceCallback( + const sp& callback) { + mAudioDeviceCallback = callback; +} + +status_t StagefrightRecorder::enableAudioDeviceCallback(bool enabled) { + mDeviceCallbackEnabled = enabled; + sp callback = mAudioDeviceCallback.promote(); + if (mAudioSourceNode != 0 && callback != 0) { + if (enabled) { + return mAudioSourceNode->addAudioDeviceCallback(callback); + } else { + return mAudioSourceNode->removeAudioDeviceCallback(callback); + } + } + return NO_ERROR; +} + status_t StagefrightRecorder::dump( int fd, const Vector& args) const { ALOGV("dump"); diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h index 5111c8e861..ec7e8ed948 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.h +++ b/media/libmediaplayerservice/StagefrightRecorder.h @@ -72,6 +72,10 @@ struct StagefrightRecorder : public MediaRecorderBase { virtual status_t dump(int fd, const Vector &args) const; // Querying a SurfaceMediaSourcer virtual sp querySurfaceMediaSource() const; + virtual status_t setInputDevice(audio_port_handle_t deviceId); + virtual status_t getRoutedDeviceId(audio_port_handle_t* deviceId); + virtual void setAudioDeviceCallback(const sp& callback); + virtual status_t enableAudioDeviceCallback(bool enabled); private: mutable Mutex mLock; @@ -144,6 +148,10 @@ private: sp mGraphicBufferProducer; sp mLooper; + audio_port_handle_t mSelectedDeviceId; + bool mDeviceCallbackEnabled; + wp mAudioDeviceCallback; + static const int kMaxHighSpeedFps = 1000; status_t prepareInternal(); diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp index f2b1f10f22..b8da980a80 100644 --- a/media/libstagefright/AudioSource.cpp +++ b/media/libstagefright/AudioSource.cpp @@ -52,7 +52,7 @@ static void AudioRecordCallbackFunction(int event, void *user, void *info) { AudioSource::AudioSource( audio_source_t inputSource, const String16 &opPackageName, uint32_t sampleRate, uint32_t channelCount, uint32_t outSampleRate, - uid_t uid, pid_t pid) + uid_t uid, pid_t pid, audio_port_handle_t selectedDeviceId) : mStarted(false), mSampleRate(sampleRate), mOutSampleRate(outSampleRate > 0 ? outSampleRate : sampleRate), @@ -101,7 +101,9 @@ AudioSource::AudioSource( AudioRecord::TRANSFER_DEFAULT, AUDIO_INPUT_FLAG_NONE, uid, - pid); + pid, + NULL /*pAttributes*/, + selectedDeviceId); mInitCheck = mRecord->initCheck(); if (mInitCheck != OK) { mRecord.clear(); @@ -465,4 +467,35 @@ int16_t AudioSource::getMaxAmplitude() { return value; } +status_t AudioSource::setInputDevice(audio_port_handle_t deviceId) { + if (mRecord != 0) { + return mRecord->setInputDevice(deviceId); + } + return NO_INIT; +} + +status_t AudioSource::getRoutedDeviceId(audio_port_handle_t* deviceId) { + if (mRecord != 0) { + *deviceId = mRecord->getRoutedDeviceId(); + return NO_ERROR; + } + return NO_INIT; +} + +status_t AudioSource::addAudioDeviceCallback( + const sp& callback) { + if (mRecord != 0) { + return mRecord->addAudioDeviceCallback(callback); + } + return NO_INIT; +} + +status_t AudioSource::removeAudioDeviceCallback( + const sp& callback) { + if (mRecord != 0) { + return mRecord->removeAudioDeviceCallback(callback); + } + return NO_INIT; +} + } // namespace android diff --git a/media/libstagefright/include/media/stagefright/AudioSource.h b/media/libstagefright/include/media/stagefright/AudioSource.h index 4984f69f77..9414aab4d9 100644 --- a/media/libstagefright/include/media/stagefright/AudioSource.h +++ b/media/libstagefright/include/media/stagefright/AudioSource.h @@ -40,7 +40,8 @@ struct AudioSource : public MediaSource, public MediaBufferObserver { uint32_t channels, uint32_t outSampleRate = 0, uid_t uid = -1, - pid_t pid = -1); + pid_t pid = -1, + audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE); status_t initCheck() const; @@ -58,6 +59,11 @@ struct AudioSource : public MediaSource, public MediaBufferObserver { status_t dataCallback(const AudioRecord::Buffer& buffer); virtual void signalBufferReturned(MediaBuffer *buffer); + status_t setInputDevice(audio_port_handle_t deviceId); + status_t getRoutedDeviceId(audio_port_handle_t* deviceId); + status_t addAudioDeviceCallback(const sp& callback); + status_t removeAudioDeviceCallback(const sp& callback); + protected: virtual ~AudioSource();