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