blob: ac00532417a0a838d5ec3b29c3b98a8a71e8a73e [file] [log] [blame]
Glenn Kastenb3db2132012-01-19 08:59:58 -08001/*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002**
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
Eric Laurent3a241992014-05-19 19:33:26 -070018//#define LOG_NDEBUG 0
19
Eric Laurentb69681c2014-05-19 19:02:51 -070020#define LOG_TAG "AudioSystem-JNI"
Glenn Kastenc81d31c2012-03-13 14:46:23 -070021#include <utils/Log.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022
Glenn Kastenc81d31c2012-03-13 14:46:23 -070023#include <jni.h>
24#include <JNIHelp.h>
Andreas Gampeed6b9df2014-11-20 22:02:20 -080025#include "core_jni_helpers.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026
27#include <media/AudioSystem.h>
Eric Laurent7f5eb9f2014-12-01 19:36:30 -080028#include <media/AudioPolicy.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029
Dima Zavin34bb4192011-05-11 14:15:23 -070030#include <system/audio.h>
Dima Zavin290029d2011-06-13 18:16:26 -070031#include <system/audio_policy.h>
Eric Laurentb69681c2014-05-19 19:02:51 -070032#include "android_media_AudioFormat.h"
33#include "android_media_AudioErrors.h"
Dima Zavin24fc2fb2011-04-19 22:30:36 -070034
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035// ----------------------------------------------------------------------------
36
37using namespace android;
38
Glenn Kastened0079d2011-04-04 10:50:50 -070039static const char* const kClassPathName = "android/media/AudioSystem";
40
Eric Laurentb69681c2014-05-19 19:02:51 -070041static jclass gArrayListClass;
42static struct {
43 jmethodID add;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -080044 jmethodID toArray;
Eric Laurentb69681c2014-05-19 19:02:51 -070045} gArrayListMethods;
46
47static jclass gAudioHandleClass;
48static jmethodID gAudioHandleCstor;
49static struct {
50 jfieldID mId;
51} gAudioHandleFields;
52
53static jclass gAudioPortClass;
54static jmethodID gAudioPortCstor;
55static struct {
56 jfieldID mHandle;
57 jfieldID mRole;
58 jfieldID mGains;
59 jfieldID mActiveConfig;
60 // other fields unused by JNI
61} gAudioPortFields;
62
63static jclass gAudioPortConfigClass;
64static jmethodID gAudioPortConfigCstor;
65static struct {
66 jfieldID mPort;
67 jfieldID mSamplingRate;
68 jfieldID mChannelMask;
69 jfieldID mFormat;
70 jfieldID mGain;
Eric Laurent3a241992014-05-19 19:33:26 -070071 jfieldID mConfigMask;
Eric Laurentb69681c2014-05-19 19:02:51 -070072} gAudioPortConfigFields;
73
74static jclass gAudioDevicePortClass;
75static jmethodID gAudioDevicePortCstor;
76
77static jclass gAudioDevicePortConfigClass;
78static jmethodID gAudioDevicePortConfigCstor;
79
80static jclass gAudioMixPortClass;
81static jmethodID gAudioMixPortCstor;
82
83static jclass gAudioMixPortConfigClass;
84static jmethodID gAudioMixPortConfigCstor;
85
86static jclass gAudioGainClass;
87static jmethodID gAudioGainCstor;
88
89static jclass gAudioGainConfigClass;
90static jmethodID gAudioGainConfigCstor;
91static struct {
92 jfieldID mIndex;
93 jfieldID mMode;
94 jfieldID mChannelMask;
95 jfieldID mValues;
96 jfieldID mRampDurationMs;
97 // other fields unused by JNI
98} gAudioGainConfigFields;
99
100static jclass gAudioPatchClass;
101static jmethodID gAudioPatchCstor;
102static struct {
103 jfieldID mHandle;
104 // other fields unused by JNI
105} gAudioPatchFields;
106
Eric Laurent7f5eb9f2014-12-01 19:36:30 -0800107static jclass gAudioMixClass;
108static struct {
109 jfieldID mRule;
110 jfieldID mFormat;
111 jfieldID mRouteFlags;
112 jfieldID mRegistrationId;
113 jfieldID mMixType;
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700114 jfieldID mCallbackFlags;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -0800115} gAudioMixFields;
116
117static jclass gAudioFormatClass;
118static struct {
119 jfieldID mEncoding;
120 jfieldID mSampleRate;
121 jfieldID mChannelMask;
122 // other fields unused by JNI
123} gAudioFormatFields;
124
125static jclass gAudioMixingRuleClass;
126static struct {
127 jfieldID mCriteria;
128 // other fields unused by JNI
129} gAudioMixingRuleFields;
130
131static jclass gAttributeMatchCriterionClass;
132static struct {
133 jfieldID mAttr;
134 jfieldID mRule;
135} gAttributeMatchCriterionFields;
136
137static jclass gAudioAttributesClass;
138static struct {
139 jfieldID mUsage;
140 jfieldID mSource;
141} gAudioAttributesFields;
142
143
Eric Laurent700e7342014-05-02 18:33:15 -0700144static const char* const kEventHandlerClassPathName =
145 "android/media/AudioPortEventHandler";
Eric Laurent2615afb2015-03-25 14:51:08 -0700146static struct {
147 jfieldID mJniCallback;
148} gEventHandlerFields;
149static struct {
150 jmethodID postEventFromNative;
151} gAudioPortEventHandlerMethods;
152
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700153static struct {
154 jmethodID postDynPolicyEventFromNative;
155} gDynPolicyEventHandlerMethods;
156
Eric Laurent2615afb2015-03-25 14:51:08 -0700157static Mutex gLock;
Eric Laurentb69681c2014-05-19 19:02:51 -0700158
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800159enum AudioError {
160 kAudioStatusOk = 0,
161 kAudioStatusError = 1,
162 kAudioStatusMediaServerDied = 100
163};
164
Eric Laurent700e7342014-05-02 18:33:15 -0700165enum {
166 AUDIOPORT_EVENT_PORT_LIST_UPDATED = 1,
167 AUDIOPORT_EVENT_PATCH_LIST_UPDATED = 2,
168 AUDIOPORT_EVENT_SERVICE_DIED = 3,
169};
170
Eric Laurentb69681c2014-05-19 19:02:51 -0700171#define MAX_PORT_GENERATION_SYNC_ATTEMPTS 5
172
Eric Laurent700e7342014-05-02 18:33:15 -0700173// ----------------------------------------------------------------------------
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700174// ref-counted object for audio port callbacks
Eric Laurent700e7342014-05-02 18:33:15 -0700175class JNIAudioPortCallback: public AudioSystem::AudioPortCallback
176{
177public:
178 JNIAudioPortCallback(JNIEnv* env, jobject thiz, jobject weak_thiz);
179 ~JNIAudioPortCallback();
180
181 virtual void onAudioPortListUpdate();
182 virtual void onAudioPatchListUpdate();
183 virtual void onServiceDied();
184
185private:
186 void sendEvent(int event);
187
Eric Laurent2615afb2015-03-25 14:51:08 -0700188 jclass mClass; // Reference to AudioPortEventHandler class
189 jobject mObject; // Weak ref to AudioPortEventHandler Java object to call on
Eric Laurent700e7342014-05-02 18:33:15 -0700190};
191
192JNIAudioPortCallback::JNIAudioPortCallback(JNIEnv* env, jobject thiz, jobject weak_thiz)
193{
194
Eric Laurent2615afb2015-03-25 14:51:08 -0700195 // Hold onto the AudioPortEventHandler class for use in calling the static method
Eric Laurent700e7342014-05-02 18:33:15 -0700196 // that posts events to the application thread.
197 jclass clazz = env->GetObjectClass(thiz);
198 if (clazz == NULL) {
199 ALOGE("Can't find class %s", kEventHandlerClassPathName);
200 return;
201 }
202 mClass = (jclass)env->NewGlobalRef(clazz);
203
Eric Laurent2615afb2015-03-25 14:51:08 -0700204 // We use a weak reference so the AudioPortEventHandler object can be garbage collected.
Eric Laurent700e7342014-05-02 18:33:15 -0700205 // The reference is only used as a proxy for callbacks.
206 mObject = env->NewGlobalRef(weak_thiz);
207}
208
209JNIAudioPortCallback::~JNIAudioPortCallback()
210{
211 // remove global references
212 JNIEnv *env = AndroidRuntime::getJNIEnv();
Eric Laurent449c5882014-11-12 11:07:48 -0800213 if (env == NULL) {
214 return;
215 }
Eric Laurent700e7342014-05-02 18:33:15 -0700216 env->DeleteGlobalRef(mObject);
217 env->DeleteGlobalRef(mClass);
218}
219
220void JNIAudioPortCallback::sendEvent(int event)
221{
222 JNIEnv *env = AndroidRuntime::getJNIEnv();
Eric Laurent449c5882014-11-12 11:07:48 -0800223 if (env == NULL) {
224 return;
225 }
Eric Laurent2615afb2015-03-25 14:51:08 -0700226 env->CallStaticVoidMethod(mClass, gAudioPortEventHandlerMethods.postEventFromNative, mObject,
Eric Laurent700e7342014-05-02 18:33:15 -0700227 event, 0, 0, NULL);
228 if (env->ExceptionCheck()) {
229 ALOGW("An exception occurred while notifying an event.");
230 env->ExceptionClear();
231 }
232}
233
234void JNIAudioPortCallback::onAudioPortListUpdate()
235{
236 sendEvent(AUDIOPORT_EVENT_PORT_LIST_UPDATED);
237}
238
239void JNIAudioPortCallback::onAudioPatchListUpdate()
240{
241 sendEvent(AUDIOPORT_EVENT_PATCH_LIST_UPDATED);
242}
243
244void JNIAudioPortCallback::onServiceDied()
245{
246 sendEvent(AUDIOPORT_EVENT_SERVICE_DIED);
247}
248
Eric Laurent2615afb2015-03-25 14:51:08 -0700249static sp<JNIAudioPortCallback> setJniCallback(JNIEnv* env,
250 jobject thiz,
251 const sp<JNIAudioPortCallback>& callback)
252{
253 Mutex::Autolock l(gLock);
254 sp<JNIAudioPortCallback> old =
255 (JNIAudioPortCallback*)env->GetLongField(thiz, gEventHandlerFields.mJniCallback);
256 if (callback.get()) {
257 callback->incStrong((void*)setJniCallback);
258 }
259 if (old != 0) {
260 old->decStrong((void*)setJniCallback);
261 }
262 env->SetLongField(thiz, gEventHandlerFields.mJniCallback, (jlong)callback.get());
263 return old;
264}
265
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800266static int check_AudioSystem_Command(status_t status)
267{
Eric Laurentdfb881f2013-07-18 14:41:39 -0700268 switch (status) {
269 case DEAD_OBJECT:
270 return kAudioStatusMediaServerDied;
271 case NO_ERROR:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800272 return kAudioStatusOk;
Eric Laurentdfb881f2013-07-18 14:41:39 -0700273 default:
274 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275 }
Eric Laurentdfb881f2013-07-18 14:41:39 -0700276 return kAudioStatusError;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277}
278
Ashok Bhat075e9a12014-01-06 13:45:09 +0000279static jint
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800280android_media_AudioSystem_muteMicrophone(JNIEnv *env, jobject thiz, jboolean on)
281{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000282 return (jint) check_AudioSystem_Command(AudioSystem::muteMicrophone(on));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800283}
284
285static jboolean
286android_media_AudioSystem_isMicrophoneMuted(JNIEnv *env, jobject thiz)
287{
288 bool state = false;
289 AudioSystem::isMicrophoneMuted(&state);
290 return state;
291}
292
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800293static jboolean
Eric Laurent25101b02011-02-02 09:33:30 -0800294android_media_AudioSystem_isStreamActive(JNIEnv *env, jobject thiz, jint stream, jint inPastMs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800295{
296 bool state = false;
Glenn Kastenbc1d77b2012-01-12 16:38:12 -0800297 AudioSystem::isStreamActive((audio_stream_type_t) stream, &state, inPastMs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800298 return state;
299}
300
Jean-Michel Trivid6770542012-10-10 12:03:41 -0700301static jboolean
Jean-Michel Trivi679d5042013-02-04 16:24:09 -0800302android_media_AudioSystem_isStreamActiveRemotely(JNIEnv *env, jobject thiz, jint stream,
303 jint inPastMs)
304{
305 bool state = false;
306 AudioSystem::isStreamActiveRemotely((audio_stream_type_t) stream, &state, inPastMs);
307 return state;
308}
309
310static jboolean
Jean-Michel Trivid6770542012-10-10 12:03:41 -0700311android_media_AudioSystem_isSourceActive(JNIEnv *env, jobject thiz, jint source)
312{
313 bool state = false;
314 AudioSystem::isSourceActive((audio_source_t) source, &state);
315 return state;
316}
317
Ashok Bhat075e9a12014-01-06 13:45:09 +0000318static jint
Jean-Michel Trivi8a21f5d2014-06-05 15:03:52 -0700319android_media_AudioSystem_newAudioSessionId(JNIEnv *env, jobject thiz)
320{
Eric Laurent62dc1762014-07-25 08:13:10 -0700321 return AudioSystem::newAudioUniqueId();
Jean-Michel Trivi8a21f5d2014-06-05 15:03:52 -0700322}
323
324static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700325android_media_AudioSystem_setParameters(JNIEnv *env, jobject thiz, jstring keyValuePairs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800326{
Eric Laurenta553c252009-07-17 12:17:14 -0700327 const jchar* c_keyValuePairs = env->GetStringCritical(keyValuePairs, 0);
328 String8 c_keyValuePairs8;
329 if (keyValuePairs) {
Dan Albert66987492014-11-20 11:41:21 -0800330 c_keyValuePairs8 = String8(
331 reinterpret_cast<const char16_t*>(c_keyValuePairs),
332 env->GetStringLength(keyValuePairs));
Eric Laurenta553c252009-07-17 12:17:14 -0700333 env->ReleaseStringCritical(keyValuePairs, c_keyValuePairs);
334 }
Glenn Kastenc94752a2013-12-19 12:40:33 -0800335 int status = check_AudioSystem_Command(AudioSystem::setParameters(c_keyValuePairs8));
Ashok Bhat075e9a12014-01-06 13:45:09 +0000336 return (jint) status;
Eric Laurenta553c252009-07-17 12:17:14 -0700337}
338
339static jstring
340android_media_AudioSystem_getParameters(JNIEnv *env, jobject thiz, jstring keys)
341{
342 const jchar* c_keys = env->GetStringCritical(keys, 0);
343 String8 c_keys8;
344 if (keys) {
Dan Albert66987492014-11-20 11:41:21 -0800345 c_keys8 = String8(reinterpret_cast<const char16_t*>(c_keys),
346 env->GetStringLength(keys));
Eric Laurenta553c252009-07-17 12:17:14 -0700347 env->ReleaseStringCritical(keys, c_keys);
348 }
Glenn Kastenc94752a2013-12-19 12:40:33 -0800349 return env->NewStringUTF(AudioSystem::getParameters(c_keys8).string());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800350}
351
Glenn Kastened0079d2011-04-04 10:50:50 -0700352static void
353android_media_AudioSystem_error_callback(status_t err)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800354{
Eric Laurent539719a2013-07-18 14:08:00 -0700355 JNIEnv *env = AndroidRuntime::getJNIEnv();
Eric Laurent0e7a4d92010-10-15 12:33:16 -0700356 if (env == NULL) {
357 return;
358 }
359
Glenn Kastened0079d2011-04-04 10:50:50 -0700360 jclass clazz = env->FindClass(kClassPathName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800361
Eric Laurentdfb881f2013-07-18 14:41:39 -0700362 env->CallStaticVoidMethod(clazz, env->GetStaticMethodID(clazz,
363 "errorCallbackFromNative","(I)V"),
364 check_AudioSystem_Command(err));
Viorel Sumanb637ccf2014-05-30 16:51:07 +0300365
366 env->DeleteLocalRef(clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800367}
368
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700369static void
370android_media_AudioSystem_dyn_policy_callback(int event, String8 regId, int val)
371{
372 JNIEnv *env = AndroidRuntime::getJNIEnv();
373 if (env == NULL) {
374 return;
375 }
376
377 jclass clazz = env->FindClass(kClassPathName);
378 const char* zechars = regId.string();
379 jstring zestring = env->NewStringUTF(zechars);
380
381 env->CallStaticVoidMethod(clazz, gDynPolicyEventHandlerMethods.postDynPolicyEventFromNative,
382 event, zestring, val);
383
384 env->ReleaseStringUTFChars(zestring, zechars);
385 env->DeleteLocalRef(clazz);
386
387}
388
Ashok Bhat075e9a12014-01-06 13:45:09 +0000389static jint
Paul McLean10804eb2015-01-28 11:16:35 -0800390android_media_AudioSystem_setDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jint state, jstring device_address, jstring device_name)
Eric Laurenta553c252009-07-17 12:17:14 -0700391{
392 const char *c_address = env->GetStringUTFChars(device_address, NULL);
Paul McLean10804eb2015-01-28 11:16:35 -0800393 const char *c_name = env->GetStringUTFChars(device_name, NULL);
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700394 int status = check_AudioSystem_Command(AudioSystem::setDeviceConnectionState(static_cast <audio_devices_t>(device),
395 static_cast <audio_policy_dev_state_t>(state),
Paul McLean10804eb2015-01-28 11:16:35 -0800396 c_address, c_name));
Eric Laurenta553c252009-07-17 12:17:14 -0700397 env->ReleaseStringUTFChars(device_address, c_address);
Paul McLean10804eb2015-01-28 11:16:35 -0800398 env->ReleaseStringUTFChars(device_name, c_name);
Ashok Bhat075e9a12014-01-06 13:45:09 +0000399 return (jint) status;
Eric Laurenta553c252009-07-17 12:17:14 -0700400}
401
Ashok Bhat075e9a12014-01-06 13:45:09 +0000402static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700403android_media_AudioSystem_getDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jstring device_address)
404{
405 const char *c_address = env->GetStringUTFChars(device_address, NULL);
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700406 int state = static_cast <int>(AudioSystem::getDeviceConnectionState(static_cast <audio_devices_t>(device),
Eric Laurenta553c252009-07-17 12:17:14 -0700407 c_address));
408 env->ReleaseStringUTFChars(device_address, c_address);
Ashok Bhat075e9a12014-01-06 13:45:09 +0000409 return (jint) state;
Eric Laurenta553c252009-07-17 12:17:14 -0700410}
411
Ashok Bhat075e9a12014-01-06 13:45:09 +0000412static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700413android_media_AudioSystem_setPhoneState(JNIEnv *env, jobject thiz, jint state)
414{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000415 return (jint) check_AudioSystem_Command(AudioSystem::setPhoneState((audio_mode_t) state));
Eric Laurenta553c252009-07-17 12:17:14 -0700416}
417
Ashok Bhat075e9a12014-01-06 13:45:09 +0000418static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700419android_media_AudioSystem_setForceUse(JNIEnv *env, jobject thiz, jint usage, jint config)
420{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000421 return (jint) check_AudioSystem_Command(AudioSystem::setForceUse(static_cast <audio_policy_force_use_t>(usage),
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700422 static_cast <audio_policy_forced_cfg_t>(config)));
Eric Laurenta553c252009-07-17 12:17:14 -0700423}
424
Ashok Bhat075e9a12014-01-06 13:45:09 +0000425static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700426android_media_AudioSystem_getForceUse(JNIEnv *env, jobject thiz, jint usage)
427{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000428 return static_cast <jint>(AudioSystem::getForceUse(static_cast <audio_policy_force_use_t>(usage)));
Eric Laurenta553c252009-07-17 12:17:14 -0700429}
430
Ashok Bhat075e9a12014-01-06 13:45:09 +0000431static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700432android_media_AudioSystem_initStreamVolume(JNIEnv *env, jobject thiz, jint stream, jint indexMin, jint indexMax)
433{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000434 return (jint) check_AudioSystem_Command(AudioSystem::initStreamVolume(static_cast <audio_stream_type_t>(stream),
Eric Laurenta553c252009-07-17 12:17:14 -0700435 indexMin,
436 indexMax));
437}
438
Ashok Bhat075e9a12014-01-06 13:45:09 +0000439static jint
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800440android_media_AudioSystem_setStreamVolumeIndex(JNIEnv *env,
441 jobject thiz,
442 jint stream,
443 jint index,
444 jint device)
Eric Laurenta553c252009-07-17 12:17:14 -0700445{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000446 return (jint) check_AudioSystem_Command(
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800447 AudioSystem::setStreamVolumeIndex(static_cast <audio_stream_type_t>(stream),
448 index,
449 (audio_devices_t)device));
Eric Laurenta553c252009-07-17 12:17:14 -0700450}
451
Ashok Bhat075e9a12014-01-06 13:45:09 +0000452static jint
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800453android_media_AudioSystem_getStreamVolumeIndex(JNIEnv *env,
454 jobject thiz,
455 jint stream,
456 jint device)
Eric Laurenta553c252009-07-17 12:17:14 -0700457{
458 int index;
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800459 if (AudioSystem::getStreamVolumeIndex(static_cast <audio_stream_type_t>(stream),
460 &index,
461 (audio_devices_t)device)
462 != NO_ERROR) {
Eric Laurenta553c252009-07-17 12:17:14 -0700463 index = -1;
464 }
Ashok Bhat075e9a12014-01-06 13:45:09 +0000465 return (jint) index;
Eric Laurenta553c252009-07-17 12:17:14 -0700466}
467
Ashok Bhat075e9a12014-01-06 13:45:09 +0000468static jint
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400469android_media_AudioSystem_setMasterVolume(JNIEnv *env, jobject thiz, jfloat value)
470{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000471 return (jint) check_AudioSystem_Command(AudioSystem::setMasterVolume(value));
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400472}
473
474static jfloat
475android_media_AudioSystem_getMasterVolume(JNIEnv *env, jobject thiz)
476{
477 float value;
478 if (AudioSystem::getMasterVolume(&value) != NO_ERROR) {
479 value = -1.0;
480 }
481 return value;
482}
483
Ashok Bhat075e9a12014-01-06 13:45:09 +0000484static jint
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400485android_media_AudioSystem_setMasterMute(JNIEnv *env, jobject thiz, jboolean mute)
486{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000487 return (jint) check_AudioSystem_Command(AudioSystem::setMasterMute(mute));
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400488}
489
Vladimir Markoc1bcdbb2014-10-29 20:34:15 +0000490static jboolean
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400491android_media_AudioSystem_getMasterMute(JNIEnv *env, jobject thiz)
492{
493 bool mute;
494 if (AudioSystem::getMasterMute(&mute) != NO_ERROR) {
495 mute = false;
496 }
497 return mute;
498}
499
Glenn Kasten8b4b97a2011-02-04 13:54:26 -0800500static jint
501android_media_AudioSystem_getDevicesForStream(JNIEnv *env, jobject thiz, jint stream)
502{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700503 return (jint) AudioSystem::getDevicesForStream(static_cast <audio_stream_type_t>(stream));
Glenn Kasten8b4b97a2011-02-04 13:54:26 -0800504}
505
Glenn Kastenc6c43652012-09-24 17:32:30 -0700506static jint
507android_media_AudioSystem_getPrimaryOutputSamplingRate(JNIEnv *env, jobject clazz)
508{
509 return (jint) AudioSystem::getPrimaryOutputSamplingRate();
510}
511
512static jint
513android_media_AudioSystem_getPrimaryOutputFrameCount(JNIEnv *env, jobject clazz)
514{
515 return (jint) AudioSystem::getPrimaryOutputFrameCount();
516}
517
Oliver Woodman61dcdf32013-06-26 12:43:36 +0100518static jint
519android_media_AudioSystem_getOutputLatency(JNIEnv *env, jobject clazz, jint stream)
520{
521 uint32_t afLatency;
522 if (AudioSystem::getOutputLatency(&afLatency, static_cast <audio_stream_type_t>(stream))
523 != NO_ERROR) {
524 afLatency = -1;
525 }
526 return (jint) afLatency;
527}
528
Glenn Kastenfd116ad2013-07-12 17:10:39 -0700529static jint
530android_media_AudioSystem_setLowRamDevice(JNIEnv *env, jobject clazz, jboolean isLowRamDevice)
531{
532 return (jint) AudioSystem::setLowRamDevice((bool) isLowRamDevice);
533}
534
Ashok Bhat075e9a12014-01-06 13:45:09 +0000535static jint
Eric Laurentdfb881f2013-07-18 14:41:39 -0700536android_media_AudioSystem_checkAudioFlinger(JNIEnv *env, jobject clazz)
537{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000538 return (jint) check_AudioSystem_Command(AudioSystem::checkAudioFlinger());
Eric Laurentdfb881f2013-07-18 14:41:39 -0700539}
540
Eric Laurentb69681c2014-05-19 19:02:51 -0700541
542static bool useInChannelMask(audio_port_type_t type, audio_port_role_t role)
543{
544 return ((type == AUDIO_PORT_TYPE_DEVICE) && (role == AUDIO_PORT_ROLE_SOURCE)) ||
545 ((type == AUDIO_PORT_TYPE_MIX) && (role == AUDIO_PORT_ROLE_SINK));
546}
547
Eric Laurent3a241992014-05-19 19:33:26 -0700548static void convertAudioGainConfigToNative(JNIEnv *env,
549 struct audio_gain_config *nAudioGainConfig,
550 const jobject jAudioGainConfig,
551 bool useInMask)
552{
553 nAudioGainConfig->index = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mIndex);
554 nAudioGainConfig->mode = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mMode);
555 ALOGV("convertAudioGainConfigToNative got gain index %d", nAudioGainConfig->index);
556 jint jMask = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mChannelMask);
557 audio_channel_mask_t nMask;
558 if (useInMask) {
559 nMask = inChannelMaskToNative(jMask);
560 ALOGV("convertAudioGainConfigToNative IN mask java %x native %x", jMask, nMask);
561 } else {
562 nMask = outChannelMaskToNative(jMask);
563 ALOGV("convertAudioGainConfigToNative OUT mask java %x native %x", jMask, nMask);
564 }
565 nAudioGainConfig->channel_mask = nMask;
566 nAudioGainConfig->ramp_duration_ms = env->GetIntField(jAudioGainConfig,
567 gAudioGainConfigFields.mRampDurationMs);
568 jintArray jValues = (jintArray)env->GetObjectField(jAudioGainConfig,
569 gAudioGainConfigFields.mValues);
570 int *nValues = env->GetIntArrayElements(jValues, NULL);
571 size_t size = env->GetArrayLength(jValues);
572 memcpy(nAudioGainConfig->values, nValues, size * sizeof(int));
573 env->DeleteLocalRef(jValues);
574}
575
576
Eric Laurentb69681c2014-05-19 19:02:51 -0700577static jint convertAudioPortConfigToNative(JNIEnv *env,
578 struct audio_port_config *nAudioPortConfig,
Eric Laurent6368a7d2014-11-19 12:18:32 -0800579 const jobject jAudioPortConfig,
580 bool useConfigMask)
Eric Laurentb69681c2014-05-19 19:02:51 -0700581{
582 jobject jAudioPort = env->GetObjectField(jAudioPortConfig, gAudioPortConfigFields.mPort);
583 jobject jHandle = env->GetObjectField(jAudioPort, gAudioPortFields.mHandle);
584 nAudioPortConfig->id = env->GetIntField(jHandle, gAudioHandleFields.mId);
585 nAudioPortConfig->role = (audio_port_role_t)env->GetIntField(jAudioPort,
586 gAudioPortFields.mRole);
587 if (env->IsInstanceOf(jAudioPort, gAudioDevicePortClass)) {
588 nAudioPortConfig->type = AUDIO_PORT_TYPE_DEVICE;
589 } else if (env->IsInstanceOf(jAudioPort, gAudioMixPortClass)) {
590 nAudioPortConfig->type = AUDIO_PORT_TYPE_MIX;
591 } else {
592 env->DeleteLocalRef(jAudioPort);
593 env->DeleteLocalRef(jHandle);
594 return (jint)AUDIO_JAVA_ERROR;
595 }
596 ALOGV("convertAudioPortConfigToNative handle %d role %d type %d",
597 nAudioPortConfig->id, nAudioPortConfig->role, nAudioPortConfig->type);
598
Eric Laurent6368a7d2014-11-19 12:18:32 -0800599 unsigned int configMask = 0;
600
Eric Laurentb69681c2014-05-19 19:02:51 -0700601 nAudioPortConfig->sample_rate = env->GetIntField(jAudioPortConfig,
602 gAudioPortConfigFields.mSamplingRate);
Eric Laurent6368a7d2014-11-19 12:18:32 -0800603 if (nAudioPortConfig->sample_rate != 0) {
604 configMask |= AUDIO_PORT_CONFIG_SAMPLE_RATE;
605 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700606
607 bool useInMask = useInChannelMask(nAudioPortConfig->type, nAudioPortConfig->role);
608 audio_channel_mask_t nMask;
609 jint jMask = env->GetIntField(jAudioPortConfig,
610 gAudioPortConfigFields.mChannelMask);
611 if (useInMask) {
612 nMask = inChannelMaskToNative(jMask);
613 ALOGV("convertAudioPortConfigToNative IN mask java %x native %x", jMask, nMask);
614 } else {
615 nMask = outChannelMaskToNative(jMask);
616 ALOGV("convertAudioPortConfigToNative OUT mask java %x native %x", jMask, nMask);
617 }
618 nAudioPortConfig->channel_mask = nMask;
Eric Laurent6368a7d2014-11-19 12:18:32 -0800619 if (nAudioPortConfig->channel_mask != AUDIO_CHANNEL_NONE) {
620 configMask |= AUDIO_PORT_CONFIG_CHANNEL_MASK;
621 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700622
623 jint jFormat = env->GetIntField(jAudioPortConfig, gAudioPortConfigFields.mFormat);
624 audio_format_t nFormat = audioFormatToNative(jFormat);
625 ALOGV("convertAudioPortConfigToNative format %d native %d", jFormat, nFormat);
626 nAudioPortConfig->format = nFormat;
Eric Laurent6368a7d2014-11-19 12:18:32 -0800627 if (nAudioPortConfig->format != AUDIO_FORMAT_DEFAULT &&
628 nAudioPortConfig->format != AUDIO_FORMAT_INVALID) {
629 configMask |= AUDIO_PORT_CONFIG_FORMAT;
630 }
631
Eric Laurentb69681c2014-05-19 19:02:51 -0700632 jobject jGain = env->GetObjectField(jAudioPortConfig, gAudioPortConfigFields.mGain);
633 if (jGain != NULL) {
Eric Laurent3a241992014-05-19 19:33:26 -0700634 convertAudioGainConfigToNative(env, &nAudioPortConfig->gain, jGain, useInMask);
Eric Laurentb69681c2014-05-19 19:02:51 -0700635 env->DeleteLocalRef(jGain);
Eric Laurent6368a7d2014-11-19 12:18:32 -0800636 configMask |= AUDIO_PORT_CONFIG_GAIN;
Eric Laurentb69681c2014-05-19 19:02:51 -0700637 } else {
638 ALOGV("convertAudioPortConfigToNative no gain");
639 nAudioPortConfig->gain.index = -1;
640 }
Eric Laurent6368a7d2014-11-19 12:18:32 -0800641 if (useConfigMask) {
642 nAudioPortConfig->config_mask = env->GetIntField(jAudioPortConfig,
643 gAudioPortConfigFields.mConfigMask);
644 } else {
645 nAudioPortConfig->config_mask = configMask;
646 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700647 env->DeleteLocalRef(jAudioPort);
648 env->DeleteLocalRef(jHandle);
649 return (jint)AUDIO_JAVA_SUCCESS;
650}
651
652static jint convertAudioPortConfigFromNative(JNIEnv *env,
653 jobject jAudioPort,
654 jobject *jAudioPortConfig,
655 const struct audio_port_config *nAudioPortConfig)
656{
657 jint jStatus = AUDIO_JAVA_SUCCESS;
658 jobject jAudioGainConfig = NULL;
659 jobject jAudioGain = NULL;
660 jintArray jGainValues;
661 bool audioportCreated = false;
662
663 ALOGV("convertAudioPortConfigFromNative jAudioPort %p", jAudioPort);
664
665 if (jAudioPort == NULL) {
666 jobject jHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
667 nAudioPortConfig->id);
668
669 ALOGV("convertAudioPortConfigFromNative handle %d is a %s", nAudioPortConfig->id,
670 nAudioPortConfig->type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix");
671
672 if (jHandle == NULL) {
673 return (jint)AUDIO_JAVA_ERROR;
674 }
675 // create dummy port and port config objects with just the correct handle
676 // and configuration data. The actual AudioPortConfig objects will be
677 // constructed by java code with correct class type (device, mix etc...)
678 // and reference to AudioPort instance in this client
679 jAudioPort = env->NewObject(gAudioPortClass, gAudioPortCstor,
Paul McLeanf29e5f32015-06-15 10:19:22 -0700680 jHandle, // handle
681 0, // role
682 NULL, // name
683 NULL, // samplingRates
684 NULL, // channelMasks
685 NULL, // channelIndexMasks
686 NULL, // formats
687 NULL); // gains
Eric Laurentb69681c2014-05-19 19:02:51 -0700688 env->DeleteLocalRef(jHandle);
689 if (jAudioPort == NULL) {
690 return (jint)AUDIO_JAVA_ERROR;
691 }
692 ALOGV("convertAudioPortConfigFromNative jAudioPort created for handle %d",
693 nAudioPortConfig->id);
694
695 audioportCreated = true;
696 }
697
698 bool useInMask = useInChannelMask(nAudioPortConfig->type, nAudioPortConfig->role);
699
700 audio_channel_mask_t nMask;
701 jint jMask;
702
703 int gainIndex = nAudioPortConfig->gain.index;
704 if (gainIndex >= 0) {
705 ALOGV("convertAudioPortConfigFromNative gain found with index %d mode %x",
706 gainIndex, nAudioPortConfig->gain.mode);
707 if (audioportCreated) {
708 ALOGV("convertAudioPortConfigFromNative creating gain");
709 jAudioGain = env->NewObject(gAudioGainClass, gAudioGainCstor,
710 gainIndex,
711 0,
712 0,
713 0,
714 0,
715 0,
716 0,
717 0,
718 0);
719 if (jAudioGain == NULL) {
720 ALOGV("convertAudioPortConfigFromNative creating gain FAILED");
721 jStatus = (jint)AUDIO_JAVA_ERROR;
722 goto exit;
723 }
724 } else {
725 ALOGV("convertAudioPortConfigFromNative reading gain from port");
726 jobjectArray jGains = (jobjectArray)env->GetObjectField(jAudioPort,
727 gAudioPortFields.mGains);
728 if (jGains == NULL) {
729 ALOGV("convertAudioPortConfigFromNative could not get gains from port");
730 jStatus = (jint)AUDIO_JAVA_ERROR;
731 goto exit;
732 }
733 jAudioGain = env->GetObjectArrayElement(jGains, gainIndex);
734 env->DeleteLocalRef(jGains);
735 if (jAudioGain == NULL) {
736 ALOGV("convertAudioPortConfigFromNative could not get gain at index %d", gainIndex);
737 jStatus = (jint)AUDIO_JAVA_ERROR;
738 goto exit;
739 }
740 }
Eric Laurent0078c7c2014-06-04 09:49:52 -0700741 int numValues;
742 if (useInMask) {
743 numValues = audio_channel_count_from_in_mask(nAudioPortConfig->gain.channel_mask);
744 } else {
745 numValues = audio_channel_count_from_out_mask(nAudioPortConfig->gain.channel_mask);
746 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700747 jGainValues = env->NewIntArray(numValues);
748 if (jGainValues == NULL) {
749 ALOGV("convertAudioPortConfigFromNative could not create gain values %d", numValues);
750 jStatus = (jint)AUDIO_JAVA_ERROR;
751 goto exit;
752 }
753 env->SetIntArrayRegion(jGainValues, 0, numValues,
754 nAudioPortConfig->gain.values);
755
756 nMask = nAudioPortConfig->gain.channel_mask;
757 if (useInMask) {
758 jMask = inChannelMaskFromNative(nMask);
759 ALOGV("convertAudioPortConfigFromNative IN mask java %x native %x", jMask, nMask);
760 } else {
761 jMask = outChannelMaskFromNative(nMask);
762 ALOGV("convertAudioPortConfigFromNative OUT mask java %x native %x", jMask, nMask);
763 }
764
765 jAudioGainConfig = env->NewObject(gAudioGainConfigClass,
766 gAudioGainConfigCstor,
767 gainIndex,
768 jAudioGain,
769 nAudioPortConfig->gain.mode,
770 jMask,
771 jGainValues,
772 nAudioPortConfig->gain.ramp_duration_ms);
773 env->DeleteLocalRef(jGainValues);
774 if (jAudioGainConfig == NULL) {
775 ALOGV("convertAudioPortConfigFromNative could not create gain config");
776 jStatus = (jint)AUDIO_JAVA_ERROR;
777 goto exit;
778 }
779 }
780 jclass clazz;
781 jmethodID methodID;
782 if (audioportCreated) {
783 clazz = gAudioPortConfigClass;
784 methodID = gAudioPortConfigCstor;
785 ALOGV("convertAudioPortConfigFromNative building a generic port config");
786 } else {
787 if (env->IsInstanceOf(jAudioPort, gAudioDevicePortClass)) {
788 clazz = gAudioDevicePortConfigClass;
789 methodID = gAudioDevicePortConfigCstor;
790 ALOGV("convertAudioPortConfigFromNative building a device config");
791 } else if (env->IsInstanceOf(jAudioPort, gAudioMixPortClass)) {
792 clazz = gAudioMixPortConfigClass;
793 methodID = gAudioMixPortConfigCstor;
794 ALOGV("convertAudioPortConfigFromNative building a mix config");
795 } else {
796 jStatus = (jint)AUDIO_JAVA_ERROR;
797 goto exit;
798 }
799 }
800 nMask = nAudioPortConfig->channel_mask;
801 if (useInMask) {
802 jMask = inChannelMaskFromNative(nMask);
803 ALOGV("convertAudioPortConfigFromNative IN mask java %x native %x", jMask, nMask);
804 } else {
805 jMask = outChannelMaskFromNative(nMask);
806 ALOGV("convertAudioPortConfigFromNative OUT mask java %x native %x", jMask, nMask);
807 }
808
809 *jAudioPortConfig = env->NewObject(clazz, methodID,
810 jAudioPort,
811 nAudioPortConfig->sample_rate,
812 jMask,
813 audioFormatFromNative(nAudioPortConfig->format),
814 jAudioGainConfig);
815 if (*jAudioPortConfig == NULL) {
816 ALOGV("convertAudioPortConfigFromNative could not create new port config");
817 jStatus = (jint)AUDIO_JAVA_ERROR;
818 } else {
819 ALOGV("convertAudioPortConfigFromNative OK");
820 }
821
822exit:
823 if (audioportCreated) {
824 env->DeleteLocalRef(jAudioPort);
825 if (jAudioGain != NULL) {
826 env->DeleteLocalRef(jAudioGain);
827 }
828 }
829 if (jAudioGainConfig != NULL) {
830 env->DeleteLocalRef(jAudioGainConfig);
831 }
832 return jStatus;
833}
834
Eric Laurentb69681c2014-05-19 19:02:51 -0700835static jint convertAudioPortFromNative(JNIEnv *env,
836 jobject *jAudioPort, const struct audio_port *nAudioPort)
837{
838 jint jStatus = (jint)AUDIO_JAVA_SUCCESS;
839 jintArray jSamplingRates = NULL;
840 jintArray jChannelMasks = NULL;
Paul McLeanf29e5f32015-06-15 10:19:22 -0700841 jintArray jChannelIndexMasks = NULL;
Eric Laurentb69681c2014-05-19 19:02:51 -0700842 jintArray jFormats = NULL;
843 jobjectArray jGains = NULL;
844 jobject jHandle = NULL;
Paul McLean10804eb2015-01-28 11:16:35 -0800845 jstring jDeviceName = NULL;
Eric Laurentb69681c2014-05-19 19:02:51 -0700846 bool useInMask;
Paul McLeanf29e5f32015-06-15 10:19:22 -0700847 size_t numPositionMasks = 0;
848 size_t numIndexMasks = 0;
Eric Laurentb69681c2014-05-19 19:02:51 -0700849
Paul McLean10804eb2015-01-28 11:16:35 -0800850 ALOGV("convertAudioPortFromNative id %d role %d type %d name %s",
851 nAudioPort->id, nAudioPort->role, nAudioPort->type, nAudioPort->name);
Eric Laurentb69681c2014-05-19 19:02:51 -0700852
853 jSamplingRates = env->NewIntArray(nAudioPort->num_sample_rates);
854 if (jSamplingRates == NULL) {
855 jStatus = (jint)AUDIO_JAVA_ERROR;
856 goto exit;
857 }
858 if (nAudioPort->num_sample_rates) {
859 env->SetIntArrayRegion(jSamplingRates, 0, nAudioPort->num_sample_rates,
860 (jint *)nAudioPort->sample_rates);
861 }
862
Paul McLeanf29e5f32015-06-15 10:19:22 -0700863 // count up how many masks are positional and indexed
864 for(size_t index = 0; index < nAudioPort->num_channel_masks; index++) {
865 const audio_channel_mask_t mask = nAudioPort->channel_masks[index];
866 if (audio_channel_mask_get_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
867 numIndexMasks++;
868 } else {
869 numPositionMasks++;
870 }
871 }
872
873 jChannelMasks = env->NewIntArray(numPositionMasks);
Eric Laurentb69681c2014-05-19 19:02:51 -0700874 if (jChannelMasks == NULL) {
875 jStatus = (jint)AUDIO_JAVA_ERROR;
876 goto exit;
877 }
Paul McLeanf29e5f32015-06-15 10:19:22 -0700878 jChannelIndexMasks = env->NewIntArray(numIndexMasks);
879 if (jChannelIndexMasks == NULL) {
880 jStatus = (jint)AUDIO_JAVA_ERROR;
881 goto exit;
882 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700883 useInMask = useInChannelMask(nAudioPort->type, nAudioPort->role);
884
Paul McLeanf29e5f32015-06-15 10:19:22 -0700885 // put the masks in the output arrays
886 for (size_t maskIndex = 0, posMaskIndex = 0, indexedMaskIndex = 0;
887 maskIndex < nAudioPort->num_channel_masks; maskIndex++) {
888 const audio_channel_mask_t mask = nAudioPort->channel_masks[maskIndex];
889 if (audio_channel_mask_get_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
890 jint jMask = audio_channel_mask_get_bits(mask);
891 env->SetIntArrayRegion(jChannelIndexMasks, indexedMaskIndex++, 1, &jMask);
Eric Laurentb69681c2014-05-19 19:02:51 -0700892 } else {
Paul McLeanf29e5f32015-06-15 10:19:22 -0700893 jint jMask = useInMask ? inChannelMaskFromNative(mask)
894 : outChannelMaskFromNative(mask);
895 env->SetIntArrayRegion(jChannelMasks, posMaskIndex++, 1, &jMask);
Eric Laurentb69681c2014-05-19 19:02:51 -0700896 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700897 }
898
Paul McLeanf29e5f32015-06-15 10:19:22 -0700899 // formats
Eric Laurentb69681c2014-05-19 19:02:51 -0700900 jFormats = env->NewIntArray(nAudioPort->num_formats);
901 if (jFormats == NULL) {
902 jStatus = (jint)AUDIO_JAVA_ERROR;
903 goto exit;
904 }
905 for (size_t j = 0; j < nAudioPort->num_formats; j++) {
906 jint jFormat = audioFormatFromNative(nAudioPort->formats[j]);
907 env->SetIntArrayRegion(jFormats, j, 1, &jFormat);
908 }
909
Paul McLeanf29e5f32015-06-15 10:19:22 -0700910 // gains
Eric Laurentb69681c2014-05-19 19:02:51 -0700911 jGains = env->NewObjectArray(nAudioPort->num_gains,
912 gAudioGainClass, NULL);
913 if (jGains == NULL) {
914 jStatus = (jint)AUDIO_JAVA_ERROR;
915 goto exit;
916 }
Paul McLeanf29e5f32015-06-15 10:19:22 -0700917
Eric Laurentb69681c2014-05-19 19:02:51 -0700918 for (size_t j = 0; j < nAudioPort->num_gains; j++) {
919 audio_channel_mask_t nMask = nAudioPort->gains[j].channel_mask;
Paul McLeanf29e5f32015-06-15 10:19:22 -0700920 jint jMask;
Eric Laurentb69681c2014-05-19 19:02:51 -0700921 if (useInMask) {
922 jMask = inChannelMaskFromNative(nMask);
923 ALOGV("convertAudioPortConfigFromNative IN mask java %x native %x", jMask, nMask);
924 } else {
925 jMask = outChannelMaskFromNative(nMask);
926 ALOGV("convertAudioPortConfigFromNative OUT mask java %x native %x", jMask, nMask);
927 }
928
929 jobject jGain = env->NewObject(gAudioGainClass, gAudioGainCstor,
930 j,
931 nAudioPort->gains[j].mode,
932 jMask,
933 nAudioPort->gains[j].min_value,
934 nAudioPort->gains[j].max_value,
935 nAudioPort->gains[j].default_value,
936 nAudioPort->gains[j].step_value,
937 nAudioPort->gains[j].min_ramp_ms,
938 nAudioPort->gains[j].max_ramp_ms);
939 if (jGain == NULL) {
940 jStatus = (jint)AUDIO_JAVA_ERROR;
941 goto exit;
942 }
943 env->SetObjectArrayElement(jGains, j, jGain);
944 env->DeleteLocalRef(jGain);
945 }
946
947 jHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
948 nAudioPort->id);
949 if (jHandle == NULL) {
950 jStatus = (jint)AUDIO_JAVA_ERROR;
951 goto exit;
952 }
953
Paul McLean10804eb2015-01-28 11:16:35 -0800954 jDeviceName = env->NewStringUTF(nAudioPort->name);
955
Eric Laurentb69681c2014-05-19 19:02:51 -0700956 if (nAudioPort->type == AUDIO_PORT_TYPE_DEVICE) {
957 ALOGV("convertAudioPortFromNative is a device %08x", nAudioPort->ext.device.type);
958 jstring jAddress = env->NewStringUTF(nAudioPort->ext.device.address);
959 *jAudioPort = env->NewObject(gAudioDevicePortClass, gAudioDevicePortCstor,
Paul McLean10804eb2015-01-28 11:16:35 -0800960 jHandle, jDeviceName,
Paul McLeanf29e5f32015-06-15 10:19:22 -0700961 jSamplingRates, jChannelMasks, jChannelIndexMasks,
962 jFormats, jGains,
Eric Laurentb69681c2014-05-19 19:02:51 -0700963 nAudioPort->ext.device.type, jAddress);
964 env->DeleteLocalRef(jAddress);
965 } else if (nAudioPort->type == AUDIO_PORT_TYPE_MIX) {
966 ALOGV("convertAudioPortFromNative is a mix");
967 *jAudioPort = env->NewObject(gAudioMixPortClass, gAudioMixPortCstor,
Eric Laurent4bcdba82015-05-01 11:37:49 -0700968 jHandle, nAudioPort->ext.mix.handle,
969 nAudioPort->role, jDeviceName,
Paul McLeanf29e5f32015-06-15 10:19:22 -0700970 jSamplingRates, jChannelMasks, jChannelIndexMasks,
Eric Laurentb69681c2014-05-19 19:02:51 -0700971 jFormats, jGains);
972 } else {
973 ALOGE("convertAudioPortFromNative unknown nAudioPort type %d", nAudioPort->type);
974 jStatus = (jint)AUDIO_JAVA_ERROR;
975 goto exit;
976 }
977 if (*jAudioPort == NULL) {
978 jStatus = (jint)AUDIO_JAVA_ERROR;
979 goto exit;
980 }
981
982 jobject jAudioPortConfig;
983 jStatus = convertAudioPortConfigFromNative(env,
984 *jAudioPort,
985 &jAudioPortConfig,
986 &nAudioPort->active_config);
987 if (jStatus != AUDIO_JAVA_SUCCESS) {
988 return jStatus;
989 }
990
991 env->SetObjectField(*jAudioPort, gAudioPortFields.mActiveConfig, jAudioPortConfig);
992
993exit:
Paul McLean10804eb2015-01-28 11:16:35 -0800994 if (jDeviceName != NULL) {
995 env->DeleteLocalRef(jDeviceName);
996 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700997 if (jSamplingRates != NULL) {
998 env->DeleteLocalRef(jSamplingRates);
999 }
1000 if (jChannelMasks != NULL) {
1001 env->DeleteLocalRef(jChannelMasks);
1002 }
1003 if (jFormats != NULL) {
1004 env->DeleteLocalRef(jFormats);
1005 }
1006 if (jGains != NULL) {
1007 env->DeleteLocalRef(jGains);
1008 }
1009 if (jHandle != NULL) {
1010 env->DeleteLocalRef(jHandle);
1011 }
1012
1013 return jStatus;
1014}
1015
1016
1017static jint
1018android_media_AudioSystem_listAudioPorts(JNIEnv *env, jobject clazz,
1019 jobject jPorts, jintArray jGeneration)
1020{
1021 ALOGV("listAudioPorts");
1022
1023 if (jPorts == NULL) {
1024 ALOGE("listAudioPorts NULL AudioPort ArrayList");
1025 return (jint)AUDIO_JAVA_BAD_VALUE;
1026 }
1027 if (!env->IsInstanceOf(jPorts, gArrayListClass)) {
1028 ALOGE("listAudioPorts not an arraylist");
1029 return (jint)AUDIO_JAVA_BAD_VALUE;
1030 }
1031
1032 if (jGeneration == NULL || env->GetArrayLength(jGeneration) != 1) {
1033 return (jint)AUDIO_JAVA_BAD_VALUE;
1034 }
1035
1036 status_t status;
1037 unsigned int generation1;
1038 unsigned int generation;
1039 unsigned int numPorts;
1040 jint *nGeneration;
1041 struct audio_port *nPorts = NULL;
1042 int attempts = MAX_PORT_GENERATION_SYNC_ATTEMPTS;
1043
1044 // get the port count and all the ports until they both return the same generation
1045 do {
1046 if (attempts-- < 0) {
1047 status = TIMED_OUT;
1048 break;
1049 }
1050
1051 numPorts = 0;
1052 status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE,
1053 AUDIO_PORT_TYPE_NONE,
1054 &numPorts,
1055 NULL,
1056 &generation1);
1057 if (status != NO_ERROR || numPorts == 0) {
1058 ALOGE_IF(status != NO_ERROR, "AudioSystem::listAudioPorts error %d", status);
1059 break;
1060 }
1061 nPorts = (struct audio_port *)realloc(nPorts, numPorts * sizeof(struct audio_port));
1062
1063 status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE,
1064 AUDIO_PORT_TYPE_NONE,
1065 &numPorts,
1066 nPorts,
1067 &generation);
1068 ALOGV("listAudioPorts AudioSystem::listAudioPorts numPorts %d generation %d generation1 %d",
1069 numPorts, generation, generation1);
1070 } while (generation1 != generation && status == NO_ERROR);
1071
1072 jint jStatus = nativeToJavaStatus(status);
1073 if (jStatus != AUDIO_JAVA_SUCCESS) {
1074 goto exit;
1075 }
1076
1077 nGeneration = env->GetIntArrayElements(jGeneration, NULL);
1078 if (nGeneration == NULL) {
1079 jStatus = (jint)AUDIO_JAVA_ERROR;
1080 goto exit;
1081 }
1082 nGeneration[0] = generation1;
1083 env->ReleaseIntArrayElements(jGeneration, nGeneration, 0);
1084
1085 for (size_t i = 0; i < numPorts; i++) {
1086 jobject jAudioPort;
1087 jStatus = convertAudioPortFromNative(env, &jAudioPort, &nPorts[i]);
1088 if (jStatus != AUDIO_JAVA_SUCCESS) {
1089 goto exit;
1090 }
1091 env->CallBooleanMethod(jPorts, gArrayListMethods.add, jAudioPort);
1092 }
1093
1094exit:
1095 free(nPorts);
1096 return jStatus;
1097}
1098
1099static int
1100android_media_AudioSystem_createAudioPatch(JNIEnv *env, jobject clazz,
1101 jobjectArray jPatches, jobjectArray jSources, jobjectArray jSinks)
1102{
1103 status_t status;
1104 jint jStatus;
1105
1106 ALOGV("createAudioPatch");
1107 if (jPatches == NULL || jSources == NULL || jSinks == NULL) {
1108 return (jint)AUDIO_JAVA_BAD_VALUE;
1109 }
1110
1111 if (env->GetArrayLength(jPatches) != 1) {
1112 return (jint)AUDIO_JAVA_BAD_VALUE;
1113 }
1114 jint numSources = env->GetArrayLength(jSources);
1115 if (numSources == 0 || numSources > AUDIO_PATCH_PORTS_MAX) {
1116 return (jint)AUDIO_JAVA_BAD_VALUE;
1117 }
1118
1119 jint numSinks = env->GetArrayLength(jSinks);
1120 if (numSinks == 0 || numSinks > AUDIO_PATCH_PORTS_MAX) {
1121 return (jint)AUDIO_JAVA_BAD_VALUE;
1122 }
1123
1124 audio_patch_handle_t handle = (audio_patch_handle_t)0;
1125 jobject jPatch = env->GetObjectArrayElement(jPatches, 0);
1126 jobject jPatchHandle = NULL;
1127 if (jPatch != NULL) {
1128 if (!env->IsInstanceOf(jPatch, gAudioPatchClass)) {
1129 return (jint)AUDIO_JAVA_BAD_VALUE;
1130 }
1131 jPatchHandle = env->GetObjectField(jPatch, gAudioPatchFields.mHandle);
1132 handle = (audio_patch_handle_t)env->GetIntField(jPatchHandle, gAudioHandleFields.mId);
1133 }
1134
1135 struct audio_patch nPatch;
1136
1137 nPatch.id = handle;
1138 nPatch.num_sources = 0;
1139 nPatch.num_sinks = 0;
1140 jobject jSource = NULL;
1141 jobject jSink = NULL;
1142
1143 for (jint i = 0; i < numSources; i++) {
1144 jSource = env->GetObjectArrayElement(jSources, i);
1145 if (!env->IsInstanceOf(jSource, gAudioPortConfigClass)) {
1146 jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
1147 goto exit;
1148 }
Eric Laurent6368a7d2014-11-19 12:18:32 -08001149 jStatus = convertAudioPortConfigToNative(env, &nPatch.sources[i], jSource, false);
Eric Laurentb69681c2014-05-19 19:02:51 -07001150 env->DeleteLocalRef(jSource);
1151 jSource = NULL;
1152 if (jStatus != AUDIO_JAVA_SUCCESS) {
1153 goto exit;
1154 }
1155 nPatch.num_sources++;
1156 }
1157
1158 for (jint i = 0; i < numSinks; i++) {
1159 jSink = env->GetObjectArrayElement(jSinks, i);
1160 if (!env->IsInstanceOf(jSink, gAudioPortConfigClass)) {
1161 jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
1162 goto exit;
1163 }
Eric Laurent6368a7d2014-11-19 12:18:32 -08001164 jStatus = convertAudioPortConfigToNative(env, &nPatch.sinks[i], jSink, false);
Eric Laurentb69681c2014-05-19 19:02:51 -07001165 env->DeleteLocalRef(jSink);
1166 jSink = NULL;
1167 if (jStatus != AUDIO_JAVA_SUCCESS) {
1168 goto exit;
1169 }
1170 nPatch.num_sinks++;
1171 }
1172
1173 ALOGV("AudioSystem::createAudioPatch");
1174 status = AudioSystem::createAudioPatch(&nPatch, &handle);
1175 ALOGV("AudioSystem::createAudioPatch() returned %d hande %d", status, handle);
1176
1177 jStatus = nativeToJavaStatus(status);
1178 if (jStatus != AUDIO_JAVA_SUCCESS) {
1179 goto exit;
1180 }
1181
1182 if (jPatchHandle == NULL) {
1183 jPatchHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
1184 handle);
1185 if (jPatchHandle == NULL) {
1186 jStatus = (jint)AUDIO_JAVA_ERROR;
1187 goto exit;
1188 }
1189 jPatch = env->NewObject(gAudioPatchClass, gAudioPatchCstor, jPatchHandle, jSources, jSinks);
1190 if (jPatch == NULL) {
1191 jStatus = (jint)AUDIO_JAVA_ERROR;
1192 goto exit;
1193 }
1194 env->SetObjectArrayElement(jPatches, 0, jPatch);
1195 } else {
1196 env->SetIntField(jPatchHandle, gAudioHandleFields.mId, handle);
1197 }
1198
1199exit:
1200 if (jPatchHandle != NULL) {
1201 env->DeleteLocalRef(jPatchHandle);
1202 }
1203 if (jPatch != NULL) {
1204 env->DeleteLocalRef(jPatch);
1205 }
1206 if (jSource != NULL) {
1207 env->DeleteLocalRef(jSource);
1208 }
1209 if (jSink != NULL) {
1210 env->DeleteLocalRef(jSink);
1211 }
1212 return jStatus;
1213}
1214
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001215static jint
Eric Laurentb69681c2014-05-19 19:02:51 -07001216android_media_AudioSystem_releaseAudioPatch(JNIEnv *env, jobject clazz,
1217 jobject jPatch)
1218{
1219 ALOGV("releaseAudioPatch");
1220 if (jPatch == NULL) {
1221 return (jint)AUDIO_JAVA_BAD_VALUE;
1222 }
1223
1224 audio_patch_handle_t handle = (audio_patch_handle_t)0;
1225 jobject jPatchHandle = NULL;
1226 if (!env->IsInstanceOf(jPatch, gAudioPatchClass)) {
1227 return (jint)AUDIO_JAVA_BAD_VALUE;
1228 }
1229 jPatchHandle = env->GetObjectField(jPatch, gAudioPatchFields.mHandle);
1230 handle = (audio_patch_handle_t)env->GetIntField(jPatchHandle, gAudioHandleFields.mId);
1231 env->DeleteLocalRef(jPatchHandle);
1232
1233 ALOGV("AudioSystem::releaseAudioPatch");
1234 status_t status = AudioSystem::releaseAudioPatch(handle);
1235 ALOGV("AudioSystem::releaseAudioPatch() returned %d", status);
1236 jint jStatus = nativeToJavaStatus(status);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001237 return jStatus;
Eric Laurentb69681c2014-05-19 19:02:51 -07001238}
1239
1240static jint
1241android_media_AudioSystem_listAudioPatches(JNIEnv *env, jobject clazz,
1242 jobject jPatches, jintArray jGeneration)
1243{
1244 ALOGV("listAudioPatches");
1245 if (jPatches == NULL) {
1246 ALOGE("listAudioPatches NULL AudioPatch ArrayList");
1247 return (jint)AUDIO_JAVA_BAD_VALUE;
1248 }
1249 if (!env->IsInstanceOf(jPatches, gArrayListClass)) {
1250 ALOGE("listAudioPatches not an arraylist");
1251 return (jint)AUDIO_JAVA_BAD_VALUE;
1252 }
1253
1254 if (jGeneration == NULL || env->GetArrayLength(jGeneration) != 1) {
1255 return (jint)AUDIO_JAVA_BAD_VALUE;
1256 }
1257
1258 status_t status;
1259 unsigned int generation1;
1260 unsigned int generation;
1261 unsigned int numPatches;
1262 jint *nGeneration;
1263 struct audio_patch *nPatches = NULL;
1264 jobjectArray jSources = NULL;
1265 jobject jSource = NULL;
1266 jobjectArray jSinks = NULL;
1267 jobject jSink = NULL;
1268 jobject jPatch = NULL;
1269 int attempts = MAX_PORT_GENERATION_SYNC_ATTEMPTS;
1270
1271 // get the patch count and all the patches until they both return the same generation
1272 do {
1273 if (attempts-- < 0) {
1274 status = TIMED_OUT;
1275 break;
1276 }
1277
1278 numPatches = 0;
1279 status = AudioSystem::listAudioPatches(&numPatches,
1280 NULL,
1281 &generation1);
1282 if (status != NO_ERROR || numPatches == 0) {
1283 ALOGE_IF(status != NO_ERROR, "listAudioPatches AudioSystem::listAudioPatches error %d",
1284 status);
1285 break;
1286 }
1287 nPatches = (struct audio_patch *)realloc(nPatches, numPatches * sizeof(struct audio_patch));
1288
1289 status = AudioSystem::listAudioPatches(&numPatches,
1290 nPatches,
1291 &generation);
1292 ALOGV("listAudioPatches AudioSystem::listAudioPatches numPatches %d generation %d generation1 %d",
1293 numPatches, generation, generation1);
1294
1295 } while (generation1 != generation && status == NO_ERROR);
1296
1297 jint jStatus = nativeToJavaStatus(status);
1298 if (jStatus != AUDIO_JAVA_SUCCESS) {
1299 goto exit;
1300 }
1301
1302 nGeneration = env->GetIntArrayElements(jGeneration, NULL);
1303 if (nGeneration == NULL) {
1304 jStatus = AUDIO_JAVA_ERROR;
1305 goto exit;
1306 }
1307 nGeneration[0] = generation1;
1308 env->ReleaseIntArrayElements(jGeneration, nGeneration, 0);
1309
1310 for (size_t i = 0; i < numPatches; i++) {
1311 jobject patchHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
1312 nPatches[i].id);
1313 if (patchHandle == NULL) {
1314 jStatus = AUDIO_JAVA_ERROR;
1315 goto exit;
1316 }
Dan Albert46d84442014-11-18 16:07:51 -08001317 ALOGV("listAudioPatches patch %zu num_sources %d num_sinks %d",
Eric Laurentb69681c2014-05-19 19:02:51 -07001318 i, nPatches[i].num_sources, nPatches[i].num_sinks);
1319
1320 env->SetIntField(patchHandle, gAudioHandleFields.mId, nPatches[i].id);
1321
1322 // load sources
1323 jSources = env->NewObjectArray(nPatches[i].num_sources,
1324 gAudioPortConfigClass, NULL);
1325 if (jSources == NULL) {
1326 jStatus = AUDIO_JAVA_ERROR;
1327 goto exit;
1328 }
1329
1330 for (size_t j = 0; j < nPatches[i].num_sources; j++) {
1331 jStatus = convertAudioPortConfigFromNative(env,
1332 NULL,
1333 &jSource,
1334 &nPatches[i].sources[j]);
1335 if (jStatus != AUDIO_JAVA_SUCCESS) {
1336 goto exit;
1337 }
1338 env->SetObjectArrayElement(jSources, j, jSource);
1339 env->DeleteLocalRef(jSource);
1340 jSource = NULL;
Dan Albert46d84442014-11-18 16:07:51 -08001341 ALOGV("listAudioPatches patch %zu source %zu is a %s handle %d",
Eric Laurentb69681c2014-05-19 19:02:51 -07001342 i, j,
1343 nPatches[i].sources[j].type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix",
1344 nPatches[i].sources[j].id);
1345 }
1346 // load sinks
1347 jSinks = env->NewObjectArray(nPatches[i].num_sinks,
1348 gAudioPortConfigClass, NULL);
1349 if (jSinks == NULL) {
1350 jStatus = AUDIO_JAVA_ERROR;
1351 goto exit;
1352 }
1353
1354 for (size_t j = 0; j < nPatches[i].num_sinks; j++) {
1355 jStatus = convertAudioPortConfigFromNative(env,
1356 NULL,
1357 &jSink,
1358 &nPatches[i].sinks[j]);
1359
1360 if (jStatus != AUDIO_JAVA_SUCCESS) {
1361 goto exit;
1362 }
1363 env->SetObjectArrayElement(jSinks, j, jSink);
1364 env->DeleteLocalRef(jSink);
1365 jSink = NULL;
Dan Albert46d84442014-11-18 16:07:51 -08001366 ALOGV("listAudioPatches patch %zu sink %zu is a %s handle %d",
Eric Laurentb69681c2014-05-19 19:02:51 -07001367 i, j,
1368 nPatches[i].sinks[j].type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix",
1369 nPatches[i].sinks[j].id);
1370 }
1371
1372 jPatch = env->NewObject(gAudioPatchClass, gAudioPatchCstor,
1373 patchHandle, jSources, jSinks);
1374 env->DeleteLocalRef(jSources);
1375 jSources = NULL;
1376 env->DeleteLocalRef(jSinks);
1377 jSinks = NULL;
1378 if (jPatch == NULL) {
1379 jStatus = AUDIO_JAVA_ERROR;
1380 goto exit;
1381 }
1382 env->CallBooleanMethod(jPatches, gArrayListMethods.add, jPatch);
1383 env->DeleteLocalRef(jPatch);
1384 jPatch = NULL;
1385 }
1386
1387exit:
1388 if (jSources != NULL) {
1389 env->DeleteLocalRef(jSources);
1390 }
1391 if (jSource != NULL) {
1392 env->DeleteLocalRef(jSource);
1393 }
1394 if (jSinks != NULL) {
1395 env->DeleteLocalRef(jSinks);
1396 }
1397 if (jSink != NULL) {
1398 env->DeleteLocalRef(jSink);
1399 }
1400 if (jPatch != NULL) {
1401 env->DeleteLocalRef(jPatch);
1402 }
1403 free(nPatches);
1404 return jStatus;
1405}
1406
Eric Laurent3a241992014-05-19 19:33:26 -07001407static jint
1408android_media_AudioSystem_setAudioPortConfig(JNIEnv *env, jobject clazz,
1409 jobject jAudioPortConfig)
1410{
1411 ALOGV("setAudioPortConfig");
1412 if (jAudioPortConfig == NULL) {
1413 return AUDIO_JAVA_BAD_VALUE;
1414 }
1415 if (!env->IsInstanceOf(jAudioPortConfig, gAudioPortConfigClass)) {
1416 return AUDIO_JAVA_BAD_VALUE;
1417 }
1418 struct audio_port_config nAudioPortConfig;
Eric Laurent6368a7d2014-11-19 12:18:32 -08001419 jint jStatus = convertAudioPortConfigToNative(env, &nAudioPortConfig, jAudioPortConfig, true);
Eric Laurent3a241992014-05-19 19:33:26 -07001420 if (jStatus != AUDIO_JAVA_SUCCESS) {
1421 return jStatus;
1422 }
1423 status_t status = AudioSystem::setAudioPortConfig(&nAudioPortConfig);
1424 ALOGV("AudioSystem::setAudioPortConfig() returned %d", status);
1425 jStatus = nativeToJavaStatus(status);
1426 return jStatus;
1427}
1428
Eric Laurent700e7342014-05-02 18:33:15 -07001429static void
1430android_media_AudioSystem_eventHandlerSetup(JNIEnv *env, jobject thiz, jobject weak_this)
1431{
1432 ALOGV("eventHandlerSetup");
1433
1434 sp<JNIAudioPortCallback> callback = new JNIAudioPortCallback(env, thiz, weak_this);
1435
Eric Laurent2615afb2015-03-25 14:51:08 -07001436 if (AudioSystem::addAudioPortCallback(callback) == NO_ERROR) {
1437 setJniCallback(env, thiz, callback);
1438 }
Eric Laurent700e7342014-05-02 18:33:15 -07001439}
1440
1441static void
1442android_media_AudioSystem_eventHandlerFinalize(JNIEnv *env, jobject thiz)
1443{
1444 ALOGV("eventHandlerFinalize");
1445
Eric Laurent2615afb2015-03-25 14:51:08 -07001446 sp<JNIAudioPortCallback> callback = setJniCallback(env, thiz, 0);
Eric Laurent700e7342014-05-02 18:33:15 -07001447
Eric Laurent2615afb2015-03-25 14:51:08 -07001448 if (callback != 0) {
1449 AudioSystem::removeAudioPortCallback(callback);
1450 }
Eric Laurent700e7342014-05-02 18:33:15 -07001451}
1452
Eric Laurentb634e1b2014-08-01 14:44:46 -07001453static jint
1454android_media_AudioSystem_getAudioHwSyncForSession(JNIEnv *env, jobject thiz, jint sessionId)
1455{
1456 return (jint)AudioSystem::getAudioHwSyncForSession((audio_session_t)sessionId);
1457}
1458
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001459static void
1460android_media_AudioSystem_registerDynPolicyCallback(JNIEnv *env, jobject thiz)
1461{
1462 AudioSystem::setDynPolicyCallback(android_media_AudioSystem_dyn_policy_callback);
1463}
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001464
1465
1466static jint convertAudioMixToNative(JNIEnv *env,
1467 AudioMix *nAudioMix,
1468 const jobject jAudioMix)
1469{
1470 nAudioMix->mMixType = env->GetIntField(jAudioMix, gAudioMixFields.mMixType);
1471 nAudioMix->mRouteFlags = env->GetIntField(jAudioMix, gAudioMixFields.mRouteFlags);
1472
1473 jstring jRegistrationId = (jstring)env->GetObjectField(jAudioMix,
1474 gAudioMixFields.mRegistrationId);
1475 const char *nRegistrationId = env->GetStringUTFChars(jRegistrationId, NULL);
1476 nAudioMix->mRegistrationId = String8(nRegistrationId);
1477 env->ReleaseStringUTFChars(jRegistrationId, nRegistrationId);
1478 env->DeleteLocalRef(jRegistrationId);
1479
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001480 nAudioMix->mCbFlags = env->GetIntField(jAudioMix, gAudioMixFields.mCallbackFlags);
1481
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001482 jobject jFormat = env->GetObjectField(jAudioMix, gAudioMixFields.mFormat);
1483 nAudioMix->mFormat.sample_rate = env->GetIntField(jFormat,
1484 gAudioFormatFields.mSampleRate);
1485 nAudioMix->mFormat.channel_mask = outChannelMaskToNative(env->GetIntField(jFormat,
1486 gAudioFormatFields.mChannelMask));
1487 nAudioMix->mFormat.format = audioFormatToNative(env->GetIntField(jFormat,
1488 gAudioFormatFields.mEncoding));
1489 env->DeleteLocalRef(jFormat);
1490
1491 jobject jRule = env->GetObjectField(jAudioMix, gAudioMixFields.mRule);
1492 jobject jRuleCriteria = env->GetObjectField(jRule, gAudioMixingRuleFields.mCriteria);
1493 env->DeleteLocalRef(jRule);
1494 jobjectArray jCriteria = (jobjectArray)env->CallObjectMethod(jRuleCriteria,
1495 gArrayListMethods.toArray);
1496 env->DeleteLocalRef(jRuleCriteria);
1497
1498 jint numCriteria = env->GetArrayLength(jCriteria);
1499 if (numCriteria > MAX_CRITERIA_PER_MIX) {
1500 numCriteria = MAX_CRITERIA_PER_MIX;
1501 }
1502
1503 for (jint i = 0; i < numCriteria; i++) {
1504 AttributeMatchCriterion nCriterion;
1505
1506 jobject jCriterion = env->GetObjectArrayElement(jCriteria, i);
1507
1508 nCriterion.mRule = env->GetIntField(jCriterion, gAttributeMatchCriterionFields.mRule);
1509
1510 jobject jAttributes = env->GetObjectField(jCriterion, gAttributeMatchCriterionFields.mAttr);
1511 if (nCriterion.mRule == RULE_MATCH_ATTRIBUTE_USAGE ||
1512 nCriterion.mRule == RULE_EXCLUDE_ATTRIBUTE_USAGE) {
1513 nCriterion.mAttr.mUsage = (audio_usage_t)env->GetIntField(jAttributes,
1514 gAudioAttributesFields.mUsage);
1515 } else {
1516 nCriterion.mAttr.mSource = (audio_source_t)env->GetIntField(jAttributes,
1517 gAudioAttributesFields.mSource);
1518 }
1519 env->DeleteLocalRef(jAttributes);
1520
1521 nAudioMix->mCriteria.add(nCriterion);
1522 env->DeleteLocalRef(jCriterion);
1523 }
1524
1525 env->DeleteLocalRef(jCriteria);
1526
1527 return (jint)AUDIO_JAVA_SUCCESS;
1528}
1529
1530static jint
1531android_media_AudioSystem_registerPolicyMixes(JNIEnv *env, jobject clazz,
1532 jobject jMixesList, jboolean registration)
1533{
1534 ALOGV("registerPolicyMixes");
1535
1536 if (jMixesList == NULL) {
1537 return (jint)AUDIO_JAVA_BAD_VALUE;
1538 }
1539 if (!env->IsInstanceOf(jMixesList, gArrayListClass)) {
1540 return (jint)AUDIO_JAVA_BAD_VALUE;
1541 }
1542 jobjectArray jMixes = (jobjectArray)env->CallObjectMethod(jMixesList,
1543 gArrayListMethods.toArray);
1544 jint numMixes = env->GetArrayLength(jMixes);
1545 if (numMixes > MAX_MIXES_PER_POLICY) {
1546 numMixes = MAX_MIXES_PER_POLICY;
1547 }
1548
1549 status_t status;
1550 jint jStatus;
1551 jobject jAudioMix = NULL;
1552 Vector <AudioMix> mixes;
1553 for (jint i = 0; i < numMixes; i++) {
1554 jAudioMix = env->GetObjectArrayElement(jMixes, i);
1555 if (!env->IsInstanceOf(jAudioMix, gAudioMixClass)) {
1556 jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
1557 goto exit;
1558 }
1559 AudioMix mix;
1560 jStatus = convertAudioMixToNative(env, &mix, jAudioMix);
1561 env->DeleteLocalRef(jAudioMix);
1562 jAudioMix = NULL;
1563 if (jStatus != AUDIO_JAVA_SUCCESS) {
1564 goto exit;
1565 }
1566 mixes.add(mix);
1567 }
1568
1569 ALOGV("AudioSystem::registerPolicyMixes numMixes %d registration %d", numMixes, registration);
1570 status = AudioSystem::registerPolicyMixes(mixes, registration);
1571 ALOGV("AudioSystem::registerPolicyMixes() returned %d", status);
1572
1573 jStatus = nativeToJavaStatus(status);
1574 if (jStatus != AUDIO_JAVA_SUCCESS) {
1575 goto exit;
1576 }
1577
1578exit:
1579 if (jAudioMix != NULL) {
1580 env->DeleteLocalRef(jAudioMix);
1581 }
1582 return jStatus;
1583}
1584
Eric Laurent0867bed2015-05-20 14:49:08 -07001585static jint
1586android_media_AudioSystem_systemReady(JNIEnv *env, jobject thiz)
1587{
1588 return nativeToJavaStatus(AudioSystem::systemReady());
1589}
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001590
1591
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001592// ----------------------------------------------------------------------------
1593
1594static JNINativeMethod gMethods[] = {
Eric Laurenta553c252009-07-17 12:17:14 -07001595 {"setParameters", "(Ljava/lang/String;)I", (void *)android_media_AudioSystem_setParameters},
1596 {"getParameters", "(Ljava/lang/String;)Ljava/lang/String;", (void *)android_media_AudioSystem_getParameters},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001597 {"muteMicrophone", "(Z)I", (void *)android_media_AudioSystem_muteMicrophone},
1598 {"isMicrophoneMuted", "()Z", (void *)android_media_AudioSystem_isMicrophoneMuted},
Jean-Michel Trivid6770542012-10-10 12:03:41 -07001599 {"isStreamActive", "(II)Z", (void *)android_media_AudioSystem_isStreamActive},
Jean-Michel Trivi679d5042013-02-04 16:24:09 -08001600 {"isStreamActiveRemotely","(II)Z", (void *)android_media_AudioSystem_isStreamActiveRemotely},
Jean-Michel Trivid6770542012-10-10 12:03:41 -07001601 {"isSourceActive", "(I)Z", (void *)android_media_AudioSystem_isSourceActive},
Jean-Michel Trivi8a21f5d2014-06-05 15:03:52 -07001602 {"newAudioSessionId", "()I", (void *)android_media_AudioSystem_newAudioSessionId},
Paul McLean10804eb2015-01-28 11:16:35 -08001603 {"setDeviceConnectionState", "(IILjava/lang/String;Ljava/lang/String;)I", (void *)android_media_AudioSystem_setDeviceConnectionState},
Eric Laurenta553c252009-07-17 12:17:14 -07001604 {"getDeviceConnectionState", "(ILjava/lang/String;)I", (void *)android_media_AudioSystem_getDeviceConnectionState},
1605 {"setPhoneState", "(I)I", (void *)android_media_AudioSystem_setPhoneState},
Eric Laurenta553c252009-07-17 12:17:14 -07001606 {"setForceUse", "(II)I", (void *)android_media_AudioSystem_setForceUse},
1607 {"getForceUse", "(I)I", (void *)android_media_AudioSystem_getForceUse},
1608 {"initStreamVolume", "(III)I", (void *)android_media_AudioSystem_initStreamVolume},
Eric Laurent9bc8358d2011-11-18 16:43:31 -08001609 {"setStreamVolumeIndex","(III)I", (void *)android_media_AudioSystem_setStreamVolumeIndex},
1610 {"getStreamVolumeIndex","(II)I", (void *)android_media_AudioSystem_getStreamVolumeIndex},
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -04001611 {"setMasterVolume", "(F)I", (void *)android_media_AudioSystem_setMasterVolume},
1612 {"getMasterVolume", "()F", (void *)android_media_AudioSystem_getMasterVolume},
1613 {"setMasterMute", "(Z)I", (void *)android_media_AudioSystem_setMasterMute},
1614 {"getMasterMute", "()Z", (void *)android_media_AudioSystem_getMasterMute},
Glenn Kasten8b4b97a2011-02-04 13:54:26 -08001615 {"getDevicesForStream", "(I)I", (void *)android_media_AudioSystem_getDevicesForStream},
Glenn Kastenc6c43652012-09-24 17:32:30 -07001616 {"getPrimaryOutputSamplingRate", "()I", (void *)android_media_AudioSystem_getPrimaryOutputSamplingRate},
1617 {"getPrimaryOutputFrameCount", "()I", (void *)android_media_AudioSystem_getPrimaryOutputFrameCount},
Oliver Woodman61dcdf32013-06-26 12:43:36 +01001618 {"getOutputLatency", "(I)I", (void *)android_media_AudioSystem_getOutputLatency},
Glenn Kastenfd116ad2013-07-12 17:10:39 -07001619 {"setLowRamDevice", "(Z)I", (void *)android_media_AudioSystem_setLowRamDevice},
Eric Laurentdfb881f2013-07-18 14:41:39 -07001620 {"checkAudioFlinger", "()I", (void *)android_media_AudioSystem_checkAudioFlinger},
Eric Laurentb69681c2014-05-19 19:02:51 -07001621 {"listAudioPorts", "(Ljava/util/ArrayList;[I)I",
1622 (void *)android_media_AudioSystem_listAudioPorts},
1623 {"createAudioPatch", "([Landroid/media/AudioPatch;[Landroid/media/AudioPortConfig;[Landroid/media/AudioPortConfig;)I",
1624 (void *)android_media_AudioSystem_createAudioPatch},
1625 {"releaseAudioPatch", "(Landroid/media/AudioPatch;)I",
1626 (void *)android_media_AudioSystem_releaseAudioPatch},
1627 {"listAudioPatches", "(Ljava/util/ArrayList;[I)I",
1628 (void *)android_media_AudioSystem_listAudioPatches},
Eric Laurent3a241992014-05-19 19:33:26 -07001629 {"setAudioPortConfig", "(Landroid/media/AudioPortConfig;)I",
1630 (void *)android_media_AudioSystem_setAudioPortConfig},
Eric Laurentb634e1b2014-08-01 14:44:46 -07001631 {"getAudioHwSyncForSession", "(I)I",
1632 (void *)android_media_AudioSystem_getAudioHwSyncForSession},
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001633 {"registerPolicyMixes", "(Ljava/util/ArrayList;Z)I",
1634 (void *)android_media_AudioSystem_registerPolicyMixes},
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001635 {"native_register_dynamic_policy_callback", "()V",
1636 (void *)android_media_AudioSystem_registerDynPolicyCallback},
Eric Laurent0867bed2015-05-20 14:49:08 -07001637 {"systemReady", "()I", (void *)android_media_AudioSystem_systemReady},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001638};
1639
Eric Laurentb69681c2014-05-19 19:02:51 -07001640
Eric Laurent700e7342014-05-02 18:33:15 -07001641static JNINativeMethod gEventHandlerMethods[] = {
1642 {"native_setup",
1643 "(Ljava/lang/Object;)V",
1644 (void *)android_media_AudioSystem_eventHandlerSetup},
1645 {"native_finalize",
1646 "()V",
1647 (void *)android_media_AudioSystem_eventHandlerFinalize},
1648};
1649
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001650int register_android_media_AudioSystem(JNIEnv *env)
1651{
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001652 jclass arrayListClass = FindClassOrDie(env, "java/util/ArrayList");
1653 gArrayListClass = MakeGlobalRefOrDie(env, arrayListClass);
1654 gArrayListMethods.add = GetMethodIDOrDie(env, arrayListClass, "add", "(Ljava/lang/Object;)Z");
Eric Laurent09378972014-12-10 10:42:08 -08001655 gArrayListMethods.toArray = GetMethodIDOrDie(env, arrayListClass, "toArray", "()[Ljava/lang/Object;");
Eric Laurentb69681c2014-05-19 19:02:51 -07001656
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001657 jclass audioHandleClass = FindClassOrDie(env, "android/media/AudioHandle");
1658 gAudioHandleClass = MakeGlobalRefOrDie(env, audioHandleClass);
1659 gAudioHandleCstor = GetMethodIDOrDie(env, audioHandleClass, "<init>", "(I)V");
1660 gAudioHandleFields.mId = GetFieldIDOrDie(env, audioHandleClass, "mId", "I");
Eric Laurentb69681c2014-05-19 19:02:51 -07001661
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001662 jclass audioPortClass = FindClassOrDie(env, "android/media/AudioPort");
1663 gAudioPortClass = MakeGlobalRefOrDie(env, audioPortClass);
1664 gAudioPortCstor = GetMethodIDOrDie(env, audioPortClass, "<init>",
Paul McLeanf29e5f32015-06-15 10:19:22 -07001665 "(Landroid/media/AudioHandle;ILjava/lang/String;[I[I[I[I[Landroid/media/AudioGain;)V");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001666 gAudioPortFields.mHandle = GetFieldIDOrDie(env, audioPortClass, "mHandle",
Eric Laurentb69681c2014-05-19 19:02:51 -07001667 "Landroid/media/AudioHandle;");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001668 gAudioPortFields.mRole = GetFieldIDOrDie(env, audioPortClass, "mRole", "I");
1669 gAudioPortFields.mGains = GetFieldIDOrDie(env, audioPortClass, "mGains",
Eric Laurentb69681c2014-05-19 19:02:51 -07001670 "[Landroid/media/AudioGain;");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001671 gAudioPortFields.mActiveConfig = GetFieldIDOrDie(env, audioPortClass, "mActiveConfig",
1672 "Landroid/media/AudioPortConfig;");
Eric Laurentb69681c2014-05-19 19:02:51 -07001673
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001674 jclass audioPortConfigClass = FindClassOrDie(env, "android/media/AudioPortConfig");
1675 gAudioPortConfigClass = MakeGlobalRefOrDie(env, audioPortConfigClass);
1676 gAudioPortConfigCstor = GetMethodIDOrDie(env, audioPortConfigClass, "<init>",
1677 "(Landroid/media/AudioPort;IIILandroid/media/AudioGainConfig;)V");
1678 gAudioPortConfigFields.mPort = GetFieldIDOrDie(env, audioPortConfigClass, "mPort",
Eric Laurentb69681c2014-05-19 19:02:51 -07001679 "Landroid/media/AudioPort;");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001680 gAudioPortConfigFields.mSamplingRate = GetFieldIDOrDie(env, audioPortConfigClass,
Eric Laurentb69681c2014-05-19 19:02:51 -07001681 "mSamplingRate", "I");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001682 gAudioPortConfigFields.mChannelMask = GetFieldIDOrDie(env, audioPortConfigClass,
Eric Laurentb69681c2014-05-19 19:02:51 -07001683 "mChannelMask", "I");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001684 gAudioPortConfigFields.mFormat = GetFieldIDOrDie(env, audioPortConfigClass, "mFormat", "I");
1685 gAudioPortConfigFields.mGain = GetFieldIDOrDie(env, audioPortConfigClass, "mGain",
Eric Laurentb69681c2014-05-19 19:02:51 -07001686 "Landroid/media/AudioGainConfig;");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001687 gAudioPortConfigFields.mConfigMask = GetFieldIDOrDie(env, audioPortConfigClass, "mConfigMask",
1688 "I");
Eric Laurentb69681c2014-05-19 19:02:51 -07001689
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001690 jclass audioDevicePortConfigClass = FindClassOrDie(env, "android/media/AudioDevicePortConfig");
1691 gAudioDevicePortConfigClass = MakeGlobalRefOrDie(env, audioDevicePortConfigClass);
1692 gAudioDevicePortConfigCstor = GetMethodIDOrDie(env, audioDevicePortConfigClass, "<init>",
1693 "(Landroid/media/AudioDevicePort;IIILandroid/media/AudioGainConfig;)V");
Eric Laurentb69681c2014-05-19 19:02:51 -07001694
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001695 jclass audioMixPortConfigClass = FindClassOrDie(env, "android/media/AudioMixPortConfig");
1696 gAudioMixPortConfigClass = MakeGlobalRefOrDie(env, audioMixPortConfigClass);
1697 gAudioMixPortConfigCstor = GetMethodIDOrDie(env, audioMixPortConfigClass, "<init>",
1698 "(Landroid/media/AudioMixPort;IIILandroid/media/AudioGainConfig;)V");
Eric Laurentb69681c2014-05-19 19:02:51 -07001699
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001700 jclass audioDevicePortClass = FindClassOrDie(env, "android/media/AudioDevicePort");
1701 gAudioDevicePortClass = MakeGlobalRefOrDie(env, audioDevicePortClass);
1702 gAudioDevicePortCstor = GetMethodIDOrDie(env, audioDevicePortClass, "<init>",
Paul McLeanf29e5f32015-06-15 10:19:22 -07001703 "(Landroid/media/AudioHandle;Ljava/lang/String;[I[I[I[I[Landroid/media/AudioGain;ILjava/lang/String;)V");
Eric Laurentb69681c2014-05-19 19:02:51 -07001704
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001705 jclass audioMixPortClass = FindClassOrDie(env, "android/media/AudioMixPort");
1706 gAudioMixPortClass = MakeGlobalRefOrDie(env, audioMixPortClass);
1707 gAudioMixPortCstor = GetMethodIDOrDie(env, audioMixPortClass, "<init>",
Paul McLeanf29e5f32015-06-15 10:19:22 -07001708 "(Landroid/media/AudioHandle;IILjava/lang/String;[I[I[I[I[Landroid/media/AudioGain;)V");
Eric Laurentb69681c2014-05-19 19:02:51 -07001709
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001710 jclass audioGainClass = FindClassOrDie(env, "android/media/AudioGain");
1711 gAudioGainClass = MakeGlobalRefOrDie(env, audioGainClass);
1712 gAudioGainCstor = GetMethodIDOrDie(env, audioGainClass, "<init>", "(IIIIIIIII)V");
Eric Laurentb69681c2014-05-19 19:02:51 -07001713
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001714 jclass audioGainConfigClass = FindClassOrDie(env, "android/media/AudioGainConfig");
1715 gAudioGainConfigClass = MakeGlobalRefOrDie(env, audioGainConfigClass);
1716 gAudioGainConfigCstor = GetMethodIDOrDie(env, audioGainConfigClass, "<init>",
Eric Laurentb69681c2014-05-19 19:02:51 -07001717 "(ILandroid/media/AudioGain;II[II)V");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001718 gAudioGainConfigFields.mIndex = GetFieldIDOrDie(env, gAudioGainConfigClass, "mIndex", "I");
1719 gAudioGainConfigFields.mMode = GetFieldIDOrDie(env, audioGainConfigClass, "mMode", "I");
1720 gAudioGainConfigFields.mChannelMask = GetFieldIDOrDie(env, audioGainConfigClass, "mChannelMask",
Eric Laurentb69681c2014-05-19 19:02:51 -07001721 "I");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001722 gAudioGainConfigFields.mValues = GetFieldIDOrDie(env, audioGainConfigClass, "mValues", "[I");
1723 gAudioGainConfigFields.mRampDurationMs = GetFieldIDOrDie(env, audioGainConfigClass,
Eric Laurentb69681c2014-05-19 19:02:51 -07001724 "mRampDurationMs", "I");
1725
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001726 jclass audioPatchClass = FindClassOrDie(env, "android/media/AudioPatch");
1727 gAudioPatchClass = MakeGlobalRefOrDie(env, audioPatchClass);
1728 gAudioPatchCstor = GetMethodIDOrDie(env, audioPatchClass, "<init>",
Eric Laurentb69681c2014-05-19 19:02:51 -07001729"(Landroid/media/AudioHandle;[Landroid/media/AudioPortConfig;[Landroid/media/AudioPortConfig;)V");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001730 gAudioPatchFields.mHandle = GetFieldIDOrDie(env, audioPatchClass, "mHandle",
Eric Laurentb69681c2014-05-19 19:02:51 -07001731 "Landroid/media/AudioHandle;");
1732
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001733 jclass eventHandlerClass = FindClassOrDie(env, kEventHandlerClassPathName);
Eric Laurent2615afb2015-03-25 14:51:08 -07001734 gAudioPortEventHandlerMethods.postEventFromNative = GetStaticMethodIDOrDie(
1735 env, eventHandlerClass, "postEventFromNative",
1736 "(Ljava/lang/Object;IIILjava/lang/Object;)V");
1737 gEventHandlerFields.mJniCallback = GetFieldIDOrDie(env,
1738 eventHandlerClass, "mJniCallback", "J");
Eric Laurent700e7342014-05-02 18:33:15 -07001739
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001740 gDynPolicyEventHandlerMethods.postDynPolicyEventFromNative =
1741 GetStaticMethodIDOrDie(env, env->FindClass(kClassPathName),
1742 "dynamicPolicyCallbackFromNative", "(ILjava/lang/String;I)V");
1743
Eric Laurent09378972014-12-10 10:42:08 -08001744 jclass audioMixClass = FindClassOrDie(env, "android/media/audiopolicy/AudioMix");
1745 gAudioMixClass = MakeGlobalRefOrDie(env, audioMixClass);
1746 gAudioMixFields.mRule = GetFieldIDOrDie(env, audioMixClass, "mRule",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001747 "Landroid/media/audiopolicy/AudioMixingRule;");
Eric Laurent09378972014-12-10 10:42:08 -08001748 gAudioMixFields.mFormat = GetFieldIDOrDie(env, audioMixClass, "mFormat",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001749 "Landroid/media/AudioFormat;");
Eric Laurent09378972014-12-10 10:42:08 -08001750 gAudioMixFields.mRouteFlags = GetFieldIDOrDie(env, audioMixClass, "mRouteFlags", "I");
1751 gAudioMixFields.mRegistrationId = GetFieldIDOrDie(env, audioMixClass, "mRegistrationId",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001752 "Ljava/lang/String;");
Eric Laurent09378972014-12-10 10:42:08 -08001753 gAudioMixFields.mMixType = GetFieldIDOrDie(env, audioMixClass, "mMixType", "I");
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001754 gAudioMixFields.mCallbackFlags = GetFieldIDOrDie(env, audioMixClass, "mCallbackFlags", "I");
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001755
Eric Laurent09378972014-12-10 10:42:08 -08001756 jclass audioFormatClass = FindClassOrDie(env, "android/media/AudioFormat");
1757 gAudioFormatClass = MakeGlobalRefOrDie(env, audioFormatClass);
1758 gAudioFormatFields.mEncoding = GetFieldIDOrDie(env, audioFormatClass, "mEncoding", "I");
1759 gAudioFormatFields.mSampleRate = GetFieldIDOrDie(env, audioFormatClass, "mSampleRate", "I");
1760 gAudioFormatFields.mChannelMask = GetFieldIDOrDie(env, audioFormatClass, "mChannelMask", "I");
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001761
Eric Laurent09378972014-12-10 10:42:08 -08001762 jclass audioMixingRuleClass = FindClassOrDie(env, "android/media/audiopolicy/AudioMixingRule");
1763 gAudioMixingRuleClass = MakeGlobalRefOrDie(env, audioMixingRuleClass);
1764 gAudioMixingRuleFields.mCriteria = GetFieldIDOrDie(env, audioMixingRuleClass, "mCriteria",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001765 "Ljava/util/ArrayList;");
1766
1767 jclass attributeMatchCriterionClass =
Eric Laurent09378972014-12-10 10:42:08 -08001768 FindClassOrDie(env, "android/media/audiopolicy/AudioMixingRule$AttributeMatchCriterion");
1769 gAttributeMatchCriterionClass = MakeGlobalRefOrDie(env, attributeMatchCriterionClass);
1770 gAttributeMatchCriterionFields.mAttr = GetFieldIDOrDie(env, attributeMatchCriterionClass, "mAttr",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001771 "Landroid/media/AudioAttributes;");
Eric Laurent09378972014-12-10 10:42:08 -08001772 gAttributeMatchCriterionFields.mRule = GetFieldIDOrDie(env, attributeMatchCriterionClass, "mRule",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001773 "I");
1774
Eric Laurent09378972014-12-10 10:42:08 -08001775 jclass audioAttributesClass = FindClassOrDie(env, "android/media/AudioAttributes");
1776 gAudioAttributesClass = MakeGlobalRefOrDie(env, audioAttributesClass);
1777 gAudioAttributesFields.mUsage = GetFieldIDOrDie(env, audioAttributesClass, "mUsage", "I");
1778 gAudioAttributesFields.mSource = GetFieldIDOrDie(env, audioAttributesClass, "mSource", "I");
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001779
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001780 AudioSystem::setErrorCallback(android_media_AudioSystem_error_callback);
Glenn Kasten18db49a2012-03-12 16:29:55 -07001781
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001782 RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
1783 return RegisterMethodsOrDie(env, kEventHandlerClassPathName, gEventHandlerMethods,
1784 NELEM(gEventHandlerMethods));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001785}