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