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