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 <jni.h>
24 #include <JNIHelp.h>
25 #include <android_runtime/AndroidRuntime.h>
26
27 #include <media/AudioSystem.h>
28 #include <media/AudioPolicy.h>
29
30 #include <system/audio.h>
31 #include <system/audio_policy.h>
32 #include "android_media_AudioFormat.h"
33 #include "android_media_AudioErrors.h"
34
35 // ----------------------------------------------------------------------------
36
37 using namespace android;
38
39 static const char* const kClassPathName = "android/media/AudioSystem";
40
41 static jclass gArrayListClass;
42 static struct {
43 jmethodID add;
44 jmethodID toArray;
45 } gArrayListMethods;
46
47 static jclass gAudioHandleClass;
48 static jmethodID gAudioHandleCstor;
49 static struct {
50 jfieldID mId;
51 } gAudioHandleFields;
52
53 static jclass gAudioPortClass;
54 static jmethodID gAudioPortCstor;
55 static struct {
56 jfieldID mHandle;
57 jfieldID mRole;
58 jfieldID mGains;
59 jfieldID mActiveConfig;
60 // other fields unused by JNI
61 } gAudioPortFields;
62
63 static jclass gAudioPortConfigClass;
64 static jmethodID gAudioPortConfigCstor;
65 static struct {
66 jfieldID mPort;
67 jfieldID mSamplingRate;
68 jfieldID mChannelMask;
69 jfieldID mFormat;
70 jfieldID mGain;
71 jfieldID mConfigMask;
72 } gAudioPortConfigFields;
73
74 static jclass gAudioDevicePortClass;
75 static jmethodID gAudioDevicePortCstor;
76
77 static jclass gAudioDevicePortConfigClass;
78 static jmethodID gAudioDevicePortConfigCstor;
79
80 static jclass gAudioMixPortClass;
81 static jmethodID gAudioMixPortCstor;
82
83 static jclass gAudioMixPortConfigClass;
84 static jmethodID gAudioMixPortConfigCstor;
85
86 static jclass gAudioGainClass;
87 static jmethodID gAudioGainCstor;
88
89 static jclass gAudioGainConfigClass;
90 static jmethodID gAudioGainConfigCstor;
91 static struct {
92 jfieldID mIndex;
93 jfieldID mMode;
94 jfieldID mChannelMask;
95 jfieldID mValues;
96 jfieldID mRampDurationMs;
97 // other fields unused by JNI
98 } gAudioGainConfigFields;
99
100 static jclass gAudioPatchClass;
101 static jmethodID gAudioPatchCstor;
102 static struct {
103 jfieldID mHandle;
104 // other fields unused by JNI
105 } gAudioPatchFields;
106
107 static jclass gAudioMixClass;
108 static struct {
109 jfieldID mRule;
110 jfieldID mFormat;
111 jfieldID mRouteFlags;
112 jfieldID mRegistrationId;
113 jfieldID mMixType;
114 } gAudioMixFields;
115
116 static jclass gAudioFormatClass;
117 static struct {
118 jfieldID mEncoding;
119 jfieldID mSampleRate;
120 jfieldID mChannelMask;
121 // other fields unused by JNI
122 } gAudioFormatFields;
123
124 static jclass gAudioMixingRuleClass;
125 static struct {
126 jfieldID mCriteria;
127 // other fields unused by JNI
128 } gAudioMixingRuleFields;
129
130 static jclass gAttributeMatchCriterionClass;
131 static struct {
132 jfieldID mAttr;
133 jfieldID mRule;
134 } gAttributeMatchCriterionFields;
135
136 static jclass gAudioAttributesClass;
137 static struct {
138 jfieldID mUsage;
139 jfieldID mSource;
140 } gAudioAttributesFields;
141
142
143 static const char* const kEventHandlerClassPathName =
144 "android/media/AudioPortEventHandler";
145 static jmethodID gPostEventFromNative;
146
147 enum AudioError {
148 kAudioStatusOk = 0,
149 kAudioStatusError = 1,
150 kAudioStatusMediaServerDied = 100
151 };
152
153 enum {
154 AUDIOPORT_EVENT_PORT_LIST_UPDATED = 1,
155 AUDIOPORT_EVENT_PATCH_LIST_UPDATED = 2,
156 AUDIOPORT_EVENT_SERVICE_DIED = 3,
157 };
158
159 #define MAX_PORT_GENERATION_SYNC_ATTEMPTS 5
160
161 // ----------------------------------------------------------------------------
162 // ref-counted object for callbacks
163 class JNIAudioPortCallback: public AudioSystem::AudioPortCallback
164 {
165 public:
166 JNIAudioPortCallback(JNIEnv* env, jobject thiz, jobject weak_thiz);
167 ~JNIAudioPortCallback();
168
169 virtual void onAudioPortListUpdate();
170 virtual void onAudioPatchListUpdate();
171 virtual void onServiceDied();
172
173 private:
174 void sendEvent(int event);
175
176 jclass mClass; // Reference to AudioPortEventHandlerDelegate class
177 jobject mObject; // Weak ref to AudioPortEventHandlerDelegate Java object to call on
178 };
179
JNIAudioPortCallback(JNIEnv * env,jobject thiz,jobject weak_thiz)180 JNIAudioPortCallback::JNIAudioPortCallback(JNIEnv* env, jobject thiz, jobject weak_thiz)
181 {
182
183 // Hold onto the SoundTriggerModule class for use in calling the static method
184 // that posts events to the application thread.
185 jclass clazz = env->GetObjectClass(thiz);
186 if (clazz == NULL) {
187 ALOGE("Can't find class %s", kEventHandlerClassPathName);
188 return;
189 }
190 mClass = (jclass)env->NewGlobalRef(clazz);
191
192 // We use a weak reference so the SoundTriggerModule object can be garbage collected.
193 // The reference is only used as a proxy for callbacks.
194 mObject = env->NewGlobalRef(weak_thiz);
195 }
196
~JNIAudioPortCallback()197 JNIAudioPortCallback::~JNIAudioPortCallback()
198 {
199 // remove global references
200 JNIEnv *env = AndroidRuntime::getJNIEnv();
201 if (env == NULL) {
202 return;
203 }
204 env->DeleteGlobalRef(mObject);
205 env->DeleteGlobalRef(mClass);
206 }
207
sendEvent(int event)208 void JNIAudioPortCallback::sendEvent(int event)
209 {
210 JNIEnv *env = AndroidRuntime::getJNIEnv();
211 if (env == NULL) {
212 return;
213 }
214 env->CallStaticVoidMethod(mClass, gPostEventFromNative, mObject,
215 event, 0, 0, NULL);
216 if (env->ExceptionCheck()) {
217 ALOGW("An exception occurred while notifying an event.");
218 env->ExceptionClear();
219 }
220 }
221
onAudioPortListUpdate()222 void JNIAudioPortCallback::onAudioPortListUpdate()
223 {
224 sendEvent(AUDIOPORT_EVENT_PORT_LIST_UPDATED);
225 }
226
onAudioPatchListUpdate()227 void JNIAudioPortCallback::onAudioPatchListUpdate()
228 {
229 sendEvent(AUDIOPORT_EVENT_PATCH_LIST_UPDATED);
230 }
231
onServiceDied()232 void JNIAudioPortCallback::onServiceDied()
233 {
234 sendEvent(AUDIOPORT_EVENT_SERVICE_DIED);
235 }
236
check_AudioSystem_Command(status_t status)237 static int check_AudioSystem_Command(status_t status)
238 {
239 switch (status) {
240 case DEAD_OBJECT:
241 return kAudioStatusMediaServerDied;
242 case NO_ERROR:
243 return kAudioStatusOk;
244 default:
245 break;
246 }
247 return kAudioStatusError;
248 }
249
250 static jint
android_media_AudioSystem_muteMicrophone(JNIEnv * env,jobject thiz,jboolean on)251 android_media_AudioSystem_muteMicrophone(JNIEnv *env, jobject thiz, jboolean on)
252 {
253 return (jint) check_AudioSystem_Command(AudioSystem::muteMicrophone(on));
254 }
255
256 static jboolean
android_media_AudioSystem_isMicrophoneMuted(JNIEnv * env,jobject thiz)257 android_media_AudioSystem_isMicrophoneMuted(JNIEnv *env, jobject thiz)
258 {
259 bool state = false;
260 AudioSystem::isMicrophoneMuted(&state);
261 return state;
262 }
263
264 static jboolean
android_media_AudioSystem_isStreamActive(JNIEnv * env,jobject thiz,jint stream,jint inPastMs)265 android_media_AudioSystem_isStreamActive(JNIEnv *env, jobject thiz, jint stream, jint inPastMs)
266 {
267 bool state = false;
268 AudioSystem::isStreamActive((audio_stream_type_t) stream, &state, inPastMs);
269 return state;
270 }
271
272 static jboolean
android_media_AudioSystem_isStreamActiveRemotely(JNIEnv * env,jobject thiz,jint stream,jint inPastMs)273 android_media_AudioSystem_isStreamActiveRemotely(JNIEnv *env, jobject thiz, jint stream,
274 jint inPastMs)
275 {
276 bool state = false;
277 AudioSystem::isStreamActiveRemotely((audio_stream_type_t) stream, &state, inPastMs);
278 return state;
279 }
280
281 static jboolean
android_media_AudioSystem_isSourceActive(JNIEnv * env,jobject thiz,jint source)282 android_media_AudioSystem_isSourceActive(JNIEnv *env, jobject thiz, jint source)
283 {
284 bool state = false;
285 AudioSystem::isSourceActive((audio_source_t) source, &state);
286 return state;
287 }
288
289 static jint
android_media_AudioSystem_newAudioSessionId(JNIEnv * env,jobject thiz)290 android_media_AudioSystem_newAudioSessionId(JNIEnv *env, jobject thiz)
291 {
292 return AudioSystem::newAudioUniqueId();
293 }
294
295 static jint
android_media_AudioSystem_setParameters(JNIEnv * env,jobject thiz,jstring keyValuePairs)296 android_media_AudioSystem_setParameters(JNIEnv *env, jobject thiz, jstring keyValuePairs)
297 {
298 const jchar* c_keyValuePairs = env->GetStringCritical(keyValuePairs, 0);
299 String8 c_keyValuePairs8;
300 if (keyValuePairs) {
301 c_keyValuePairs8 = String8(c_keyValuePairs, env->GetStringLength(keyValuePairs));
302 env->ReleaseStringCritical(keyValuePairs, c_keyValuePairs);
303 }
304 int status = check_AudioSystem_Command(AudioSystem::setParameters(c_keyValuePairs8));
305 return (jint) status;
306 }
307
308 static jstring
android_media_AudioSystem_getParameters(JNIEnv * env,jobject thiz,jstring keys)309 android_media_AudioSystem_getParameters(JNIEnv *env, jobject thiz, jstring keys)
310 {
311 const jchar* c_keys = env->GetStringCritical(keys, 0);
312 String8 c_keys8;
313 if (keys) {
314 c_keys8 = String8(c_keys, env->GetStringLength(keys));
315 env->ReleaseStringCritical(keys, c_keys);
316 }
317 return env->NewStringUTF(AudioSystem::getParameters(c_keys8).string());
318 }
319
320 static void
android_media_AudioSystem_error_callback(status_t err)321 android_media_AudioSystem_error_callback(status_t err)
322 {
323 JNIEnv *env = AndroidRuntime::getJNIEnv();
324 if (env == NULL) {
325 return;
326 }
327
328 jclass clazz = env->FindClass(kClassPathName);
329
330 env->CallStaticVoidMethod(clazz, env->GetStaticMethodID(clazz,
331 "errorCallbackFromNative","(I)V"),
332 check_AudioSystem_Command(err));
333
334 env->DeleteLocalRef(clazz);
335 }
336
337 static jint
android_media_AudioSystem_setDeviceConnectionState(JNIEnv * env,jobject thiz,jint device,jint state,jstring device_address)338 android_media_AudioSystem_setDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jint state, jstring device_address)
339 {
340 const char *c_address = env->GetStringUTFChars(device_address, NULL);
341 int status = check_AudioSystem_Command(AudioSystem::setDeviceConnectionState(static_cast <audio_devices_t>(device),
342 static_cast <audio_policy_dev_state_t>(state),
343 c_address));
344 env->ReleaseStringUTFChars(device_address, c_address);
345 return (jint) status;
346 }
347
348 static jint
android_media_AudioSystem_getDeviceConnectionState(JNIEnv * env,jobject thiz,jint device,jstring device_address)349 android_media_AudioSystem_getDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jstring device_address)
350 {
351 const char *c_address = env->GetStringUTFChars(device_address, NULL);
352 int state = static_cast <int>(AudioSystem::getDeviceConnectionState(static_cast <audio_devices_t>(device),
353 c_address));
354 env->ReleaseStringUTFChars(device_address, c_address);
355 return (jint) state;
356 }
357
358 static jint
android_media_AudioSystem_setPhoneState(JNIEnv * env,jobject thiz,jint state)359 android_media_AudioSystem_setPhoneState(JNIEnv *env, jobject thiz, jint state)
360 {
361 return (jint) check_AudioSystem_Command(AudioSystem::setPhoneState((audio_mode_t) state));
362 }
363
364 static jint
android_media_AudioSystem_setForceUse(JNIEnv * env,jobject thiz,jint usage,jint config)365 android_media_AudioSystem_setForceUse(JNIEnv *env, jobject thiz, jint usage, jint config)
366 {
367 return (jint) check_AudioSystem_Command(AudioSystem::setForceUse(static_cast <audio_policy_force_use_t>(usage),
368 static_cast <audio_policy_forced_cfg_t>(config)));
369 }
370
371 static jint
android_media_AudioSystem_getForceUse(JNIEnv * env,jobject thiz,jint usage)372 android_media_AudioSystem_getForceUse(JNIEnv *env, jobject thiz, jint usage)
373 {
374 return static_cast <jint>(AudioSystem::getForceUse(static_cast <audio_policy_force_use_t>(usage)));
375 }
376
377 static jint
android_media_AudioSystem_initStreamVolume(JNIEnv * env,jobject thiz,jint stream,jint indexMin,jint indexMax)378 android_media_AudioSystem_initStreamVolume(JNIEnv *env, jobject thiz, jint stream, jint indexMin, jint indexMax)
379 {
380 return (jint) check_AudioSystem_Command(AudioSystem::initStreamVolume(static_cast <audio_stream_type_t>(stream),
381 indexMin,
382 indexMax));
383 }
384
385 static jint
android_media_AudioSystem_setStreamVolumeIndex(JNIEnv * env,jobject thiz,jint stream,jint index,jint device)386 android_media_AudioSystem_setStreamVolumeIndex(JNIEnv *env,
387 jobject thiz,
388 jint stream,
389 jint index,
390 jint device)
391 {
392 return (jint) check_AudioSystem_Command(
393 AudioSystem::setStreamVolumeIndex(static_cast <audio_stream_type_t>(stream),
394 index,
395 (audio_devices_t)device));
396 }
397
398 static jint
android_media_AudioSystem_getStreamVolumeIndex(JNIEnv * env,jobject thiz,jint stream,jint device)399 android_media_AudioSystem_getStreamVolumeIndex(JNIEnv *env,
400 jobject thiz,
401 jint stream,
402 jint device)
403 {
404 int index;
405 if (AudioSystem::getStreamVolumeIndex(static_cast <audio_stream_type_t>(stream),
406 &index,
407 (audio_devices_t)device)
408 != NO_ERROR) {
409 index = -1;
410 }
411 return (jint) index;
412 }
413
414 static jint
android_media_AudioSystem_setMasterVolume(JNIEnv * env,jobject thiz,jfloat value)415 android_media_AudioSystem_setMasterVolume(JNIEnv *env, jobject thiz, jfloat value)
416 {
417 return (jint) check_AudioSystem_Command(AudioSystem::setMasterVolume(value));
418 }
419
420 static jfloat
android_media_AudioSystem_getMasterVolume(JNIEnv * env,jobject thiz)421 android_media_AudioSystem_getMasterVolume(JNIEnv *env, jobject thiz)
422 {
423 float value;
424 if (AudioSystem::getMasterVolume(&value) != NO_ERROR) {
425 value = -1.0;
426 }
427 return value;
428 }
429
430 static jint
android_media_AudioSystem_setMasterMute(JNIEnv * env,jobject thiz,jboolean mute)431 android_media_AudioSystem_setMasterMute(JNIEnv *env, jobject thiz, jboolean mute)
432 {
433 return (jint) check_AudioSystem_Command(AudioSystem::setMasterMute(mute));
434 }
435
436 static jboolean
android_media_AudioSystem_getMasterMute(JNIEnv * env,jobject thiz)437 android_media_AudioSystem_getMasterMute(JNIEnv *env, jobject thiz)
438 {
439 bool mute;
440 if (AudioSystem::getMasterMute(&mute) != NO_ERROR) {
441 mute = false;
442 }
443 return mute;
444 }
445
446 static jint
android_media_AudioSystem_getDevicesForStream(JNIEnv * env,jobject thiz,jint stream)447 android_media_AudioSystem_getDevicesForStream(JNIEnv *env, jobject thiz, jint stream)
448 {
449 return (jint) AudioSystem::getDevicesForStream(static_cast <audio_stream_type_t>(stream));
450 }
451
452 static jint
android_media_AudioSystem_getPrimaryOutputSamplingRate(JNIEnv * env,jobject clazz)453 android_media_AudioSystem_getPrimaryOutputSamplingRate(JNIEnv *env, jobject clazz)
454 {
455 return (jint) AudioSystem::getPrimaryOutputSamplingRate();
456 }
457
458 static jint
android_media_AudioSystem_getPrimaryOutputFrameCount(JNIEnv * env,jobject clazz)459 android_media_AudioSystem_getPrimaryOutputFrameCount(JNIEnv *env, jobject clazz)
460 {
461 return (jint) AudioSystem::getPrimaryOutputFrameCount();
462 }
463
464 static jint
android_media_AudioSystem_getOutputLatency(JNIEnv * env,jobject clazz,jint stream)465 android_media_AudioSystem_getOutputLatency(JNIEnv *env, jobject clazz, jint stream)
466 {
467 uint32_t afLatency;
468 if (AudioSystem::getOutputLatency(&afLatency, static_cast <audio_stream_type_t>(stream))
469 != NO_ERROR) {
470 afLatency = -1;
471 }
472 return (jint) afLatency;
473 }
474
475 static jint
android_media_AudioSystem_setLowRamDevice(JNIEnv * env,jobject clazz,jboolean isLowRamDevice)476 android_media_AudioSystem_setLowRamDevice(JNIEnv *env, jobject clazz, jboolean isLowRamDevice)
477 {
478 return (jint) AudioSystem::setLowRamDevice((bool) isLowRamDevice);
479 }
480
481 static jint
android_media_AudioSystem_checkAudioFlinger(JNIEnv * env,jobject clazz)482 android_media_AudioSystem_checkAudioFlinger(JNIEnv *env, jobject clazz)
483 {
484 return (jint) check_AudioSystem_Command(AudioSystem::checkAudioFlinger());
485 }
486
487
useInChannelMask(audio_port_type_t type,audio_port_role_t role)488 static bool useInChannelMask(audio_port_type_t type, audio_port_role_t role)
489 {
490 return ((type == AUDIO_PORT_TYPE_DEVICE) && (role == AUDIO_PORT_ROLE_SOURCE)) ||
491 ((type == AUDIO_PORT_TYPE_MIX) && (role == AUDIO_PORT_ROLE_SINK));
492 }
493
convertAudioGainConfigToNative(JNIEnv * env,struct audio_gain_config * nAudioGainConfig,const jobject jAudioGainConfig,bool useInMask)494 static void convertAudioGainConfigToNative(JNIEnv *env,
495 struct audio_gain_config *nAudioGainConfig,
496 const jobject jAudioGainConfig,
497 bool useInMask)
498 {
499 nAudioGainConfig->index = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mIndex);
500 nAudioGainConfig->mode = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mMode);
501 ALOGV("convertAudioGainConfigToNative got gain index %d", nAudioGainConfig->index);
502 jint jMask = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mChannelMask);
503 audio_channel_mask_t nMask;
504 if (useInMask) {
505 nMask = inChannelMaskToNative(jMask);
506 ALOGV("convertAudioGainConfigToNative IN mask java %x native %x", jMask, nMask);
507 } else {
508 nMask = outChannelMaskToNative(jMask);
509 ALOGV("convertAudioGainConfigToNative OUT mask java %x native %x", jMask, nMask);
510 }
511 nAudioGainConfig->channel_mask = nMask;
512 nAudioGainConfig->ramp_duration_ms = env->GetIntField(jAudioGainConfig,
513 gAudioGainConfigFields.mRampDurationMs);
514 jintArray jValues = (jintArray)env->GetObjectField(jAudioGainConfig,
515 gAudioGainConfigFields.mValues);
516 int *nValues = env->GetIntArrayElements(jValues, NULL);
517 size_t size = env->GetArrayLength(jValues);
518 memcpy(nAudioGainConfig->values, nValues, size * sizeof(int));
519 env->DeleteLocalRef(jValues);
520 }
521
522
convertAudioPortConfigToNative(JNIEnv * env,struct audio_port_config * nAudioPortConfig,const jobject jAudioPortConfig,bool useConfigMask)523 static jint convertAudioPortConfigToNative(JNIEnv *env,
524 struct audio_port_config *nAudioPortConfig,
525 const jobject jAudioPortConfig,
526 bool useConfigMask)
527 {
528 jobject jAudioPort = env->GetObjectField(jAudioPortConfig, gAudioPortConfigFields.mPort);
529 jobject jHandle = env->GetObjectField(jAudioPort, gAudioPortFields.mHandle);
530 nAudioPortConfig->id = env->GetIntField(jHandle, gAudioHandleFields.mId);
531 nAudioPortConfig->role = (audio_port_role_t)env->GetIntField(jAudioPort,
532 gAudioPortFields.mRole);
533 if (env->IsInstanceOf(jAudioPort, gAudioDevicePortClass)) {
534 nAudioPortConfig->type = AUDIO_PORT_TYPE_DEVICE;
535 } else if (env->IsInstanceOf(jAudioPort, gAudioMixPortClass)) {
536 nAudioPortConfig->type = AUDIO_PORT_TYPE_MIX;
537 } else {
538 env->DeleteLocalRef(jAudioPort);
539 env->DeleteLocalRef(jHandle);
540 return (jint)AUDIO_JAVA_ERROR;
541 }
542 ALOGV("convertAudioPortConfigToNative handle %d role %d type %d",
543 nAudioPortConfig->id, nAudioPortConfig->role, nAudioPortConfig->type);
544
545 unsigned int configMask = 0;
546
547 nAudioPortConfig->sample_rate = env->GetIntField(jAudioPortConfig,
548 gAudioPortConfigFields.mSamplingRate);
549 if (nAudioPortConfig->sample_rate != 0) {
550 configMask |= AUDIO_PORT_CONFIG_SAMPLE_RATE;
551 }
552
553 bool useInMask = useInChannelMask(nAudioPortConfig->type, nAudioPortConfig->role);
554 audio_channel_mask_t nMask;
555 jint jMask = env->GetIntField(jAudioPortConfig,
556 gAudioPortConfigFields.mChannelMask);
557 if (useInMask) {
558 nMask = inChannelMaskToNative(jMask);
559 ALOGV("convertAudioPortConfigToNative IN mask java %x native %x", jMask, nMask);
560 } else {
561 nMask = outChannelMaskToNative(jMask);
562 ALOGV("convertAudioPortConfigToNative OUT mask java %x native %x", jMask, nMask);
563 }
564 nAudioPortConfig->channel_mask = nMask;
565 if (nAudioPortConfig->channel_mask != AUDIO_CHANNEL_NONE) {
566 configMask |= AUDIO_PORT_CONFIG_CHANNEL_MASK;
567 }
568
569 jint jFormat = env->GetIntField(jAudioPortConfig, gAudioPortConfigFields.mFormat);
570 audio_format_t nFormat = audioFormatToNative(jFormat);
571 ALOGV("convertAudioPortConfigToNative format %d native %d", jFormat, nFormat);
572 nAudioPortConfig->format = nFormat;
573 if (nAudioPortConfig->format != AUDIO_FORMAT_DEFAULT &&
574 nAudioPortConfig->format != AUDIO_FORMAT_INVALID) {
575 configMask |= AUDIO_PORT_CONFIG_FORMAT;
576 }
577
578 jobject jGain = env->GetObjectField(jAudioPortConfig, gAudioPortConfigFields.mGain);
579 if (jGain != NULL) {
580 convertAudioGainConfigToNative(env, &nAudioPortConfig->gain, jGain, useInMask);
581 env->DeleteLocalRef(jGain);
582 configMask |= AUDIO_PORT_CONFIG_GAIN;
583 } else {
584 ALOGV("convertAudioPortConfigToNative no gain");
585 nAudioPortConfig->gain.index = -1;
586 }
587 if (useConfigMask) {
588 nAudioPortConfig->config_mask = env->GetIntField(jAudioPortConfig,
589 gAudioPortConfigFields.mConfigMask);
590 } else {
591 nAudioPortConfig->config_mask = configMask;
592 }
593 env->DeleteLocalRef(jAudioPort);
594 env->DeleteLocalRef(jHandle);
595 return (jint)AUDIO_JAVA_SUCCESS;
596 }
597
convertAudioPortConfigFromNative(JNIEnv * env,jobject jAudioPort,jobject * jAudioPortConfig,const struct audio_port_config * nAudioPortConfig)598 static jint convertAudioPortConfigFromNative(JNIEnv *env,
599 jobject jAudioPort,
600 jobject *jAudioPortConfig,
601 const struct audio_port_config *nAudioPortConfig)
602 {
603 jint jStatus = AUDIO_JAVA_SUCCESS;
604 jobject jAudioGainConfig = NULL;
605 jobject jAudioGain = NULL;
606 jintArray jGainValues;
607 bool audioportCreated = false;
608
609 ALOGV("convertAudioPortConfigFromNative jAudioPort %p", jAudioPort);
610
611 if (jAudioPort == NULL) {
612 jobject jHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
613 nAudioPortConfig->id);
614
615 ALOGV("convertAudioPortConfigFromNative handle %d is a %s", nAudioPortConfig->id,
616 nAudioPortConfig->type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix");
617
618 if (jHandle == NULL) {
619 return (jint)AUDIO_JAVA_ERROR;
620 }
621 // create dummy port and port config objects with just the correct handle
622 // and configuration data. The actual AudioPortConfig objects will be
623 // constructed by java code with correct class type (device, mix etc...)
624 // and reference to AudioPort instance in this client
625 jAudioPort = env->NewObject(gAudioPortClass, gAudioPortCstor,
626 jHandle,
627 0,
628 NULL,
629 NULL,
630 NULL,
631 NULL);
632 env->DeleteLocalRef(jHandle);
633 if (jAudioPort == NULL) {
634 return (jint)AUDIO_JAVA_ERROR;
635 }
636 ALOGV("convertAudioPortConfigFromNative jAudioPort created for handle %d",
637 nAudioPortConfig->id);
638
639 audioportCreated = true;
640 }
641
642 bool useInMask = useInChannelMask(nAudioPortConfig->type, nAudioPortConfig->role);
643
644 audio_channel_mask_t nMask;
645 jint jMask;
646
647 int gainIndex = nAudioPortConfig->gain.index;
648 if (gainIndex >= 0) {
649 ALOGV("convertAudioPortConfigFromNative gain found with index %d mode %x",
650 gainIndex, nAudioPortConfig->gain.mode);
651 if (audioportCreated) {
652 ALOGV("convertAudioPortConfigFromNative creating gain");
653 jAudioGain = env->NewObject(gAudioGainClass, gAudioGainCstor,
654 gainIndex,
655 0,
656 0,
657 0,
658 0,
659 0,
660 0,
661 0,
662 0);
663 if (jAudioGain == NULL) {
664 ALOGV("convertAudioPortConfigFromNative creating gain FAILED");
665 jStatus = (jint)AUDIO_JAVA_ERROR;
666 goto exit;
667 }
668 } else {
669 ALOGV("convertAudioPortConfigFromNative reading gain from port");
670 jobjectArray jGains = (jobjectArray)env->GetObjectField(jAudioPort,
671 gAudioPortFields.mGains);
672 if (jGains == NULL) {
673 ALOGV("convertAudioPortConfigFromNative could not get gains from port");
674 jStatus = (jint)AUDIO_JAVA_ERROR;
675 goto exit;
676 }
677 jAudioGain = env->GetObjectArrayElement(jGains, gainIndex);
678 env->DeleteLocalRef(jGains);
679 if (jAudioGain == NULL) {
680 ALOGV("convertAudioPortConfigFromNative could not get gain at index %d", gainIndex);
681 jStatus = (jint)AUDIO_JAVA_ERROR;
682 goto exit;
683 }
684 }
685 int numValues;
686 if (useInMask) {
687 numValues = audio_channel_count_from_in_mask(nAudioPortConfig->gain.channel_mask);
688 } else {
689 numValues = audio_channel_count_from_out_mask(nAudioPortConfig->gain.channel_mask);
690 }
691 jGainValues = env->NewIntArray(numValues);
692 if (jGainValues == NULL) {
693 ALOGV("convertAudioPortConfigFromNative could not create gain values %d", numValues);
694 jStatus = (jint)AUDIO_JAVA_ERROR;
695 goto exit;
696 }
697 env->SetIntArrayRegion(jGainValues, 0, numValues,
698 nAudioPortConfig->gain.values);
699
700 nMask = nAudioPortConfig->gain.channel_mask;
701 if (useInMask) {
702 jMask = inChannelMaskFromNative(nMask);
703 ALOGV("convertAudioPortConfigFromNative IN mask java %x native %x", jMask, nMask);
704 } else {
705 jMask = outChannelMaskFromNative(nMask);
706 ALOGV("convertAudioPortConfigFromNative OUT mask java %x native %x", jMask, nMask);
707 }
708
709 jAudioGainConfig = env->NewObject(gAudioGainConfigClass,
710 gAudioGainConfigCstor,
711 gainIndex,
712 jAudioGain,
713 nAudioPortConfig->gain.mode,
714 jMask,
715 jGainValues,
716 nAudioPortConfig->gain.ramp_duration_ms);
717 env->DeleteLocalRef(jGainValues);
718 if (jAudioGainConfig == NULL) {
719 ALOGV("convertAudioPortConfigFromNative could not create gain config");
720 jStatus = (jint)AUDIO_JAVA_ERROR;
721 goto exit;
722 }
723 }
724 jclass clazz;
725 jmethodID methodID;
726 if (audioportCreated) {
727 clazz = gAudioPortConfigClass;
728 methodID = gAudioPortConfigCstor;
729 ALOGV("convertAudioPortConfigFromNative building a generic port config");
730 } else {
731 if (env->IsInstanceOf(jAudioPort, gAudioDevicePortClass)) {
732 clazz = gAudioDevicePortConfigClass;
733 methodID = gAudioDevicePortConfigCstor;
734 ALOGV("convertAudioPortConfigFromNative building a device config");
735 } else if (env->IsInstanceOf(jAudioPort, gAudioMixPortClass)) {
736 clazz = gAudioMixPortConfigClass;
737 methodID = gAudioMixPortConfigCstor;
738 ALOGV("convertAudioPortConfigFromNative building a mix config");
739 } else {
740 jStatus = (jint)AUDIO_JAVA_ERROR;
741 goto exit;
742 }
743 }
744 nMask = nAudioPortConfig->channel_mask;
745 if (useInMask) {
746 jMask = inChannelMaskFromNative(nMask);
747 ALOGV("convertAudioPortConfigFromNative IN mask java %x native %x", jMask, nMask);
748 } else {
749 jMask = outChannelMaskFromNative(nMask);
750 ALOGV("convertAudioPortConfigFromNative OUT mask java %x native %x", jMask, nMask);
751 }
752
753 *jAudioPortConfig = env->NewObject(clazz, methodID,
754 jAudioPort,
755 nAudioPortConfig->sample_rate,
756 jMask,
757 audioFormatFromNative(nAudioPortConfig->format),
758 jAudioGainConfig);
759 if (*jAudioPortConfig == NULL) {
760 ALOGV("convertAudioPortConfigFromNative could not create new port config");
761 jStatus = (jint)AUDIO_JAVA_ERROR;
762 } else {
763 ALOGV("convertAudioPortConfigFromNative OK");
764 }
765
766 exit:
767 if (audioportCreated) {
768 env->DeleteLocalRef(jAudioPort);
769 if (jAudioGain != NULL) {
770 env->DeleteLocalRef(jAudioGain);
771 }
772 }
773 if (jAudioGainConfig != NULL) {
774 env->DeleteLocalRef(jAudioGainConfig);
775 }
776 return jStatus;
777 }
778
convertAudioPortFromNative(JNIEnv * env,jobject * jAudioPort,const struct audio_port * nAudioPort)779 static jint convertAudioPortFromNative(JNIEnv *env,
780 jobject *jAudioPort, const struct audio_port *nAudioPort)
781 {
782 jint jStatus = (jint)AUDIO_JAVA_SUCCESS;
783 jintArray jSamplingRates = NULL;
784 jintArray jChannelMasks = NULL;
785 jintArray jFormats = NULL;
786 jobjectArray jGains = NULL;
787 jobject jHandle = NULL;
788 bool useInMask;
789
790 ALOGV("convertAudioPortFromNative id %d role %d type %d",
791 nAudioPort->id, nAudioPort->role, nAudioPort->type);
792
793 jSamplingRates = env->NewIntArray(nAudioPort->num_sample_rates);
794 if (jSamplingRates == NULL) {
795 jStatus = (jint)AUDIO_JAVA_ERROR;
796 goto exit;
797 }
798 if (nAudioPort->num_sample_rates) {
799 env->SetIntArrayRegion(jSamplingRates, 0, nAudioPort->num_sample_rates,
800 (jint *)nAudioPort->sample_rates);
801 }
802
803 jChannelMasks = env->NewIntArray(nAudioPort->num_channel_masks);
804 if (jChannelMasks == NULL) {
805 jStatus = (jint)AUDIO_JAVA_ERROR;
806 goto exit;
807 }
808 useInMask = useInChannelMask(nAudioPort->type, nAudioPort->role);
809
810 jint jMask;
811 for (size_t j = 0; j < nAudioPort->num_channel_masks; j++) {
812 if (useInMask) {
813 jMask = inChannelMaskFromNative(nAudioPort->channel_masks[j]);
814 } else {
815 jMask = outChannelMaskFromNative(nAudioPort->channel_masks[j]);
816 }
817 env->SetIntArrayRegion(jChannelMasks, j, 1, &jMask);
818 }
819
820 jFormats = env->NewIntArray(nAudioPort->num_formats);
821 if (jFormats == NULL) {
822 jStatus = (jint)AUDIO_JAVA_ERROR;
823 goto exit;
824 }
825 for (size_t j = 0; j < nAudioPort->num_formats; j++) {
826 jint jFormat = audioFormatFromNative(nAudioPort->formats[j]);
827 env->SetIntArrayRegion(jFormats, j, 1, &jFormat);
828 }
829
830 jGains = env->NewObjectArray(nAudioPort->num_gains,
831 gAudioGainClass, NULL);
832 if (jGains == NULL) {
833 jStatus = (jint)AUDIO_JAVA_ERROR;
834 goto exit;
835 }
836 for (size_t j = 0; j < nAudioPort->num_gains; j++) {
837 audio_channel_mask_t nMask = nAudioPort->gains[j].channel_mask;
838 if (useInMask) {
839 jMask = inChannelMaskFromNative(nMask);
840 ALOGV("convertAudioPortConfigFromNative IN mask java %x native %x", jMask, nMask);
841 } else {
842 jMask = outChannelMaskFromNative(nMask);
843 ALOGV("convertAudioPortConfigFromNative OUT mask java %x native %x", jMask, nMask);
844 }
845
846 jobject jGain = env->NewObject(gAudioGainClass, gAudioGainCstor,
847 j,
848 nAudioPort->gains[j].mode,
849 jMask,
850 nAudioPort->gains[j].min_value,
851 nAudioPort->gains[j].max_value,
852 nAudioPort->gains[j].default_value,
853 nAudioPort->gains[j].step_value,
854 nAudioPort->gains[j].min_ramp_ms,
855 nAudioPort->gains[j].max_ramp_ms);
856 if (jGain == NULL) {
857 jStatus = (jint)AUDIO_JAVA_ERROR;
858 goto exit;
859 }
860 env->SetObjectArrayElement(jGains, j, jGain);
861 env->DeleteLocalRef(jGain);
862 }
863
864 jHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
865 nAudioPort->id);
866 if (jHandle == NULL) {
867 jStatus = (jint)AUDIO_JAVA_ERROR;
868 goto exit;
869 }
870
871 if (nAudioPort->type == AUDIO_PORT_TYPE_DEVICE) {
872 ALOGV("convertAudioPortFromNative is a device %08x", nAudioPort->ext.device.type);
873 jstring jAddress = env->NewStringUTF(nAudioPort->ext.device.address);
874 *jAudioPort = env->NewObject(gAudioDevicePortClass, gAudioDevicePortCstor,
875 jHandle, jSamplingRates, jChannelMasks, jFormats, jGains,
876 nAudioPort->ext.device.type, jAddress);
877 env->DeleteLocalRef(jAddress);
878 } else if (nAudioPort->type == AUDIO_PORT_TYPE_MIX) {
879 ALOGV("convertAudioPortFromNative is a mix");
880 *jAudioPort = env->NewObject(gAudioMixPortClass, gAudioMixPortCstor,
881 jHandle, nAudioPort->role, jSamplingRates, jChannelMasks,
882 jFormats, jGains);
883 } else {
884 ALOGE("convertAudioPortFromNative unknown nAudioPort type %d", nAudioPort->type);
885 jStatus = (jint)AUDIO_JAVA_ERROR;
886 goto exit;
887 }
888 if (*jAudioPort == NULL) {
889 jStatus = (jint)AUDIO_JAVA_ERROR;
890 goto exit;
891 }
892
893 jobject jAudioPortConfig;
894 jStatus = convertAudioPortConfigFromNative(env,
895 *jAudioPort,
896 &jAudioPortConfig,
897 &nAudioPort->active_config);
898 if (jStatus != AUDIO_JAVA_SUCCESS) {
899 return jStatus;
900 }
901
902 env->SetObjectField(*jAudioPort, gAudioPortFields.mActiveConfig, jAudioPortConfig);
903
904 exit:
905 if (jSamplingRates != NULL) {
906 env->DeleteLocalRef(jSamplingRates);
907 }
908 if (jChannelMasks != NULL) {
909 env->DeleteLocalRef(jChannelMasks);
910 }
911 if (jFormats != NULL) {
912 env->DeleteLocalRef(jFormats);
913 }
914 if (jGains != NULL) {
915 env->DeleteLocalRef(jGains);
916 }
917 if (jHandle != NULL) {
918 env->DeleteLocalRef(jHandle);
919 }
920
921 return jStatus;
922 }
923
924
925 static jint
android_media_AudioSystem_listAudioPorts(JNIEnv * env,jobject clazz,jobject jPorts,jintArray jGeneration)926 android_media_AudioSystem_listAudioPorts(JNIEnv *env, jobject clazz,
927 jobject jPorts, jintArray jGeneration)
928 {
929 ALOGV("listAudioPorts");
930
931 if (jPorts == NULL) {
932 ALOGE("listAudioPorts NULL AudioPort ArrayList");
933 return (jint)AUDIO_JAVA_BAD_VALUE;
934 }
935 if (!env->IsInstanceOf(jPorts, gArrayListClass)) {
936 ALOGE("listAudioPorts not an arraylist");
937 return (jint)AUDIO_JAVA_BAD_VALUE;
938 }
939
940 if (jGeneration == NULL || env->GetArrayLength(jGeneration) != 1) {
941 return (jint)AUDIO_JAVA_BAD_VALUE;
942 }
943
944 status_t status;
945 unsigned int generation1;
946 unsigned int generation;
947 unsigned int numPorts;
948 jint *nGeneration;
949 struct audio_port *nPorts = NULL;
950 int attempts = MAX_PORT_GENERATION_SYNC_ATTEMPTS;
951
952 // get the port count and all the ports until they both return the same generation
953 do {
954 if (attempts-- < 0) {
955 status = TIMED_OUT;
956 break;
957 }
958
959 numPorts = 0;
960 status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE,
961 AUDIO_PORT_TYPE_NONE,
962 &numPorts,
963 NULL,
964 &generation1);
965 if (status != NO_ERROR || numPorts == 0) {
966 ALOGE_IF(status != NO_ERROR, "AudioSystem::listAudioPorts error %d", status);
967 break;
968 }
969 nPorts = (struct audio_port *)realloc(nPorts, numPorts * sizeof(struct audio_port));
970
971 status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE,
972 AUDIO_PORT_TYPE_NONE,
973 &numPorts,
974 nPorts,
975 &generation);
976 ALOGV("listAudioPorts AudioSystem::listAudioPorts numPorts %d generation %d generation1 %d",
977 numPorts, generation, generation1);
978 } while (generation1 != generation && status == NO_ERROR);
979
980 jint jStatus = nativeToJavaStatus(status);
981 if (jStatus != AUDIO_JAVA_SUCCESS) {
982 goto exit;
983 }
984
985 nGeneration = env->GetIntArrayElements(jGeneration, NULL);
986 if (nGeneration == NULL) {
987 jStatus = (jint)AUDIO_JAVA_ERROR;
988 goto exit;
989 }
990 nGeneration[0] = generation1;
991 env->ReleaseIntArrayElements(jGeneration, nGeneration, 0);
992
993 for (size_t i = 0; i < numPorts; i++) {
994 jobject jAudioPort;
995 jStatus = convertAudioPortFromNative(env, &jAudioPort, &nPorts[i]);
996 if (jStatus != AUDIO_JAVA_SUCCESS) {
997 goto exit;
998 }
999 env->CallBooleanMethod(jPorts, gArrayListMethods.add, jAudioPort);
1000 }
1001
1002 exit:
1003 free(nPorts);
1004 return jStatus;
1005 }
1006
1007 static int
android_media_AudioSystem_createAudioPatch(JNIEnv * env,jobject clazz,jobjectArray jPatches,jobjectArray jSources,jobjectArray jSinks)1008 android_media_AudioSystem_createAudioPatch(JNIEnv *env, jobject clazz,
1009 jobjectArray jPatches, jobjectArray jSources, jobjectArray jSinks)
1010 {
1011 status_t status;
1012 jint jStatus;
1013
1014 ALOGV("createAudioPatch");
1015 if (jPatches == NULL || jSources == NULL || jSinks == NULL) {
1016 return (jint)AUDIO_JAVA_BAD_VALUE;
1017 }
1018
1019 if (env->GetArrayLength(jPatches) != 1) {
1020 return (jint)AUDIO_JAVA_BAD_VALUE;
1021 }
1022 jint numSources = env->GetArrayLength(jSources);
1023 if (numSources == 0 || numSources > AUDIO_PATCH_PORTS_MAX) {
1024 return (jint)AUDIO_JAVA_BAD_VALUE;
1025 }
1026
1027 jint numSinks = env->GetArrayLength(jSinks);
1028 if (numSinks == 0 || numSinks > AUDIO_PATCH_PORTS_MAX) {
1029 return (jint)AUDIO_JAVA_BAD_VALUE;
1030 }
1031
1032 audio_patch_handle_t handle = (audio_patch_handle_t)0;
1033 jobject jPatch = env->GetObjectArrayElement(jPatches, 0);
1034 jobject jPatchHandle = NULL;
1035 if (jPatch != NULL) {
1036 if (!env->IsInstanceOf(jPatch, gAudioPatchClass)) {
1037 return (jint)AUDIO_JAVA_BAD_VALUE;
1038 }
1039 jPatchHandle = env->GetObjectField(jPatch, gAudioPatchFields.mHandle);
1040 handle = (audio_patch_handle_t)env->GetIntField(jPatchHandle, gAudioHandleFields.mId);
1041 }
1042
1043 struct audio_patch nPatch;
1044
1045 nPatch.id = handle;
1046 nPatch.num_sources = 0;
1047 nPatch.num_sinks = 0;
1048 jobject jSource = NULL;
1049 jobject jSink = NULL;
1050
1051 for (jint i = 0; i < numSources; i++) {
1052 jSource = env->GetObjectArrayElement(jSources, i);
1053 if (!env->IsInstanceOf(jSource, gAudioPortConfigClass)) {
1054 jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
1055 goto exit;
1056 }
1057 jStatus = convertAudioPortConfigToNative(env, &nPatch.sources[i], jSource, false);
1058 env->DeleteLocalRef(jSource);
1059 jSource = NULL;
1060 if (jStatus != AUDIO_JAVA_SUCCESS) {
1061 goto exit;
1062 }
1063 nPatch.num_sources++;
1064 }
1065
1066 for (jint i = 0; i < numSinks; i++) {
1067 jSink = env->GetObjectArrayElement(jSinks, i);
1068 if (!env->IsInstanceOf(jSink, gAudioPortConfigClass)) {
1069 jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
1070 goto exit;
1071 }
1072 jStatus = convertAudioPortConfigToNative(env, &nPatch.sinks[i], jSink, false);
1073 env->DeleteLocalRef(jSink);
1074 jSink = NULL;
1075 if (jStatus != AUDIO_JAVA_SUCCESS) {
1076 goto exit;
1077 }
1078 nPatch.num_sinks++;
1079 }
1080
1081 ALOGV("AudioSystem::createAudioPatch");
1082 status = AudioSystem::createAudioPatch(&nPatch, &handle);
1083 ALOGV("AudioSystem::createAudioPatch() returned %d hande %d", status, handle);
1084
1085 jStatus = nativeToJavaStatus(status);
1086 if (jStatus != AUDIO_JAVA_SUCCESS) {
1087 goto exit;
1088 }
1089
1090 if (jPatchHandle == NULL) {
1091 jPatchHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
1092 handle);
1093 if (jPatchHandle == NULL) {
1094 jStatus = (jint)AUDIO_JAVA_ERROR;
1095 goto exit;
1096 }
1097 jPatch = env->NewObject(gAudioPatchClass, gAudioPatchCstor, jPatchHandle, jSources, jSinks);
1098 if (jPatch == NULL) {
1099 jStatus = (jint)AUDIO_JAVA_ERROR;
1100 goto exit;
1101 }
1102 env->SetObjectArrayElement(jPatches, 0, jPatch);
1103 } else {
1104 env->SetIntField(jPatchHandle, gAudioHandleFields.mId, handle);
1105 }
1106
1107 exit:
1108 if (jPatchHandle != NULL) {
1109 env->DeleteLocalRef(jPatchHandle);
1110 }
1111 if (jPatch != NULL) {
1112 env->DeleteLocalRef(jPatch);
1113 }
1114 if (jSource != NULL) {
1115 env->DeleteLocalRef(jSource);
1116 }
1117 if (jSink != NULL) {
1118 env->DeleteLocalRef(jSink);
1119 }
1120 return jStatus;
1121 }
1122
1123 static int
android_media_AudioSystem_releaseAudioPatch(JNIEnv * env,jobject clazz,jobject jPatch)1124 android_media_AudioSystem_releaseAudioPatch(JNIEnv *env, jobject clazz,
1125 jobject jPatch)
1126 {
1127 ALOGV("releaseAudioPatch");
1128 if (jPatch == NULL) {
1129 return (jint)AUDIO_JAVA_BAD_VALUE;
1130 }
1131
1132 audio_patch_handle_t handle = (audio_patch_handle_t)0;
1133 jobject jPatchHandle = NULL;
1134 if (!env->IsInstanceOf(jPatch, gAudioPatchClass)) {
1135 return (jint)AUDIO_JAVA_BAD_VALUE;
1136 }
1137 jPatchHandle = env->GetObjectField(jPatch, gAudioPatchFields.mHandle);
1138 handle = (audio_patch_handle_t)env->GetIntField(jPatchHandle, gAudioHandleFields.mId);
1139 env->DeleteLocalRef(jPatchHandle);
1140
1141 ALOGV("AudioSystem::releaseAudioPatch");
1142 status_t status = AudioSystem::releaseAudioPatch(handle);
1143 ALOGV("AudioSystem::releaseAudioPatch() returned %d", status);
1144 jint jStatus = nativeToJavaStatus(status);
1145 return status;
1146 }
1147
1148 static jint
android_media_AudioSystem_listAudioPatches(JNIEnv * env,jobject clazz,jobject jPatches,jintArray jGeneration)1149 android_media_AudioSystem_listAudioPatches(JNIEnv *env, jobject clazz,
1150 jobject jPatches, jintArray jGeneration)
1151 {
1152 ALOGV("listAudioPatches");
1153 if (jPatches == NULL) {
1154 ALOGE("listAudioPatches NULL AudioPatch ArrayList");
1155 return (jint)AUDIO_JAVA_BAD_VALUE;
1156 }
1157 if (!env->IsInstanceOf(jPatches, gArrayListClass)) {
1158 ALOGE("listAudioPatches not an arraylist");
1159 return (jint)AUDIO_JAVA_BAD_VALUE;
1160 }
1161
1162 if (jGeneration == NULL || env->GetArrayLength(jGeneration) != 1) {
1163 return (jint)AUDIO_JAVA_BAD_VALUE;
1164 }
1165
1166 status_t status;
1167 unsigned int generation1;
1168 unsigned int generation;
1169 unsigned int numPatches;
1170 jint *nGeneration;
1171 struct audio_patch *nPatches = NULL;
1172 jobjectArray jSources = NULL;
1173 jobject jSource = NULL;
1174 jobjectArray jSinks = NULL;
1175 jobject jSink = NULL;
1176 jobject jPatch = NULL;
1177 int attempts = MAX_PORT_GENERATION_SYNC_ATTEMPTS;
1178
1179 // get the patch count and all the patches until they both return the same generation
1180 do {
1181 if (attempts-- < 0) {
1182 status = TIMED_OUT;
1183 break;
1184 }
1185
1186 numPatches = 0;
1187 status = AudioSystem::listAudioPatches(&numPatches,
1188 NULL,
1189 &generation1);
1190 if (status != NO_ERROR || numPatches == 0) {
1191 ALOGE_IF(status != NO_ERROR, "listAudioPatches AudioSystem::listAudioPatches error %d",
1192 status);
1193 break;
1194 }
1195 nPatches = (struct audio_patch *)realloc(nPatches, numPatches * sizeof(struct audio_patch));
1196
1197 status = AudioSystem::listAudioPatches(&numPatches,
1198 nPatches,
1199 &generation);
1200 ALOGV("listAudioPatches AudioSystem::listAudioPatches numPatches %d generation %d generation1 %d",
1201 numPatches, generation, generation1);
1202
1203 } while (generation1 != generation && status == NO_ERROR);
1204
1205 jint jStatus = nativeToJavaStatus(status);
1206 if (jStatus != AUDIO_JAVA_SUCCESS) {
1207 goto exit;
1208 }
1209
1210 nGeneration = env->GetIntArrayElements(jGeneration, NULL);
1211 if (nGeneration == NULL) {
1212 jStatus = AUDIO_JAVA_ERROR;
1213 goto exit;
1214 }
1215 nGeneration[0] = generation1;
1216 env->ReleaseIntArrayElements(jGeneration, nGeneration, 0);
1217
1218 for (size_t i = 0; i < numPatches; i++) {
1219 jobject patchHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
1220 nPatches[i].id);
1221 if (patchHandle == NULL) {
1222 jStatus = AUDIO_JAVA_ERROR;
1223 goto exit;
1224 }
1225 ALOGV("listAudioPatches patch %d num_sources %d num_sinks %d",
1226 i, nPatches[i].num_sources, nPatches[i].num_sinks);
1227
1228 env->SetIntField(patchHandle, gAudioHandleFields.mId, nPatches[i].id);
1229
1230 // load sources
1231 jSources = env->NewObjectArray(nPatches[i].num_sources,
1232 gAudioPortConfigClass, NULL);
1233 if (jSources == NULL) {
1234 jStatus = AUDIO_JAVA_ERROR;
1235 goto exit;
1236 }
1237
1238 for (size_t j = 0; j < nPatches[i].num_sources; j++) {
1239 jStatus = convertAudioPortConfigFromNative(env,
1240 NULL,
1241 &jSource,
1242 &nPatches[i].sources[j]);
1243 if (jStatus != AUDIO_JAVA_SUCCESS) {
1244 goto exit;
1245 }
1246 env->SetObjectArrayElement(jSources, j, jSource);
1247 env->DeleteLocalRef(jSource);
1248 jSource = NULL;
1249 ALOGV("listAudioPatches patch %d source %d is a %s handle %d",
1250 i, j,
1251 nPatches[i].sources[j].type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix",
1252 nPatches[i].sources[j].id);
1253 }
1254 // load sinks
1255 jSinks = env->NewObjectArray(nPatches[i].num_sinks,
1256 gAudioPortConfigClass, NULL);
1257 if (jSinks == NULL) {
1258 jStatus = AUDIO_JAVA_ERROR;
1259 goto exit;
1260 }
1261
1262 for (size_t j = 0; j < nPatches[i].num_sinks; j++) {
1263 jStatus = convertAudioPortConfigFromNative(env,
1264 NULL,
1265 &jSink,
1266 &nPatches[i].sinks[j]);
1267
1268 if (jStatus != AUDIO_JAVA_SUCCESS) {
1269 goto exit;
1270 }
1271 env->SetObjectArrayElement(jSinks, j, jSink);
1272 env->DeleteLocalRef(jSink);
1273 jSink = NULL;
1274 ALOGV("listAudioPatches patch %d sink %d is a %s handle %d",
1275 i, j,
1276 nPatches[i].sinks[j].type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix",
1277 nPatches[i].sinks[j].id);
1278 }
1279
1280 jPatch = env->NewObject(gAudioPatchClass, gAudioPatchCstor,
1281 patchHandle, jSources, jSinks);
1282 env->DeleteLocalRef(jSources);
1283 jSources = NULL;
1284 env->DeleteLocalRef(jSinks);
1285 jSinks = NULL;
1286 if (jPatch == NULL) {
1287 jStatus = AUDIO_JAVA_ERROR;
1288 goto exit;
1289 }
1290 env->CallBooleanMethod(jPatches, gArrayListMethods.add, jPatch);
1291 env->DeleteLocalRef(jPatch);
1292 jPatch = NULL;
1293 }
1294
1295 exit:
1296 if (jSources != NULL) {
1297 env->DeleteLocalRef(jSources);
1298 }
1299 if (jSource != NULL) {
1300 env->DeleteLocalRef(jSource);
1301 }
1302 if (jSinks != NULL) {
1303 env->DeleteLocalRef(jSinks);
1304 }
1305 if (jSink != NULL) {
1306 env->DeleteLocalRef(jSink);
1307 }
1308 if (jPatch != NULL) {
1309 env->DeleteLocalRef(jPatch);
1310 }
1311 free(nPatches);
1312 return jStatus;
1313 }
1314
1315 static jint
android_media_AudioSystem_setAudioPortConfig(JNIEnv * env,jobject clazz,jobject jAudioPortConfig)1316 android_media_AudioSystem_setAudioPortConfig(JNIEnv *env, jobject clazz,
1317 jobject jAudioPortConfig)
1318 {
1319 ALOGV("setAudioPortConfig");
1320 if (jAudioPortConfig == NULL) {
1321 return AUDIO_JAVA_BAD_VALUE;
1322 }
1323 if (!env->IsInstanceOf(jAudioPortConfig, gAudioPortConfigClass)) {
1324 return AUDIO_JAVA_BAD_VALUE;
1325 }
1326 struct audio_port_config nAudioPortConfig;
1327 jint jStatus = convertAudioPortConfigToNative(env, &nAudioPortConfig, jAudioPortConfig, true);
1328 if (jStatus != AUDIO_JAVA_SUCCESS) {
1329 return jStatus;
1330 }
1331 status_t status = AudioSystem::setAudioPortConfig(&nAudioPortConfig);
1332 ALOGV("AudioSystem::setAudioPortConfig() returned %d", status);
1333 jStatus = nativeToJavaStatus(status);
1334 return jStatus;
1335 }
1336
1337 static void
android_media_AudioSystem_eventHandlerSetup(JNIEnv * env,jobject thiz,jobject weak_this)1338 android_media_AudioSystem_eventHandlerSetup(JNIEnv *env, jobject thiz, jobject weak_this)
1339 {
1340 ALOGV("eventHandlerSetup");
1341
1342 sp<JNIAudioPortCallback> callback = new JNIAudioPortCallback(env, thiz, weak_this);
1343
1344 AudioSystem::setAudioPortCallback(callback);
1345 }
1346
1347 static void
android_media_AudioSystem_eventHandlerFinalize(JNIEnv * env,jobject thiz)1348 android_media_AudioSystem_eventHandlerFinalize(JNIEnv *env, jobject thiz)
1349 {
1350 ALOGV("eventHandlerFinalize");
1351
1352 sp<JNIAudioPortCallback> callback;
1353
1354 AudioSystem::setAudioPortCallback(callback);
1355 }
1356
1357 static jint
android_media_AudioSystem_getAudioHwSyncForSession(JNIEnv * env,jobject thiz,jint sessionId)1358 android_media_AudioSystem_getAudioHwSyncForSession(JNIEnv *env, jobject thiz, jint sessionId)
1359 {
1360 return (jint)AudioSystem::getAudioHwSyncForSession((audio_session_t)sessionId);
1361 }
1362
1363
1364
1365
convertAudioMixToNative(JNIEnv * env,AudioMix * nAudioMix,const jobject jAudioMix)1366 static jint convertAudioMixToNative(JNIEnv *env,
1367 AudioMix *nAudioMix,
1368 const jobject jAudioMix)
1369 {
1370 nAudioMix->mMixType = env->GetIntField(jAudioMix, gAudioMixFields.mMixType);
1371 nAudioMix->mRouteFlags = env->GetIntField(jAudioMix, gAudioMixFields.mRouteFlags);
1372
1373 jstring jRegistrationId = (jstring)env->GetObjectField(jAudioMix,
1374 gAudioMixFields.mRegistrationId);
1375 const char *nRegistrationId = env->GetStringUTFChars(jRegistrationId, NULL);
1376 nAudioMix->mRegistrationId = String8(nRegistrationId);
1377 env->ReleaseStringUTFChars(jRegistrationId, nRegistrationId);
1378 env->DeleteLocalRef(jRegistrationId);
1379
1380 jobject jFormat = env->GetObjectField(jAudioMix, gAudioMixFields.mFormat);
1381 nAudioMix->mFormat.sample_rate = env->GetIntField(jFormat,
1382 gAudioFormatFields.mSampleRate);
1383 nAudioMix->mFormat.channel_mask = outChannelMaskToNative(env->GetIntField(jFormat,
1384 gAudioFormatFields.mChannelMask));
1385 nAudioMix->mFormat.format = audioFormatToNative(env->GetIntField(jFormat,
1386 gAudioFormatFields.mEncoding));
1387 env->DeleteLocalRef(jFormat);
1388
1389 jobject jRule = env->GetObjectField(jAudioMix, gAudioMixFields.mRule);
1390 jobject jRuleCriteria = env->GetObjectField(jRule, gAudioMixingRuleFields.mCriteria);
1391 env->DeleteLocalRef(jRule);
1392 jobjectArray jCriteria = (jobjectArray)env->CallObjectMethod(jRuleCriteria,
1393 gArrayListMethods.toArray);
1394 env->DeleteLocalRef(jRuleCriteria);
1395
1396 jint numCriteria = env->GetArrayLength(jCriteria);
1397 if (numCriteria > MAX_CRITERIA_PER_MIX) {
1398 numCriteria = MAX_CRITERIA_PER_MIX;
1399 }
1400
1401 for (jint i = 0; i < numCriteria; i++) {
1402 AttributeMatchCriterion nCriterion;
1403
1404 jobject jCriterion = env->GetObjectArrayElement(jCriteria, i);
1405
1406 nCriterion.mRule = env->GetIntField(jCriterion, gAttributeMatchCriterionFields.mRule);
1407
1408 jobject jAttributes = env->GetObjectField(jCriterion, gAttributeMatchCriterionFields.mAttr);
1409 if (nCriterion.mRule == RULE_MATCH_ATTRIBUTE_USAGE ||
1410 nCriterion.mRule == RULE_EXCLUDE_ATTRIBUTE_USAGE) {
1411 nCriterion.mAttr.mUsage = (audio_usage_t)env->GetIntField(jAttributes,
1412 gAudioAttributesFields.mUsage);
1413 } else {
1414 nCriterion.mAttr.mSource = (audio_source_t)env->GetIntField(jAttributes,
1415 gAudioAttributesFields.mSource);
1416 }
1417 env->DeleteLocalRef(jAttributes);
1418
1419 nAudioMix->mCriteria.add(nCriterion);
1420 env->DeleteLocalRef(jCriterion);
1421 }
1422
1423 env->DeleteLocalRef(jCriteria);
1424
1425 return (jint)AUDIO_JAVA_SUCCESS;
1426 }
1427
1428 static jint
android_media_AudioSystem_registerPolicyMixes(JNIEnv * env,jobject clazz,jobject jMixesList,jboolean registration)1429 android_media_AudioSystem_registerPolicyMixes(JNIEnv *env, jobject clazz,
1430 jobject jMixesList, jboolean registration)
1431 {
1432 ALOGV("registerPolicyMixes");
1433
1434 if (jMixesList == NULL) {
1435 return (jint)AUDIO_JAVA_BAD_VALUE;
1436 }
1437 if (!env->IsInstanceOf(jMixesList, gArrayListClass)) {
1438 return (jint)AUDIO_JAVA_BAD_VALUE;
1439 }
1440 jobjectArray jMixes = (jobjectArray)env->CallObjectMethod(jMixesList,
1441 gArrayListMethods.toArray);
1442 jint numMixes = env->GetArrayLength(jMixes);
1443 if (numMixes > MAX_MIXES_PER_POLICY) {
1444 numMixes = MAX_MIXES_PER_POLICY;
1445 }
1446
1447 status_t status;
1448 jint jStatus;
1449 jobject jAudioMix = NULL;
1450 Vector <AudioMix> mixes;
1451 for (jint i = 0; i < numMixes; i++) {
1452 jAudioMix = env->GetObjectArrayElement(jMixes, i);
1453 if (!env->IsInstanceOf(jAudioMix, gAudioMixClass)) {
1454 jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
1455 goto exit;
1456 }
1457 AudioMix mix;
1458 jStatus = convertAudioMixToNative(env, &mix, jAudioMix);
1459 env->DeleteLocalRef(jAudioMix);
1460 jAudioMix = NULL;
1461 if (jStatus != AUDIO_JAVA_SUCCESS) {
1462 goto exit;
1463 }
1464 mixes.add(mix);
1465 }
1466
1467 ALOGV("AudioSystem::registerPolicyMixes numMixes %d registration %d", numMixes, registration);
1468 status = AudioSystem::registerPolicyMixes(mixes, registration);
1469 ALOGV("AudioSystem::registerPolicyMixes() returned %d", status);
1470
1471 jStatus = nativeToJavaStatus(status);
1472 if (jStatus != AUDIO_JAVA_SUCCESS) {
1473 goto exit;
1474 }
1475
1476 exit:
1477 if (jAudioMix != NULL) {
1478 env->DeleteLocalRef(jAudioMix);
1479 }
1480 return jStatus;
1481 }
1482
1483
1484
1485 // ----------------------------------------------------------------------------
1486
1487 static JNINativeMethod gMethods[] = {
1488 {"setParameters", "(Ljava/lang/String;)I", (void *)android_media_AudioSystem_setParameters},
1489 {"getParameters", "(Ljava/lang/String;)Ljava/lang/String;", (void *)android_media_AudioSystem_getParameters},
1490 {"muteMicrophone", "(Z)I", (void *)android_media_AudioSystem_muteMicrophone},
1491 {"isMicrophoneMuted", "()Z", (void *)android_media_AudioSystem_isMicrophoneMuted},
1492 {"isStreamActive", "(II)Z", (void *)android_media_AudioSystem_isStreamActive},
1493 {"isStreamActiveRemotely","(II)Z", (void *)android_media_AudioSystem_isStreamActiveRemotely},
1494 {"isSourceActive", "(I)Z", (void *)android_media_AudioSystem_isSourceActive},
1495 {"newAudioSessionId", "()I", (void *)android_media_AudioSystem_newAudioSessionId},
1496 {"setDeviceConnectionState", "(IILjava/lang/String;)I", (void *)android_media_AudioSystem_setDeviceConnectionState},
1497 {"getDeviceConnectionState", "(ILjava/lang/String;)I", (void *)android_media_AudioSystem_getDeviceConnectionState},
1498 {"setPhoneState", "(I)I", (void *)android_media_AudioSystem_setPhoneState},
1499 {"setForceUse", "(II)I", (void *)android_media_AudioSystem_setForceUse},
1500 {"getForceUse", "(I)I", (void *)android_media_AudioSystem_getForceUse},
1501 {"initStreamVolume", "(III)I", (void *)android_media_AudioSystem_initStreamVolume},
1502 {"setStreamVolumeIndex","(III)I", (void *)android_media_AudioSystem_setStreamVolumeIndex},
1503 {"getStreamVolumeIndex","(II)I", (void *)android_media_AudioSystem_getStreamVolumeIndex},
1504 {"setMasterVolume", "(F)I", (void *)android_media_AudioSystem_setMasterVolume},
1505 {"getMasterVolume", "()F", (void *)android_media_AudioSystem_getMasterVolume},
1506 {"setMasterMute", "(Z)I", (void *)android_media_AudioSystem_setMasterMute},
1507 {"getMasterMute", "()Z", (void *)android_media_AudioSystem_getMasterMute},
1508 {"getDevicesForStream", "(I)I", (void *)android_media_AudioSystem_getDevicesForStream},
1509 {"getPrimaryOutputSamplingRate", "()I", (void *)android_media_AudioSystem_getPrimaryOutputSamplingRate},
1510 {"getPrimaryOutputFrameCount", "()I", (void *)android_media_AudioSystem_getPrimaryOutputFrameCount},
1511 {"getOutputLatency", "(I)I", (void *)android_media_AudioSystem_getOutputLatency},
1512 {"setLowRamDevice", "(Z)I", (void *)android_media_AudioSystem_setLowRamDevice},
1513 {"checkAudioFlinger", "()I", (void *)android_media_AudioSystem_checkAudioFlinger},
1514 {"listAudioPorts", "(Ljava/util/ArrayList;[I)I",
1515 (void *)android_media_AudioSystem_listAudioPorts},
1516 {"createAudioPatch", "([Landroid/media/AudioPatch;[Landroid/media/AudioPortConfig;[Landroid/media/AudioPortConfig;)I",
1517 (void *)android_media_AudioSystem_createAudioPatch},
1518 {"releaseAudioPatch", "(Landroid/media/AudioPatch;)I",
1519 (void *)android_media_AudioSystem_releaseAudioPatch},
1520 {"listAudioPatches", "(Ljava/util/ArrayList;[I)I",
1521 (void *)android_media_AudioSystem_listAudioPatches},
1522 {"setAudioPortConfig", "(Landroid/media/AudioPortConfig;)I",
1523 (void *)android_media_AudioSystem_setAudioPortConfig},
1524 {"getAudioHwSyncForSession", "(I)I",
1525 (void *)android_media_AudioSystem_getAudioHwSyncForSession},
1526 {"registerPolicyMixes", "(Ljava/util/ArrayList;Z)I",
1527 (void *)android_media_AudioSystem_registerPolicyMixes},
1528
1529 };
1530
1531
1532 static JNINativeMethod gEventHandlerMethods[] = {
1533 {"native_setup",
1534 "(Ljava/lang/Object;)V",
1535 (void *)android_media_AudioSystem_eventHandlerSetup},
1536 {"native_finalize",
1537 "()V",
1538 (void *)android_media_AudioSystem_eventHandlerFinalize},
1539 };
1540
register_android_media_AudioSystem(JNIEnv * env)1541 int register_android_media_AudioSystem(JNIEnv *env)
1542 {
1543
1544 jclass arrayListClass = env->FindClass("java/util/ArrayList");
1545 gArrayListClass = (jclass) env->NewGlobalRef(arrayListClass);
1546 gArrayListMethods.add = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
1547 gArrayListMethods.toArray = env->GetMethodID(arrayListClass, "toArray", "()[Ljava/lang/Object;");
1548
1549 jclass audioHandleClass = env->FindClass("android/media/AudioHandle");
1550 gAudioHandleClass = (jclass) env->NewGlobalRef(audioHandleClass);
1551 gAudioHandleCstor = env->GetMethodID(audioHandleClass, "<init>", "(I)V");
1552 gAudioHandleFields.mId = env->GetFieldID(audioHandleClass, "mId", "I");
1553
1554 jclass audioPortClass = env->FindClass("android/media/AudioPort");
1555 gAudioPortClass = (jclass) env->NewGlobalRef(audioPortClass);
1556 gAudioPortCstor = env->GetMethodID(audioPortClass, "<init>",
1557 "(Landroid/media/AudioHandle;I[I[I[I[Landroid/media/AudioGain;)V");
1558 gAudioPortFields.mHandle = env->GetFieldID(audioPortClass, "mHandle",
1559 "Landroid/media/AudioHandle;");
1560 gAudioPortFields.mRole = env->GetFieldID(audioPortClass, "mRole", "I");
1561 gAudioPortFields.mGains = env->GetFieldID(audioPortClass, "mGains",
1562 "[Landroid/media/AudioGain;");
1563 gAudioPortFields.mActiveConfig = env->GetFieldID(audioPortClass, "mActiveConfig",
1564 "Landroid/media/AudioPortConfig;");
1565
1566 jclass audioPortConfigClass = env->FindClass("android/media/AudioPortConfig");
1567 gAudioPortConfigClass = (jclass) env->NewGlobalRef(audioPortConfigClass);
1568 gAudioPortConfigCstor = env->GetMethodID(audioPortConfigClass, "<init>",
1569 "(Landroid/media/AudioPort;IIILandroid/media/AudioGainConfig;)V");
1570 gAudioPortConfigFields.mPort = env->GetFieldID(audioPortConfigClass, "mPort",
1571 "Landroid/media/AudioPort;");
1572 gAudioPortConfigFields.mSamplingRate = env->GetFieldID(audioPortConfigClass,
1573 "mSamplingRate", "I");
1574 gAudioPortConfigFields.mChannelMask = env->GetFieldID(audioPortConfigClass,
1575 "mChannelMask", "I");
1576 gAudioPortConfigFields.mFormat = env->GetFieldID(audioPortConfigClass, "mFormat", "I");
1577 gAudioPortConfigFields.mGain = env->GetFieldID(audioPortConfigClass, "mGain",
1578 "Landroid/media/AudioGainConfig;");
1579 gAudioPortConfigFields.mConfigMask = env->GetFieldID(audioPortConfigClass, "mConfigMask", "I");
1580
1581 jclass audioDevicePortConfigClass = env->FindClass("android/media/AudioDevicePortConfig");
1582 gAudioDevicePortConfigClass = (jclass) env->NewGlobalRef(audioDevicePortConfigClass);
1583 gAudioDevicePortConfigCstor = env->GetMethodID(audioDevicePortConfigClass, "<init>",
1584 "(Landroid/media/AudioDevicePort;IIILandroid/media/AudioGainConfig;)V");
1585
1586 jclass audioMixPortConfigClass = env->FindClass("android/media/AudioMixPortConfig");
1587 gAudioMixPortConfigClass = (jclass) env->NewGlobalRef(audioMixPortConfigClass);
1588 gAudioMixPortConfigCstor = env->GetMethodID(audioMixPortConfigClass, "<init>",
1589 "(Landroid/media/AudioMixPort;IIILandroid/media/AudioGainConfig;)V");
1590
1591 jclass audioDevicePortClass = env->FindClass("android/media/AudioDevicePort");
1592 gAudioDevicePortClass = (jclass) env->NewGlobalRef(audioDevicePortClass);
1593 gAudioDevicePortCstor = env->GetMethodID(audioDevicePortClass, "<init>",
1594 "(Landroid/media/AudioHandle;[I[I[I[Landroid/media/AudioGain;ILjava/lang/String;)V");
1595
1596 jclass audioMixPortClass = env->FindClass("android/media/AudioMixPort");
1597 gAudioMixPortClass = (jclass) env->NewGlobalRef(audioMixPortClass);
1598 gAudioMixPortCstor = env->GetMethodID(audioMixPortClass, "<init>",
1599 "(Landroid/media/AudioHandle;I[I[I[I[Landroid/media/AudioGain;)V");
1600
1601 jclass audioGainClass = env->FindClass("android/media/AudioGain");
1602 gAudioGainClass = (jclass) env->NewGlobalRef(audioGainClass);
1603 gAudioGainCstor = env->GetMethodID(audioGainClass, "<init>", "(IIIIIIIII)V");
1604
1605 jclass audioGainConfigClass = env->FindClass("android/media/AudioGainConfig");
1606 gAudioGainConfigClass = (jclass) env->NewGlobalRef(audioGainConfigClass);
1607 gAudioGainConfigCstor = env->GetMethodID(audioGainConfigClass, "<init>",
1608 "(ILandroid/media/AudioGain;II[II)V");
1609 gAudioGainConfigFields.mIndex = env->GetFieldID(gAudioGainConfigClass, "mIndex", "I");
1610 gAudioGainConfigFields.mMode = env->GetFieldID(audioGainConfigClass, "mMode", "I");
1611 gAudioGainConfigFields.mChannelMask = env->GetFieldID(audioGainConfigClass, "mChannelMask",
1612 "I");
1613 gAudioGainConfigFields.mValues = env->GetFieldID(audioGainConfigClass, "mValues", "[I");
1614 gAudioGainConfigFields.mRampDurationMs = env->GetFieldID(audioGainConfigClass,
1615 "mRampDurationMs", "I");
1616
1617 jclass audioPatchClass = env->FindClass("android/media/AudioPatch");
1618 gAudioPatchClass = (jclass) env->NewGlobalRef(audioPatchClass);
1619 gAudioPatchCstor = env->GetMethodID(audioPatchClass, "<init>",
1620 "(Landroid/media/AudioHandle;[Landroid/media/AudioPortConfig;[Landroid/media/AudioPortConfig;)V");
1621 gAudioPatchFields.mHandle = env->GetFieldID(audioPatchClass, "mHandle",
1622 "Landroid/media/AudioHandle;");
1623
1624 jclass eventHandlerClass = env->FindClass(kEventHandlerClassPathName);
1625 gPostEventFromNative = env->GetStaticMethodID(eventHandlerClass, "postEventFromNative",
1626 "(Ljava/lang/Object;IIILjava/lang/Object;)V");
1627
1628
1629 jclass audioMixClass = env->FindClass("android/media/audiopolicy/AudioMix");
1630 gAudioMixClass = (jclass) env->NewGlobalRef(audioMixClass);
1631 gAudioMixFields.mRule = env->GetFieldID(audioMixClass, "mRule",
1632 "Landroid/media/audiopolicy/AudioMixingRule;");
1633 gAudioMixFields.mFormat = env->GetFieldID(audioMixClass, "mFormat",
1634 "Landroid/media/AudioFormat;");
1635 gAudioMixFields.mRouteFlags = env->GetFieldID(audioMixClass, "mRouteFlags", "I");
1636 gAudioMixFields.mRegistrationId = env->GetFieldID(audioMixClass, "mRegistrationId",
1637 "Ljava/lang/String;");
1638 gAudioMixFields.mMixType = env->GetFieldID(audioMixClass, "mMixType", "I");
1639
1640 jclass audioFormatClass = env->FindClass("android/media/AudioFormat");
1641 gAudioFormatClass = (jclass) env->NewGlobalRef(audioFormatClass);
1642 gAudioFormatFields.mEncoding = env->GetFieldID(audioFormatClass, "mEncoding", "I");
1643 gAudioFormatFields.mSampleRate = env->GetFieldID(audioFormatClass, "mSampleRate", "I");
1644 gAudioFormatFields.mChannelMask = env->GetFieldID(audioFormatClass, "mChannelMask", "I");
1645
1646 jclass audioMixingRuleClass = env->FindClass("android/media/audiopolicy/AudioMixingRule");
1647 gAudioMixingRuleClass = (jclass) env->NewGlobalRef(audioMixingRuleClass);
1648 gAudioMixingRuleFields.mCriteria = env->GetFieldID(audioMixingRuleClass, "mCriteria",
1649 "Ljava/util/ArrayList;");
1650
1651 jclass attributeMatchCriterionClass =
1652 env->FindClass("android/media/audiopolicy/AudioMixingRule$AttributeMatchCriterion");
1653 gAttributeMatchCriterionClass = (jclass) env->NewGlobalRef(attributeMatchCriterionClass);
1654 gAttributeMatchCriterionFields.mAttr = env->GetFieldID(attributeMatchCriterionClass, "mAttr",
1655 "Landroid/media/AudioAttributes;");
1656 gAttributeMatchCriterionFields.mRule = env->GetFieldID(attributeMatchCriterionClass, "mRule",
1657 "I");
1658
1659 jclass audioAttributesClass = env->FindClass("android/media/AudioAttributes");
1660 gAudioAttributesClass = (jclass) env->NewGlobalRef(audioAttributesClass);
1661 gAudioAttributesFields.mUsage = env->GetFieldID(audioAttributesClass, "mUsage", "I");
1662 gAudioAttributesFields.mSource = env->GetFieldID(audioAttributesClass, "mSource", "I");
1663
1664 AudioSystem::setErrorCallback(android_media_AudioSystem_error_callback);
1665
1666 int status = AndroidRuntime::registerNativeMethods(env,
1667 kClassPathName, gMethods, NELEM(gMethods));
1668
1669 if (status == 0) {
1670 status = AndroidRuntime::registerNativeMethods(env,
1671 kEventHandlerClassPathName, gEventHandlerMethods, NELEM(gEventHandlerMethods));
1672 }
1673 return status;
1674 }
1675