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(µphones);
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, µphones[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