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