1/*
2 **
3 ** Copyright 2008, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 **     http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17
18//#define LOG_NDEBUG 0
19#define LOG_TAG "IMediaRecorder"
20
21#include <inttypes.h>
22#include <unistd.h>
23
24#include <utils/Log.h>
25#include <binder/Parcel.h>
26#include <camera/android/hardware/ICamera.h>
27#include <camera/ICameraRecordingProxy.h>
28#include <media/IMediaRecorderClient.h>
29#include <media/IMediaRecorder.h>
30#include <gui/Surface.h>
31#include <gui/IGraphicBufferProducer.h>
32#include <media/stagefright/PersistentSurface.h>
33
34namespace android {
35
36enum {
37    RELEASE = IBinder::FIRST_CALL_TRANSACTION,
38    INIT,
39    CLOSE,
40    SET_INPUT_SURFACE,
41    QUERY_SURFACE_MEDIASOURCE,
42    RESET,
43    STOP,
44    START,
45    PREPARE,
46    GET_MAX_AMPLITUDE,
47    SET_VIDEO_SOURCE,
48    SET_AUDIO_SOURCE,
49    SET_OUTPUT_FORMAT,
50    SET_VIDEO_ENCODER,
51    SET_AUDIO_ENCODER,
52    SET_OUTPUT_FILE_FD,
53    SET_NEXT_OUTPUT_FILE_FD,
54    SET_VIDEO_SIZE,
55    SET_VIDEO_FRAMERATE,
56    SET_PARAMETERS,
57    SET_PREVIEW_SURFACE,
58    SET_CAMERA,
59    SET_LISTENER,
60    SET_CLIENT_NAME,
61    PAUSE,
62    RESUME,
63    GET_METRICS,
64    SET_INPUT_DEVICE,
65    GET_ROUTED_DEVICE_ID,
66    ENABLE_AUDIO_DEVICE_CALLBACK,
67    GET_ACTIVE_MICROPHONES,
68
69};
70
71class BpMediaRecorder: public BpInterface<IMediaRecorder>
72{
73public:
74    explicit BpMediaRecorder(const sp<IBinder>& impl)
75    : BpInterface<IMediaRecorder>(impl)
76    {
77    }
78
79    status_t setCamera(const sp<hardware::ICamera>& camera, const sp<ICameraRecordingProxy>& proxy)
80    {
81        ALOGV("setCamera(%p,%p)", camera.get(), proxy.get());
82        Parcel data, reply;
83        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
84        data.writeStrongBinder(IInterface::asBinder(camera));
85        data.writeStrongBinder(IInterface::asBinder(proxy));
86        remote()->transact(SET_CAMERA, data, &reply);
87        return reply.readInt32();
88    }
89
90    status_t setInputSurface(const sp<PersistentSurface>& surface)
91    {
92        ALOGV("setInputSurface(%p)", surface.get());
93        Parcel data, reply;
94        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
95        surface->writeToParcel(&data);
96        remote()->transact(SET_INPUT_SURFACE, data, &reply);
97        return reply.readInt32();
98    }
99
100    sp<IGraphicBufferProducer> querySurfaceMediaSource()
101    {
102        ALOGV("Query SurfaceMediaSource");
103        Parcel data, reply;
104        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
105        remote()->transact(QUERY_SURFACE_MEDIASOURCE, data, &reply);
106        int returnedNull = reply.readInt32();
107        if (returnedNull) {
108            return NULL;
109        }
110        return interface_cast<IGraphicBufferProducer>(reply.readStrongBinder());
111    }
112
113    status_t setPreviewSurface(const sp<IGraphicBufferProducer>& surface)
114    {
115        ALOGV("setPreviewSurface(%p)", surface.get());
116        Parcel data, reply;
117        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
118        data.writeStrongBinder(IInterface::asBinder(surface));
119        remote()->transact(SET_PREVIEW_SURFACE, data, &reply);
120        return reply.readInt32();
121    }
122
123    status_t init()
124    {
125        ALOGV("init");
126        Parcel data, reply;
127        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
128        remote()->transact(INIT, data, &reply);
129        return reply.readInt32();
130    }
131
132    status_t setVideoSource(int vs)
133    {
134        ALOGV("setVideoSource(%d)", vs);
135        Parcel data, reply;
136        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
137        data.writeInt32(vs);
138        remote()->transact(SET_VIDEO_SOURCE, data, &reply);
139        return reply.readInt32();
140    }
141
142    status_t setAudioSource(int as)
143    {
144        ALOGV("setAudioSource(%d)", as);
145        Parcel data, reply;
146        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
147        data.writeInt32(as);
148        remote()->transact(SET_AUDIO_SOURCE, data, &reply);
149        return reply.readInt32();
150    }
151
152    status_t setOutputFormat(int of)
153    {
154        ALOGV("setOutputFormat(%d)", of);
155        Parcel data, reply;
156        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
157        data.writeInt32(of);
158        remote()->transact(SET_OUTPUT_FORMAT, data, &reply);
159        return reply.readInt32();
160    }
161
162    status_t setVideoEncoder(int ve)
163    {
164        ALOGV("setVideoEncoder(%d)", ve);
165        Parcel data, reply;
166        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
167        data.writeInt32(ve);
168        remote()->transact(SET_VIDEO_ENCODER, data, &reply);
169        return reply.readInt32();
170    }
171
172    status_t setAudioEncoder(int ae)
173    {
174        ALOGV("setAudioEncoder(%d)", ae);
175        Parcel data, reply;
176        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
177        data.writeInt32(ae);
178        remote()->transact(SET_AUDIO_ENCODER, data, &reply);
179        return reply.readInt32();
180    }
181
182    status_t setOutputFile(int fd) {
183        ALOGV("setOutputFile(%d)", fd);
184        Parcel data, reply;
185        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
186        data.writeFileDescriptor(fd);
187        remote()->transact(SET_OUTPUT_FILE_FD, data, &reply);
188        return reply.readInt32();
189    }
190
191    status_t setNextOutputFile(int fd) {
192        ALOGV("setNextOutputFile(%d)", fd);
193        Parcel data, reply;
194        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
195        data.writeFileDescriptor(fd);
196        remote()->transact(SET_NEXT_OUTPUT_FILE_FD, data, &reply);
197        return reply.readInt32();
198    }
199
200    status_t setVideoSize(int width, int height)
201    {
202        ALOGV("setVideoSize(%dx%d)", width, height);
203        Parcel data, reply;
204        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
205        data.writeInt32(width);
206        data.writeInt32(height);
207        remote()->transact(SET_VIDEO_SIZE, data, &reply);
208        return reply.readInt32();
209    }
210
211    status_t setVideoFrameRate(int frames_per_second)
212    {
213        ALOGV("setVideoFrameRate(%d)", frames_per_second);
214        Parcel data, reply;
215        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
216        data.writeInt32(frames_per_second);
217        remote()->transact(SET_VIDEO_FRAMERATE, data, &reply);
218        return reply.readInt32();
219    }
220
221    status_t setParameters(const String8& params)
222    {
223        ALOGV("setParameter(%s)", params.string());
224        Parcel data, reply;
225        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
226        data.writeString8(params);
227        remote()->transact(SET_PARAMETERS, data, &reply);
228        return reply.readInt32();
229    }
230
231    status_t setListener(const sp<IMediaRecorderClient>& listener)
232    {
233        ALOGV("setListener(%p)", listener.get());
234        Parcel data, reply;
235        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
236        data.writeStrongBinder(IInterface::asBinder(listener));
237        remote()->transact(SET_LISTENER, data, &reply);
238        return reply.readInt32();
239    }
240
241    status_t setClientName(const String16& clientName)
242    {
243        ALOGV("setClientName(%s)", String8(clientName).string());
244        Parcel data, reply;
245        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
246        data.writeString16(clientName);
247        remote()->transact(SET_CLIENT_NAME, data, &reply);
248        return reply.readInt32();
249    }
250
251    status_t prepare()
252    {
253        ALOGV("prepare");
254        Parcel data, reply;
255        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
256        remote()->transact(PREPARE, data, &reply);
257        return reply.readInt32();
258    }
259
260    status_t getMaxAmplitude(int* max)
261    {
262        ALOGV("getMaxAmplitude");
263        Parcel data, reply;
264        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
265        remote()->transact(GET_MAX_AMPLITUDE, data, &reply);
266        *max = reply.readInt32();
267        return reply.readInt32();
268    }
269
270    status_t getMetrics(Parcel* reply)
271    {
272        ALOGV("getMetrics");
273        Parcel data;
274        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
275        status_t ret = remote()->transact(GET_METRICS, data, reply);
276        if (ret == NO_ERROR) {
277            return OK;
278        }
279        return UNKNOWN_ERROR;
280    }
281
282    status_t start()
283    {
284        ALOGV("start");
285        Parcel data, reply;
286        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
287        remote()->transact(START, data, &reply);
288        return reply.readInt32();
289    }
290
291    status_t stop()
292    {
293        ALOGV("stop");
294        Parcel data, reply;
295        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
296        remote()->transact(STOP, data, &reply);
297        return reply.readInt32();
298    }
299
300    status_t reset()
301    {
302        ALOGV("reset");
303        Parcel data, reply;
304        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
305        remote()->transact(RESET, data, &reply);
306        return reply.readInt32();
307    }
308
309    status_t pause()
310    {
311        ALOGV("pause");
312        Parcel data, reply;
313        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
314        remote()->transact(PAUSE, data, &reply);
315        return reply.readInt32();
316    }
317
318    status_t resume()
319    {
320        ALOGV("resume");
321        Parcel data, reply;
322        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
323        remote()->transact(RESUME, data, &reply);
324        return reply.readInt32();
325    }
326
327    status_t close()
328    {
329        ALOGV("close");
330        Parcel data, reply;
331        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
332        remote()->transact(CLOSE, data, &reply);
333        return reply.readInt32();
334    }
335
336    status_t release()
337    {
338        ALOGV("release");
339        Parcel data, reply;
340        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
341        remote()->transact(RELEASE, data, &reply);
342        return reply.readInt32();
343    }
344
345    status_t setInputDevice(audio_port_handle_t deviceId)
346    {
347        ALOGV("setInputDevice");
348        Parcel data, reply;
349        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
350        data.writeInt32(deviceId);
351
352        status_t status = remote()->transact(SET_INPUT_DEVICE, data, &reply);
353        if (status != OK) {
354            ALOGE("setInputDevice binder call failed: %d", status);
355            return status;
356        }
357        return reply.readInt32();;
358    }
359
360    audio_port_handle_t getRoutedDeviceId(audio_port_handle_t *deviceId)
361    {
362        ALOGV("getRoutedDeviceId");
363        Parcel data, reply;
364        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
365
366        status_t status = remote()->transact(GET_ROUTED_DEVICE_ID, data, &reply);
367        if (status != OK) {
368            ALOGE("getRoutedDeviceid binder call failed: %d", status);
369            *deviceId = AUDIO_PORT_HANDLE_NONE;
370            return status;
371        }
372
373        status = reply.readInt32();
374        if (status != NO_ERROR) {
375            *deviceId = AUDIO_PORT_HANDLE_NONE;
376        } else {
377            *deviceId = reply.readInt32();
378        }
379        return status;
380    }
381
382    status_t enableAudioDeviceCallback(bool enabled)
383    {
384        ALOGV("enableAudioDeviceCallback");
385        Parcel data, reply;
386        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
387        data.writeBool(enabled);
388        status_t status = remote()->transact(ENABLE_AUDIO_DEVICE_CALLBACK, data, &reply);
389        if (status != OK) {
390            ALOGE("enableAudioDeviceCallback binder call failed: %d, %d", enabled, status);
391            return status;
392        }
393        return reply.readInt32();
394    }
395
396    status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones)
397    {
398        ALOGV("getActiveMicrophones");
399        Parcel data, reply;
400        data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
401        status_t status = remote()->transact(GET_ACTIVE_MICROPHONES, data, &reply);
402        if (status != OK
403                || (status = (status_t)reply.readInt32()) != NO_ERROR) {
404            return status;
405        }
406        status = reply.readParcelableVector(activeMicrophones);
407        return status;
408    }
409
410};
411
412IMPLEMENT_META_INTERFACE(MediaRecorder, "android.media.IMediaRecorder");
413
414// ----------------------------------------------------------------------
415
416status_t BnMediaRecorder::onTransact(
417                                     uint32_t code, const Parcel& data, Parcel* reply,
418                                     uint32_t flags)
419{
420    switch (code) {
421        case RELEASE: {
422            ALOGV("RELEASE");
423            CHECK_INTERFACE(IMediaRecorder, data, reply);
424            reply->writeInt32(release());
425            return NO_ERROR;
426        } break;
427        case INIT: {
428            ALOGV("INIT");
429            CHECK_INTERFACE(IMediaRecorder, data, reply);
430            reply->writeInt32(init());
431            return NO_ERROR;
432        } break;
433        case CLOSE: {
434            ALOGV("CLOSE");
435            CHECK_INTERFACE(IMediaRecorder, data, reply);
436            reply->writeInt32(close());
437            return NO_ERROR;
438        } break;
439        case RESET: {
440            ALOGV("RESET");
441            CHECK_INTERFACE(IMediaRecorder, data, reply);
442            reply->writeInt32(reset());
443            return NO_ERROR;
444        } break;
445        case STOP: {
446            ALOGV("STOP");
447            CHECK_INTERFACE(IMediaRecorder, data, reply);
448            reply->writeInt32(stop());
449            return NO_ERROR;
450        } break;
451        case START: {
452            ALOGV("START");
453            CHECK_INTERFACE(IMediaRecorder, data, reply);
454            reply->writeInt32(start());
455            return NO_ERROR;
456        } break;
457        case PAUSE: {
458            ALOGV("PAUSE");
459            CHECK_INTERFACE(IMediaRecorder, data, reply);
460            reply->writeInt32(pause());
461            return NO_ERROR;
462        } break;
463        case RESUME: {
464            ALOGV("RESUME");
465            CHECK_INTERFACE(IMediaRecorder, data, reply);
466            reply->writeInt32(resume());
467            return NO_ERROR;
468        } break;
469        case PREPARE: {
470            ALOGV("PREPARE");
471            CHECK_INTERFACE(IMediaRecorder, data, reply);
472            reply->writeInt32(prepare());
473            return NO_ERROR;
474        } break;
475        case GET_MAX_AMPLITUDE: {
476            ALOGV("GET_MAX_AMPLITUDE");
477            CHECK_INTERFACE(IMediaRecorder, data, reply);
478            int max = 0;
479            status_t ret = getMaxAmplitude(&max);
480            reply->writeInt32(max);
481            reply->writeInt32(ret);
482            return NO_ERROR;
483        } break;
484        case GET_METRICS: {
485            ALOGV("GET_METRICS");
486            status_t ret = getMetrics(reply);
487            return ret;
488        } break;
489        case SET_VIDEO_SOURCE: {
490            ALOGV("SET_VIDEO_SOURCE");
491            CHECK_INTERFACE(IMediaRecorder, data, reply);
492            int vs = data.readInt32();
493            reply->writeInt32(setVideoSource(vs));
494            return NO_ERROR;
495        } break;
496        case SET_AUDIO_SOURCE: {
497            ALOGV("SET_AUDIO_SOURCE");
498            CHECK_INTERFACE(IMediaRecorder, data, reply);
499            int as = data.readInt32();
500            reply->writeInt32(setAudioSource(as));
501            return NO_ERROR;
502        } break;
503        case SET_OUTPUT_FORMAT: {
504            ALOGV("SET_OUTPUT_FORMAT");
505            CHECK_INTERFACE(IMediaRecorder, data, reply);
506            int of = data.readInt32();
507            reply->writeInt32(setOutputFormat(of));
508            return NO_ERROR;
509        } break;
510        case SET_VIDEO_ENCODER: {
511            ALOGV("SET_VIDEO_ENCODER");
512            CHECK_INTERFACE(IMediaRecorder, data, reply);
513            int ve = data.readInt32();
514            reply->writeInt32(setVideoEncoder(ve));
515            return NO_ERROR;
516        } break;
517        case SET_AUDIO_ENCODER: {
518            ALOGV("SET_AUDIO_ENCODER");
519            CHECK_INTERFACE(IMediaRecorder, data, reply);
520            int ae = data.readInt32();
521            reply->writeInt32(setAudioEncoder(ae));
522            return NO_ERROR;
523
524        } break;
525        case SET_OUTPUT_FILE_FD: {
526            ALOGV("SET_OUTPUT_FILE_FD");
527            CHECK_INTERFACE(IMediaRecorder, data, reply);
528            int fd = dup(data.readFileDescriptor());
529            reply->writeInt32(setOutputFile(fd));
530            ::close(fd);
531            return NO_ERROR;
532        } break;
533        case SET_NEXT_OUTPUT_FILE_FD: {
534            ALOGV("SET_NEXT_OUTPUT_FILE_FD");
535            CHECK_INTERFACE(IMediaRecorder, data, reply);
536            int fd = dup(data.readFileDescriptor());
537            reply->writeInt32(setNextOutputFile(fd));
538            ::close(fd);
539            return NO_ERROR;
540        } break;
541        case SET_VIDEO_SIZE: {
542            ALOGV("SET_VIDEO_SIZE");
543            CHECK_INTERFACE(IMediaRecorder, data, reply);
544            int width = data.readInt32();
545            int height = data.readInt32();
546            reply->writeInt32(setVideoSize(width, height));
547            return NO_ERROR;
548        } break;
549        case SET_VIDEO_FRAMERATE: {
550            ALOGV("SET_VIDEO_FRAMERATE");
551            CHECK_INTERFACE(IMediaRecorder, data, reply);
552            int frames_per_second = data.readInt32();
553            reply->writeInt32(setVideoFrameRate(frames_per_second));
554            return NO_ERROR;
555        } break;
556        case SET_PARAMETERS: {
557            ALOGV("SET_PARAMETER");
558            CHECK_INTERFACE(IMediaRecorder, data, reply);
559            reply->writeInt32(setParameters(data.readString8()));
560            return NO_ERROR;
561        } break;
562        case SET_LISTENER: {
563            ALOGV("SET_LISTENER");
564            CHECK_INTERFACE(IMediaRecorder, data, reply);
565            sp<IMediaRecorderClient> listener =
566                interface_cast<IMediaRecorderClient>(data.readStrongBinder());
567            reply->writeInt32(setListener(listener));
568            return NO_ERROR;
569        } break;
570        case SET_CLIENT_NAME: {
571            ALOGV("SET_CLIENT_NAME");
572            CHECK_INTERFACE(IMediaRecorder, data, reply);
573            reply->writeInt32(setClientName(data.readString16()));
574            return NO_ERROR;
575        }
576        case SET_PREVIEW_SURFACE: {
577            ALOGV("SET_PREVIEW_SURFACE");
578            CHECK_INTERFACE(IMediaRecorder, data, reply);
579            sp<IGraphicBufferProducer> surface = interface_cast<IGraphicBufferProducer>(
580                    data.readStrongBinder());
581            reply->writeInt32(setPreviewSurface(surface));
582            return NO_ERROR;
583        } break;
584        case SET_CAMERA: {
585            ALOGV("SET_CAMERA");
586            CHECK_INTERFACE(IMediaRecorder, data, reply);
587            sp<hardware::ICamera> camera =
588                    interface_cast<hardware::ICamera>(data.readStrongBinder());
589            sp<ICameraRecordingProxy> proxy =
590                    interface_cast<ICameraRecordingProxy>(data.readStrongBinder());
591            reply->writeInt32(setCamera(camera, proxy));
592            return NO_ERROR;
593        } break;
594        case SET_INPUT_SURFACE: {
595            ALOGV("SET_INPUT_SURFACE");
596            CHECK_INTERFACE(IMediaRecorder, data, reply);
597            sp<PersistentSurface> surface = new PersistentSurface();
598            surface->readFromParcel(&data);
599            reply->writeInt32(setInputSurface(surface));
600            return NO_ERROR;
601        } break;
602        case QUERY_SURFACE_MEDIASOURCE: {
603            ALOGV("QUERY_SURFACE_MEDIASOURCE");
604            CHECK_INTERFACE(IMediaRecorder, data, reply);
605            // call the mediaserver side to create
606            // a surfacemediasource
607            sp<IGraphicBufferProducer> surfaceMediaSource = querySurfaceMediaSource();
608            // The mediaserver might have failed to create a source
609            int returnedNull= (surfaceMediaSource == NULL) ? 1 : 0 ;
610            reply->writeInt32(returnedNull);
611            if (!returnedNull) {
612                reply->writeStrongBinder(IInterface::asBinder(surfaceMediaSource));
613            }
614            return NO_ERROR;
615        } break;
616        case SET_INPUT_DEVICE: {
617            ALOGV("SET_INPUT_DEVICE");
618            CHECK_INTERFACE(IMediaRecorder, data, reply);
619            audio_port_handle_t deviceId;
620            status_t status = data.readInt32(&deviceId);
621            if (status == NO_ERROR) {
622                reply->writeInt32(setInputDevice(deviceId));
623            } else {
624                reply->writeInt32(BAD_VALUE);
625            }
626            return NO_ERROR;
627        } break;
628        case GET_ROUTED_DEVICE_ID: {
629            ALOGV("GET_ROUTED_DEVICE_ID");
630            CHECK_INTERFACE(IMediaRecorder, data, reply);
631            audio_port_handle_t deviceId;
632            status_t status = getRoutedDeviceId(&deviceId);
633            reply->writeInt32(status);
634            if (status == NO_ERROR) {
635                reply->writeInt32(deviceId);
636            }
637            return NO_ERROR;
638        } break;
639        case ENABLE_AUDIO_DEVICE_CALLBACK: {
640            ALOGV("ENABLE_AUDIO_DEVICE_CALLBACK");
641            CHECK_INTERFACE(IMediaRecorder, data, reply);
642            bool enabled;
643            status_t status = data.readBool(&enabled);
644            if (status == NO_ERROR) {
645                reply->writeInt32(enableAudioDeviceCallback(enabled));
646            } else {
647                reply->writeInt32(BAD_VALUE);
648            }
649            return NO_ERROR;
650        } break;
651        case GET_ACTIVE_MICROPHONES: {
652            ALOGV("GET_ACTIVE_MICROPHONES");
653            CHECK_INTERFACE(IMediaRecorder, data, reply);
654            std::vector<media::MicrophoneInfo> activeMicrophones;
655            status_t status = getActiveMicrophones(&activeMicrophones);
656            reply->writeInt32(status);
657            if (status != NO_ERROR) {
658                return NO_ERROR;
659            }
660            reply->writeParcelableVector(activeMicrophones);
661            return NO_ERROR;
662
663        }
664        default:
665            return BBinder::onTransact(code, data, reply, flags);
666    }
667}
668
669// ----------------------------------------------------------------------------
670
671} // namespace android
672