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