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