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