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