blob: 288433af6a0d0f66150aaca3cfd424de2f7c9d2b [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18
19#define LOG_TAG "AudioRecord-JNI"
20
21#include <stdio.h>
22#include <unistd.h>
23#include <fcntl.h>
24#include <math.h>
25
26#include "jni.h"
27#include "JNIHelp.h"
28#include "android_runtime/AndroidRuntime.h"
29
30#include "utils/Log.h"
31#include "media/AudioSystem.h"
32#include "media/AudioRecord.h"
33
34
35// ----------------------------------------------------------------------------
36
37using namespace android;
38
39// ----------------------------------------------------------------------------
40static const char* const kClassPathName = "android/media/AudioRecord";
41
42struct fields_t {
43 // these fields provide access from C++ to the...
44 jclass audioRecordClass; //... AudioRecord class
45 jmethodID postNativeEventInJava; //... event post callback method
46 int PCM16; //... format constants
47 int PCM8; //... format constants
48 int SOURCE_DEFAULT; //... record source constants
49 int SOURCE_MIC; //... record source constants
50 jfieldID nativeRecorderInJavaObj; // provides access to the C++ AudioRecord object
51 jfieldID nativeCallbackCookie; // provides access to the AudioRecord callback data
52};
53static fields_t javaAudioRecordFields;
54
55struct audiorecord_callback_cookie {
56 jclass audioRecord_class;
57 jobject audioRecord_ref;
58 };
59
60// ----------------------------------------------------------------------------
61
62#define AUDIORECORD_SUCCESS 0
63#define AUDIORECORD_ERROR -1
64#define AUDIORECORD_ERROR_BAD_VALUE -2
65#define AUDIORECORD_ERROR_INVALID_OPERATION -3
66#define AUDIORECORD_ERROR_SETUP_ZEROFRAMECOUNT -16
67#define AUDIORECORD_ERROR_SETUP_INVALIDCHANNELCOUNT -17
68#define AUDIORECORD_ERROR_SETUP_INVALIDFORMAT -18
69#define AUDIORECORD_ERROR_SETUP_INVALIDSTREAMTYPE -19
70#define AUDIORECORD_ERROR_SETUP_NATIVEINITFAILED -20
71
72jint android_media_translateRecorderErrorCode(int code) {
73 switch(code) {
74 case NO_ERROR:
75 return AUDIORECORD_SUCCESS;
76 case BAD_VALUE:
77 return AUDIORECORD_ERROR_BAD_VALUE;
78 case INVALID_OPERATION:
79 return AUDIORECORD_ERROR_INVALID_OPERATION;
80 default:
81 return AUDIORECORD_ERROR;
82 }
83}
84
85
86// ----------------------------------------------------------------------------
87static void recorderCallback(int event, void* user, void *info) {
88 if (event == AudioRecord::EVENT_MORE_DATA) {
89 // set size to 0 to signal we're not using the callback to read more data
90 AudioRecord::Buffer* pBuff = (AudioRecord::Buffer*)info;
91 pBuff->size = 0;
92
93 } else if (event == AudioRecord::EVENT_MARKER) {
94 audiorecord_callback_cookie *callbackInfo = (audiorecord_callback_cookie *)user;
95 JNIEnv *env = AndroidRuntime::getJNIEnv();
96 if (user && env) {
97 env->CallStaticVoidMethod(
98 callbackInfo->audioRecord_class,
99 javaAudioRecordFields.postNativeEventInJava,
100 callbackInfo->audioRecord_ref, event, 0,0, NULL);
101 if (env->ExceptionCheck()) {
102 env->ExceptionDescribe();
103 env->ExceptionClear();
104 }
105 }
106
107 } else if (event == AudioRecord::EVENT_NEW_POS) {
108 audiorecord_callback_cookie *callbackInfo = (audiorecord_callback_cookie *)user;
109 JNIEnv *env = AndroidRuntime::getJNIEnv();
110 if (user && env) {
111 env->CallStaticVoidMethod(
112 callbackInfo->audioRecord_class,
113 javaAudioRecordFields.postNativeEventInJava,
114 callbackInfo->audioRecord_ref, event, 0,0, NULL);
115 if (env->ExceptionCheck()) {
116 env->ExceptionDescribe();
117 env->ExceptionClear();
118 }
119 }
120 }
121}
122
123
124// ----------------------------------------------------------------------------
125static int
126android_media_AudioRecord_setup(JNIEnv *env, jobject thiz, jobject weak_this,
127 jint source, jint sampleRateInHertz, jint nbChannels,
128 jint audioFormat, jint buffSizeInBytes)
129{
130 //LOGV(">> Entering android_media_AudioRecord_setup");
131 //LOGV("sampleRate=%d, audioFormat=%d, nbChannels=%d, buffSizeInBytes=%d",
132 // sampleRateInHertz, audioFormat, nbChannels, buffSizeInBytes);
133
134 if ((nbChannels == 0) || (nbChannels > 2)) {
135 LOGE("Error creating AudioRecord: channel count is not 1 or 2.");
136 return AUDIORECORD_ERROR_SETUP_INVALIDCHANNELCOUNT;
137 }
138
139 // compare the format against the Java constants
140 if ((audioFormat != javaAudioRecordFields.PCM16)
141 && (audioFormat != javaAudioRecordFields.PCM8)) {
142 LOGE("Error creating AudioRecord: unsupported audio format.");
143 return AUDIORECORD_ERROR_SETUP_INVALIDFORMAT;
144 }
145
146 int bytesPerSample = audioFormat==javaAudioRecordFields.PCM16 ? 2 : 1;
147 int format = audioFormat==javaAudioRecordFields.PCM16 ?
148 AudioSystem::PCM_16_BIT : AudioSystem::PCM_8_BIT;
149
150 if (buffSizeInBytes == 0) {
151 LOGE("Error creating AudioRecord: frameCount is 0.");
152 return AUDIORECORD_ERROR_SETUP_ZEROFRAMECOUNT;
153 }
154 int frameSize = nbChannels * bytesPerSample;
155 size_t frameCount = buffSizeInBytes / frameSize;
156
157 // compare the source against the Java constants
158 AudioRecord::stream_type arSource;
159 if (source == javaAudioRecordFields.SOURCE_DEFAULT) {
160 arSource = AudioRecord::DEFAULT_INPUT;
161 } else if (source == javaAudioRecordFields.SOURCE_MIC) {
162 arSource = AudioRecord::MIC_INPUT;
163 } else {
164 LOGE("Error creating AudioRecord: unknown source.");
165 return AUDIORECORD_ERROR_SETUP_INVALIDSTREAMTYPE;
166 }
167
168 audiorecord_callback_cookie *lpCallbackData = NULL;
169 AudioRecord* lpRecorder = NULL;
170
171 // create an uninitialized AudioRecord object
172 lpRecorder = new AudioRecord();
173 if(lpRecorder == NULL) {
174 LOGE("Error creating AudioRecord instance.");
175 return AUDIORECORD_ERROR_SETUP_NATIVEINITFAILED;
176 }
177
178 // create the callback information:
179 // this data will be passed with every AudioRecord callback
180 jclass clazz = env->GetObjectClass(thiz);
181 if (clazz == NULL) {
182 LOGE("Can't find %s when setting up callback.", kClassPathName);
183 goto native_track_failure;
184 }
185 lpCallbackData = new audiorecord_callback_cookie;
186 lpCallbackData->audioRecord_class = (jclass)env->NewGlobalRef(clazz);
187 // we use a weak reference so the AudioRecord object can be garbage collected.
188 lpCallbackData->audioRecord_ref = env->NewGlobalRef(weak_this);
189
190 lpRecorder->set(arSource,
191 sampleRateInHertz,
192 format, // word length, PCM
193 nbChannels,
194 frameCount,
195 0, // flags
196 recorderCallback,// callback_t
197 lpCallbackData,// void* user
198 0, // notificationFrames,
199 true); // threadCanCallJava)
200
201 if(lpRecorder->initCheck() != NO_ERROR) {
202 LOGE("Error creating AudioRecord instance: initialization check failed.");
203 goto native_init_failure;
204 }
205
206 // save our newly created C++ AudioRecord in the "nativeRecorderInJavaObj" field
207 // of the Java object
208 env->SetIntField(thiz, javaAudioRecordFields.nativeRecorderInJavaObj, (int)lpRecorder);
209
210 // save our newly created callback information in the "nativeCallbackCookie" field
211 // of the Java object (in mNativeCallbackCookie) so we can free the memory in finalize()
212 env->SetIntField(thiz, javaAudioRecordFields.nativeCallbackCookie, (int)lpCallbackData);
213
214 return AUDIORECORD_SUCCESS;
215
216 // failure:
217native_init_failure:
218 delete lpCallbackData;
219
220native_track_failure:
221 delete lpRecorder;
222
223 env->SetIntField(thiz, javaAudioRecordFields.nativeRecorderInJavaObj, 0);
224 env->SetIntField(thiz, javaAudioRecordFields.nativeCallbackCookie, 0);
225
226 return AUDIORECORD_ERROR_SETUP_NATIVEINITFAILED;
227}
228
229
230
231// ----------------------------------------------------------------------------
232static void
233android_media_AudioRecord_start(JNIEnv *env, jobject thiz)
234{
235 AudioRecord *lpRecorder =
236 (AudioRecord *)env->GetIntField(thiz, javaAudioRecordFields.nativeRecorderInJavaObj);
237 if (lpRecorder == NULL ) {
238 jniThrowException(env, "java/lang/IllegalStateException", NULL);
239 return;
240 }
241
242 lpRecorder->start();
243}
244
245
246// ----------------------------------------------------------------------------
247static void
248android_media_AudioRecord_stop(JNIEnv *env, jobject thiz)
249{
250 AudioRecord *lpRecorder =
251 (AudioRecord *)env->GetIntField(thiz, javaAudioRecordFields.nativeRecorderInJavaObj);
252 if (lpRecorder == NULL ) {
253 jniThrowException(env, "java/lang/IllegalStateException", NULL);
254 return;
255 }
256
257 lpRecorder->stop();
258 //LOGV("Called lpRecorder->stop()");
259}
260
261
262// ----------------------------------------------------------------------------
263static void android_media_AudioRecord_finalize(JNIEnv *env, jobject thiz) {
264
265 // delete the AudioRecord object
266 AudioRecord *lpRecorder =
267 (AudioRecord *)env->GetIntField(thiz, javaAudioRecordFields.nativeRecorderInJavaObj);
268
269 if (lpRecorder) {
270 LOGV("About to delete lpRecorder: %x\n", (int)lpRecorder);
271 lpRecorder->stop();
272 delete lpRecorder;
273 }
274
275 // delete the callback information
276 audiorecord_callback_cookie *lpCookie = (audiorecord_callback_cookie *)env->GetIntField(
277 thiz, javaAudioRecordFields.nativeCallbackCookie);
278 if (lpCookie) {
279 LOGV("deleting lpCookie: %x\n", (int)lpCookie);
280 delete lpCookie;
281 }
282
283}
284
285
286// ----------------------------------------------------------------------------
287static void android_media_AudioRecord_release(JNIEnv *env, jobject thiz) {
288
289 // do everything a call to finalize would
290 android_media_AudioRecord_finalize(env, thiz);
291 // + reset the native resources in the Java object so any attempt to access
292 // them after a call to release fails.
293 env->SetIntField(thiz, javaAudioRecordFields.nativeRecorderInJavaObj, 0);
294 env->SetIntField(thiz, javaAudioRecordFields.nativeCallbackCookie, 0);
295}
296
297
298// ----------------------------------------------------------------------------
299static jint android_media_AudioRecord_readInByteArray(JNIEnv *env, jobject thiz,
300 jbyteArray javaAudioData,
301 jint offsetInBytes, jint sizeInBytes) {
302 jbyte* recordBuff = NULL;
303 AudioRecord *lpRecorder = NULL;
304
305 // get the audio recorder from which we'll read new audio samples
306 lpRecorder =
307 (AudioRecord *)env->GetIntField(thiz, javaAudioRecordFields.nativeRecorderInJavaObj);
308 if (lpRecorder == NULL) {
309 LOGE("Unable to retrieve AudioRecord object, can't record");
310 return 0;
311 }
312
313 if (!javaAudioData) {
314 LOGE("Invalid Java array to store recorded audio, can't record");
315 return 0;
316 }
317
318 // get the pointer to where we'll record the audio
319 recordBuff = (jbyte *)env->GetPrimitiveArrayCritical(javaAudioData, NULL);
320
321 if (recordBuff == NULL) {
322 LOGE("Error retrieving destination for recorded audio data, can't record");
323 return 0;
324 }
325
326 // read the new audio data from the native AudioRecord object
327 ssize_t recorderBuffSize = lpRecorder->frameCount()*lpRecorder->frameSize();
328 ssize_t readSize = lpRecorder->read(recordBuff + offsetInBytes,
329 sizeInBytes > (jint)recorderBuffSize ?
330 (jint)recorderBuffSize : sizeInBytes );
331 env->ReleasePrimitiveArrayCritical(javaAudioData, recordBuff, 0);
332
333 return (jint) readSize;
334}
335
336// ----------------------------------------------------------------------------
337static jint android_media_AudioRecord_readInShortArray(JNIEnv *env, jobject thiz,
338 jshortArray javaAudioData,
339 jint offsetInShorts, jint sizeInShorts) {
340
341 return (android_media_AudioRecord_readInByteArray(env, thiz,
342 (jbyteArray) javaAudioData,
343 offsetInShorts*2, sizeInShorts*2)
344 / 2);
345}
346
347// ----------------------------------------------------------------------------
348static jint android_media_AudioRecord_readInDirectBuffer(JNIEnv *env, jobject thiz,
349 jobject jBuffer, jint sizeInBytes) {
350 AudioRecord *lpRecorder = NULL;
351 //LOGV("Entering android_media_AudioRecord_readInBuffer");
352
353 // get the audio recorder from which we'll read new audio samples
354 lpRecorder =
355 (AudioRecord *)env->GetIntField(thiz, javaAudioRecordFields.nativeRecorderInJavaObj);
356 if(lpRecorder==NULL)
357 return 0;
358
359 // direct buffer and direct access supported?
360 long capacity = env->GetDirectBufferCapacity(jBuffer);
361 if(capacity == -1) {
362 // buffer direct access is not supported
363 LOGE("Buffer direct access is not supported, can't record");
364 return 0;
365 }
366 //LOGV("capacity = %ld", capacity);
367 jbyte* nativeFromJavaBuf = (jbyte*) env->GetDirectBufferAddress(jBuffer);
368 if(nativeFromJavaBuf==NULL) {
369 LOGE("Buffer direct access is not supported, can't record");
370 return 0;
371 }
372
373 // read new data from the recorder
374 return (jint) lpRecorder->read(nativeFromJavaBuf,
375 capacity < sizeInBytes ? capacity : sizeInBytes);
376}
377
378
379// ----------------------------------------------------------------------------
380static jint android_media_AudioRecord_set_marker_pos(JNIEnv *env, jobject thiz,
381 jint markerPos) {
382
383 AudioRecord *lpRecorder = (AudioRecord *)env->GetIntField(
384 thiz, javaAudioRecordFields.nativeRecorderInJavaObj);
385
386 if (lpRecorder) {
387 return
388 android_media_translateRecorderErrorCode( lpRecorder->setMarkerPosition(markerPos) );
389 } else {
390 jniThrowException(env, "java/lang/IllegalStateException",
391 "Unable to retrieve AudioRecord pointer for setMarkerPosition()");
392 return AUDIORECORD_ERROR;
393 }
394}
395
396
397// ----------------------------------------------------------------------------
398static jint android_media_AudioRecord_get_marker_pos(JNIEnv *env, jobject thiz) {
399
400 AudioRecord *lpRecorder = (AudioRecord *)env->GetIntField(
401 thiz, javaAudioRecordFields.nativeRecorderInJavaObj);
402 uint32_t markerPos = 0;
403
404 if (lpRecorder) {
405 lpRecorder->getMarkerPosition(&markerPos);
406 return (jint)markerPos;
407 } else {
408 jniThrowException(env, "java/lang/IllegalStateException",
409 "Unable to retrieve AudioRecord pointer for getMarkerPosition()");
410 return AUDIORECORD_ERROR;
411 }
412}
413
414
415// ----------------------------------------------------------------------------
416static jint android_media_AudioRecord_set_pos_update_period(JNIEnv *env, jobject thiz,
417 jint period) {
418
419 AudioRecord *lpRecorder = (AudioRecord *)env->GetIntField(
420 thiz, javaAudioRecordFields.nativeRecorderInJavaObj);
421
422 if (lpRecorder) {
423 return
424 android_media_translateRecorderErrorCode( lpRecorder->setPositionUpdatePeriod(period) );
425 } else {
426 jniThrowException(env, "java/lang/IllegalStateException",
427 "Unable to retrieve AudioRecord pointer for setPositionUpdatePeriod()");
428 return AUDIORECORD_ERROR;
429 }
430}
431
432
433// ----------------------------------------------------------------------------
434static jint android_media_AudioRecord_get_pos_update_period(JNIEnv *env, jobject thiz) {
435
436 AudioRecord *lpRecorder = (AudioRecord *)env->GetIntField(
437 thiz, javaAudioRecordFields.nativeRecorderInJavaObj);
438 uint32_t period = 0;
439
440 if (lpRecorder) {
441 lpRecorder->getPositionUpdatePeriod(&period);
442 return (jint)period;
443 } else {
444 jniThrowException(env, "java/lang/IllegalStateException",
445 "Unable to retrieve AudioRecord pointer for getPositionUpdatePeriod()");
446 return AUDIORECORD_ERROR;
447 }
448}
449
450
451// ----------------------------------------------------------------------------
452// returns the minimum required size for the successful creation of an AudioRecord instance.
453// returns 0 if the parameter combination is not supported.
454// return -1 if there was an error querying the buffer size.
455static jint android_media_AudioRecord_get_min_buff_size(JNIEnv *env, jobject thiz,
456 jint sampleRateInHertz, jint nbChannels, jint audioFormat) {
457
458 size_t inputBuffSize = 0;
459 LOGV(">> android_media_AudioRecord_get_min_buff_size(%d, %d, %d)", sampleRateInHertz, nbChannels, audioFormat);
460
461 status_t result = AudioSystem::getInputBufferSize(
462 sampleRateInHertz,
463 (audioFormat == javaAudioRecordFields.PCM16 ?
464 AudioSystem::PCM_16_BIT : AudioSystem::PCM_8_BIT),
465 nbChannels, &inputBuffSize);
466 switch(result) {
467 case(NO_ERROR):
468 if(inputBuffSize == 0) {
469 LOGV("Recording parameters are not supported: %dHz, %d channel(s), (java) format %d",
470 sampleRateInHertz, nbChannels, audioFormat);
471 return 0;
472 } else {
473 // the minimum buffer size is twice the hardware input buffer size
474 return 2*inputBuffSize;
475 }
476 break;
477 case(PERMISSION_DENIED):
478 default:
479 return -1;
480 }
481}
482
483
484// ----------------------------------------------------------------------------
485// ----------------------------------------------------------------------------
486static JNINativeMethod gMethods[] = {
487 // name, signature, funcPtr
488 {"native_start", "()V", (void *)android_media_AudioRecord_start},
489 {"native_stop", "()V", (void *)android_media_AudioRecord_stop},
490 {"native_setup", "(Ljava/lang/Object;IIIII)I",
491 (void *)android_media_AudioRecord_setup},
492 {"native_finalize", "()V", (void *)android_media_AudioRecord_finalize},
493 {"native_release", "()V", (void *)android_media_AudioRecord_release},
494 {"native_read_in_byte_array",
495 "([BII)I", (void *)android_media_AudioRecord_readInByteArray},
496 {"native_read_in_short_array",
497 "([SII)I", (void *)android_media_AudioRecord_readInShortArray},
498 {"native_read_in_direct_buffer","(Ljava/lang/Object;I)I",
499 (void *)android_media_AudioRecord_readInDirectBuffer},
500 {"native_set_marker_pos","(I)I", (void *)android_media_AudioRecord_set_marker_pos},
501 {"native_get_marker_pos","()I", (void *)android_media_AudioRecord_get_marker_pos},
502 {"native_set_pos_update_period",
503 "(I)I", (void *)android_media_AudioRecord_set_pos_update_period},
504 {"native_get_pos_update_period",
505 "()I", (void *)android_media_AudioRecord_get_pos_update_period},
506 {"native_get_min_buff_size",
507 "(III)I", (void *)android_media_AudioRecord_get_min_buff_size},
508};
509
510// field names found in android/media/AudioRecord.java
511#define JAVA_POSTEVENT_CALLBACK_NAME "postEventFromNative"
512#define JAVA_CONST_PCM16_NAME "ENCODING_PCM_16BIT"
513#define JAVA_CONST_PCM8_NAME "ENCODING_PCM_8BIT"
514#define JAVA_CONST_SOURCEDEFAULT_NAME "SOURCE_DEFAULT"
515#define JAVA_CONST_SOURCEMIC_NAME "SOURCE_MIC"
516#define JAVA_NATIVERECORDERINJAVAOBJ_FIELD_NAME "mNativeRecorderInJavaObj"
517#define JAVA_NATIVECALLBACKINFO_FIELD_NAME "mNativeCallbackCookie"
518
519#define JAVA_AUDIOFORMAT_CLASS_NAME "android/media/AudioFormat"
520
521// ----------------------------------------------------------------------------
522
523extern bool android_media_getIntConstantFromClass(JNIEnv* pEnv,
524 jclass theClass, const char* className, const char* constName, int* constVal);
525
526// ----------------------------------------------------------------------------
527int register_android_media_AudioRecord(JNIEnv *env)
528{
529 javaAudioRecordFields.audioRecordClass = NULL;
530 javaAudioRecordFields.postNativeEventInJava = NULL;
531 javaAudioRecordFields.nativeRecorderInJavaObj = NULL;
532 javaAudioRecordFields.nativeCallbackCookie = NULL;
533
534
535 // Get the AudioRecord class
536 javaAudioRecordFields.audioRecordClass = env->FindClass(kClassPathName);
537 if (javaAudioRecordFields.audioRecordClass == NULL) {
538 LOGE("Can't find %s", kClassPathName);
539 return -1;
540 }
541
542 // Get the postEvent method
543 javaAudioRecordFields.postNativeEventInJava = env->GetStaticMethodID(
544 javaAudioRecordFields.audioRecordClass,
545 JAVA_POSTEVENT_CALLBACK_NAME, "(Ljava/lang/Object;IIILjava/lang/Object;)V");
546 if (javaAudioRecordFields.postNativeEventInJava == NULL) {
547 LOGE("Can't find AudioRecord.%s", JAVA_POSTEVENT_CALLBACK_NAME);
548 return -1;
549 }
550
551 // Get the variables
552 // mNativeRecorderInJavaObj
553 javaAudioRecordFields.nativeRecorderInJavaObj =
554 env->GetFieldID(javaAudioRecordFields.audioRecordClass,
555 JAVA_NATIVERECORDERINJAVAOBJ_FIELD_NAME, "I");
556 if (javaAudioRecordFields.nativeRecorderInJavaObj == NULL) {
557 LOGE("Can't find AudioRecord.%s", JAVA_NATIVERECORDERINJAVAOBJ_FIELD_NAME);
558 return -1;
559 }
560 // mNativeCallbackCookie
561 javaAudioRecordFields.nativeCallbackCookie = env->GetFieldID(
562 javaAudioRecordFields.audioRecordClass,
563 JAVA_NATIVECALLBACKINFO_FIELD_NAME, "I");
564 if (javaAudioRecordFields.nativeCallbackCookie == NULL) {
565 LOGE("Can't find AudioRecord.%s", JAVA_NATIVECALLBACKINFO_FIELD_NAME);
566 return -1;
567 }
568
569 // Get the format constants from the AudioFormat class
570 jclass audioFormatClass = NULL;
571 audioFormatClass = env->FindClass(JAVA_AUDIOFORMAT_CLASS_NAME);
572 if (audioFormatClass == NULL) {
573 LOGE("Can't find %s", JAVA_AUDIOFORMAT_CLASS_NAME);
574 return -1;
575 }
576 if ( !android_media_getIntConstantFromClass(env, audioFormatClass,
577 JAVA_AUDIOFORMAT_CLASS_NAME,
578 JAVA_CONST_PCM16_NAME, &(javaAudioRecordFields.PCM16))
579 || !android_media_getIntConstantFromClass(env, audioFormatClass,
580 JAVA_AUDIOFORMAT_CLASS_NAME,
581 JAVA_CONST_PCM8_NAME, &(javaAudioRecordFields.PCM8)) ) {
582 // error log performed in getIntConstantFromClass()
583 return -1;
584 }
585
586 // Get the recording source constants from the AudioRecord class
587 if ( !android_media_getIntConstantFromClass(env, javaAudioRecordFields.audioRecordClass,
588 kClassPathName,
589 JAVA_CONST_SOURCEDEFAULT_NAME, &(javaAudioRecordFields.SOURCE_DEFAULT))
590 || !android_media_getIntConstantFromClass(env, javaAudioRecordFields.audioRecordClass,
591 kClassPathName,
592 JAVA_CONST_SOURCEMIC_NAME, &(javaAudioRecordFields.SOURCE_MIC)) ) {
593 // error log performed in getIntConstantFromClass()
594 return -1;
595 }
596
597 return AndroidRuntime::registerNativeMethods(env,
598 kClassPathName, gMethods, NELEM(gMethods));
599}
600
601// ----------------------------------------------------------------------------