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