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