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