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