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