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