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