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