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