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