Add AudioRouting interface in AudioRecorder.

Bug: 64038649
Test: Run cts in RoutingTest
      Switching input device when using MediaRecorder

Change-Id: I53f22974f8c3dacaef6044ea742e62951961c1fd
gugelfrei
jiabin 7 years ago
parent b6549b6297
commit fec2f93fae

@ -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;

@ -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

@ -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);
}

@ -19,6 +19,7 @@
#define ANDROID_IMEDIARECORDER_H
#include <binder/IInterface.h>
#include <system/audio.h>
namespace android {
@ -64,6 +65,10 @@ public:
virtual status_t release() = 0;
virtual status_t setInputSurface(const sp<PersistentSurface>& surface) = 0;
virtual sp<IGraphicBufferProducer> 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;
};
// ----------------------------------------------------------------------------

@ -18,6 +18,7 @@
#define MEDIA_RECORDER_BASE_H_
#include <media/AudioSystem.h>
#include <media/mediarecorder.h>
#include <system/audio.h>
@ -62,6 +63,10 @@ struct MediaRecorderBase {
virtual status_t dump(int fd, const Vector<String16>& args) const = 0;
virtual status_t setInputSurface(const sp<PersistentSurface>& surface) = 0;
virtual sp<IGraphicBufferProducer> 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<AudioSystem::AudioDeviceCallback>& callback) = 0;
virtual status_t enableAudioDeviceCallback(bool enabled) = 0;
protected:

@ -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<PersistentSurface>& surface);
sp<IGraphicBufferProducer> 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();

@ -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

@ -411,6 +411,25 @@ void MediaRecorderClient::ServiceDeathNotifier::unlinkToDeath() {
}
}
MediaRecorderClient::AudioDeviceUpdatedNotifier::AudioDeviceUpdatedNotifier(
const sp<IMediaRecorderClient>& listener) {
mListener = listener;
}
MediaRecorderClient::AudioDeviceUpdatedNotifier::~AudioDeviceUpdatedNotifier() {
}
void MediaRecorderClient::AudioDeviceUpdatedNotifier::onAudioDeviceUpdate(
audio_io_handle_t audioIo,
audio_port_handle_t deviceId) {
sp<IMediaRecorderClient> 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<IMediaRecorderClient>& 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<String16>& 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

@ -18,6 +18,7 @@
#ifndef ANDROID_MEDIARECORDERCLIENT_H
#define ANDROID_MEDIARECORDERCLIENT_H
#include <media/AudioSystem.h>
#include <media/IMediaRecorder.h>
#include <android/hardware/media/omx/1.0/IOmx.h>
@ -58,6 +59,18 @@ class MediaRecorderClient : public BnMediaRecorder
wp<IMediaRecorderClient> mListener;
};
class AudioDeviceUpdatedNotifier: public AudioSystem::AudioDeviceCallback
{
public:
AudioDeviceUpdatedNotifier(const sp<IMediaRecorderClient>& listener);
virtual ~AudioDeviceUpdatedNotifier();
virtual void onAudioDeviceUpdate(
audio_io_handle_t audioIo,
audio_port_handle_t deviceId);
private:
wp<IMediaRecorderClient> mListener;
};
void clearDeathNotifiers_l();
public:
@ -91,6 +104,9 @@ public:
virtual status_t dump(int fd, const Vector<String16>& args);
virtual status_t setInputSurface(const sp<PersistentSurface>& surface);
virtual sp<IGraphicBufferProducer> 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<ServiceDeathNotifier> mCameraDeathListener;
sp<ServiceDeathNotifier> mCodecDeathListener;
sp<AudioDeviceUpdatedNotifier> mAudioDeviceUpdatedNotifier;
pid_t mPid;
Mutex mLock;

@ -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<IGraphicBufferProducer> StagefrightRecorder::querySurfaceMediaSource() const {
@ -1069,7 +1071,8 @@ sp<MediaCodecSource> StagefrightRecorder::createAudioSource() {
mAudioChannels,
mSampleRate,
mClientUid,
mClientPid);
mClientPid,
mSelectedDeviceId);
status_t err = audioSource->initCheck();
@ -1120,6 +1123,10 @@ sp<MediaCodecSource> StagefrightRecorder::createAudioSource() {
sp<MediaCodecSource> audioEncoder =
MediaCodecSource::Create(mLooper, format, audioSource);
sp<AudioSystem::AudioDeviceCallback> 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<AudioSystem::AudioDeviceCallback>& callback) {
mAudioDeviceCallback = callback;
}
status_t StagefrightRecorder::enableAudioDeviceCallback(bool enabled) {
mDeviceCallbackEnabled = enabled;
sp<AudioSystem::AudioDeviceCallback> 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<String16>& args) const {
ALOGV("dump");

@ -72,6 +72,10 @@ struct StagefrightRecorder : public MediaRecorderBase {
virtual status_t dump(int fd, const Vector<String16> &args) const;
// Querying a SurfaceMediaSourcer
virtual sp<IGraphicBufferProducer> 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<AudioSystem::AudioDeviceCallback>& callback);
virtual status_t enableAudioDeviceCallback(bool enabled);
private:
mutable Mutex mLock;
@ -144,6 +148,10 @@ private:
sp<IGraphicBufferProducer> mGraphicBufferProducer;
sp<ALooper> mLooper;
audio_port_handle_t mSelectedDeviceId;
bool mDeviceCallbackEnabled;
wp<AudioSystem::AudioDeviceCallback> mAudioDeviceCallback;
static const int kMaxHighSpeedFps = 1000;
status_t prepareInternal();

@ -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<AudioSystem::AudioDeviceCallback>& callback) {
if (mRecord != 0) {
return mRecord->addAudioDeviceCallback(callback);
}
return NO_INIT;
}
status_t AudioSource::removeAudioDeviceCallback(
const sp<AudioSystem::AudioDeviceCallback>& callback) {
if (mRecord != 0) {
return mRecord->removeAudioDeviceCallback(callback);
}
return NO_INIT;
}
} // namespace android

@ -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<AudioSystem::AudioDeviceCallback>& callback);
status_t removeAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback);
protected:
virtual ~AudioSource();

Loading…
Cancel
Save