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