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