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