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