Merge "Surface MicrophoneDirection API in MediaRecorder"
diff --git a/media/libaudioclient/AudioRecord.cpp b/media/libaudioclient/AudioRecord.cpp
index 8df1921..5851533 100644
--- a/media/libaudioclient/AudioRecord.cpp
+++ b/media/libaudioclient/AudioRecord.cpp
@@ -117,7 +117,9 @@
     : mActive(false), mStatus(NO_INIT), mOpPackageName(opPackageName),
       mSessionId(AUDIO_SESSION_ALLOCATE),
       mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT),
-      mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE), mRoutedDeviceId(AUDIO_PORT_HANDLE_NONE)
+      mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE), mRoutedDeviceId(AUDIO_PORT_HANDLE_NONE),
+      mSelectedMicDirection(MIC_DIRECTION_UNSPECIFIED),
+      mSelectedMicFieldDimension(MIC_FIELD_DIMENSION_DEFAULT)
 {
 }
 
@@ -137,7 +139,9 @@
         uid_t uid,
         pid_t pid,
         const audio_attributes_t* pAttributes,
-        audio_port_handle_t selectedDeviceId)
+        audio_port_handle_t selectedDeviceId,
+        audio_microphone_direction_t selectedMicDirection,
+        float microphoneFieldDimension)
     : mActive(false),
       mStatus(NO_INIT),
       mOpPackageName(opPackageName),
@@ -148,7 +152,8 @@
 {
     (void)set(inputSource, sampleRate, format, channelMask, frameCount, cbf, user,
             notificationFrames, false /*threadCanCallJava*/, sessionId, transferType, flags,
-            uid, pid, pAttributes, selectedDeviceId);
+            uid, pid, pAttributes, selectedDeviceId,
+            selectedMicDirection, microphoneFieldDimension);
 }
 
 AudioRecord::~AudioRecord()
@@ -197,7 +202,9 @@
         uid_t uid,
         pid_t pid,
         const audio_attributes_t* pAttributes,
-        audio_port_handle_t selectedDeviceId)
+        audio_port_handle_t selectedDeviceId,
+        audio_microphone_direction_t selectedMicDirection,
+        float microphoneFieldDimension)
 {
     status_t status = NO_ERROR;
     uint32_t channelCount;
@@ -213,6 +220,8 @@
           sessionId, transferType, flags, String8(mOpPackageName).string(), uid, pid);
 
     mSelectedDeviceId = selectedDeviceId;
+    mSelectedMicDirection = selectedMicDirection;
+    mSelectedMicFieldDimension = microphoneFieldDimension;
 
     switch (transferType) {
     case TRANSFER_DEFAULT:
@@ -400,6 +409,10 @@
         status = restoreRecord_l("start");
     }
 
+    // Call these directly because we are already holding the lock.
+    mAudioRecord->setMicrophoneDirection(mSelectedMicDirection);
+    mAudioRecord->setMicrophoneFieldDimension(mSelectedMicFieldDimension);
+
     if (status != NO_ERROR) {
         mActive = false;
         ALOGE("%s(%d): status %d", __func__, mPortId, status);
@@ -617,6 +630,8 @@
              mNotificationFramesAct, mNotificationFramesReq);
     result.appendFormat("  input(%d), latency(%u), selected device Id(%d), routed device Id(%d)\n",
                         mInput, mLatency, mSelectedDeviceId, mRoutedDeviceId);
+    result.appendFormat("  mic direction(%d) mic field dimension(%f)",
+                        mSelectedMicDirection, mSelectedMicFieldDimension);
     ::write(fd, result.string(), result.size());
     return NO_ERROR;
 }
@@ -1369,12 +1384,34 @@
 status_t AudioRecord::setMicrophoneDirection(audio_microphone_direction_t direction)
 {
     AutoMutex lock(mLock);
-    return mAudioRecord->setMicrophoneDirection(direction).transactionError();
+    if (mSelectedMicDirection == direction) {
+        // NOP
+        return OK;
+    }
+
+    mSelectedMicDirection = direction;
+    if (mAudioRecord == 0) {
+        // the internal AudioRecord hasn't be created yet, so just stash the attribute.
+        return OK;
+    } else {
+        return mAudioRecord->setMicrophoneDirection(direction).transactionError();
+    }
 }
 
 status_t AudioRecord::setMicrophoneFieldDimension(float zoom) {
     AutoMutex lock(mLock);
-    return mAudioRecord->setMicrophoneFieldDimension(zoom).transactionError();
+    if (mSelectedMicFieldDimension == zoom) {
+        // NOP
+        return OK;
+    }
+
+    mSelectedMicFieldDimension = zoom;
+    if (mAudioRecord == 0) {
+        // the internal AudioRecord hasn't be created yet, so just stash the attribute.
+        return OK;
+    } else {
+        return mAudioRecord->setMicrophoneFieldDimension(zoom).transactionError();
+    }
 }
 
 // =========================================================================
diff --git a/media/libaudioclient/include/media/AudioRecord.h b/media/libaudioclient/include/media/AudioRecord.h
index a9f8711..b4ddb69 100644
--- a/media/libaudioclient/include/media/AudioRecord.h
+++ b/media/libaudioclient/include/media/AudioRecord.h
@@ -189,7 +189,10 @@
                                     uid_t uid = AUDIO_UID_INVALID,
                                     pid_t pid = -1,
                                     const audio_attributes_t* pAttributes = NULL,
-                                    audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE);
+                                    audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE,
+                                    audio_microphone_direction_t
+                                        selectedMicDirection = MIC_DIRECTION_UNSPECIFIED,
+                                    float selectedMicFieldDimension = MIC_FIELD_DIMENSION_DEFAULT);
 
     /* Terminates the AudioRecord and unregisters it from AudioFlinger.
      * Also destroys all resources associated with the AudioRecord.
@@ -228,7 +231,10 @@
                             uid_t uid = AUDIO_UID_INVALID,
                             pid_t pid = -1,
                             const audio_attributes_t* pAttributes = NULL,
-                            audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE);
+                            audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE,
+                            audio_microphone_direction_t
+                                selectedMicDirection = MIC_DIRECTION_UNSPECIFIED,
+                            float selectedMicFieldDimension = MIC_FIELD_DIMENSION_DEFAULT);
 
     /* Result of constructing the AudioRecord. This must be checked for successful initialization
      * before using any AudioRecord API (except for set()), because using
@@ -716,6 +722,9 @@
                                               // activity and connected devices
     wp<AudioSystem::AudioDeviceCallback> mDeviceCallback;
 
+    audio_microphone_direction_t mSelectedMicDirection;
+    float mSelectedMicFieldDimension;
+
 private:
     class MediaMetrics {
       public:
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index 56ee18e..f283569 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -66,6 +66,8 @@
     ENABLE_AUDIO_DEVICE_CALLBACK,
     GET_ACTIVE_MICROPHONES,
     GET_PORT_ID,
+    SET_MICROPHONE_DIRECTION,
+    SET_MICROPHONE_FIELD_DIMENSION
 };
 
 class BpMediaRecorder: public BpInterface<IMediaRecorder>
@@ -407,6 +409,24 @@
         return status;
     }
 
+    status_t setMicrophoneDirection(audio_microphone_direction_t direction) {
+        ALOGV("setMicrophoneDirection(%d)", direction);
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        data.writeInt32(direction);
+        status_t status = remote()->transact(SET_MICROPHONE_DIRECTION, data, &reply);
+        return status == NO_ERROR ? (status_t)reply.readInt32() : status;
+    }
+
+    status_t setMicrophoneFieldDimension(float zoom) {
+        ALOGV("setMicrophoneFieldDimension(%f)", zoom);
+        Parcel data, reply;
+        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
+        data.writeFloat(zoom);
+        status_t status = remote()->transact(SET_MICROPHONE_FIELD_DIMENSION, data, &reply);
+        return status == NO_ERROR ? (status_t)reply.readInt32() : status;
+    }
+
     status_t getPortId(audio_port_handle_t *portId)
     {
         ALOGV("getPortId");
@@ -689,6 +709,23 @@
             }
             return NO_ERROR;
         }
+        case SET_MICROPHONE_DIRECTION: {
+            ALOGV("SET_MICROPHONE_DIRECTION");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            int direction = data.readInt32();
+            status_t status =
+                setMicrophoneDirection(static_cast<audio_microphone_direction_t>(direction));
+            reply->writeInt32(status);
+            return NO_ERROR;
+        }
+        case SET_MICROPHONE_FIELD_DIMENSION: {
+            ALOGV("SET_MICROPHONE_FIELD_DIMENSION");
+            CHECK_INTERFACE(IMediaRecorder, data, reply);
+            float zoom = data.readFloat();
+            status_t status = setMicrophoneFieldDimension(zoom);
+            reply->writeInt32(status);
+            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 e7c466d..0b09420 100644
--- a/media/libmedia/include/media/IMediaRecorder.h
+++ b/media/libmedia/include/media/IMediaRecorder.h
@@ -73,6 +73,8 @@
     virtual status_t enableAudioDeviceCallback(bool enabled) = 0;
     virtual status_t getActiveMicrophones(
                         std::vector<media::MicrophoneInfo>* activeMicrophones) = 0;
+    virtual status_t setMicrophoneDirection(audio_microphone_direction_t direction) = 0;
+    virtual status_t setMicrophoneFieldDimension(float zoom) = 0;
     virtual status_t getPortId(audio_port_handle_t *portId) = 0;
 };
 
diff --git a/media/libmedia/include/media/MediaRecorderBase.h b/media/libmedia/include/media/MediaRecorderBase.h
index e1c5d47..88282ac 100644
--- a/media/libmedia/include/media/MediaRecorderBase.h
+++ b/media/libmedia/include/media/MediaRecorderBase.h
@@ -72,6 +72,8 @@
     virtual status_t enableAudioDeviceCallback(bool enabled) = 0;
     virtual status_t getActiveMicrophones(
                         std::vector<media::MicrophoneInfo>* activeMicrophones) = 0;
+    virtual status_t setMicrophoneDirection(audio_microphone_direction_t direction) = 0;
+    virtual status_t setMicrophoneFieldDimension(float zoom) = 0;
     virtual status_t getPortId(audio_port_handle_t *portId) const = 0;
 
 
diff --git a/media/libmedia/include/media/mediarecorder.h b/media/libmedia/include/media/mediarecorder.h
index 33be559..8580437 100644
--- a/media/libmedia/include/media/mediarecorder.h
+++ b/media/libmedia/include/media/mediarecorder.h
@@ -264,6 +264,9 @@
     status_t    getRoutedDeviceId(audio_port_handle_t *deviceId);
     status_t    enableAudioDeviceCallback(bool enabled);
     status_t    getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
+    status_t    setMicrophoneDirection(audio_microphone_direction_t direction);
+    status_t    setMicrophoneFieldDimension(float zoom);
+
     status_t    getPortId(audio_port_handle_t *portId) const;
 
 private:
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index d07e703..6c59a29 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -842,6 +842,16 @@
     return mMediaRecorder->getActiveMicrophones(activeMicrophones);
 }
 
+status_t MediaRecorder::setMicrophoneDirection(audio_microphone_direction_t direction) {
+    ALOGV("setMicrophoneDirection(%d)", direction);
+    return mMediaRecorder->setMicrophoneDirection(direction);
+}
+
+status_t MediaRecorder::setMicrophoneFieldDimension(float zoom) {
+    ALOGV("setMicrophoneFieldDimension(%f)", zoom);
+    return mMediaRecorder->setMicrophoneFieldDimension(zoom);
+}
+
 status_t MediaRecorder::getPortId(audio_port_handle_t *portId) const
 {
     ALOGV("getPortId");
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index 3fa8e3f..d6628d9 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -538,6 +538,22 @@
     return NO_INIT;
 }
 
+status_t MediaRecorderClient::setMicrophoneDirection(audio_microphone_direction_t direction) {
+    ALOGV("setMicrophoneDirection(%d)", direction);
+    if (mRecorder != NULL) {
+        return mRecorder->setMicrophoneDirection(direction);
+    }
+    return NO_INIT;
+}
+
+status_t MediaRecorderClient::setMicrophoneFieldDimension(float zoom) {
+    ALOGV("setMicrophoneFieldDimension(%f)", zoom);
+    if (mRecorder != NULL) {
+        return mRecorder->setMicrophoneFieldDimension(zoom);
+    }
+    return NO_INIT;
+}
+
 status_t MediaRecorderClient::getPortId(audio_port_handle_t *portId) {
     ALOGV("getPortId");
     Mutex::Autolock lock(mLock);
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index 303cefc..8da718f 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -109,6 +109,8 @@
     virtual     status_t   enableAudioDeviceCallback(bool enabled);
     virtual     status_t   getActiveMicrophones(
                               std::vector<media::MicrophoneInfo>* activeMicrophones);
+    virtual     status_t   setMicrophoneDirection(audio_microphone_direction_t direction);
+    virtual     status_t   setMicrophoneFieldDimension(float zoom);
                 status_t   getPortId(audio_port_handle_t *portId) override;
 
 private:
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index d111313..3e3872d 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -118,7 +118,9 @@
       mVideoSource(VIDEO_SOURCE_LIST_END),
       mStarted(false),
       mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE),
-      mDeviceCallbackEnabled(false) {
+      mDeviceCallbackEnabled(false),
+      mSelectedMicDirection(MIC_DIRECTION_UNSPECIFIED),
+      mSelectedMicFieldDimension(MIC_FIELD_DIMENSION_NORMAL) {
 
     ALOGV("Constructor");
 
@@ -1090,7 +1092,9 @@
                 mSampleRate,
                 mClientUid,
                 mClientPid,
-                mSelectedDeviceId);
+                mSelectedDeviceId,
+                mSelectedMicDirection,
+                mSelectedMicFieldDimension);
 
     status_t err = audioSource->initCheck();
 
@@ -2269,6 +2273,24 @@
     return NO_INIT;
 }
 
+status_t StagefrightRecorder::setMicrophoneDirection(audio_microphone_direction_t direction) {
+    ALOGV("setMicrophoneDirection(%d)", direction);
+    mSelectedMicDirection = direction;
+    if (mAudioSourceNode != 0) {
+        return mAudioSourceNode->setMicrophoneDirection(direction);
+    }
+    return NO_INIT;
+}
+
+status_t StagefrightRecorder::setMicrophoneFieldDimension(float zoom) {
+    ALOGV("setMicrophoneFieldDimension(%f)", zoom);
+    mSelectedMicFieldDimension = zoom;
+    if (mAudioSourceNode != 0) {
+        return mAudioSourceNode->setMicrophoneFieldDimension(zoom);
+    }
+    return NO_INIT;
+}
+
 status_t StagefrightRecorder::getPortId(audio_port_handle_t *portId) const {
     if (mAudioSourceNode != 0) {
         return mAudioSourceNode->getPortId(portId);
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index a292e58..236b19e 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -77,6 +77,8 @@
     virtual void setAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback);
     virtual status_t enableAudioDeviceCallback(bool enabled);
     virtual status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
+    virtual status_t setMicrophoneDirection(audio_microphone_direction_t direction);
+    virtual status_t setMicrophoneFieldDimension(float zoom);
             status_t getPortId(audio_port_handle_t *portId) const override;
 
 private:
@@ -159,6 +161,9 @@
     bool mDeviceCallbackEnabled;
     wp<AudioSystem::AudioDeviceCallback> mAudioDeviceCallback;
 
+    audio_microphone_direction_t mSelectedMicDirection;
+    float mSelectedMicFieldDimension;
+
     static const int kMaxHighSpeedFps = 1000;
 
     status_t prepareInternal();
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index 5027303..5f86bd3 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -52,7 +52,9 @@
 AudioSource::AudioSource(
         audio_source_t inputSource, const String16 &opPackageName,
         uint32_t sampleRate, uint32_t channelCount, uint32_t outSampleRate,
-        uid_t uid, pid_t pid, audio_port_handle_t selectedDeviceId)
+        uid_t uid, pid_t pid, audio_port_handle_t selectedDeviceId,
+        audio_microphone_direction_t selectedMicDirection,
+        float selectedMicFieldDimension)
     : mStarted(false),
       mSampleRate(sampleRate),
       mOutSampleRate(outSampleRate > 0 ? outSampleRate : sampleRate),
@@ -103,7 +105,9 @@
                     uid,
                     pid,
                     NULL /*pAttributes*/,
-                    selectedDeviceId);
+                    selectedDeviceId,
+                    selectedMicDirection,
+                    selectedMicFieldDimension);
         mInitCheck = mRecord->initCheck();
         if (mInitCheck != OK) {
             mRecord.clear();
@@ -506,6 +510,22 @@
     return NO_INIT;
 }
 
+status_t AudioSource::setMicrophoneDirection(audio_microphone_direction_t direction) {
+    ALOGV("setMicrophoneDirection(%d)", direction);
+    if (mRecord != 0) {
+        return mRecord->setMicrophoneDirection(direction);
+    }
+    return NO_INIT;
+}
+
+status_t AudioSource::setMicrophoneFieldDimension(float zoom) {
+    ALOGV("setMicrophoneFieldDimension(%f)", zoom);
+    if (mRecord != 0) {
+        return mRecord->setMicrophoneFieldDimension(zoom);
+    }
+    return NO_INIT;
+}
+
 status_t AudioSource::getPortId(audio_port_handle_t *portId) const {
     if (mRecord != 0) {
         *portId = mRecord->getPortId();
diff --git a/media/libstagefright/include/media/stagefright/AudioSource.h b/media/libstagefright/include/media/stagefright/AudioSource.h
index b0e32d0..18e5f10 100644
--- a/media/libstagefright/include/media/stagefright/AudioSource.h
+++ b/media/libstagefright/include/media/stagefright/AudioSource.h
@@ -44,7 +44,9 @@
             uint32_t outSampleRate = 0,
             uid_t uid = -1,
             pid_t pid = -1,
-            audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE);
+            audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE,
+            audio_microphone_direction_t selectedMicDirection = MIC_DIRECTION_UNSPECIFIED,
+            float selectedMicFieldDimension = MIC_FIELD_DIMENSION_NORMAL);
 
     status_t initCheck() const;
 
@@ -68,6 +70,8 @@
     status_t removeAudioDeviceCallback(const sp<AudioSystem::AudioDeviceCallback>& callback);
 
     status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones);
+    status_t setMicrophoneDirection(audio_microphone_direction_t direction);
+    status_t setMicrophoneFieldDimension(float zoom);
 
     status_t getPortId(audio_port_handle_t *portId) const;
 
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 468676a..f4a31ed 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -7740,14 +7740,14 @@
 
 status_t AudioFlinger::RecordThread::setMicrophoneDirection(audio_microphone_direction_t direction)
 {
-    ALOGV("RecordThread::setMicrophoneDirection");
+    ALOGV("setMicrophoneDirection(%d)", direction);
     AutoMutex _l(mLock);
     return mInput->stream->setMicrophoneDirection(direction);
 }
 
 status_t AudioFlinger::RecordThread::setMicrophoneFieldDimension(float zoom)
 {
-    ALOGV("RecordThread::setMicrophoneFieldDimension");
+    ALOGV("setMicrophoneFieldDimension(%f)", zoom);
     AutoMutex _l(mLock);
     return mInput->stream->setMicrophoneFieldDimension(zoom);
 }