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