1 /*
2 **
3 ** Copyright 2006, 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
20 #define LOG_TAG "AudioSystem-JNI"
21 #include <utils/Log.h>
22
23 #include <sstream>
24 #include <vector>
25 #include <jni.h>
26 #include <nativehelper/JNIHelp.h>
27 #include "core_jni_helpers.h"
28
29 #include <media/AudioSystem.h>
30 #include <media/AudioPolicy.h>
31 #include <media/MicrophoneInfo.h>
32 #include <nativehelper/ScopedLocalRef.h>
33 #include <system/audio.h>
34 #include <system/audio_policy.h>
35 #include "android_media_AudioFormat.h"
36 #include "android_media_AudioErrors.h"
37 #include "android_media_MicrophoneInfo.h"
38
39 // ----------------------------------------------------------------------------
40
41 using namespace android;
42
43 static const char* const kClassPathName = "android/media/AudioSystem";
44
45 static jclass gArrayListClass;
46 static struct {
47 jmethodID add;
48 jmethodID toArray;
49 } gArrayListMethods;
50
51 static jclass gBooleanClass;
52 static jmethodID gBooleanCstor;
53
54 static jclass gIntegerClass;
55 static jmethodID gIntegerCstor;
56
57 static jclass gMapClass;
58 static jmethodID gMapPut;
59
60 static jclass gAudioHandleClass;
61 static jmethodID gAudioHandleCstor;
62 static struct {
63 jfieldID mId;
64 } gAudioHandleFields;
65
66 static jclass gAudioPortClass;
67 static jmethodID gAudioPortCstor;
68 static struct {
69 jfieldID mHandle;
70 jfieldID mRole;
71 jfieldID mGains;
72 jfieldID mActiveConfig;
73 // other fields unused by JNI
74 } gAudioPortFields;
75
76 static jclass gAudioPortConfigClass;
77 static jmethodID gAudioPortConfigCstor;
78 static struct {
79 jfieldID mPort;
80 jfieldID mSamplingRate;
81 jfieldID mChannelMask;
82 jfieldID mFormat;
83 jfieldID mGain;
84 jfieldID mConfigMask;
85 } gAudioPortConfigFields;
86
87 static jclass gAudioDevicePortClass;
88 static jmethodID gAudioDevicePortCstor;
89
90 static jclass gAudioDevicePortConfigClass;
91 static jmethodID gAudioDevicePortConfigCstor;
92
93 static jclass gAudioMixPortClass;
94 static jmethodID gAudioMixPortCstor;
95
96 static jclass gAudioMixPortConfigClass;
97 static jmethodID gAudioMixPortConfigCstor;
98
99 static jclass gAudioGainClass;
100 static jmethodID gAudioGainCstor;
101
102 static jclass gAudioGainConfigClass;
103 static jmethodID gAudioGainConfigCstor;
104 static struct {
105 jfieldID mIndex;
106 jfieldID mMode;
107 jfieldID mChannelMask;
108 jfieldID mValues;
109 jfieldID mRampDurationMs;
110 // other fields unused by JNI
111 } gAudioGainConfigFields;
112
113 static jclass gAudioPatchClass;
114 static jmethodID gAudioPatchCstor;
115 static struct {
116 jfieldID mHandle;
117 // other fields unused by JNI
118 } gAudioPatchFields;
119
120 static jclass gAudioMixClass;
121 static struct {
122 jfieldID mRule;
123 jfieldID mFormat;
124 jfieldID mRouteFlags;
125 jfieldID mDeviceType;
126 jfieldID mDeviceAddress;
127 jfieldID mMixType;
128 jfieldID mCallbackFlags;
129 } gAudioMixFields;
130
131 static jclass gAudioFormatClass;
132 static struct {
133 jfieldID mEncoding;
134 jfieldID mSampleRate;
135 jfieldID mChannelMask;
136 // other fields unused by JNI
137 } gAudioFormatFields;
138
139 static jclass gAudioMixingRuleClass;
140 static struct {
141 jfieldID mCriteria;
142 // other fields unused by JNI
143 } gAudioMixingRuleFields;
144
145 static jclass gAudioMixMatchCriterionClass;
146 static struct {
147 jfieldID mAttr;
148 jfieldID mIntProp;
149 jfieldID mRule;
150 } gAudioMixMatchCriterionFields;
151
152 static jclass gAudioAttributesClass;
153 static struct {
154 jfieldID mUsage;
155 jfieldID mSource;
156 } gAudioAttributesFields;
157
158 static const char* const kEventHandlerClassPathName =
159 "android/media/AudioPortEventHandler";
160 static struct {
161 jfieldID mJniCallback;
162 } gEventHandlerFields;
163 static struct {
164 jmethodID postEventFromNative;
165 } gAudioPortEventHandlerMethods;
166
167 static struct {
168 jmethodID postDynPolicyEventFromNative;
169 jmethodID postRecordConfigEventFromNative;
170 } gAudioPolicyEventHandlerMethods;
171
172 static Mutex gLock;
173
174 enum AudioError {
175 kAudioStatusOk = 0,
176 kAudioStatusError = 1,
177 kAudioStatusMediaServerDied = 100
178 };
179
180 enum {
181 AUDIOPORT_EVENT_PORT_LIST_UPDATED = 1,
182 AUDIOPORT_EVENT_PATCH_LIST_UPDATED = 2,
183 AUDIOPORT_EVENT_SERVICE_DIED = 3,
184 };
185
186 #define MAX_PORT_GENERATION_SYNC_ATTEMPTS 5
187
188 // ----------------------------------------------------------------------------
189 // ref-counted object for audio port callbacks
190 class JNIAudioPortCallback: public AudioSystem::AudioPortCallback
191 {
192 public:
193 JNIAudioPortCallback(JNIEnv* env, jobject thiz, jobject weak_thiz);
194 ~JNIAudioPortCallback();
195
196 virtual void onAudioPortListUpdate();
197 virtual void onAudioPatchListUpdate();
198 virtual void onServiceDied();
199
200 private:
201 void sendEvent(int event);
202
203 jclass mClass; // Reference to AudioPortEventHandler class
204 jobject mObject; // Weak ref to AudioPortEventHandler Java object to call on
205 };
206
JNIAudioPortCallback(JNIEnv * env,jobject thiz,jobject weak_thiz)207 JNIAudioPortCallback::JNIAudioPortCallback(JNIEnv* env, jobject thiz, jobject weak_thiz)
208 {
209
210 // Hold onto the AudioPortEventHandler class for use in calling the static method
211 // that posts events to the application thread.
212 jclass clazz = env->GetObjectClass(thiz);
213 if (clazz == NULL) {
214 ALOGE("Can't find class %s", kEventHandlerClassPathName);
215 return;
216 }
217 mClass = (jclass)env->NewGlobalRef(clazz);
218
219 // We use a weak reference so the AudioPortEventHandler object can be garbage collected.
220 // The reference is only used as a proxy for callbacks.
221 mObject = env->NewGlobalRef(weak_thiz);
222 }
223
~JNIAudioPortCallback()224 JNIAudioPortCallback::~JNIAudioPortCallback()
225 {
226 // remove global references
227 JNIEnv *env = AndroidRuntime::getJNIEnv();
228 if (env == NULL) {
229 return;
230 }
231 env->DeleteGlobalRef(mObject);
232 env->DeleteGlobalRef(mClass);
233 }
234
sendEvent(int event)235 void JNIAudioPortCallback::sendEvent(int event)
236 {
237 JNIEnv *env = AndroidRuntime::getJNIEnv();
238 if (env == NULL) {
239 return;
240 }
241 env->CallStaticVoidMethod(mClass, gAudioPortEventHandlerMethods.postEventFromNative, mObject,
242 event, 0, 0, NULL);
243 if (env->ExceptionCheck()) {
244 ALOGW("An exception occurred while notifying an event.");
245 env->ExceptionClear();
246 }
247 }
248
onAudioPortListUpdate()249 void JNIAudioPortCallback::onAudioPortListUpdate()
250 {
251 sendEvent(AUDIOPORT_EVENT_PORT_LIST_UPDATED);
252 }
253
onAudioPatchListUpdate()254 void JNIAudioPortCallback::onAudioPatchListUpdate()
255 {
256 sendEvent(AUDIOPORT_EVENT_PATCH_LIST_UPDATED);
257 }
258
onServiceDied()259 void JNIAudioPortCallback::onServiceDied()
260 {
261 sendEvent(AUDIOPORT_EVENT_SERVICE_DIED);
262 }
263
setJniCallback(JNIEnv * env,jobject thiz,const sp<JNIAudioPortCallback> & callback)264 static sp<JNIAudioPortCallback> setJniCallback(JNIEnv* env,
265 jobject thiz,
266 const sp<JNIAudioPortCallback>& callback)
267 {
268 Mutex::Autolock l(gLock);
269 sp<JNIAudioPortCallback> old =
270 (JNIAudioPortCallback*)env->GetLongField(thiz, gEventHandlerFields.mJniCallback);
271 if (callback.get()) {
272 callback->incStrong((void*)setJniCallback);
273 }
274 if (old != 0) {
275 old->decStrong((void*)setJniCallback);
276 }
277 env->SetLongField(thiz, gEventHandlerFields.mJniCallback, (jlong)callback.get());
278 return old;
279 }
280
check_AudioSystem_Command(status_t status)281 static int check_AudioSystem_Command(status_t status)
282 {
283 switch (status) {
284 case DEAD_OBJECT:
285 return kAudioStatusMediaServerDied;
286 case NO_ERROR:
287 return kAudioStatusOk;
288 default:
289 break;
290 }
291 return kAudioStatusError;
292 }
293
294 static jint
android_media_AudioSystem_muteMicrophone(JNIEnv * env,jobject thiz,jboolean on)295 android_media_AudioSystem_muteMicrophone(JNIEnv *env, jobject thiz, jboolean on)
296 {
297 return (jint) check_AudioSystem_Command(AudioSystem::muteMicrophone(on));
298 }
299
300 static jboolean
android_media_AudioSystem_isMicrophoneMuted(JNIEnv * env,jobject thiz)301 android_media_AudioSystem_isMicrophoneMuted(JNIEnv *env, jobject thiz)
302 {
303 bool state = false;
304 AudioSystem::isMicrophoneMuted(&state);
305 return state;
306 }
307
308 static jboolean
android_media_AudioSystem_isStreamActive(JNIEnv * env,jobject thiz,jint stream,jint inPastMs)309 android_media_AudioSystem_isStreamActive(JNIEnv *env, jobject thiz, jint stream, jint inPastMs)
310 {
311 bool state = false;
312 AudioSystem::isStreamActive((audio_stream_type_t) stream, &state, inPastMs);
313 return state;
314 }
315
316 static jboolean
android_media_AudioSystem_isStreamActiveRemotely(JNIEnv * env,jobject thiz,jint stream,jint inPastMs)317 android_media_AudioSystem_isStreamActiveRemotely(JNIEnv *env, jobject thiz, jint stream,
318 jint inPastMs)
319 {
320 bool state = false;
321 AudioSystem::isStreamActiveRemotely((audio_stream_type_t) stream, &state, inPastMs);
322 return state;
323 }
324
325 static jboolean
android_media_AudioSystem_isSourceActive(JNIEnv * env,jobject thiz,jint source)326 android_media_AudioSystem_isSourceActive(JNIEnv *env, jobject thiz, jint source)
327 {
328 bool state = false;
329 AudioSystem::isSourceActive((audio_source_t) source, &state);
330 return state;
331 }
332
333 static jint
android_media_AudioSystem_newAudioSessionId(JNIEnv * env,jobject thiz)334 android_media_AudioSystem_newAudioSessionId(JNIEnv *env, jobject thiz)
335 {
336 return AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
337 }
338
339 static jint
android_media_AudioSystem_newAudioPlayerId(JNIEnv * env,jobject thiz)340 android_media_AudioSystem_newAudioPlayerId(JNIEnv *env, jobject thiz)
341 {
342 return AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_PLAYER);
343 }
344
345 static jint
android_media_AudioSystem_setParameters(JNIEnv * env,jobject thiz,jstring keyValuePairs)346 android_media_AudioSystem_setParameters(JNIEnv *env, jobject thiz, jstring keyValuePairs)
347 {
348 const jchar* c_keyValuePairs = env->GetStringCritical(keyValuePairs, 0);
349 String8 c_keyValuePairs8;
350 if (keyValuePairs) {
351 c_keyValuePairs8 = String8(
352 reinterpret_cast<const char16_t*>(c_keyValuePairs),
353 env->GetStringLength(keyValuePairs));
354 env->ReleaseStringCritical(keyValuePairs, c_keyValuePairs);
355 }
356 int status = check_AudioSystem_Command(AudioSystem::setParameters(c_keyValuePairs8));
357 return (jint) status;
358 }
359
360 static jstring
android_media_AudioSystem_getParameters(JNIEnv * env,jobject thiz,jstring keys)361 android_media_AudioSystem_getParameters(JNIEnv *env, jobject thiz, jstring keys)
362 {
363 const jchar* c_keys = env->GetStringCritical(keys, 0);
364 String8 c_keys8;
365 if (keys) {
366 c_keys8 = String8(reinterpret_cast<const char16_t*>(c_keys),
367 env->GetStringLength(keys));
368 env->ReleaseStringCritical(keys, c_keys);
369 }
370 return env->NewStringUTF(AudioSystem::getParameters(c_keys8).string());
371 }
372
373 static void
android_media_AudioSystem_error_callback(status_t err)374 android_media_AudioSystem_error_callback(status_t err)
375 {
376 JNIEnv *env = AndroidRuntime::getJNIEnv();
377 if (env == NULL) {
378 return;
379 }
380
381 jclass clazz = env->FindClass(kClassPathName);
382
383 env->CallStaticVoidMethod(clazz, env->GetStaticMethodID(clazz,
384 "errorCallbackFromNative","(I)V"),
385 check_AudioSystem_Command(err));
386
387 env->DeleteLocalRef(clazz);
388 }
389
390 static void
android_media_AudioSystem_dyn_policy_callback(int event,String8 regId,int val)391 android_media_AudioSystem_dyn_policy_callback(int event, String8 regId, int val)
392 {
393 JNIEnv *env = AndroidRuntime::getJNIEnv();
394 if (env == NULL) {
395 return;
396 }
397
398 jclass clazz = env->FindClass(kClassPathName);
399 const char* zechars = regId.string();
400 jstring zestring = env->NewStringUTF(zechars);
401
402 env->CallStaticVoidMethod(clazz, gAudioPolicyEventHandlerMethods.postDynPolicyEventFromNative,
403 event, zestring, val);
404
405 env->ReleaseStringUTFChars(zestring, zechars);
406 env->DeleteLocalRef(clazz);
407 }
408
409 static void
android_media_AudioSystem_recording_callback(int event,const record_client_info_t * clientInfo,const audio_config_base_t * clientConfig,const audio_config_base_t * deviceConfig,audio_patch_handle_t patchHandle)410 android_media_AudioSystem_recording_callback(int event, const record_client_info_t *clientInfo,
411 const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig,
412 audio_patch_handle_t patchHandle)
413 {
414 JNIEnv *env = AndroidRuntime::getJNIEnv();
415 if (env == NULL) {
416 return;
417 }
418 if (clientInfo == NULL || clientConfig == NULL || deviceConfig == NULL) {
419 ALOGE("Unexpected null client/device info or configurations in recording callback");
420 return;
421 }
422
423 // create an array for 2*3 integers to store the record configurations (client + device)
424 // plus 1 integer for the patch handle
425 const int REC_PARAM_SIZE = 7;
426 jintArray recParamArray = env->NewIntArray(REC_PARAM_SIZE);
427 if (recParamArray == NULL) {
428 ALOGE("recording callback: Couldn't allocate int array for configuration data");
429 return;
430 }
431 jint recParamData[REC_PARAM_SIZE];
432 recParamData[0] = (jint) audioFormatFromNative(clientConfig->format);
433 // FIXME this doesn't support index-based masks
434 recParamData[1] = (jint) inChannelMaskFromNative(clientConfig->channel_mask);
435 recParamData[2] = (jint) clientConfig->sample_rate;
436 recParamData[3] = (jint) audioFormatFromNative(deviceConfig->format);
437 // FIXME this doesn't support index-based masks
438 recParamData[4] = (jint) inChannelMaskFromNative(deviceConfig->channel_mask);
439 recParamData[5] = (jint) deviceConfig->sample_rate;
440 recParamData[6] = (jint) patchHandle;
441 env->SetIntArrayRegion(recParamArray, 0, REC_PARAM_SIZE, recParamData);
442
443 // callback into java
444 jclass clazz = env->FindClass(kClassPathName);
445 env->CallStaticVoidMethod(clazz,
446 gAudioPolicyEventHandlerMethods.postRecordConfigEventFromNative,
447 event, (jint) clientInfo->uid, clientInfo->session, clientInfo->source, recParamArray);
448 env->DeleteLocalRef(clazz);
449
450 env->DeleteLocalRef(recParamArray);
451 }
452
453 static jint
android_media_AudioSystem_setDeviceConnectionState(JNIEnv * env,jobject thiz,jint device,jint state,jstring device_address,jstring device_name)454 android_media_AudioSystem_setDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jint state, jstring device_address, jstring device_name)
455 {
456 const char *c_address = env->GetStringUTFChars(device_address, NULL);
457 const char *c_name = env->GetStringUTFChars(device_name, NULL);
458 int status = check_AudioSystem_Command(AudioSystem::setDeviceConnectionState(static_cast <audio_devices_t>(device),
459 static_cast <audio_policy_dev_state_t>(state),
460 c_address, c_name));
461 env->ReleaseStringUTFChars(device_address, c_address);
462 env->ReleaseStringUTFChars(device_name, c_name);
463 return (jint) status;
464 }
465
466 static jint
android_media_AudioSystem_getDeviceConnectionState(JNIEnv * env,jobject thiz,jint device,jstring device_address)467 android_media_AudioSystem_getDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jstring device_address)
468 {
469 const char *c_address = env->GetStringUTFChars(device_address, NULL);
470 int state = static_cast <int>(AudioSystem::getDeviceConnectionState(static_cast <audio_devices_t>(device),
471 c_address));
472 env->ReleaseStringUTFChars(device_address, c_address);
473 return (jint) state;
474 }
475
476 static jint
android_media_AudioSystem_handleDeviceConfigChange(JNIEnv * env,jobject thiz,jint device,jstring device_address,jstring device_name)477 android_media_AudioSystem_handleDeviceConfigChange(JNIEnv *env, jobject thiz, jint device, jstring device_address, jstring device_name)
478 {
479 const char *c_address = env->GetStringUTFChars(device_address, NULL);
480 const char *c_name = env->GetStringUTFChars(device_name, NULL);
481 int status = check_AudioSystem_Command(AudioSystem::handleDeviceConfigChange(static_cast <audio_devices_t>(device),
482 c_address, c_name));
483 env->ReleaseStringUTFChars(device_address, c_address);
484 env->ReleaseStringUTFChars(device_name, c_name);
485 return (jint) status;
486 }
487
488 static jint
android_media_AudioSystem_setPhoneState(JNIEnv * env,jobject thiz,jint state)489 android_media_AudioSystem_setPhoneState(JNIEnv *env, jobject thiz, jint state)
490 {
491 return (jint) check_AudioSystem_Command(AudioSystem::setPhoneState((audio_mode_t) state));
492 }
493
494 static jint
android_media_AudioSystem_setForceUse(JNIEnv * env,jobject thiz,jint usage,jint config)495 android_media_AudioSystem_setForceUse(JNIEnv *env, jobject thiz, jint usage, jint config)
496 {
497 return (jint) check_AudioSystem_Command(AudioSystem::setForceUse(static_cast <audio_policy_force_use_t>(usage),
498 static_cast <audio_policy_forced_cfg_t>(config)));
499 }
500
501 static jint
android_media_AudioSystem_getForceUse(JNIEnv * env,jobject thiz,jint usage)502 android_media_AudioSystem_getForceUse(JNIEnv *env, jobject thiz, jint usage)
503 {
504 return static_cast <jint>(AudioSystem::getForceUse(static_cast <audio_policy_force_use_t>(usage)));
505 }
506
507 static jint
android_media_AudioSystem_initStreamVolume(JNIEnv * env,jobject thiz,jint stream,jint indexMin,jint indexMax)508 android_media_AudioSystem_initStreamVolume(JNIEnv *env, jobject thiz, jint stream, jint indexMin, jint indexMax)
509 {
510 return (jint) check_AudioSystem_Command(AudioSystem::initStreamVolume(static_cast <audio_stream_type_t>(stream),
511 indexMin,
512 indexMax));
513 }
514
515 static jint
android_media_AudioSystem_setStreamVolumeIndex(JNIEnv * env,jobject thiz,jint stream,jint index,jint device)516 android_media_AudioSystem_setStreamVolumeIndex(JNIEnv *env,
517 jobject thiz,
518 jint stream,
519 jint index,
520 jint device)
521 {
522 return (jint) check_AudioSystem_Command(
523 AudioSystem::setStreamVolumeIndex(static_cast <audio_stream_type_t>(stream),
524 index,
525 (audio_devices_t)device));
526 }
527
528 static jint
android_media_AudioSystem_getStreamVolumeIndex(JNIEnv * env,jobject thiz,jint stream,jint device)529 android_media_AudioSystem_getStreamVolumeIndex(JNIEnv *env,
530 jobject thiz,
531 jint stream,
532 jint device)
533 {
534 int index;
535 if (AudioSystem::getStreamVolumeIndex(static_cast <audio_stream_type_t>(stream),
536 &index,
537 (audio_devices_t)device)
538 != NO_ERROR) {
539 index = -1;
540 }
541 return (jint) index;
542 }
543
544 static jint
android_media_AudioSystem_setMasterVolume(JNIEnv * env,jobject thiz,jfloat value)545 android_media_AudioSystem_setMasterVolume(JNIEnv *env, jobject thiz, jfloat value)
546 {
547 return (jint) check_AudioSystem_Command(AudioSystem::setMasterVolume(value));
548 }
549
550 static jfloat
android_media_AudioSystem_getMasterVolume(JNIEnv * env,jobject thiz)551 android_media_AudioSystem_getMasterVolume(JNIEnv *env, jobject thiz)
552 {
553 float value;
554 if (AudioSystem::getMasterVolume(&value) != NO_ERROR) {
555 value = -1.0;
556 }
557 return value;
558 }
559
560 static jint
android_media_AudioSystem_setMasterMute(JNIEnv * env,jobject thiz,jboolean mute)561 android_media_AudioSystem_setMasterMute(JNIEnv *env, jobject thiz, jboolean mute)
562 {
563 return (jint) check_AudioSystem_Command(AudioSystem::setMasterMute(mute));
564 }
565
566 static jboolean
android_media_AudioSystem_getMasterMute(JNIEnv * env,jobject thiz)567 android_media_AudioSystem_getMasterMute(JNIEnv *env, jobject thiz)
568 {
569 bool mute;
570 if (AudioSystem::getMasterMute(&mute) != NO_ERROR) {
571 mute = false;
572 }
573 return mute;
574 }
575
576 static jint
android_media_AudioSystem_setMasterMono(JNIEnv * env,jobject thiz,jboolean mono)577 android_media_AudioSystem_setMasterMono(JNIEnv *env, jobject thiz, jboolean mono)
578 {
579 return (jint) check_AudioSystem_Command(AudioSystem::setMasterMono(mono));
580 }
581
582 static jboolean
android_media_AudioSystem_getMasterMono(JNIEnv * env,jobject thiz)583 android_media_AudioSystem_getMasterMono(JNIEnv *env, jobject thiz)
584 {
585 bool mono;
586 if (AudioSystem::getMasterMono(&mono) != NO_ERROR) {
587 mono = false;
588 }
589 return mono;
590 }
591
592 static jint
android_media_AudioSystem_getDevicesForStream(JNIEnv * env,jobject thiz,jint stream)593 android_media_AudioSystem_getDevicesForStream(JNIEnv *env, jobject thiz, jint stream)
594 {
595 return (jint) AudioSystem::getDevicesForStream(static_cast <audio_stream_type_t>(stream));
596 }
597
598 static jint
android_media_AudioSystem_getPrimaryOutputSamplingRate(JNIEnv * env,jobject clazz)599 android_media_AudioSystem_getPrimaryOutputSamplingRate(JNIEnv *env, jobject clazz)
600 {
601 return (jint) AudioSystem::getPrimaryOutputSamplingRate();
602 }
603
604 static jint
android_media_AudioSystem_getPrimaryOutputFrameCount(JNIEnv * env,jobject clazz)605 android_media_AudioSystem_getPrimaryOutputFrameCount(JNIEnv *env, jobject clazz)
606 {
607 return (jint) AudioSystem::getPrimaryOutputFrameCount();
608 }
609
610 static jint
android_media_AudioSystem_getOutputLatency(JNIEnv * env,jobject clazz,jint stream)611 android_media_AudioSystem_getOutputLatency(JNIEnv *env, jobject clazz, jint stream)
612 {
613 uint32_t afLatency;
614 if (AudioSystem::getOutputLatency(&afLatency, static_cast <audio_stream_type_t>(stream))
615 != NO_ERROR) {
616 afLatency = -1;
617 }
618 return (jint) afLatency;
619 }
620
621 static jint
android_media_AudioSystem_setLowRamDevice(JNIEnv * env,jobject clazz,jboolean isLowRamDevice,jlong totalMemory)622 android_media_AudioSystem_setLowRamDevice(
623 JNIEnv *env, jobject clazz, jboolean isLowRamDevice, jlong totalMemory)
624 {
625 return (jint) AudioSystem::setLowRamDevice((bool) isLowRamDevice, (int64_t) totalMemory);
626 }
627
628 static jint
android_media_AudioSystem_checkAudioFlinger(JNIEnv * env,jobject clazz)629 android_media_AudioSystem_checkAudioFlinger(JNIEnv *env, jobject clazz)
630 {
631 return (jint) check_AudioSystem_Command(AudioSystem::checkAudioFlinger());
632 }
633
634
useInChannelMask(audio_port_type_t type,audio_port_role_t role)635 static bool useInChannelMask(audio_port_type_t type, audio_port_role_t role)
636 {
637 return ((type == AUDIO_PORT_TYPE_DEVICE) && (role == AUDIO_PORT_ROLE_SOURCE)) ||
638 ((type == AUDIO_PORT_TYPE_MIX) && (role == AUDIO_PORT_ROLE_SINK));
639 }
640
convertAudioGainConfigToNative(JNIEnv * env,struct audio_gain_config * nAudioGainConfig,const jobject jAudioGainConfig,bool useInMask)641 static void convertAudioGainConfigToNative(JNIEnv *env,
642 struct audio_gain_config *nAudioGainConfig,
643 const jobject jAudioGainConfig,
644 bool useInMask)
645 {
646 nAudioGainConfig->index = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mIndex);
647 nAudioGainConfig->mode = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mMode);
648 ALOGV("convertAudioGainConfigToNative got gain index %d", nAudioGainConfig->index);
649 jint jMask = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mChannelMask);
650 audio_channel_mask_t nMask;
651 if (useInMask) {
652 nMask = inChannelMaskToNative(jMask);
653 ALOGV("convertAudioGainConfigToNative IN mask java %x native %x", jMask, nMask);
654 } else {
655 nMask = outChannelMaskToNative(jMask);
656 ALOGV("convertAudioGainConfigToNative OUT mask java %x native %x", jMask, nMask);
657 }
658 nAudioGainConfig->channel_mask = nMask;
659 nAudioGainConfig->ramp_duration_ms = env->GetIntField(jAudioGainConfig,
660 gAudioGainConfigFields.mRampDurationMs);
661 jintArray jValues = (jintArray)env->GetObjectField(jAudioGainConfig,
662 gAudioGainConfigFields.mValues);
663 int *nValues = env->GetIntArrayElements(jValues, NULL);
664 size_t size = env->GetArrayLength(jValues);
665 memcpy(nAudioGainConfig->values, nValues, size * sizeof(int));
666 env->DeleteLocalRef(jValues);
667 }
668
669
convertAudioPortConfigToNative(JNIEnv * env,struct audio_port_config * nAudioPortConfig,const jobject jAudioPortConfig,bool useConfigMask)670 static jint convertAudioPortConfigToNative(JNIEnv *env,
671 struct audio_port_config *nAudioPortConfig,
672 const jobject jAudioPortConfig,
673 bool useConfigMask)
674 {
675 jobject jAudioPort = env->GetObjectField(jAudioPortConfig, gAudioPortConfigFields.mPort);
676 jobject jHandle = env->GetObjectField(jAudioPort, gAudioPortFields.mHandle);
677 nAudioPortConfig->id = env->GetIntField(jHandle, gAudioHandleFields.mId);
678 nAudioPortConfig->role = (audio_port_role_t)env->GetIntField(jAudioPort,
679 gAudioPortFields.mRole);
680 if (env->IsInstanceOf(jAudioPort, gAudioDevicePortClass)) {
681 nAudioPortConfig->type = AUDIO_PORT_TYPE_DEVICE;
682 } else if (env->IsInstanceOf(jAudioPort, gAudioMixPortClass)) {
683 nAudioPortConfig->type = AUDIO_PORT_TYPE_MIX;
684 } else {
685 env->DeleteLocalRef(jAudioPort);
686 env->DeleteLocalRef(jHandle);
687 return (jint)AUDIO_JAVA_ERROR;
688 }
689 ALOGV("convertAudioPortConfigToNative handle %d role %d type %d",
690 nAudioPortConfig->id, nAudioPortConfig->role, nAudioPortConfig->type);
691
692 unsigned int configMask = 0;
693
694 nAudioPortConfig->sample_rate = env->GetIntField(jAudioPortConfig,
695 gAudioPortConfigFields.mSamplingRate);
696 if (nAudioPortConfig->sample_rate != 0) {
697 configMask |= AUDIO_PORT_CONFIG_SAMPLE_RATE;
698 }
699
700 bool useInMask = useInChannelMask(nAudioPortConfig->type, nAudioPortConfig->role);
701 audio_channel_mask_t nMask;
702 jint jMask = env->GetIntField(jAudioPortConfig,
703 gAudioPortConfigFields.mChannelMask);
704 if (useInMask) {
705 nMask = inChannelMaskToNative(jMask);
706 ALOGV("convertAudioPortConfigToNative IN mask java %x native %x", jMask, nMask);
707 } else {
708 nMask = outChannelMaskToNative(jMask);
709 ALOGV("convertAudioPortConfigToNative OUT mask java %x native %x", jMask, nMask);
710 }
711 nAudioPortConfig->channel_mask = nMask;
712 if (nAudioPortConfig->channel_mask != AUDIO_CHANNEL_NONE) {
713 configMask |= AUDIO_PORT_CONFIG_CHANNEL_MASK;
714 }
715
716 jint jFormat = env->GetIntField(jAudioPortConfig, gAudioPortConfigFields.mFormat);
717 audio_format_t nFormat = audioFormatToNative(jFormat);
718 ALOGV("convertAudioPortConfigToNative format %d native %d", jFormat, nFormat);
719 nAudioPortConfig->format = nFormat;
720 if (nAudioPortConfig->format != AUDIO_FORMAT_DEFAULT &&
721 nAudioPortConfig->format != AUDIO_FORMAT_INVALID) {
722 configMask |= AUDIO_PORT_CONFIG_FORMAT;
723 }
724
725 jobject jGain = env->GetObjectField(jAudioPortConfig, gAudioPortConfigFields.mGain);
726 if (jGain != NULL) {
727 convertAudioGainConfigToNative(env, &nAudioPortConfig->gain, jGain, useInMask);
728 env->DeleteLocalRef(jGain);
729 configMask |= AUDIO_PORT_CONFIG_GAIN;
730 } else {
731 ALOGV("convertAudioPortConfigToNative no gain");
732 nAudioPortConfig->gain.index = -1;
733 }
734 if (useConfigMask) {
735 nAudioPortConfig->config_mask = env->GetIntField(jAudioPortConfig,
736 gAudioPortConfigFields.mConfigMask);
737 } else {
738 nAudioPortConfig->config_mask = configMask;
739 }
740 env->DeleteLocalRef(jAudioPort);
741 env->DeleteLocalRef(jHandle);
742 return (jint)AUDIO_JAVA_SUCCESS;
743 }
744
convertAudioPortConfigFromNative(JNIEnv * env,jobject jAudioPort,jobject * jAudioPortConfig,const struct audio_port_config * nAudioPortConfig)745 static jint convertAudioPortConfigFromNative(JNIEnv *env,
746 jobject jAudioPort,
747 jobject *jAudioPortConfig,
748 const struct audio_port_config *nAudioPortConfig)
749 {
750 jint jStatus = AUDIO_JAVA_SUCCESS;
751 jobject jAudioGainConfig = NULL;
752 jobject jAudioGain = NULL;
753 jintArray jGainValues;
754 bool audioportCreated = false;
755
756 ALOGV("convertAudioPortConfigFromNative jAudioPort %p", jAudioPort);
757
758 if (jAudioPort == NULL) {
759 jobject jHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
760 nAudioPortConfig->id);
761
762 ALOGV("convertAudioPortConfigFromNative handle %d is a %s", nAudioPortConfig->id,
763 nAudioPortConfig->type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix");
764
765 if (jHandle == NULL) {
766 return (jint)AUDIO_JAVA_ERROR;
767 }
768 // create dummy port and port config objects with just the correct handle
769 // and configuration data. The actual AudioPortConfig objects will be
770 // constructed by java code with correct class type (device, mix etc...)
771 // and reference to AudioPort instance in this client
772 jAudioPort = env->NewObject(gAudioPortClass, gAudioPortCstor,
773 jHandle, // handle
774 0, // role
775 NULL, // name
776 NULL, // samplingRates
777 NULL, // channelMasks
778 NULL, // channelIndexMasks
779 NULL, // formats
780 NULL); // gains
781 env->DeleteLocalRef(jHandle);
782 if (jAudioPort == NULL) {
783 return (jint)AUDIO_JAVA_ERROR;
784 }
785 ALOGV("convertAudioPortConfigFromNative jAudioPort created for handle %d",
786 nAudioPortConfig->id);
787
788 audioportCreated = true;
789 }
790
791 bool useInMask = useInChannelMask(nAudioPortConfig->type, nAudioPortConfig->role);
792
793 audio_channel_mask_t nMask;
794 jint jMask;
795
796 int gainIndex = nAudioPortConfig->gain.index;
797 if (gainIndex >= 0) {
798 ALOGV("convertAudioPortConfigFromNative gain found with index %d mode %x",
799 gainIndex, nAudioPortConfig->gain.mode);
800 if (audioportCreated) {
801 ALOGV("convertAudioPortConfigFromNative creating gain");
802 jAudioGain = env->NewObject(gAudioGainClass, gAudioGainCstor,
803 gainIndex,
804 0,
805 0,
806 0,
807 0,
808 0,
809 0,
810 0,
811 0);
812 if (jAudioGain == NULL) {
813 ALOGV("convertAudioPortConfigFromNative creating gain FAILED");
814 jStatus = (jint)AUDIO_JAVA_ERROR;
815 goto exit;
816 }
817 } else {
818 ALOGV("convertAudioPortConfigFromNative reading gain from port");
819 jobjectArray jGains = (jobjectArray)env->GetObjectField(jAudioPort,
820 gAudioPortFields.mGains);
821 if (jGains == NULL) {
822 ALOGV("convertAudioPortConfigFromNative could not get gains from port");
823 jStatus = (jint)AUDIO_JAVA_ERROR;
824 goto exit;
825 }
826 jAudioGain = env->GetObjectArrayElement(jGains, gainIndex);
827 env->DeleteLocalRef(jGains);
828 if (jAudioGain == NULL) {
829 ALOGV("convertAudioPortConfigFromNative could not get gain at index %d", gainIndex);
830 jStatus = (jint)AUDIO_JAVA_ERROR;
831 goto exit;
832 }
833 }
834 int numValues;
835 if (useInMask) {
836 numValues = audio_channel_count_from_in_mask(nAudioPortConfig->gain.channel_mask);
837 } else {
838 numValues = audio_channel_count_from_out_mask(nAudioPortConfig->gain.channel_mask);
839 }
840 jGainValues = env->NewIntArray(numValues);
841 if (jGainValues == NULL) {
842 ALOGV("convertAudioPortConfigFromNative could not create gain values %d", numValues);
843 jStatus = (jint)AUDIO_JAVA_ERROR;
844 goto exit;
845 }
846 env->SetIntArrayRegion(jGainValues, 0, numValues,
847 nAudioPortConfig->gain.values);
848
849 nMask = nAudioPortConfig->gain.channel_mask;
850 if (useInMask) {
851 jMask = inChannelMaskFromNative(nMask);
852 ALOGV("convertAudioPortConfigFromNative IN mask java %x native %x", jMask, nMask);
853 } else {
854 jMask = outChannelMaskFromNative(nMask);
855 ALOGV("convertAudioPortConfigFromNative OUT mask java %x native %x", jMask, nMask);
856 }
857
858 jAudioGainConfig = env->NewObject(gAudioGainConfigClass,
859 gAudioGainConfigCstor,
860 gainIndex,
861 jAudioGain,
862 nAudioPortConfig->gain.mode,
863 jMask,
864 jGainValues,
865 nAudioPortConfig->gain.ramp_duration_ms);
866 env->DeleteLocalRef(jGainValues);
867 if (jAudioGainConfig == NULL) {
868 ALOGV("convertAudioPortConfigFromNative could not create gain config");
869 jStatus = (jint)AUDIO_JAVA_ERROR;
870 goto exit;
871 }
872 }
873 jclass clazz;
874 jmethodID methodID;
875 if (audioportCreated) {
876 clazz = gAudioPortConfigClass;
877 methodID = gAudioPortConfigCstor;
878 ALOGV("convertAudioPortConfigFromNative building a generic port config");
879 } else {
880 if (env->IsInstanceOf(jAudioPort, gAudioDevicePortClass)) {
881 clazz = gAudioDevicePortConfigClass;
882 methodID = gAudioDevicePortConfigCstor;
883 ALOGV("convertAudioPortConfigFromNative building a device config");
884 } else if (env->IsInstanceOf(jAudioPort, gAudioMixPortClass)) {
885 clazz = gAudioMixPortConfigClass;
886 methodID = gAudioMixPortConfigCstor;
887 ALOGV("convertAudioPortConfigFromNative building a mix config");
888 } else {
889 jStatus = (jint)AUDIO_JAVA_ERROR;
890 goto exit;
891 }
892 }
893 nMask = nAudioPortConfig->channel_mask;
894 if (useInMask) {
895 jMask = inChannelMaskFromNative(nMask);
896 ALOGV("convertAudioPortConfigFromNative IN mask java %x native %x", jMask, nMask);
897 } else {
898 jMask = outChannelMaskFromNative(nMask);
899 ALOGV("convertAudioPortConfigFromNative OUT mask java %x native %x", jMask, nMask);
900 }
901
902 *jAudioPortConfig = env->NewObject(clazz, methodID,
903 jAudioPort,
904 nAudioPortConfig->sample_rate,
905 jMask,
906 audioFormatFromNative(nAudioPortConfig->format),
907 jAudioGainConfig);
908 if (*jAudioPortConfig == NULL) {
909 ALOGV("convertAudioPortConfigFromNative could not create new port config");
910 jStatus = (jint)AUDIO_JAVA_ERROR;
911 } else {
912 ALOGV("convertAudioPortConfigFromNative OK");
913 }
914
915 exit:
916 if (audioportCreated) {
917 env->DeleteLocalRef(jAudioPort);
918 if (jAudioGain != NULL) {
919 env->DeleteLocalRef(jAudioGain);
920 }
921 }
922 if (jAudioGainConfig != NULL) {
923 env->DeleteLocalRef(jAudioGainConfig);
924 }
925 return jStatus;
926 }
927
hasFormat(int * formats,size_t size,int format)928 static bool hasFormat(int* formats, size_t size, int format) {
929 for (size_t index = 0; index < size; index++) {
930 if (formats[index] == format) {
931 return true; // found
932 }
933 }
934 return false; // not found
935 }
936
937 // TODO: pull out to separate file
938 template <typename T, size_t N>
array_size(const T (&)[N])939 static constexpr size_t array_size(const T (&)[N]) {
940 return N;
941 }
942
convertAudioPortFromNative(JNIEnv * env,jobject * jAudioPort,const struct audio_port * nAudioPort)943 static jint convertAudioPortFromNative(JNIEnv *env,
944 jobject *jAudioPort, const struct audio_port *nAudioPort)
945 {
946 jint jStatus = (jint)AUDIO_JAVA_SUCCESS;
947 jintArray jSamplingRates = NULL;
948 jintArray jChannelMasks = NULL;
949 jintArray jChannelIndexMasks = NULL;
950 int* cFormats = NULL;
951 jintArray jFormats = NULL;
952 jobjectArray jGains = NULL;
953 jobject jHandle = NULL;
954 jstring jDeviceName = NULL;
955 bool useInMask;
956 size_t numPositionMasks = 0;
957 size_t numIndexMasks = 0;
958 size_t numUniqueFormats = 0;
959
960 ALOGV("convertAudioPortFromNative id %d role %d type %d name %s",
961 nAudioPort->id, nAudioPort->role, nAudioPort->type, nAudioPort->name);
962
963 // Verify audio port array count info.
964 if (nAudioPort->num_sample_rates > array_size(nAudioPort->sample_rates)
965 || nAudioPort->num_channel_masks > array_size(nAudioPort->channel_masks)
966 || nAudioPort->num_formats > array_size(nAudioPort->formats)
967 || nAudioPort->num_gains > array_size(nAudioPort->gains)) {
968
969 std::stringstream ss;
970 ss << "convertAudioPortFromNative array count out of bounds:"
971 << " num_sample_rates " << nAudioPort->num_sample_rates
972 << " num_channel_masks " << nAudioPort->num_channel_masks
973 << " num_formats " << nAudioPort->num_formats
974 << " num_gains " << nAudioPort->num_gains
975 ;
976 std::string s = ss.str();
977
978 // Prefer to log through Java wtf instead of native ALOGE.
979 ScopedLocalRef<jclass> jLogClass(env, env->FindClass("android/util/Log"));
980 jmethodID jWtfId = (jLogClass.get() == nullptr)
981 ? nullptr
982 : env->GetStaticMethodID(jLogClass.get(), "wtf",
983 "(Ljava/lang/String;Ljava/lang/String;)I");
984 if (jWtfId != nullptr) {
985 ScopedLocalRef<jstring> jMessage(env, env->NewStringUTF(s.c_str()));
986 ScopedLocalRef<jstring> jTag(env, env->NewStringUTF(LOG_TAG));
987 (void)env->CallStaticIntMethod(jLogClass.get(), jWtfId, jTag.get(), jMessage.get());
988 } else {
989 ALOGE("%s", s.c_str());
990 }
991 jStatus = (jint)AUDIO_JAVA_ERROR;
992 goto exit;
993 }
994
995 jSamplingRates = env->NewIntArray(nAudioPort->num_sample_rates);
996 if (jSamplingRates == NULL) {
997 jStatus = (jint)AUDIO_JAVA_ERROR;
998 goto exit;
999 }
1000 if (nAudioPort->num_sample_rates) {
1001 env->SetIntArrayRegion(jSamplingRates, 0, nAudioPort->num_sample_rates,
1002 (jint *)nAudioPort->sample_rates);
1003 }
1004
1005 // count up how many masks are positional and indexed
1006 for(size_t index = 0; index < nAudioPort->num_channel_masks; index++) {
1007 const audio_channel_mask_t mask = nAudioPort->channel_masks[index];
1008 if (audio_channel_mask_get_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
1009 numIndexMasks++;
1010 } else {
1011 numPositionMasks++;
1012 }
1013 }
1014
1015 jChannelMasks = env->NewIntArray(numPositionMasks);
1016 if (jChannelMasks == NULL) {
1017 jStatus = (jint)AUDIO_JAVA_ERROR;
1018 goto exit;
1019 }
1020 jChannelIndexMasks = env->NewIntArray(numIndexMasks);
1021 if (jChannelIndexMasks == NULL) {
1022 jStatus = (jint)AUDIO_JAVA_ERROR;
1023 goto exit;
1024 }
1025 useInMask = useInChannelMask(nAudioPort->type, nAudioPort->role);
1026
1027 // put the masks in the output arrays
1028 for (size_t maskIndex = 0, posMaskIndex = 0, indexedMaskIndex = 0;
1029 maskIndex < nAudioPort->num_channel_masks; maskIndex++) {
1030 const audio_channel_mask_t mask = nAudioPort->channel_masks[maskIndex];
1031 if (audio_channel_mask_get_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
1032 jint jMask = audio_channel_mask_get_bits(mask);
1033 env->SetIntArrayRegion(jChannelIndexMasks, indexedMaskIndex++, 1, &jMask);
1034 } else {
1035 jint jMask = useInMask ? inChannelMaskFromNative(mask)
1036 : outChannelMaskFromNative(mask);
1037 env->SetIntArrayRegion(jChannelMasks, posMaskIndex++, 1, &jMask);
1038 }
1039 }
1040
1041 // formats
1042 if (nAudioPort->num_formats != 0) {
1043 cFormats = new int[nAudioPort->num_formats];
1044 for (size_t index = 0; index < nAudioPort->num_formats; index++) {
1045 int format = audioFormatFromNative(nAudioPort->formats[index]);
1046 if (!hasFormat(cFormats, numUniqueFormats, format)) {
1047 cFormats[numUniqueFormats++] = format;
1048 }
1049 }
1050 }
1051 jFormats = env->NewIntArray(numUniqueFormats);
1052 if (jFormats == NULL) {
1053 jStatus = (jint)AUDIO_JAVA_ERROR;
1054 goto exit;
1055 }
1056 if (numUniqueFormats != 0) {
1057 env->SetIntArrayRegion(jFormats, 0, numUniqueFormats, cFormats);
1058 }
1059
1060 // gains
1061 jGains = env->NewObjectArray(nAudioPort->num_gains,
1062 gAudioGainClass, NULL);
1063 if (jGains == NULL) {
1064 jStatus = (jint)AUDIO_JAVA_ERROR;
1065 goto exit;
1066 }
1067
1068 for (size_t j = 0; j < nAudioPort->num_gains; j++) {
1069 audio_channel_mask_t nMask = nAudioPort->gains[j].channel_mask;
1070 jint jMask;
1071 if (useInMask) {
1072 jMask = inChannelMaskFromNative(nMask);
1073 ALOGV("convertAudioPortConfigFromNative IN mask java %x native %x", jMask, nMask);
1074 } else {
1075 jMask = outChannelMaskFromNative(nMask);
1076 ALOGV("convertAudioPortConfigFromNative OUT mask java %x native %x", jMask, nMask);
1077 }
1078
1079 jobject jGain = env->NewObject(gAudioGainClass, gAudioGainCstor,
1080 j,
1081 nAudioPort->gains[j].mode,
1082 jMask,
1083 nAudioPort->gains[j].min_value,
1084 nAudioPort->gains[j].max_value,
1085 nAudioPort->gains[j].default_value,
1086 nAudioPort->gains[j].step_value,
1087 nAudioPort->gains[j].min_ramp_ms,
1088 nAudioPort->gains[j].max_ramp_ms);
1089 if (jGain == NULL) {
1090 jStatus = (jint)AUDIO_JAVA_ERROR;
1091 goto exit;
1092 }
1093 env->SetObjectArrayElement(jGains, j, jGain);
1094 env->DeleteLocalRef(jGain);
1095 }
1096
1097 jHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
1098 nAudioPort->id);
1099 if (jHandle == NULL) {
1100 jStatus = (jint)AUDIO_JAVA_ERROR;
1101 goto exit;
1102 }
1103
1104 jDeviceName = env->NewStringUTF(nAudioPort->name);
1105
1106 if (nAudioPort->type == AUDIO_PORT_TYPE_DEVICE) {
1107 ALOGV("convertAudioPortFromNative is a device %08x", nAudioPort->ext.device.type);
1108 jstring jAddress = env->NewStringUTF(nAudioPort->ext.device.address);
1109 *jAudioPort = env->NewObject(gAudioDevicePortClass, gAudioDevicePortCstor,
1110 jHandle, jDeviceName,
1111 jSamplingRates, jChannelMasks, jChannelIndexMasks,
1112 jFormats, jGains,
1113 nAudioPort->ext.device.type, jAddress);
1114 env->DeleteLocalRef(jAddress);
1115 } else if (nAudioPort->type == AUDIO_PORT_TYPE_MIX) {
1116 ALOGV("convertAudioPortFromNative is a mix");
1117 *jAudioPort = env->NewObject(gAudioMixPortClass, gAudioMixPortCstor,
1118 jHandle, nAudioPort->ext.mix.handle,
1119 nAudioPort->role, jDeviceName,
1120 jSamplingRates, jChannelMasks, jChannelIndexMasks,
1121 jFormats, jGains);
1122 } else {
1123 ALOGE("convertAudioPortFromNative unknown nAudioPort type %d", nAudioPort->type);
1124 jStatus = (jint)AUDIO_JAVA_ERROR;
1125 goto exit;
1126 }
1127 if (*jAudioPort == NULL) {
1128 jStatus = (jint)AUDIO_JAVA_ERROR;
1129 goto exit;
1130 }
1131
1132 jobject jAudioPortConfig;
1133 jStatus = convertAudioPortConfigFromNative(env,
1134 *jAudioPort,
1135 &jAudioPortConfig,
1136 &nAudioPort->active_config);
1137 if (jStatus != AUDIO_JAVA_SUCCESS) {
1138 goto exit;
1139 }
1140
1141 env->SetObjectField(*jAudioPort, gAudioPortFields.mActiveConfig, jAudioPortConfig);
1142
1143 exit:
1144 if (jDeviceName != NULL) {
1145 env->DeleteLocalRef(jDeviceName);
1146 }
1147 if (jSamplingRates != NULL) {
1148 env->DeleteLocalRef(jSamplingRates);
1149 }
1150 if (jChannelMasks != NULL) {
1151 env->DeleteLocalRef(jChannelMasks);
1152 }
1153 if (jChannelIndexMasks != NULL) {
1154 env->DeleteLocalRef(jChannelIndexMasks);
1155 }
1156 if (cFormats != NULL) {
1157 delete[] cFormats;
1158 }
1159 if (jFormats != NULL) {
1160 env->DeleteLocalRef(jFormats);
1161 }
1162 if (jGains != NULL) {
1163 env->DeleteLocalRef(jGains);
1164 }
1165 if (jHandle != NULL) {
1166 env->DeleteLocalRef(jHandle);
1167 }
1168
1169 return jStatus;
1170 }
1171
1172 static jint
android_media_AudioSystem_listAudioPorts(JNIEnv * env,jobject clazz,jobject jPorts,jintArray jGeneration)1173 android_media_AudioSystem_listAudioPorts(JNIEnv *env, jobject clazz,
1174 jobject jPorts, jintArray jGeneration)
1175 {
1176 ALOGV("listAudioPorts");
1177
1178 if (jPorts == NULL) {
1179 ALOGE("listAudioPorts NULL AudioPort ArrayList");
1180 return (jint)AUDIO_JAVA_BAD_VALUE;
1181 }
1182 if (!env->IsInstanceOf(jPorts, gArrayListClass)) {
1183 ALOGE("listAudioPorts not an arraylist");
1184 return (jint)AUDIO_JAVA_BAD_VALUE;
1185 }
1186
1187 if (jGeneration == NULL || env->GetArrayLength(jGeneration) != 1) {
1188 return (jint)AUDIO_JAVA_BAD_VALUE;
1189 }
1190
1191 status_t status;
1192 unsigned int generation1;
1193 unsigned int generation;
1194 unsigned int numPorts;
1195 jint *nGeneration;
1196 struct audio_port *nPorts = NULL;
1197 int attempts = MAX_PORT_GENERATION_SYNC_ATTEMPTS;
1198 jint jStatus;
1199
1200 // get the port count and all the ports until they both return the same generation
1201 do {
1202 if (attempts-- < 0) {
1203 status = TIMED_OUT;
1204 break;
1205 }
1206
1207 numPorts = 0;
1208 status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE,
1209 AUDIO_PORT_TYPE_NONE,
1210 &numPorts,
1211 NULL,
1212 &generation1);
1213 if (status != NO_ERROR) {
1214 ALOGE_IF(status != NO_ERROR, "AudioSystem::listAudioPorts error %d", status);
1215 break;
1216 }
1217 if (numPorts == 0) {
1218 jStatus = (jint)AUDIO_JAVA_SUCCESS;
1219 goto exit;
1220 }
1221 nPorts = (struct audio_port *)realloc(nPorts, numPorts * sizeof(struct audio_port));
1222
1223 status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE,
1224 AUDIO_PORT_TYPE_NONE,
1225 &numPorts,
1226 nPorts,
1227 &generation);
1228 ALOGV("listAudioPorts AudioSystem::listAudioPorts numPorts %d generation %d generation1 %d",
1229 numPorts, generation, generation1);
1230 } while (generation1 != generation && status == NO_ERROR);
1231
1232 jStatus = nativeToJavaStatus(status);
1233 if (jStatus != AUDIO_JAVA_SUCCESS) {
1234 goto exit;
1235 }
1236
1237 for (size_t i = 0; i < numPorts; i++) {
1238 jobject jAudioPort;
1239 jStatus = convertAudioPortFromNative(env, &jAudioPort, &nPorts[i]);
1240 if (jStatus != AUDIO_JAVA_SUCCESS) {
1241 goto exit;
1242 }
1243 env->CallBooleanMethod(jPorts, gArrayListMethods.add, jAudioPort);
1244 }
1245
1246 exit:
1247 nGeneration = env->GetIntArrayElements(jGeneration, NULL);
1248 if (nGeneration == NULL) {
1249 jStatus = (jint)AUDIO_JAVA_ERROR;
1250 } else {
1251 nGeneration[0] = generation1;
1252 env->ReleaseIntArrayElements(jGeneration, nGeneration, 0);
1253 }
1254 free(nPorts);
1255 return jStatus;
1256 }
1257
1258 static int
android_media_AudioSystem_createAudioPatch(JNIEnv * env,jobject clazz,jobjectArray jPatches,jobjectArray jSources,jobjectArray jSinks)1259 android_media_AudioSystem_createAudioPatch(JNIEnv *env, jobject clazz,
1260 jobjectArray jPatches, jobjectArray jSources, jobjectArray jSinks)
1261 {
1262 status_t status;
1263 jint jStatus;
1264
1265 ALOGV("createAudioPatch");
1266 if (jPatches == NULL || jSources == NULL || jSinks == NULL) {
1267 return (jint)AUDIO_JAVA_BAD_VALUE;
1268 }
1269
1270 if (env->GetArrayLength(jPatches) != 1) {
1271 return (jint)AUDIO_JAVA_BAD_VALUE;
1272 }
1273 jint numSources = env->GetArrayLength(jSources);
1274 if (numSources == 0 || numSources > AUDIO_PATCH_PORTS_MAX) {
1275 return (jint)AUDIO_JAVA_BAD_VALUE;
1276 }
1277
1278 jint numSinks = env->GetArrayLength(jSinks);
1279 if (numSinks == 0 || numSinks > AUDIO_PATCH_PORTS_MAX) {
1280 return (jint)AUDIO_JAVA_BAD_VALUE;
1281 }
1282
1283 audio_patch_handle_t handle = (audio_patch_handle_t)0;
1284 jobject jPatch = env->GetObjectArrayElement(jPatches, 0);
1285 jobject jPatchHandle = NULL;
1286 if (jPatch != NULL) {
1287 if (!env->IsInstanceOf(jPatch, gAudioPatchClass)) {
1288 return (jint)AUDIO_JAVA_BAD_VALUE;
1289 }
1290 jPatchHandle = env->GetObjectField(jPatch, gAudioPatchFields.mHandle);
1291 handle = (audio_patch_handle_t)env->GetIntField(jPatchHandle, gAudioHandleFields.mId);
1292 }
1293
1294 struct audio_patch nPatch;
1295
1296 nPatch.id = handle;
1297 nPatch.num_sources = 0;
1298 nPatch.num_sinks = 0;
1299 jobject jSource = NULL;
1300 jobject jSink = NULL;
1301
1302 for (jint i = 0; i < numSources; i++) {
1303 jSource = env->GetObjectArrayElement(jSources, i);
1304 if (!env->IsInstanceOf(jSource, gAudioPortConfigClass)) {
1305 jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
1306 goto exit;
1307 }
1308 jStatus = convertAudioPortConfigToNative(env, &nPatch.sources[i], jSource, false);
1309 env->DeleteLocalRef(jSource);
1310 jSource = NULL;
1311 if (jStatus != AUDIO_JAVA_SUCCESS) {
1312 goto exit;
1313 }
1314 nPatch.num_sources++;
1315 }
1316
1317 for (jint i = 0; i < numSinks; i++) {
1318 jSink = env->GetObjectArrayElement(jSinks, i);
1319 if (!env->IsInstanceOf(jSink, gAudioPortConfigClass)) {
1320 jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
1321 goto exit;
1322 }
1323 jStatus = convertAudioPortConfigToNative(env, &nPatch.sinks[i], jSink, false);
1324 env->DeleteLocalRef(jSink);
1325 jSink = NULL;
1326 if (jStatus != AUDIO_JAVA_SUCCESS) {
1327 goto exit;
1328 }
1329 nPatch.num_sinks++;
1330 }
1331
1332 ALOGV("AudioSystem::createAudioPatch");
1333 status = AudioSystem::createAudioPatch(&nPatch, &handle);
1334 ALOGV("AudioSystem::createAudioPatch() returned %d hande %d", status, handle);
1335
1336 jStatus = nativeToJavaStatus(status);
1337 if (jStatus != AUDIO_JAVA_SUCCESS) {
1338 goto exit;
1339 }
1340
1341 if (jPatchHandle == NULL) {
1342 jPatchHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
1343 handle);
1344 if (jPatchHandle == NULL) {
1345 jStatus = (jint)AUDIO_JAVA_ERROR;
1346 goto exit;
1347 }
1348 jPatch = env->NewObject(gAudioPatchClass, gAudioPatchCstor, jPatchHandle, jSources, jSinks);
1349 if (jPatch == NULL) {
1350 jStatus = (jint)AUDIO_JAVA_ERROR;
1351 goto exit;
1352 }
1353 env->SetObjectArrayElement(jPatches, 0, jPatch);
1354 } else {
1355 env->SetIntField(jPatchHandle, gAudioHandleFields.mId, handle);
1356 }
1357
1358 exit:
1359 if (jPatchHandle != NULL) {
1360 env->DeleteLocalRef(jPatchHandle);
1361 }
1362 if (jPatch != NULL) {
1363 env->DeleteLocalRef(jPatch);
1364 }
1365 if (jSource != NULL) {
1366 env->DeleteLocalRef(jSource);
1367 }
1368 if (jSink != NULL) {
1369 env->DeleteLocalRef(jSink);
1370 }
1371 return jStatus;
1372 }
1373
1374 static jint
android_media_AudioSystem_releaseAudioPatch(JNIEnv * env,jobject clazz,jobject jPatch)1375 android_media_AudioSystem_releaseAudioPatch(JNIEnv *env, jobject clazz,
1376 jobject jPatch)
1377 {
1378 ALOGV("releaseAudioPatch");
1379 if (jPatch == NULL) {
1380 return (jint)AUDIO_JAVA_BAD_VALUE;
1381 }
1382
1383 audio_patch_handle_t handle = (audio_patch_handle_t)0;
1384 jobject jPatchHandle = NULL;
1385 if (!env->IsInstanceOf(jPatch, gAudioPatchClass)) {
1386 return (jint)AUDIO_JAVA_BAD_VALUE;
1387 }
1388 jPatchHandle = env->GetObjectField(jPatch, gAudioPatchFields.mHandle);
1389 handle = (audio_patch_handle_t)env->GetIntField(jPatchHandle, gAudioHandleFields.mId);
1390 env->DeleteLocalRef(jPatchHandle);
1391
1392 ALOGV("AudioSystem::releaseAudioPatch");
1393 status_t status = AudioSystem::releaseAudioPatch(handle);
1394 ALOGV("AudioSystem::releaseAudioPatch() returned %d", status);
1395 jint jStatus = nativeToJavaStatus(status);
1396 return jStatus;
1397 }
1398
1399 static jint
android_media_AudioSystem_listAudioPatches(JNIEnv * env,jobject clazz,jobject jPatches,jintArray jGeneration)1400 android_media_AudioSystem_listAudioPatches(JNIEnv *env, jobject clazz,
1401 jobject jPatches, jintArray jGeneration)
1402 {
1403 ALOGV("listAudioPatches");
1404 if (jPatches == NULL) {
1405 ALOGE("listAudioPatches NULL AudioPatch ArrayList");
1406 return (jint)AUDIO_JAVA_BAD_VALUE;
1407 }
1408 if (!env->IsInstanceOf(jPatches, gArrayListClass)) {
1409 ALOGE("listAudioPatches not an arraylist");
1410 return (jint)AUDIO_JAVA_BAD_VALUE;
1411 }
1412
1413 if (jGeneration == NULL || env->GetArrayLength(jGeneration) != 1) {
1414 return (jint)AUDIO_JAVA_BAD_VALUE;
1415 }
1416
1417 status_t status;
1418 unsigned int generation1;
1419 unsigned int generation;
1420 unsigned int numPatches;
1421 jint *nGeneration;
1422 struct audio_patch *nPatches = NULL;
1423 jobjectArray jSources = NULL;
1424 jobject jSource = NULL;
1425 jobjectArray jSinks = NULL;
1426 jobject jSink = NULL;
1427 jobject jPatch = NULL;
1428 int attempts = MAX_PORT_GENERATION_SYNC_ATTEMPTS;
1429 jint jStatus;
1430
1431 // get the patch count and all the patches until they both return the same generation
1432 do {
1433 if (attempts-- < 0) {
1434 status = TIMED_OUT;
1435 break;
1436 }
1437
1438 numPatches = 0;
1439 status = AudioSystem::listAudioPatches(&numPatches,
1440 NULL,
1441 &generation1);
1442 if (status != NO_ERROR) {
1443 ALOGE_IF(status != NO_ERROR, "listAudioPatches AudioSystem::listAudioPatches error %d",
1444 status);
1445 break;
1446 }
1447 if (numPatches == 0) {
1448 jStatus = (jint)AUDIO_JAVA_SUCCESS;
1449 goto exit;
1450 }
1451
1452 nPatches = (struct audio_patch *)realloc(nPatches, numPatches * sizeof(struct audio_patch));
1453
1454 status = AudioSystem::listAudioPatches(&numPatches,
1455 nPatches,
1456 &generation);
1457 ALOGV("listAudioPatches AudioSystem::listAudioPatches numPatches %d generation %d generation1 %d",
1458 numPatches, generation, generation1);
1459
1460 } while (generation1 != generation && status == NO_ERROR);
1461
1462 jStatus = nativeToJavaStatus(status);
1463 if (jStatus != AUDIO_JAVA_SUCCESS) {
1464 goto exit;
1465 }
1466
1467 for (size_t i = 0; i < numPatches; i++) {
1468 jobject patchHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
1469 nPatches[i].id);
1470 if (patchHandle == NULL) {
1471 jStatus = AUDIO_JAVA_ERROR;
1472 goto exit;
1473 }
1474 ALOGV("listAudioPatches patch %zu num_sources %d num_sinks %d",
1475 i, nPatches[i].num_sources, nPatches[i].num_sinks);
1476
1477 env->SetIntField(patchHandle, gAudioHandleFields.mId, nPatches[i].id);
1478
1479 // load sources
1480 jSources = env->NewObjectArray(nPatches[i].num_sources,
1481 gAudioPortConfigClass, NULL);
1482 if (jSources == NULL) {
1483 jStatus = AUDIO_JAVA_ERROR;
1484 goto exit;
1485 }
1486
1487 for (size_t j = 0; j < nPatches[i].num_sources; j++) {
1488 jStatus = convertAudioPortConfigFromNative(env,
1489 NULL,
1490 &jSource,
1491 &nPatches[i].sources[j]);
1492 if (jStatus != AUDIO_JAVA_SUCCESS) {
1493 goto exit;
1494 }
1495 env->SetObjectArrayElement(jSources, j, jSource);
1496 env->DeleteLocalRef(jSource);
1497 jSource = NULL;
1498 ALOGV("listAudioPatches patch %zu source %zu is a %s handle %d",
1499 i, j,
1500 nPatches[i].sources[j].type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix",
1501 nPatches[i].sources[j].id);
1502 }
1503 // load sinks
1504 jSinks = env->NewObjectArray(nPatches[i].num_sinks,
1505 gAudioPortConfigClass, NULL);
1506 if (jSinks == NULL) {
1507 jStatus = AUDIO_JAVA_ERROR;
1508 goto exit;
1509 }
1510
1511 for (size_t j = 0; j < nPatches[i].num_sinks; j++) {
1512 jStatus = convertAudioPortConfigFromNative(env,
1513 NULL,
1514 &jSink,
1515 &nPatches[i].sinks[j]);
1516
1517 if (jStatus != AUDIO_JAVA_SUCCESS) {
1518 goto exit;
1519 }
1520 env->SetObjectArrayElement(jSinks, j, jSink);
1521 env->DeleteLocalRef(jSink);
1522 jSink = NULL;
1523 ALOGV("listAudioPatches patch %zu sink %zu is a %s handle %d",
1524 i, j,
1525 nPatches[i].sinks[j].type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix",
1526 nPatches[i].sinks[j].id);
1527 }
1528
1529 jPatch = env->NewObject(gAudioPatchClass, gAudioPatchCstor,
1530 patchHandle, jSources, jSinks);
1531 env->DeleteLocalRef(jSources);
1532 jSources = NULL;
1533 env->DeleteLocalRef(jSinks);
1534 jSinks = NULL;
1535 if (jPatch == NULL) {
1536 jStatus = AUDIO_JAVA_ERROR;
1537 goto exit;
1538 }
1539 env->CallBooleanMethod(jPatches, gArrayListMethods.add, jPatch);
1540 env->DeleteLocalRef(jPatch);
1541 jPatch = NULL;
1542 }
1543
1544 exit:
1545
1546 nGeneration = env->GetIntArrayElements(jGeneration, NULL);
1547 if (nGeneration == NULL) {
1548 jStatus = AUDIO_JAVA_ERROR;
1549 } else {
1550 nGeneration[0] = generation1;
1551 env->ReleaseIntArrayElements(jGeneration, nGeneration, 0);
1552 }
1553
1554 if (jSources != NULL) {
1555 env->DeleteLocalRef(jSources);
1556 }
1557 if (jSource != NULL) {
1558 env->DeleteLocalRef(jSource);
1559 }
1560 if (jSinks != NULL) {
1561 env->DeleteLocalRef(jSinks);
1562 }
1563 if (jSink != NULL) {
1564 env->DeleteLocalRef(jSink);
1565 }
1566 if (jPatch != NULL) {
1567 env->DeleteLocalRef(jPatch);
1568 }
1569 free(nPatches);
1570 return jStatus;
1571 }
1572
1573 static jint
android_media_AudioSystem_setAudioPortConfig(JNIEnv * env,jobject clazz,jobject jAudioPortConfig)1574 android_media_AudioSystem_setAudioPortConfig(JNIEnv *env, jobject clazz,
1575 jobject jAudioPortConfig)
1576 {
1577 ALOGV("setAudioPortConfig");
1578 if (jAudioPortConfig == NULL) {
1579 return AUDIO_JAVA_BAD_VALUE;
1580 }
1581 if (!env->IsInstanceOf(jAudioPortConfig, gAudioPortConfigClass)) {
1582 return AUDIO_JAVA_BAD_VALUE;
1583 }
1584 struct audio_port_config nAudioPortConfig;
1585 jint jStatus = convertAudioPortConfigToNative(env, &nAudioPortConfig, jAudioPortConfig, true);
1586 if (jStatus != AUDIO_JAVA_SUCCESS) {
1587 return jStatus;
1588 }
1589 status_t status = AudioSystem::setAudioPortConfig(&nAudioPortConfig);
1590 ALOGV("AudioSystem::setAudioPortConfig() returned %d", status);
1591 jStatus = nativeToJavaStatus(status);
1592 return jStatus;
1593 }
1594
1595 static void
android_media_AudioSystem_eventHandlerSetup(JNIEnv * env,jobject thiz,jobject weak_this)1596 android_media_AudioSystem_eventHandlerSetup(JNIEnv *env, jobject thiz, jobject weak_this)
1597 {
1598 ALOGV("eventHandlerSetup");
1599
1600 sp<JNIAudioPortCallback> callback = new JNIAudioPortCallback(env, thiz, weak_this);
1601
1602 if (AudioSystem::addAudioPortCallback(callback) == NO_ERROR) {
1603 setJniCallback(env, thiz, callback);
1604 }
1605 }
1606
1607 static void
android_media_AudioSystem_eventHandlerFinalize(JNIEnv * env,jobject thiz)1608 android_media_AudioSystem_eventHandlerFinalize(JNIEnv *env, jobject thiz)
1609 {
1610 ALOGV("eventHandlerFinalize");
1611
1612 sp<JNIAudioPortCallback> callback = setJniCallback(env, thiz, 0);
1613
1614 if (callback != 0) {
1615 AudioSystem::removeAudioPortCallback(callback);
1616 }
1617 }
1618
1619 static jint
android_media_AudioSystem_getAudioHwSyncForSession(JNIEnv * env,jobject thiz,jint sessionId)1620 android_media_AudioSystem_getAudioHwSyncForSession(JNIEnv *env, jobject thiz, jint sessionId)
1621 {
1622 return (jint) AudioSystem::getAudioHwSyncForSession((audio_session_t) sessionId);
1623 }
1624
1625 static void
android_media_AudioSystem_registerDynPolicyCallback(JNIEnv * env,jobject thiz)1626 android_media_AudioSystem_registerDynPolicyCallback(JNIEnv *env, jobject thiz)
1627 {
1628 AudioSystem::setDynPolicyCallback(android_media_AudioSystem_dyn_policy_callback);
1629 }
1630
1631 static void
android_media_AudioSystem_registerRecordingCallback(JNIEnv * env,jobject thiz)1632 android_media_AudioSystem_registerRecordingCallback(JNIEnv *env, jobject thiz)
1633 {
1634 AudioSystem::setRecordConfigCallback(android_media_AudioSystem_recording_callback);
1635 }
1636
1637
convertAudioMixToNative(JNIEnv * env,AudioMix * nAudioMix,const jobject jAudioMix)1638 static jint convertAudioMixToNative(JNIEnv *env,
1639 AudioMix *nAudioMix,
1640 const jobject jAudioMix)
1641 {
1642 nAudioMix->mMixType = env->GetIntField(jAudioMix, gAudioMixFields.mMixType);
1643 nAudioMix->mRouteFlags = env->GetIntField(jAudioMix, gAudioMixFields.mRouteFlags);
1644 nAudioMix->mDeviceType = (audio_devices_t)
1645 env->GetIntField(jAudioMix, gAudioMixFields.mDeviceType);
1646
1647 jstring jDeviceAddress = (jstring)env->GetObjectField(jAudioMix,
1648 gAudioMixFields.mDeviceAddress);
1649 const char *nDeviceAddress = env->GetStringUTFChars(jDeviceAddress, NULL);
1650 nAudioMix->mDeviceAddress = String8(nDeviceAddress);
1651 env->ReleaseStringUTFChars(jDeviceAddress, nDeviceAddress);
1652 env->DeleteLocalRef(jDeviceAddress);
1653
1654 nAudioMix->mCbFlags = env->GetIntField(jAudioMix, gAudioMixFields.mCallbackFlags);
1655
1656 jobject jFormat = env->GetObjectField(jAudioMix, gAudioMixFields.mFormat);
1657 nAudioMix->mFormat.sample_rate = env->GetIntField(jFormat,
1658 gAudioFormatFields.mSampleRate);
1659 nAudioMix->mFormat.channel_mask = outChannelMaskToNative(env->GetIntField(jFormat,
1660 gAudioFormatFields.mChannelMask));
1661 nAudioMix->mFormat.format = audioFormatToNative(env->GetIntField(jFormat,
1662 gAudioFormatFields.mEncoding));
1663 env->DeleteLocalRef(jFormat);
1664
1665 jobject jRule = env->GetObjectField(jAudioMix, gAudioMixFields.mRule);
1666 jobject jRuleCriteria = env->GetObjectField(jRule, gAudioMixingRuleFields.mCriteria);
1667 env->DeleteLocalRef(jRule);
1668 jobjectArray jCriteria = (jobjectArray)env->CallObjectMethod(jRuleCriteria,
1669 gArrayListMethods.toArray);
1670 env->DeleteLocalRef(jRuleCriteria);
1671
1672 jint numCriteria = env->GetArrayLength(jCriteria);
1673 if (numCriteria > MAX_CRITERIA_PER_MIX) {
1674 numCriteria = MAX_CRITERIA_PER_MIX;
1675 }
1676
1677 for (jint i = 0; i < numCriteria; i++) {
1678 AudioMixMatchCriterion nCriterion;
1679
1680 jobject jCriterion = env->GetObjectArrayElement(jCriteria, i);
1681
1682 nCriterion.mRule = env->GetIntField(jCriterion, gAudioMixMatchCriterionFields.mRule);
1683
1684 const uint32_t match_rule = nCriterion.mRule & ~RULE_EXCLUSION_MASK;
1685 switch (match_rule) {
1686 case RULE_MATCH_UID:
1687 nCriterion.mValue.mUid = env->GetIntField(jCriterion,
1688 gAudioMixMatchCriterionFields.mIntProp);
1689 break;
1690 case RULE_MATCH_ATTRIBUTE_USAGE:
1691 case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET: {
1692 jobject jAttributes = env->GetObjectField(jCriterion, gAudioMixMatchCriterionFields.mAttr);
1693 if (match_rule == RULE_MATCH_ATTRIBUTE_USAGE) {
1694 nCriterion.mValue.mUsage = (audio_usage_t)env->GetIntField(jAttributes,
1695 gAudioAttributesFields.mUsage);
1696 } else {
1697 nCriterion.mValue.mSource = (audio_source_t)env->GetIntField(jAttributes,
1698 gAudioAttributesFields.mSource);
1699 }
1700 env->DeleteLocalRef(jAttributes);
1701 }
1702 break;
1703 }
1704
1705 nAudioMix->mCriteria.add(nCriterion);
1706 env->DeleteLocalRef(jCriterion);
1707 }
1708
1709 env->DeleteLocalRef(jCriteria);
1710
1711 return (jint)AUDIO_JAVA_SUCCESS;
1712 }
1713
1714 static jint
android_media_AudioSystem_registerPolicyMixes(JNIEnv * env,jobject clazz,jobject jMixesList,jboolean registration)1715 android_media_AudioSystem_registerPolicyMixes(JNIEnv *env, jobject clazz,
1716 jobject jMixesList, jboolean registration)
1717 {
1718 ALOGV("registerPolicyMixes");
1719
1720 if (jMixesList == NULL) {
1721 return (jint)AUDIO_JAVA_BAD_VALUE;
1722 }
1723 if (!env->IsInstanceOf(jMixesList, gArrayListClass)) {
1724 return (jint)AUDIO_JAVA_BAD_VALUE;
1725 }
1726 jobjectArray jMixes = (jobjectArray)env->CallObjectMethod(jMixesList,
1727 gArrayListMethods.toArray);
1728 jint numMixes = env->GetArrayLength(jMixes);
1729 if (numMixes > MAX_MIXES_PER_POLICY) {
1730 numMixes = MAX_MIXES_PER_POLICY;
1731 }
1732
1733 status_t status;
1734 jint jStatus;
1735 jobject jAudioMix = NULL;
1736 Vector <AudioMix> mixes;
1737 for (jint i = 0; i < numMixes; i++) {
1738 jAudioMix = env->GetObjectArrayElement(jMixes, i);
1739 if (!env->IsInstanceOf(jAudioMix, gAudioMixClass)) {
1740 jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
1741 goto exit;
1742 }
1743 AudioMix mix;
1744 jStatus = convertAudioMixToNative(env, &mix, jAudioMix);
1745 env->DeleteLocalRef(jAudioMix);
1746 jAudioMix = NULL;
1747 if (jStatus != AUDIO_JAVA_SUCCESS) {
1748 goto exit;
1749 }
1750 mixes.add(mix);
1751 }
1752
1753 ALOGV("AudioSystem::registerPolicyMixes numMixes %d registration %d", numMixes, registration);
1754 status = AudioSystem::registerPolicyMixes(mixes, registration);
1755 ALOGV("AudioSystem::registerPolicyMixes() returned %d", status);
1756
1757 jStatus = nativeToJavaStatus(status);
1758 if (jStatus != AUDIO_JAVA_SUCCESS) {
1759 goto exit;
1760 }
1761
1762 exit:
1763 if (jAudioMix != NULL) {
1764 env->DeleteLocalRef(jAudioMix);
1765 }
1766 return jStatus;
1767 }
1768
1769 static jint
android_media_AudioSystem_systemReady(JNIEnv * env,jobject thiz)1770 android_media_AudioSystem_systemReady(JNIEnv *env, jobject thiz)
1771 {
1772 return nativeToJavaStatus(AudioSystem::systemReady());
1773 }
1774
1775 static jfloat
android_media_AudioSystem_getStreamVolumeDB(JNIEnv * env,jobject thiz,jint stream,jint index,jint device)1776 android_media_AudioSystem_getStreamVolumeDB(JNIEnv *env, jobject thiz,
1777 jint stream, jint index, jint device)
1778 {
1779 return (jfloat)AudioSystem::getStreamVolumeDB((audio_stream_type_t)stream,
1780 (int)index,
1781 (audio_devices_t)device);
1782 }
1783
1784 static jboolean
android_media_AudioSystem_isOffloadSupported(JNIEnv * env,jobject thiz,jint encoding,jint sampleRate,jint channelMask,jint channelIndexMask)1785 android_media_AudioSystem_isOffloadSupported(JNIEnv *env, jobject thiz,
1786 jint encoding, jint sampleRate, jint channelMask, jint channelIndexMask)
1787 {
1788 audio_offload_info_t format = AUDIO_INFO_INITIALIZER;
1789 format.format = (audio_format_t) audioFormatToNative(encoding);
1790 format.sample_rate = (uint32_t) sampleRate;
1791 format.channel_mask = nativeChannelMaskFromJavaChannelMasks(channelMask, channelIndexMask);
1792 format.stream_type = AUDIO_STREAM_MUSIC;
1793 format.has_video = false;
1794 format.is_streaming = false;
1795 // offload duration unknown at this point:
1796 // client side code cannot access "audio.offload.min.duration.secs" property to make a query
1797 // agnostic of duration, so using acceptable estimate of 2mn
1798 format.duration_us = 120 * 1000000;
1799 return AudioSystem::isOffloadSupported(format);
1800 }
1801
1802 static jint
android_media_AudioSystem_getMicrophones(JNIEnv * env,jobject thiz,jobject jMicrophonesInfo)1803 android_media_AudioSystem_getMicrophones(JNIEnv *env, jobject thiz, jobject jMicrophonesInfo)
1804 {
1805 ALOGV("getMicrophones");
1806
1807 if (jMicrophonesInfo == NULL) {
1808 ALOGE("jMicrophonesInfo NULL MicrophoneInfo ArrayList");
1809 return (jint)AUDIO_JAVA_BAD_VALUE;
1810 }
1811 if (!env->IsInstanceOf(jMicrophonesInfo, gArrayListClass)) {
1812 ALOGE("getMicrophones not an arraylist");
1813 return (jint)AUDIO_JAVA_BAD_VALUE;
1814 }
1815
1816 jint jStatus;
1817 std::vector<media::MicrophoneInfo> microphones;
1818 status_t status = AudioSystem::getMicrophones(µphones);
1819 if (status != NO_ERROR) {
1820 ALOGE_IF(status != NO_ERROR, "AudioSystem::getMicrophones error %d", status);
1821 jStatus = nativeToJavaStatus(status);
1822 return jStatus;
1823 }
1824 if (microphones.size() == 0) {
1825 jStatus = (jint)AUDIO_JAVA_SUCCESS;
1826 return jStatus;
1827 }
1828 for (size_t i = 0; i < microphones.size(); i++) {
1829 jobject jMicrophoneInfo;
1830 jStatus = convertMicrophoneInfoFromNative(env, &jMicrophoneInfo, µphones[i]);
1831 if (jStatus != AUDIO_JAVA_SUCCESS) {
1832 return jStatus;
1833 }
1834 env->CallBooleanMethod(jMicrophonesInfo, gArrayListMethods.add, jMicrophoneInfo);
1835 env->DeleteLocalRef(jMicrophoneInfo);
1836 }
1837
1838 return jStatus;
1839 }
1840
1841 static jint
android_media_AudioSystem_getSurroundFormats(JNIEnv * env,jobject thiz,jobject jSurroundFormats,jboolean reported)1842 android_media_AudioSystem_getSurroundFormats(JNIEnv *env, jobject thiz,
1843 jobject jSurroundFormats, jboolean reported)
1844 {
1845 ALOGV("getSurroundFormats");
1846
1847 if (jSurroundFormats == NULL) {
1848 ALOGE("jSurroundFormats is NULL");
1849 return (jint)AUDIO_JAVA_BAD_VALUE;
1850 }
1851 if (!env->IsInstanceOf(jSurroundFormats, gMapClass)) {
1852 ALOGE("getSurroundFormats not a map");
1853 return (jint)AUDIO_JAVA_BAD_VALUE;
1854 }
1855
1856 jint jStatus;
1857 unsigned int numSurroundFormats = 0;
1858 audio_format_t *surroundFormats = NULL;
1859 bool *surroundFormatsEnabled = NULL;
1860 status_t status = AudioSystem::getSurroundFormats(
1861 &numSurroundFormats, surroundFormats, surroundFormatsEnabled, reported);
1862 if (status != NO_ERROR) {
1863 ALOGE_IF(status != NO_ERROR, "AudioSystem::getSurroundFormats error %d", status);
1864 jStatus = nativeToJavaStatus(status);
1865 goto exit;
1866 }
1867 if (numSurroundFormats == 0) {
1868 jStatus = (jint)AUDIO_JAVA_SUCCESS;
1869 goto exit;
1870 }
1871 surroundFormats = (audio_format_t *)calloc(numSurroundFormats, sizeof(audio_format_t));
1872 surroundFormatsEnabled = (bool *)calloc(numSurroundFormats, sizeof(bool));
1873 status = AudioSystem::getSurroundFormats(
1874 &numSurroundFormats, surroundFormats, surroundFormatsEnabled, reported);
1875 jStatus = nativeToJavaStatus(status);
1876 if (status != NO_ERROR) {
1877 ALOGE_IF(status != NO_ERROR, "AudioSystem::getSurroundFormats error %d", status);
1878 goto exit;
1879 }
1880 for (size_t i = 0; i < numSurroundFormats; i++) {
1881 jobject surroundFormat = env->NewObject(gIntegerClass, gIntegerCstor,
1882 audioFormatFromNative(surroundFormats[i]));
1883 jobject enabled = env->NewObject(gBooleanClass, gBooleanCstor, surroundFormatsEnabled[i]);
1884 env->CallObjectMethod(jSurroundFormats, gMapPut, surroundFormat, enabled);
1885 env->DeleteLocalRef(surroundFormat);
1886 env->DeleteLocalRef(enabled);
1887 }
1888
1889 exit:
1890 free(surroundFormats);
1891 free(surroundFormatsEnabled);
1892 return jStatus;
1893 }
1894
1895 static jint
android_media_AudioSystem_setSurroundFormatEnabled(JNIEnv * env,jobject thiz,jint audioFormat,jboolean enabled)1896 android_media_AudioSystem_setSurroundFormatEnabled(JNIEnv *env, jobject thiz,
1897 jint audioFormat, jboolean enabled)
1898 {
1899 status_t status = AudioSystem::setSurroundFormatEnabled(audioFormatToNative(audioFormat),
1900 (bool)enabled);
1901 if (status != NO_ERROR) {
1902 ALOGE_IF(status != NO_ERROR, "AudioSystem::setSurroundFormatEnabled error %d", status);
1903 }
1904 return (jint)nativeToJavaStatus(status);
1905 }
1906
1907 // ----------------------------------------------------------------------------
1908
1909 static const JNINativeMethod gMethods[] = {
1910 {"setParameters", "(Ljava/lang/String;)I", (void *)android_media_AudioSystem_setParameters},
1911 {"getParameters", "(Ljava/lang/String;)Ljava/lang/String;", (void *)android_media_AudioSystem_getParameters},
1912 {"muteMicrophone", "(Z)I", (void *)android_media_AudioSystem_muteMicrophone},
1913 {"isMicrophoneMuted", "()Z", (void *)android_media_AudioSystem_isMicrophoneMuted},
1914 {"isStreamActive", "(II)Z", (void *)android_media_AudioSystem_isStreamActive},
1915 {"isStreamActiveRemotely","(II)Z", (void *)android_media_AudioSystem_isStreamActiveRemotely},
1916 {"isSourceActive", "(I)Z", (void *)android_media_AudioSystem_isSourceActive},
1917 {"newAudioSessionId", "()I", (void *)android_media_AudioSystem_newAudioSessionId},
1918 {"newAudioPlayerId", "()I", (void *)android_media_AudioSystem_newAudioPlayerId},
1919 {"setDeviceConnectionState", "(IILjava/lang/String;Ljava/lang/String;)I", (void *)android_media_AudioSystem_setDeviceConnectionState},
1920 {"getDeviceConnectionState", "(ILjava/lang/String;)I", (void *)android_media_AudioSystem_getDeviceConnectionState},
1921 {"handleDeviceConfigChange", "(ILjava/lang/String;Ljava/lang/String;)I", (void *)android_media_AudioSystem_handleDeviceConfigChange},
1922 {"setPhoneState", "(I)I", (void *)android_media_AudioSystem_setPhoneState},
1923 {"setForceUse", "(II)I", (void *)android_media_AudioSystem_setForceUse},
1924 {"getForceUse", "(I)I", (void *)android_media_AudioSystem_getForceUse},
1925 {"initStreamVolume", "(III)I", (void *)android_media_AudioSystem_initStreamVolume},
1926 {"setStreamVolumeIndex","(III)I", (void *)android_media_AudioSystem_setStreamVolumeIndex},
1927 {"getStreamVolumeIndex","(II)I", (void *)android_media_AudioSystem_getStreamVolumeIndex},
1928 {"setMasterVolume", "(F)I", (void *)android_media_AudioSystem_setMasterVolume},
1929 {"getMasterVolume", "()F", (void *)android_media_AudioSystem_getMasterVolume},
1930 {"setMasterMute", "(Z)I", (void *)android_media_AudioSystem_setMasterMute},
1931 {"getMasterMute", "()Z", (void *)android_media_AudioSystem_getMasterMute},
1932 {"setMasterMono", "(Z)I", (void *)android_media_AudioSystem_setMasterMono},
1933 {"getMasterMono", "()Z", (void *)android_media_AudioSystem_getMasterMono},
1934 {"getDevicesForStream", "(I)I", (void *)android_media_AudioSystem_getDevicesForStream},
1935 {"getPrimaryOutputSamplingRate", "()I", (void *)android_media_AudioSystem_getPrimaryOutputSamplingRate},
1936 {"getPrimaryOutputFrameCount", "()I", (void *)android_media_AudioSystem_getPrimaryOutputFrameCount},
1937 {"getOutputLatency", "(I)I", (void *)android_media_AudioSystem_getOutputLatency},
1938 {"setLowRamDevice", "(ZJ)I", (void *)android_media_AudioSystem_setLowRamDevice},
1939 {"checkAudioFlinger", "()I", (void *)android_media_AudioSystem_checkAudioFlinger},
1940 {"listAudioPorts", "(Ljava/util/ArrayList;[I)I",
1941 (void *)android_media_AudioSystem_listAudioPorts},
1942 {"createAudioPatch", "([Landroid/media/AudioPatch;[Landroid/media/AudioPortConfig;[Landroid/media/AudioPortConfig;)I",
1943 (void *)android_media_AudioSystem_createAudioPatch},
1944 {"releaseAudioPatch", "(Landroid/media/AudioPatch;)I",
1945 (void *)android_media_AudioSystem_releaseAudioPatch},
1946 {"listAudioPatches", "(Ljava/util/ArrayList;[I)I",
1947 (void *)android_media_AudioSystem_listAudioPatches},
1948 {"setAudioPortConfig", "(Landroid/media/AudioPortConfig;)I",
1949 (void *)android_media_AudioSystem_setAudioPortConfig},
1950 {"getAudioHwSyncForSession", "(I)I",
1951 (void *)android_media_AudioSystem_getAudioHwSyncForSession},
1952 {"registerPolicyMixes", "(Ljava/util/ArrayList;Z)I",
1953 (void *)android_media_AudioSystem_registerPolicyMixes},
1954 {"native_register_dynamic_policy_callback", "()V",
1955 (void *)android_media_AudioSystem_registerDynPolicyCallback},
1956 {"native_register_recording_callback", "()V",
1957 (void *)android_media_AudioSystem_registerRecordingCallback},
1958 {"systemReady", "()I", (void *)android_media_AudioSystem_systemReady},
1959 {"getStreamVolumeDB", "(III)F", (void *)android_media_AudioSystem_getStreamVolumeDB},
1960 {"native_is_offload_supported", "(IIII)Z", (void *)android_media_AudioSystem_isOffloadSupported},
1961 {"getMicrophones", "(Ljava/util/ArrayList;)I", (void *)android_media_AudioSystem_getMicrophones},
1962 {"getSurroundFormats", "(Ljava/util/Map;Z)I", (void *)android_media_AudioSystem_getSurroundFormats},
1963 {"setSurroundFormatEnabled", "(IZ)I", (void *)android_media_AudioSystem_setSurroundFormatEnabled},
1964 };
1965
1966
1967 static const JNINativeMethod gEventHandlerMethods[] = {
1968 {"native_setup",
1969 "(Ljava/lang/Object;)V",
1970 (void *)android_media_AudioSystem_eventHandlerSetup},
1971 {"native_finalize",
1972 "()V",
1973 (void *)android_media_AudioSystem_eventHandlerFinalize},
1974 };
1975
register_android_media_AudioSystem(JNIEnv * env)1976 int register_android_media_AudioSystem(JNIEnv *env)
1977 {
1978 jclass arrayListClass = FindClassOrDie(env, "java/util/ArrayList");
1979 gArrayListClass = MakeGlobalRefOrDie(env, arrayListClass);
1980 gArrayListMethods.add = GetMethodIDOrDie(env, arrayListClass, "add", "(Ljava/lang/Object;)Z");
1981 gArrayListMethods.toArray = GetMethodIDOrDie(env, arrayListClass, "toArray", "()[Ljava/lang/Object;");
1982
1983 jclass booleanClass = FindClassOrDie(env, "java/lang/Boolean");
1984 gBooleanClass = MakeGlobalRefOrDie(env, booleanClass);
1985 gBooleanCstor = GetMethodIDOrDie(env, booleanClass, "<init>", "(Z)V");
1986
1987 jclass integerClass = FindClassOrDie(env, "java/lang/Integer");
1988 gIntegerClass = MakeGlobalRefOrDie(env, integerClass);
1989 gIntegerCstor = GetMethodIDOrDie(env, integerClass, "<init>", "(I)V");
1990
1991 jclass mapClass = FindClassOrDie(env, "java/util/Map");
1992 gMapClass = MakeGlobalRefOrDie(env, mapClass);
1993 gMapPut = GetMethodIDOrDie(env, mapClass, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
1994
1995 jclass audioHandleClass = FindClassOrDie(env, "android/media/AudioHandle");
1996 gAudioHandleClass = MakeGlobalRefOrDie(env, audioHandleClass);
1997 gAudioHandleCstor = GetMethodIDOrDie(env, audioHandleClass, "<init>", "(I)V");
1998 gAudioHandleFields.mId = GetFieldIDOrDie(env, audioHandleClass, "mId", "I");
1999
2000 jclass audioPortClass = FindClassOrDie(env, "android/media/AudioPort");
2001 gAudioPortClass = MakeGlobalRefOrDie(env, audioPortClass);
2002 gAudioPortCstor = GetMethodIDOrDie(env, audioPortClass, "<init>",
2003 "(Landroid/media/AudioHandle;ILjava/lang/String;[I[I[I[I[Landroid/media/AudioGain;)V");
2004 gAudioPortFields.mHandle = GetFieldIDOrDie(env, audioPortClass, "mHandle",
2005 "Landroid/media/AudioHandle;");
2006 gAudioPortFields.mRole = GetFieldIDOrDie(env, audioPortClass, "mRole", "I");
2007 gAudioPortFields.mGains = GetFieldIDOrDie(env, audioPortClass, "mGains",
2008 "[Landroid/media/AudioGain;");
2009 gAudioPortFields.mActiveConfig = GetFieldIDOrDie(env, audioPortClass, "mActiveConfig",
2010 "Landroid/media/AudioPortConfig;");
2011
2012 jclass audioPortConfigClass = FindClassOrDie(env, "android/media/AudioPortConfig");
2013 gAudioPortConfigClass = MakeGlobalRefOrDie(env, audioPortConfigClass);
2014 gAudioPortConfigCstor = GetMethodIDOrDie(env, audioPortConfigClass, "<init>",
2015 "(Landroid/media/AudioPort;IIILandroid/media/AudioGainConfig;)V");
2016 gAudioPortConfigFields.mPort = GetFieldIDOrDie(env, audioPortConfigClass, "mPort",
2017 "Landroid/media/AudioPort;");
2018 gAudioPortConfigFields.mSamplingRate = GetFieldIDOrDie(env, audioPortConfigClass,
2019 "mSamplingRate", "I");
2020 gAudioPortConfigFields.mChannelMask = GetFieldIDOrDie(env, audioPortConfigClass,
2021 "mChannelMask", "I");
2022 gAudioPortConfigFields.mFormat = GetFieldIDOrDie(env, audioPortConfigClass, "mFormat", "I");
2023 gAudioPortConfigFields.mGain = GetFieldIDOrDie(env, audioPortConfigClass, "mGain",
2024 "Landroid/media/AudioGainConfig;");
2025 gAudioPortConfigFields.mConfigMask = GetFieldIDOrDie(env, audioPortConfigClass, "mConfigMask",
2026 "I");
2027
2028 jclass audioDevicePortConfigClass = FindClassOrDie(env, "android/media/AudioDevicePortConfig");
2029 gAudioDevicePortConfigClass = MakeGlobalRefOrDie(env, audioDevicePortConfigClass);
2030 gAudioDevicePortConfigCstor = GetMethodIDOrDie(env, audioDevicePortConfigClass, "<init>",
2031 "(Landroid/media/AudioDevicePort;IIILandroid/media/AudioGainConfig;)V");
2032
2033 jclass audioMixPortConfigClass = FindClassOrDie(env, "android/media/AudioMixPortConfig");
2034 gAudioMixPortConfigClass = MakeGlobalRefOrDie(env, audioMixPortConfigClass);
2035 gAudioMixPortConfigCstor = GetMethodIDOrDie(env, audioMixPortConfigClass, "<init>",
2036 "(Landroid/media/AudioMixPort;IIILandroid/media/AudioGainConfig;)V");
2037
2038 jclass audioDevicePortClass = FindClassOrDie(env, "android/media/AudioDevicePort");
2039 gAudioDevicePortClass = MakeGlobalRefOrDie(env, audioDevicePortClass);
2040 gAudioDevicePortCstor = GetMethodIDOrDie(env, audioDevicePortClass, "<init>",
2041 "(Landroid/media/AudioHandle;Ljava/lang/String;[I[I[I[I[Landroid/media/AudioGain;ILjava/lang/String;)V");
2042
2043 jclass audioMixPortClass = FindClassOrDie(env, "android/media/AudioMixPort");
2044 gAudioMixPortClass = MakeGlobalRefOrDie(env, audioMixPortClass);
2045 gAudioMixPortCstor = GetMethodIDOrDie(env, audioMixPortClass, "<init>",
2046 "(Landroid/media/AudioHandle;IILjava/lang/String;[I[I[I[I[Landroid/media/AudioGain;)V");
2047
2048 jclass audioGainClass = FindClassOrDie(env, "android/media/AudioGain");
2049 gAudioGainClass = MakeGlobalRefOrDie(env, audioGainClass);
2050 gAudioGainCstor = GetMethodIDOrDie(env, audioGainClass, "<init>", "(IIIIIIIII)V");
2051
2052 jclass audioGainConfigClass = FindClassOrDie(env, "android/media/AudioGainConfig");
2053 gAudioGainConfigClass = MakeGlobalRefOrDie(env, audioGainConfigClass);
2054 gAudioGainConfigCstor = GetMethodIDOrDie(env, audioGainConfigClass, "<init>",
2055 "(ILandroid/media/AudioGain;II[II)V");
2056 gAudioGainConfigFields.mIndex = GetFieldIDOrDie(env, gAudioGainConfigClass, "mIndex", "I");
2057 gAudioGainConfigFields.mMode = GetFieldIDOrDie(env, audioGainConfigClass, "mMode", "I");
2058 gAudioGainConfigFields.mChannelMask = GetFieldIDOrDie(env, audioGainConfigClass, "mChannelMask",
2059 "I");
2060 gAudioGainConfigFields.mValues = GetFieldIDOrDie(env, audioGainConfigClass, "mValues", "[I");
2061 gAudioGainConfigFields.mRampDurationMs = GetFieldIDOrDie(env, audioGainConfigClass,
2062 "mRampDurationMs", "I");
2063
2064 jclass audioPatchClass = FindClassOrDie(env, "android/media/AudioPatch");
2065 gAudioPatchClass = MakeGlobalRefOrDie(env, audioPatchClass);
2066 gAudioPatchCstor = GetMethodIDOrDie(env, audioPatchClass, "<init>",
2067 "(Landroid/media/AudioHandle;[Landroid/media/AudioPortConfig;[Landroid/media/AudioPortConfig;)V");
2068 gAudioPatchFields.mHandle = GetFieldIDOrDie(env, audioPatchClass, "mHandle",
2069 "Landroid/media/AudioHandle;");
2070
2071 jclass eventHandlerClass = FindClassOrDie(env, kEventHandlerClassPathName);
2072 gAudioPortEventHandlerMethods.postEventFromNative = GetStaticMethodIDOrDie(
2073 env, eventHandlerClass, "postEventFromNative",
2074 "(Ljava/lang/Object;IIILjava/lang/Object;)V");
2075 gEventHandlerFields.mJniCallback = GetFieldIDOrDie(env,
2076 eventHandlerClass, "mJniCallback", "J");
2077
2078 gAudioPolicyEventHandlerMethods.postDynPolicyEventFromNative =
2079 GetStaticMethodIDOrDie(env, env->FindClass(kClassPathName),
2080 "dynamicPolicyCallbackFromNative", "(ILjava/lang/String;I)V");
2081 gAudioPolicyEventHandlerMethods.postRecordConfigEventFromNative =
2082 GetStaticMethodIDOrDie(env, env->FindClass(kClassPathName),
2083 "recordingCallbackFromNative", "(IIII[I)V");
2084
2085 jclass audioMixClass = FindClassOrDie(env, "android/media/audiopolicy/AudioMix");
2086 gAudioMixClass = MakeGlobalRefOrDie(env, audioMixClass);
2087 gAudioMixFields.mRule = GetFieldIDOrDie(env, audioMixClass, "mRule",
2088 "Landroid/media/audiopolicy/AudioMixingRule;");
2089 gAudioMixFields.mFormat = GetFieldIDOrDie(env, audioMixClass, "mFormat",
2090 "Landroid/media/AudioFormat;");
2091 gAudioMixFields.mRouteFlags = GetFieldIDOrDie(env, audioMixClass, "mRouteFlags", "I");
2092 gAudioMixFields.mDeviceType = GetFieldIDOrDie(env, audioMixClass, "mDeviceSystemType", "I");
2093 gAudioMixFields.mDeviceAddress = GetFieldIDOrDie(env, audioMixClass, "mDeviceAddress",
2094 "Ljava/lang/String;");
2095 gAudioMixFields.mMixType = GetFieldIDOrDie(env, audioMixClass, "mMixType", "I");
2096 gAudioMixFields.mCallbackFlags = GetFieldIDOrDie(env, audioMixClass, "mCallbackFlags", "I");
2097
2098 jclass audioFormatClass = FindClassOrDie(env, "android/media/AudioFormat");
2099 gAudioFormatClass = MakeGlobalRefOrDie(env, audioFormatClass);
2100 gAudioFormatFields.mEncoding = GetFieldIDOrDie(env, audioFormatClass, "mEncoding", "I");
2101 gAudioFormatFields.mSampleRate = GetFieldIDOrDie(env, audioFormatClass, "mSampleRate", "I");
2102 gAudioFormatFields.mChannelMask = GetFieldIDOrDie(env, audioFormatClass, "mChannelMask", "I");
2103
2104 jclass audioMixingRuleClass = FindClassOrDie(env, "android/media/audiopolicy/AudioMixingRule");
2105 gAudioMixingRuleClass = MakeGlobalRefOrDie(env, audioMixingRuleClass);
2106 gAudioMixingRuleFields.mCriteria = GetFieldIDOrDie(env, audioMixingRuleClass, "mCriteria",
2107 "Ljava/util/ArrayList;");
2108
2109 jclass audioMixMatchCriterionClass =
2110 FindClassOrDie(env, "android/media/audiopolicy/AudioMixingRule$AudioMixMatchCriterion");
2111 gAudioMixMatchCriterionClass = MakeGlobalRefOrDie(env,audioMixMatchCriterionClass);
2112 gAudioMixMatchCriterionFields.mAttr = GetFieldIDOrDie(env, audioMixMatchCriterionClass, "mAttr",
2113 "Landroid/media/AudioAttributes;");
2114 gAudioMixMatchCriterionFields.mIntProp = GetFieldIDOrDie(env, audioMixMatchCriterionClass, "mIntProp",
2115 "I");
2116 gAudioMixMatchCriterionFields.mRule = GetFieldIDOrDie(env, audioMixMatchCriterionClass, "mRule",
2117 "I");
2118
2119 jclass audioAttributesClass = FindClassOrDie(env, "android/media/AudioAttributes");
2120 gAudioAttributesClass = MakeGlobalRefOrDie(env, audioAttributesClass);
2121 gAudioAttributesFields.mUsage = GetFieldIDOrDie(env, audioAttributesClass, "mUsage", "I");
2122 gAudioAttributesFields.mSource = GetFieldIDOrDie(env, audioAttributesClass, "mSource", "I");
2123
2124 AudioSystem::setErrorCallback(android_media_AudioSystem_error_callback);
2125
2126 RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
2127 return RegisterMethodsOrDie(env, kEventHandlerClassPathName, gEventHandlerMethods,
2128 NELEM(gEventHandlerMethods));
2129 }
2130