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