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 
JNIAudioPortCallback(JNIEnv * env,jobject thiz,jobject weak_thiz)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 
~JNIAudioPortCallback()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 
sendEvent(int event)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 
onAudioPortListUpdate()249 void JNIAudioPortCallback::onAudioPortListUpdate()
250 {
251     sendEvent(AUDIOPORT_EVENT_PORT_LIST_UPDATED);
252 }
253 
onAudioPatchListUpdate()254 void JNIAudioPortCallback::onAudioPatchListUpdate()
255 {
256     sendEvent(AUDIOPORT_EVENT_PATCH_LIST_UPDATED);
257 }
258 
onServiceDied()259 void JNIAudioPortCallback::onServiceDied()
260 {
261     sendEvent(AUDIOPORT_EVENT_SERVICE_DIED);
262 }
263 
setJniCallback(JNIEnv * env,jobject thiz,const sp<JNIAudioPortCallback> & callback)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 
check_AudioSystem_Command(status_t status)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
android_media_AudioSystem_muteMicrophone(JNIEnv * env,jobject thiz,jboolean on)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
android_media_AudioSystem_isMicrophoneMuted(JNIEnv * env,jobject thiz)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
android_media_AudioSystem_isStreamActive(JNIEnv * env,jobject thiz,jint stream,jint inPastMs)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
android_media_AudioSystem_isStreamActiveRemotely(JNIEnv * env,jobject thiz,jint stream,jint inPastMs)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
android_media_AudioSystem_isSourceActive(JNIEnv * env,jobject thiz,jint source)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
android_media_AudioSystem_newAudioSessionId(JNIEnv * env,jobject thiz)334 android_media_AudioSystem_newAudioSessionId(JNIEnv *env, jobject thiz)
335 {
336     return AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
337 }
338 
339 static jint
android_media_AudioSystem_newAudioPlayerId(JNIEnv * env,jobject thiz)340 android_media_AudioSystem_newAudioPlayerId(JNIEnv *env, jobject thiz)
341 {
342     return AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_PLAYER);
343 }
344 
345 static jint
android_media_AudioSystem_setParameters(JNIEnv * env,jobject thiz,jstring keyValuePairs)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
android_media_AudioSystem_getParameters(JNIEnv * env,jobject thiz,jstring keys)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
android_media_AudioSystem_error_callback(status_t err)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
android_media_AudioSystem_dyn_policy_callback(int event,String8 regId,int val)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
android_media_AudioSystem_recording_callback(int event,const record_client_info_t * clientInfo,const audio_config_base_t * clientConfig,const audio_config_base_t * deviceConfig,audio_patch_handle_t patchHandle)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
android_media_AudioSystem_setDeviceConnectionState(JNIEnv * env,jobject thiz,jint device,jint state,jstring device_address,jstring device_name)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
android_media_AudioSystem_getDeviceConnectionState(JNIEnv * env,jobject thiz,jint device,jstring device_address)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
android_media_AudioSystem_handleDeviceConfigChange(JNIEnv * env,jobject thiz,jint device,jstring device_address,jstring device_name)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
android_media_AudioSystem_setPhoneState(JNIEnv * env,jobject thiz,jint state)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
android_media_AudioSystem_setForceUse(JNIEnv * env,jobject thiz,jint usage,jint config)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
android_media_AudioSystem_getForceUse(JNIEnv * env,jobject thiz,jint usage)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
android_media_AudioSystem_initStreamVolume(JNIEnv * env,jobject thiz,jint stream,jint indexMin,jint indexMax)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
android_media_AudioSystem_setStreamVolumeIndex(JNIEnv * env,jobject thiz,jint stream,jint index,jint device)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
android_media_AudioSystem_getStreamVolumeIndex(JNIEnv * env,jobject thiz,jint stream,jint device)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
android_media_AudioSystem_setMasterVolume(JNIEnv * env,jobject thiz,jfloat value)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
android_media_AudioSystem_getMasterVolume(JNIEnv * env,jobject thiz)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
android_media_AudioSystem_setMasterMute(JNIEnv * env,jobject thiz,jboolean mute)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
android_media_AudioSystem_getMasterMute(JNIEnv * env,jobject thiz)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
android_media_AudioSystem_setMasterMono(JNIEnv * env,jobject thiz,jboolean mono)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
android_media_AudioSystem_getMasterMono(JNIEnv * env,jobject thiz)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
android_media_AudioSystem_getDevicesForStream(JNIEnv * env,jobject thiz,jint stream)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
android_media_AudioSystem_getPrimaryOutputSamplingRate(JNIEnv * env,jobject clazz)599 android_media_AudioSystem_getPrimaryOutputSamplingRate(JNIEnv *env, jobject clazz)
600 {
601     return (jint) AudioSystem::getPrimaryOutputSamplingRate();
602 }
603 
604 static jint
android_media_AudioSystem_getPrimaryOutputFrameCount(JNIEnv * env,jobject clazz)605 android_media_AudioSystem_getPrimaryOutputFrameCount(JNIEnv *env, jobject clazz)
606 {
607     return (jint) AudioSystem::getPrimaryOutputFrameCount();
608 }
609 
610 static jint
android_media_AudioSystem_getOutputLatency(JNIEnv * env,jobject clazz,jint stream)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
android_media_AudioSystem_setLowRamDevice(JNIEnv * env,jobject clazz,jboolean isLowRamDevice,jlong totalMemory)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
android_media_AudioSystem_checkAudioFlinger(JNIEnv * env,jobject clazz)629 android_media_AudioSystem_checkAudioFlinger(JNIEnv *env, jobject clazz)
630 {
631     return (jint) check_AudioSystem_Command(AudioSystem::checkAudioFlinger());
632 }
633 
634 
useInChannelMask(audio_port_type_t type,audio_port_role_t role)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 
convertAudioGainConfigToNative(JNIEnv * env,struct audio_gain_config * nAudioGainConfig,const jobject jAudioGainConfig,bool useInMask)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 
convertAudioPortConfigToNative(JNIEnv * env,struct audio_port_config * nAudioPortConfig,const jobject jAudioPortConfig,bool useConfigMask)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 
convertAudioPortConfigFromNative(JNIEnv * env,jobject jAudioPort,jobject * jAudioPortConfig,const struct audio_port_config * nAudioPortConfig)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 
hasFormat(int * formats,size_t size,int format)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>
array_size(const T (&)[N])939 static constexpr size_t array_size(const T (&)[N]) {
940     return N;
941 }
942 
convertAudioPortFromNative(JNIEnv * env,jobject * jAudioPort,const struct audio_port * nAudioPort)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
android_media_AudioSystem_listAudioPorts(JNIEnv * env,jobject clazz,jobject jPorts,jintArray jGeneration)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
android_media_AudioSystem_createAudioPatch(JNIEnv * env,jobject clazz,jobjectArray jPatches,jobjectArray jSources,jobjectArray jSinks)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
android_media_AudioSystem_releaseAudioPatch(JNIEnv * env,jobject clazz,jobject jPatch)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
android_media_AudioSystem_listAudioPatches(JNIEnv * env,jobject clazz,jobject jPatches,jintArray jGeneration)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
android_media_AudioSystem_setAudioPortConfig(JNIEnv * env,jobject clazz,jobject jAudioPortConfig)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
android_media_AudioSystem_eventHandlerSetup(JNIEnv * env,jobject thiz,jobject weak_this)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
android_media_AudioSystem_eventHandlerFinalize(JNIEnv * env,jobject thiz)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
android_media_AudioSystem_getAudioHwSyncForSession(JNIEnv * env,jobject thiz,jint sessionId)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
android_media_AudioSystem_registerDynPolicyCallback(JNIEnv * env,jobject thiz)1626 android_media_AudioSystem_registerDynPolicyCallback(JNIEnv *env, jobject thiz)
1627 {
1628     AudioSystem::setDynPolicyCallback(android_media_AudioSystem_dyn_policy_callback);
1629 }
1630 
1631 static void
android_media_AudioSystem_registerRecordingCallback(JNIEnv * env,jobject thiz)1632 android_media_AudioSystem_registerRecordingCallback(JNIEnv *env, jobject thiz)
1633 {
1634     AudioSystem::setRecordConfigCallback(android_media_AudioSystem_recording_callback);
1635 }
1636 
1637 
convertAudioMixToNative(JNIEnv * env,AudioMix * nAudioMix,const jobject jAudioMix)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
android_media_AudioSystem_registerPolicyMixes(JNIEnv * env,jobject clazz,jobject jMixesList,jboolean registration)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
android_media_AudioSystem_systemReady(JNIEnv * env,jobject thiz)1770 android_media_AudioSystem_systemReady(JNIEnv *env, jobject thiz)
1771 {
1772     return nativeToJavaStatus(AudioSystem::systemReady());
1773 }
1774 
1775 static jfloat
android_media_AudioSystem_getStreamVolumeDB(JNIEnv * env,jobject thiz,jint stream,jint index,jint device)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
android_media_AudioSystem_isOffloadSupported(JNIEnv * env,jobject thiz,jint encoding,jint sampleRate,jint channelMask,jint channelIndexMask)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
android_media_AudioSystem_getMicrophones(JNIEnv * env,jobject thiz,jobject jMicrophonesInfo)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
android_media_AudioSystem_getSurroundFormats(JNIEnv * env,jobject thiz,jobject jSurroundFormats,jboolean reported)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
android_media_AudioSystem_setSurroundFormatEnabled(JNIEnv * env,jobject thiz,jint audioFormat,jboolean enabled)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 
register_android_media_AudioSystem(JNIEnv * env)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