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