blob: 7d9e4a284cec53a2013808c6db4fbe507ef39427 [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
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -0800131static jclass gAudioMixMatchCriterionClass;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -0800132static struct {
133 jfieldID mAttr;
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -0800134 jfieldID mIntProp;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -0800135 jfieldID mRule;
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -0800136} gAudioMixMatchCriterionFields;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -0800137
138static jclass gAudioAttributesClass;
139static struct {
140 jfieldID mUsage;
141 jfieldID mSource;
142} gAudioAttributesFields;
143
144
Eric Laurent700e7342014-05-02 18:33:15 -0700145static const char* const kEventHandlerClassPathName =
146 "android/media/AudioPortEventHandler";
Eric Laurent2615afb2015-03-25 14:51:08 -0700147static struct {
148 jfieldID mJniCallback;
149} gEventHandlerFields;
150static struct {
151 jmethodID postEventFromNative;
152} gAudioPortEventHandlerMethods;
153
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700154static struct {
155 jmethodID postDynPolicyEventFromNative;
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800156 jmethodID postRecordConfigEventFromNative;
157} gAudioPolicyEventHandlerMethods;
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700158
Eric Laurent2615afb2015-03-25 14:51:08 -0700159static Mutex gLock;
Eric Laurentb69681c2014-05-19 19:02:51 -0700160
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800161enum AudioError {
162 kAudioStatusOk = 0,
163 kAudioStatusError = 1,
164 kAudioStatusMediaServerDied = 100
165};
166
Eric Laurent700e7342014-05-02 18:33:15 -0700167enum {
168 AUDIOPORT_EVENT_PORT_LIST_UPDATED = 1,
169 AUDIOPORT_EVENT_PATCH_LIST_UPDATED = 2,
170 AUDIOPORT_EVENT_SERVICE_DIED = 3,
171};
172
Eric Laurentb69681c2014-05-19 19:02:51 -0700173#define MAX_PORT_GENERATION_SYNC_ATTEMPTS 5
174
Eric Laurent700e7342014-05-02 18:33:15 -0700175// ----------------------------------------------------------------------------
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700176// ref-counted object for audio port callbacks
Eric Laurent700e7342014-05-02 18:33:15 -0700177class JNIAudioPortCallback: public AudioSystem::AudioPortCallback
178{
179public:
180 JNIAudioPortCallback(JNIEnv* env, jobject thiz, jobject weak_thiz);
181 ~JNIAudioPortCallback();
182
183 virtual void onAudioPortListUpdate();
184 virtual void onAudioPatchListUpdate();
185 virtual void onServiceDied();
186
187private:
188 void sendEvent(int event);
189
Eric Laurent2615afb2015-03-25 14:51:08 -0700190 jclass mClass; // Reference to AudioPortEventHandler class
191 jobject mObject; // Weak ref to AudioPortEventHandler Java object to call on
Eric Laurent700e7342014-05-02 18:33:15 -0700192};
193
194JNIAudioPortCallback::JNIAudioPortCallback(JNIEnv* env, jobject thiz, jobject weak_thiz)
195{
196
Eric Laurent2615afb2015-03-25 14:51:08 -0700197 // Hold onto the AudioPortEventHandler class for use in calling the static method
Eric Laurent700e7342014-05-02 18:33:15 -0700198 // that posts events to the application thread.
199 jclass clazz = env->GetObjectClass(thiz);
200 if (clazz == NULL) {
201 ALOGE("Can't find class %s", kEventHandlerClassPathName);
202 return;
203 }
204 mClass = (jclass)env->NewGlobalRef(clazz);
205
Eric Laurent2615afb2015-03-25 14:51:08 -0700206 // We use a weak reference so the AudioPortEventHandler object can be garbage collected.
Eric Laurent700e7342014-05-02 18:33:15 -0700207 // The reference is only used as a proxy for callbacks.
208 mObject = env->NewGlobalRef(weak_thiz);
209}
210
211JNIAudioPortCallback::~JNIAudioPortCallback()
212{
213 // remove global references
214 JNIEnv *env = AndroidRuntime::getJNIEnv();
Eric Laurent449c5882014-11-12 11:07:48 -0800215 if (env == NULL) {
216 return;
217 }
Eric Laurent700e7342014-05-02 18:33:15 -0700218 env->DeleteGlobalRef(mObject);
219 env->DeleteGlobalRef(mClass);
220}
221
222void JNIAudioPortCallback::sendEvent(int event)
223{
224 JNIEnv *env = AndroidRuntime::getJNIEnv();
Eric Laurent449c5882014-11-12 11:07:48 -0800225 if (env == NULL) {
226 return;
227 }
Eric Laurent2615afb2015-03-25 14:51:08 -0700228 env->CallStaticVoidMethod(mClass, gAudioPortEventHandlerMethods.postEventFromNative, mObject,
Eric Laurent700e7342014-05-02 18:33:15 -0700229 event, 0, 0, NULL);
230 if (env->ExceptionCheck()) {
231 ALOGW("An exception occurred while notifying an event.");
232 env->ExceptionClear();
233 }
234}
235
236void JNIAudioPortCallback::onAudioPortListUpdate()
237{
238 sendEvent(AUDIOPORT_EVENT_PORT_LIST_UPDATED);
239}
240
241void JNIAudioPortCallback::onAudioPatchListUpdate()
242{
243 sendEvent(AUDIOPORT_EVENT_PATCH_LIST_UPDATED);
244}
245
246void JNIAudioPortCallback::onServiceDied()
247{
248 sendEvent(AUDIOPORT_EVENT_SERVICE_DIED);
249}
250
Eric Laurent2615afb2015-03-25 14:51:08 -0700251static sp<JNIAudioPortCallback> setJniCallback(JNIEnv* env,
252 jobject thiz,
253 const sp<JNIAudioPortCallback>& callback)
254{
255 Mutex::Autolock l(gLock);
256 sp<JNIAudioPortCallback> old =
257 (JNIAudioPortCallback*)env->GetLongField(thiz, gEventHandlerFields.mJniCallback);
258 if (callback.get()) {
259 callback->incStrong((void*)setJniCallback);
260 }
261 if (old != 0) {
262 old->decStrong((void*)setJniCallback);
263 }
264 env->SetLongField(thiz, gEventHandlerFields.mJniCallback, (jlong)callback.get());
265 return old;
266}
267
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800268static int check_AudioSystem_Command(status_t status)
269{
Eric Laurentdfb881f2013-07-18 14:41:39 -0700270 switch (status) {
271 case DEAD_OBJECT:
272 return kAudioStatusMediaServerDied;
273 case NO_ERROR:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800274 return kAudioStatusOk;
Eric Laurentdfb881f2013-07-18 14:41:39 -0700275 default:
276 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277 }
Eric Laurentdfb881f2013-07-18 14:41:39 -0700278 return kAudioStatusError;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279}
280
Ashok Bhat075e9a12014-01-06 13:45:09 +0000281static jint
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800282android_media_AudioSystem_muteMicrophone(JNIEnv *env, jobject thiz, jboolean on)
283{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000284 return (jint) check_AudioSystem_Command(AudioSystem::muteMicrophone(on));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800285}
286
287static jboolean
288android_media_AudioSystem_isMicrophoneMuted(JNIEnv *env, jobject thiz)
289{
290 bool state = false;
291 AudioSystem::isMicrophoneMuted(&state);
292 return state;
293}
294
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800295static jboolean
Eric Laurent25101b02011-02-02 09:33:30 -0800296android_media_AudioSystem_isStreamActive(JNIEnv *env, jobject thiz, jint stream, jint inPastMs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800297{
298 bool state = false;
Glenn Kastenbc1d77b2012-01-12 16:38:12 -0800299 AudioSystem::isStreamActive((audio_stream_type_t) stream, &state, inPastMs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800300 return state;
301}
302
Jean-Michel Trivid6770542012-10-10 12:03:41 -0700303static jboolean
Jean-Michel Trivi679d5042013-02-04 16:24:09 -0800304android_media_AudioSystem_isStreamActiveRemotely(JNIEnv *env, jobject thiz, jint stream,
305 jint inPastMs)
306{
307 bool state = false;
308 AudioSystem::isStreamActiveRemotely((audio_stream_type_t) stream, &state, inPastMs);
309 return state;
310}
311
312static jboolean
Jean-Michel Trivid6770542012-10-10 12:03:41 -0700313android_media_AudioSystem_isSourceActive(JNIEnv *env, jobject thiz, jint source)
314{
315 bool state = false;
316 AudioSystem::isSourceActive((audio_source_t) source, &state);
317 return state;
318}
319
Ashok Bhat075e9a12014-01-06 13:45:09 +0000320static jint
Jean-Michel Trivi8a21f5d2014-06-05 15:03:52 -0700321android_media_AudioSystem_newAudioSessionId(JNIEnv *env, jobject thiz)
322{
Eric Laurent62dc1762014-07-25 08:13:10 -0700323 return AudioSystem::newAudioUniqueId();
Jean-Michel Trivi8a21f5d2014-06-05 15:03:52 -0700324}
325
326static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700327android_media_AudioSystem_setParameters(JNIEnv *env, jobject thiz, jstring keyValuePairs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800328{
Eric Laurenta553c252009-07-17 12:17:14 -0700329 const jchar* c_keyValuePairs = env->GetStringCritical(keyValuePairs, 0);
330 String8 c_keyValuePairs8;
331 if (keyValuePairs) {
Dan Albert66987492014-11-20 11:41:21 -0800332 c_keyValuePairs8 = String8(
333 reinterpret_cast<const char16_t*>(c_keyValuePairs),
334 env->GetStringLength(keyValuePairs));
Eric Laurenta553c252009-07-17 12:17:14 -0700335 env->ReleaseStringCritical(keyValuePairs, c_keyValuePairs);
336 }
Glenn Kastenc94752a2013-12-19 12:40:33 -0800337 int status = check_AudioSystem_Command(AudioSystem::setParameters(c_keyValuePairs8));
Ashok Bhat075e9a12014-01-06 13:45:09 +0000338 return (jint) status;
Eric Laurenta553c252009-07-17 12:17:14 -0700339}
340
341static jstring
342android_media_AudioSystem_getParameters(JNIEnv *env, jobject thiz, jstring keys)
343{
344 const jchar* c_keys = env->GetStringCritical(keys, 0);
345 String8 c_keys8;
346 if (keys) {
Dan Albert66987492014-11-20 11:41:21 -0800347 c_keys8 = String8(reinterpret_cast<const char16_t*>(c_keys),
348 env->GetStringLength(keys));
Eric Laurenta553c252009-07-17 12:17:14 -0700349 env->ReleaseStringCritical(keys, c_keys);
350 }
Glenn Kastenc94752a2013-12-19 12:40:33 -0800351 return env->NewStringUTF(AudioSystem::getParameters(c_keys8).string());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800352}
353
Glenn Kastened0079d2011-04-04 10:50:50 -0700354static void
355android_media_AudioSystem_error_callback(status_t err)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800356{
Eric Laurent539719a2013-07-18 14:08:00 -0700357 JNIEnv *env = AndroidRuntime::getJNIEnv();
Eric Laurent0e7a4d92010-10-15 12:33:16 -0700358 if (env == NULL) {
359 return;
360 }
361
Glenn Kastened0079d2011-04-04 10:50:50 -0700362 jclass clazz = env->FindClass(kClassPathName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363
Eric Laurentdfb881f2013-07-18 14:41:39 -0700364 env->CallStaticVoidMethod(clazz, env->GetStaticMethodID(clazz,
365 "errorCallbackFromNative","(I)V"),
366 check_AudioSystem_Command(err));
Viorel Sumanb637ccf2014-05-30 16:51:07 +0300367
368 env->DeleteLocalRef(clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800369}
370
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700371static void
372android_media_AudioSystem_dyn_policy_callback(int event, String8 regId, int val)
373{
374 JNIEnv *env = AndroidRuntime::getJNIEnv();
375 if (env == NULL) {
376 return;
377 }
378
379 jclass clazz = env->FindClass(kClassPathName);
380 const char* zechars = regId.string();
381 jstring zestring = env->NewStringUTF(zechars);
382
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800383 env->CallStaticVoidMethod(clazz, gAudioPolicyEventHandlerMethods.postDynPolicyEventFromNative,
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700384 event, zestring, val);
385
386 env->ReleaseStringUTFChars(zestring, zechars);
387 env->DeleteLocalRef(clazz);
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800388}
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700389
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800390static void
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800391android_media_AudioSystem_recording_callback(int event, int session, int source,
392 const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig)
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800393{
394 JNIEnv *env = AndroidRuntime::getJNIEnv();
395 if (env == NULL) {
396 return;
397 }
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800398 if (clientConfig == NULL || deviceConfig == NULL) {
399 ALOGE("Unexpected null client/device configurations in recording callback");
400 return;
401 }
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800402
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800403 // create an array for 2*3 integers to store the record configurations (client + device)
404 jintArray recParamArray = env->NewIntArray(6);
405 if (recParamArray == NULL) {
406 ALOGE("recording callback: Couldn't allocate int array for configuration data");
407 return;
408 }
409 jint recParamData[6];
410 recParamData[0] = (jint) audioFormatFromNative(clientConfig->format);
411 // FIXME this doesn't support index-based masks
412 recParamData[1] = (jint) inChannelMaskFromNative(clientConfig->channel_mask);
413 recParamData[2] = (jint) clientConfig->sample_rate;
414 recParamData[3] = (jint) audioFormatFromNative(deviceConfig->format);
415 // FIXME this doesn't support index-based masks
416 recParamData[4] = (jint) inChannelMaskFromNative(deviceConfig->channel_mask);
417 recParamData[5] = (jint) deviceConfig->sample_rate;
418 env->SetIntArrayRegion(recParamArray, 0, 6, recParamData);
419
420 // callback into java
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800421 jclass clazz = env->FindClass(kClassPathName);
422 env->CallStaticVoidMethod(clazz,
423 gAudioPolicyEventHandlerMethods.postRecordConfigEventFromNative,
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800424 event, session, source, recParamArray);
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800425 env->DeleteLocalRef(clazz);
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800426
427 env->DeleteLocalRef(recParamArray);
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700428}
429
Ashok Bhat075e9a12014-01-06 13:45:09 +0000430static jint
Paul McLean10804eb2015-01-28 11:16:35 -0800431android_media_AudioSystem_setDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jint state, jstring device_address, jstring device_name)
Eric Laurenta553c252009-07-17 12:17:14 -0700432{
433 const char *c_address = env->GetStringUTFChars(device_address, NULL);
Paul McLean10804eb2015-01-28 11:16:35 -0800434 const char *c_name = env->GetStringUTFChars(device_name, NULL);
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700435 int status = check_AudioSystem_Command(AudioSystem::setDeviceConnectionState(static_cast <audio_devices_t>(device),
436 static_cast <audio_policy_dev_state_t>(state),
Paul McLean10804eb2015-01-28 11:16:35 -0800437 c_address, c_name));
Eric Laurenta553c252009-07-17 12:17:14 -0700438 env->ReleaseStringUTFChars(device_address, c_address);
Paul McLean10804eb2015-01-28 11:16:35 -0800439 env->ReleaseStringUTFChars(device_name, c_name);
Ashok Bhat075e9a12014-01-06 13:45:09 +0000440 return (jint) status;
Eric Laurenta553c252009-07-17 12:17:14 -0700441}
442
Ashok Bhat075e9a12014-01-06 13:45:09 +0000443static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700444android_media_AudioSystem_getDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jstring device_address)
445{
446 const char *c_address = env->GetStringUTFChars(device_address, NULL);
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700447 int state = static_cast <int>(AudioSystem::getDeviceConnectionState(static_cast <audio_devices_t>(device),
Eric Laurenta553c252009-07-17 12:17:14 -0700448 c_address));
449 env->ReleaseStringUTFChars(device_address, c_address);
Ashok Bhat075e9a12014-01-06 13:45:09 +0000450 return (jint) state;
Eric Laurenta553c252009-07-17 12:17:14 -0700451}
452
Ashok Bhat075e9a12014-01-06 13:45:09 +0000453static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700454android_media_AudioSystem_setPhoneState(JNIEnv *env, jobject thiz, jint state)
455{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000456 return (jint) check_AudioSystem_Command(AudioSystem::setPhoneState((audio_mode_t) state));
Eric Laurenta553c252009-07-17 12:17:14 -0700457}
458
Ashok Bhat075e9a12014-01-06 13:45:09 +0000459static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700460android_media_AudioSystem_setForceUse(JNIEnv *env, jobject thiz, jint usage, jint config)
461{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000462 return (jint) check_AudioSystem_Command(AudioSystem::setForceUse(static_cast <audio_policy_force_use_t>(usage),
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700463 static_cast <audio_policy_forced_cfg_t>(config)));
Eric Laurenta553c252009-07-17 12:17:14 -0700464}
465
Ashok Bhat075e9a12014-01-06 13:45:09 +0000466static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700467android_media_AudioSystem_getForceUse(JNIEnv *env, jobject thiz, jint usage)
468{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000469 return static_cast <jint>(AudioSystem::getForceUse(static_cast <audio_policy_force_use_t>(usage)));
Eric Laurenta553c252009-07-17 12:17:14 -0700470}
471
Ashok Bhat075e9a12014-01-06 13:45:09 +0000472static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700473android_media_AudioSystem_initStreamVolume(JNIEnv *env, jobject thiz, jint stream, jint indexMin, jint indexMax)
474{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000475 return (jint) check_AudioSystem_Command(AudioSystem::initStreamVolume(static_cast <audio_stream_type_t>(stream),
Eric Laurenta553c252009-07-17 12:17:14 -0700476 indexMin,
477 indexMax));
478}
479
Ashok Bhat075e9a12014-01-06 13:45:09 +0000480static jint
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800481android_media_AudioSystem_setStreamVolumeIndex(JNIEnv *env,
482 jobject thiz,
483 jint stream,
484 jint index,
485 jint device)
Eric Laurenta553c252009-07-17 12:17:14 -0700486{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000487 return (jint) check_AudioSystem_Command(
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800488 AudioSystem::setStreamVolumeIndex(static_cast <audio_stream_type_t>(stream),
489 index,
490 (audio_devices_t)device));
Eric Laurenta553c252009-07-17 12:17:14 -0700491}
492
Ashok Bhat075e9a12014-01-06 13:45:09 +0000493static jint
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800494android_media_AudioSystem_getStreamVolumeIndex(JNIEnv *env,
495 jobject thiz,
496 jint stream,
497 jint device)
Eric Laurenta553c252009-07-17 12:17:14 -0700498{
499 int index;
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800500 if (AudioSystem::getStreamVolumeIndex(static_cast <audio_stream_type_t>(stream),
501 &index,
502 (audio_devices_t)device)
503 != NO_ERROR) {
Eric Laurenta553c252009-07-17 12:17:14 -0700504 index = -1;
505 }
Ashok Bhat075e9a12014-01-06 13:45:09 +0000506 return (jint) index;
Eric Laurenta553c252009-07-17 12:17:14 -0700507}
508
Ashok Bhat075e9a12014-01-06 13:45:09 +0000509static jint
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400510android_media_AudioSystem_setMasterVolume(JNIEnv *env, jobject thiz, jfloat value)
511{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000512 return (jint) check_AudioSystem_Command(AudioSystem::setMasterVolume(value));
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400513}
514
515static jfloat
516android_media_AudioSystem_getMasterVolume(JNIEnv *env, jobject thiz)
517{
518 float value;
519 if (AudioSystem::getMasterVolume(&value) != NO_ERROR) {
520 value = -1.0;
521 }
522 return value;
523}
524
Ashok Bhat075e9a12014-01-06 13:45:09 +0000525static jint
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400526android_media_AudioSystem_setMasterMute(JNIEnv *env, jobject thiz, jboolean mute)
527{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000528 return (jint) check_AudioSystem_Command(AudioSystem::setMasterMute(mute));
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400529}
530
Vladimir Markoc1bcdbb2014-10-29 20:34:15 +0000531static jboolean
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400532android_media_AudioSystem_getMasterMute(JNIEnv *env, jobject thiz)
533{
534 bool mute;
535 if (AudioSystem::getMasterMute(&mute) != NO_ERROR) {
536 mute = false;
537 }
538 return mute;
539}
540
Glenn Kasten8b4b97a2011-02-04 13:54:26 -0800541static jint
Andy Hungf04b84d2015-12-18 17:33:27 -0800542android_media_AudioSystem_setMasterMono(JNIEnv *env, jobject thiz, jboolean mono)
543{
544 return (jint) check_AudioSystem_Command(AudioSystem::setMasterMono(mono));
545}
546
547static jboolean
548android_media_AudioSystem_getMasterMono(JNIEnv *env, jobject thiz)
549{
550 bool mono;
551 if (AudioSystem::getMasterMono(&mono) != NO_ERROR) {
552 mono = false;
553 }
554 return mono;
555}
556
557static jint
Glenn Kasten8b4b97a2011-02-04 13:54:26 -0800558android_media_AudioSystem_getDevicesForStream(JNIEnv *env, jobject thiz, jint stream)
559{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700560 return (jint) AudioSystem::getDevicesForStream(static_cast <audio_stream_type_t>(stream));
Glenn Kasten8b4b97a2011-02-04 13:54:26 -0800561}
562
Glenn Kastenc6c43652012-09-24 17:32:30 -0700563static jint
564android_media_AudioSystem_getPrimaryOutputSamplingRate(JNIEnv *env, jobject clazz)
565{
566 return (jint) AudioSystem::getPrimaryOutputSamplingRate();
567}
568
569static jint
570android_media_AudioSystem_getPrimaryOutputFrameCount(JNIEnv *env, jobject clazz)
571{
572 return (jint) AudioSystem::getPrimaryOutputFrameCount();
573}
574
Oliver Woodman61dcdf32013-06-26 12:43:36 +0100575static jint
576android_media_AudioSystem_getOutputLatency(JNIEnv *env, jobject clazz, jint stream)
577{
578 uint32_t afLatency;
579 if (AudioSystem::getOutputLatency(&afLatency, static_cast <audio_stream_type_t>(stream))
580 != NO_ERROR) {
581 afLatency = -1;
582 }
583 return (jint) afLatency;
584}
585
Glenn Kastenfd116ad2013-07-12 17:10:39 -0700586static jint
587android_media_AudioSystem_setLowRamDevice(JNIEnv *env, jobject clazz, jboolean isLowRamDevice)
588{
589 return (jint) AudioSystem::setLowRamDevice((bool) isLowRamDevice);
590}
591
Ashok Bhat075e9a12014-01-06 13:45:09 +0000592static jint
Eric Laurentdfb881f2013-07-18 14:41:39 -0700593android_media_AudioSystem_checkAudioFlinger(JNIEnv *env, jobject clazz)
594{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000595 return (jint) check_AudioSystem_Command(AudioSystem::checkAudioFlinger());
Eric Laurentdfb881f2013-07-18 14:41:39 -0700596}
597
Eric Laurentb69681c2014-05-19 19:02:51 -0700598
599static bool useInChannelMask(audio_port_type_t type, audio_port_role_t role)
600{
601 return ((type == AUDIO_PORT_TYPE_DEVICE) && (role == AUDIO_PORT_ROLE_SOURCE)) ||
602 ((type == AUDIO_PORT_TYPE_MIX) && (role == AUDIO_PORT_ROLE_SINK));
603}
604
Eric Laurent3a241992014-05-19 19:33:26 -0700605static void convertAudioGainConfigToNative(JNIEnv *env,
606 struct audio_gain_config *nAudioGainConfig,
607 const jobject jAudioGainConfig,
608 bool useInMask)
609{
610 nAudioGainConfig->index = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mIndex);
611 nAudioGainConfig->mode = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mMode);
612 ALOGV("convertAudioGainConfigToNative got gain index %d", nAudioGainConfig->index);
613 jint jMask = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mChannelMask);
614 audio_channel_mask_t nMask;
615 if (useInMask) {
616 nMask = inChannelMaskToNative(jMask);
617 ALOGV("convertAudioGainConfigToNative IN mask java %x native %x", jMask, nMask);
618 } else {
619 nMask = outChannelMaskToNative(jMask);
620 ALOGV("convertAudioGainConfigToNative OUT mask java %x native %x", jMask, nMask);
621 }
622 nAudioGainConfig->channel_mask = nMask;
623 nAudioGainConfig->ramp_duration_ms = env->GetIntField(jAudioGainConfig,
624 gAudioGainConfigFields.mRampDurationMs);
625 jintArray jValues = (jintArray)env->GetObjectField(jAudioGainConfig,
626 gAudioGainConfigFields.mValues);
627 int *nValues = env->GetIntArrayElements(jValues, NULL);
628 size_t size = env->GetArrayLength(jValues);
629 memcpy(nAudioGainConfig->values, nValues, size * sizeof(int));
630 env->DeleteLocalRef(jValues);
631}
632
633
Eric Laurentb69681c2014-05-19 19:02:51 -0700634static jint convertAudioPortConfigToNative(JNIEnv *env,
635 struct audio_port_config *nAudioPortConfig,
Eric Laurent6368a7d2014-11-19 12:18:32 -0800636 const jobject jAudioPortConfig,
637 bool useConfigMask)
Eric Laurentb69681c2014-05-19 19:02:51 -0700638{
639 jobject jAudioPort = env->GetObjectField(jAudioPortConfig, gAudioPortConfigFields.mPort);
640 jobject jHandle = env->GetObjectField(jAudioPort, gAudioPortFields.mHandle);
641 nAudioPortConfig->id = env->GetIntField(jHandle, gAudioHandleFields.mId);
642 nAudioPortConfig->role = (audio_port_role_t)env->GetIntField(jAudioPort,
643 gAudioPortFields.mRole);
644 if (env->IsInstanceOf(jAudioPort, gAudioDevicePortClass)) {
645 nAudioPortConfig->type = AUDIO_PORT_TYPE_DEVICE;
646 } else if (env->IsInstanceOf(jAudioPort, gAudioMixPortClass)) {
647 nAudioPortConfig->type = AUDIO_PORT_TYPE_MIX;
648 } else {
649 env->DeleteLocalRef(jAudioPort);
650 env->DeleteLocalRef(jHandle);
651 return (jint)AUDIO_JAVA_ERROR;
652 }
653 ALOGV("convertAudioPortConfigToNative handle %d role %d type %d",
654 nAudioPortConfig->id, nAudioPortConfig->role, nAudioPortConfig->type);
655
Eric Laurent6368a7d2014-11-19 12:18:32 -0800656 unsigned int configMask = 0;
657
Eric Laurentb69681c2014-05-19 19:02:51 -0700658 nAudioPortConfig->sample_rate = env->GetIntField(jAudioPortConfig,
659 gAudioPortConfigFields.mSamplingRate);
Eric Laurent6368a7d2014-11-19 12:18:32 -0800660 if (nAudioPortConfig->sample_rate != 0) {
661 configMask |= AUDIO_PORT_CONFIG_SAMPLE_RATE;
662 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700663
664 bool useInMask = useInChannelMask(nAudioPortConfig->type, nAudioPortConfig->role);
665 audio_channel_mask_t nMask;
666 jint jMask = env->GetIntField(jAudioPortConfig,
667 gAudioPortConfigFields.mChannelMask);
668 if (useInMask) {
669 nMask = inChannelMaskToNative(jMask);
670 ALOGV("convertAudioPortConfigToNative IN mask java %x native %x", jMask, nMask);
671 } else {
672 nMask = outChannelMaskToNative(jMask);
673 ALOGV("convertAudioPortConfigToNative OUT mask java %x native %x", jMask, nMask);
674 }
675 nAudioPortConfig->channel_mask = nMask;
Eric Laurent6368a7d2014-11-19 12:18:32 -0800676 if (nAudioPortConfig->channel_mask != AUDIO_CHANNEL_NONE) {
677 configMask |= AUDIO_PORT_CONFIG_CHANNEL_MASK;
678 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700679
680 jint jFormat = env->GetIntField(jAudioPortConfig, gAudioPortConfigFields.mFormat);
681 audio_format_t nFormat = audioFormatToNative(jFormat);
682 ALOGV("convertAudioPortConfigToNative format %d native %d", jFormat, nFormat);
683 nAudioPortConfig->format = nFormat;
Eric Laurent6368a7d2014-11-19 12:18:32 -0800684 if (nAudioPortConfig->format != AUDIO_FORMAT_DEFAULT &&
685 nAudioPortConfig->format != AUDIO_FORMAT_INVALID) {
686 configMask |= AUDIO_PORT_CONFIG_FORMAT;
687 }
688
Eric Laurentb69681c2014-05-19 19:02:51 -0700689 jobject jGain = env->GetObjectField(jAudioPortConfig, gAudioPortConfigFields.mGain);
690 if (jGain != NULL) {
Eric Laurent3a241992014-05-19 19:33:26 -0700691 convertAudioGainConfigToNative(env, &nAudioPortConfig->gain, jGain, useInMask);
Eric Laurentb69681c2014-05-19 19:02:51 -0700692 env->DeleteLocalRef(jGain);
Eric Laurent6368a7d2014-11-19 12:18:32 -0800693 configMask |= AUDIO_PORT_CONFIG_GAIN;
Eric Laurentb69681c2014-05-19 19:02:51 -0700694 } else {
695 ALOGV("convertAudioPortConfigToNative no gain");
696 nAudioPortConfig->gain.index = -1;
697 }
Eric Laurent6368a7d2014-11-19 12:18:32 -0800698 if (useConfigMask) {
699 nAudioPortConfig->config_mask = env->GetIntField(jAudioPortConfig,
700 gAudioPortConfigFields.mConfigMask);
701 } else {
702 nAudioPortConfig->config_mask = configMask;
703 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700704 env->DeleteLocalRef(jAudioPort);
705 env->DeleteLocalRef(jHandle);
706 return (jint)AUDIO_JAVA_SUCCESS;
707}
708
709static jint convertAudioPortConfigFromNative(JNIEnv *env,
710 jobject jAudioPort,
711 jobject *jAudioPortConfig,
712 const struct audio_port_config *nAudioPortConfig)
713{
714 jint jStatus = AUDIO_JAVA_SUCCESS;
715 jobject jAudioGainConfig = NULL;
716 jobject jAudioGain = NULL;
717 jintArray jGainValues;
718 bool audioportCreated = false;
719
720 ALOGV("convertAudioPortConfigFromNative jAudioPort %p", jAudioPort);
721
722 if (jAudioPort == NULL) {
723 jobject jHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
724 nAudioPortConfig->id);
725
726 ALOGV("convertAudioPortConfigFromNative handle %d is a %s", nAudioPortConfig->id,
727 nAudioPortConfig->type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix");
728
729 if (jHandle == NULL) {
730 return (jint)AUDIO_JAVA_ERROR;
731 }
732 // create dummy port and port config objects with just the correct handle
733 // and configuration data. The actual AudioPortConfig objects will be
734 // constructed by java code with correct class type (device, mix etc...)
735 // and reference to AudioPort instance in this client
736 jAudioPort = env->NewObject(gAudioPortClass, gAudioPortCstor,
Paul McLeanf29e5f32015-06-15 10:19:22 -0700737 jHandle, // handle
738 0, // role
739 NULL, // name
740 NULL, // samplingRates
741 NULL, // channelMasks
742 NULL, // channelIndexMasks
743 NULL, // formats
744 NULL); // gains
Eric Laurentb69681c2014-05-19 19:02:51 -0700745 env->DeleteLocalRef(jHandle);
746 if (jAudioPort == NULL) {
747 return (jint)AUDIO_JAVA_ERROR;
748 }
749 ALOGV("convertAudioPortConfigFromNative jAudioPort created for handle %d",
750 nAudioPortConfig->id);
751
752 audioportCreated = true;
753 }
754
755 bool useInMask = useInChannelMask(nAudioPortConfig->type, nAudioPortConfig->role);
756
757 audio_channel_mask_t nMask;
758 jint jMask;
759
760 int gainIndex = nAudioPortConfig->gain.index;
761 if (gainIndex >= 0) {
762 ALOGV("convertAudioPortConfigFromNative gain found with index %d mode %x",
763 gainIndex, nAudioPortConfig->gain.mode);
764 if (audioportCreated) {
765 ALOGV("convertAudioPortConfigFromNative creating gain");
766 jAudioGain = env->NewObject(gAudioGainClass, gAudioGainCstor,
767 gainIndex,
768 0,
769 0,
770 0,
771 0,
772 0,
773 0,
774 0,
775 0);
776 if (jAudioGain == NULL) {
777 ALOGV("convertAudioPortConfigFromNative creating gain FAILED");
778 jStatus = (jint)AUDIO_JAVA_ERROR;
779 goto exit;
780 }
781 } else {
782 ALOGV("convertAudioPortConfigFromNative reading gain from port");
783 jobjectArray jGains = (jobjectArray)env->GetObjectField(jAudioPort,
784 gAudioPortFields.mGains);
785 if (jGains == NULL) {
786 ALOGV("convertAudioPortConfigFromNative could not get gains from port");
787 jStatus = (jint)AUDIO_JAVA_ERROR;
788 goto exit;
789 }
790 jAudioGain = env->GetObjectArrayElement(jGains, gainIndex);
791 env->DeleteLocalRef(jGains);
792 if (jAudioGain == NULL) {
793 ALOGV("convertAudioPortConfigFromNative could not get gain at index %d", gainIndex);
794 jStatus = (jint)AUDIO_JAVA_ERROR;
795 goto exit;
796 }
797 }
Eric Laurent0078c7c2014-06-04 09:49:52 -0700798 int numValues;
799 if (useInMask) {
800 numValues = audio_channel_count_from_in_mask(nAudioPortConfig->gain.channel_mask);
801 } else {
802 numValues = audio_channel_count_from_out_mask(nAudioPortConfig->gain.channel_mask);
803 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700804 jGainValues = env->NewIntArray(numValues);
805 if (jGainValues == NULL) {
806 ALOGV("convertAudioPortConfigFromNative could not create gain values %d", numValues);
807 jStatus = (jint)AUDIO_JAVA_ERROR;
808 goto exit;
809 }
810 env->SetIntArrayRegion(jGainValues, 0, numValues,
811 nAudioPortConfig->gain.values);
812
813 nMask = nAudioPortConfig->gain.channel_mask;
814 if (useInMask) {
815 jMask = inChannelMaskFromNative(nMask);
816 ALOGV("convertAudioPortConfigFromNative IN mask java %x native %x", jMask, nMask);
817 } else {
818 jMask = outChannelMaskFromNative(nMask);
819 ALOGV("convertAudioPortConfigFromNative OUT mask java %x native %x", jMask, nMask);
820 }
821
822 jAudioGainConfig = env->NewObject(gAudioGainConfigClass,
823 gAudioGainConfigCstor,
824 gainIndex,
825 jAudioGain,
826 nAudioPortConfig->gain.mode,
827 jMask,
828 jGainValues,
829 nAudioPortConfig->gain.ramp_duration_ms);
830 env->DeleteLocalRef(jGainValues);
831 if (jAudioGainConfig == NULL) {
832 ALOGV("convertAudioPortConfigFromNative could not create gain config");
833 jStatus = (jint)AUDIO_JAVA_ERROR;
834 goto exit;
835 }
836 }
837 jclass clazz;
838 jmethodID methodID;
839 if (audioportCreated) {
840 clazz = gAudioPortConfigClass;
841 methodID = gAudioPortConfigCstor;
842 ALOGV("convertAudioPortConfigFromNative building a generic port config");
843 } else {
844 if (env->IsInstanceOf(jAudioPort, gAudioDevicePortClass)) {
845 clazz = gAudioDevicePortConfigClass;
846 methodID = gAudioDevicePortConfigCstor;
847 ALOGV("convertAudioPortConfigFromNative building a device config");
848 } else if (env->IsInstanceOf(jAudioPort, gAudioMixPortClass)) {
849 clazz = gAudioMixPortConfigClass;
850 methodID = gAudioMixPortConfigCstor;
851 ALOGV("convertAudioPortConfigFromNative building a mix config");
852 } else {
853 jStatus = (jint)AUDIO_JAVA_ERROR;
854 goto exit;
855 }
856 }
857 nMask = nAudioPortConfig->channel_mask;
858 if (useInMask) {
859 jMask = inChannelMaskFromNative(nMask);
860 ALOGV("convertAudioPortConfigFromNative IN mask java %x native %x", jMask, nMask);
861 } else {
862 jMask = outChannelMaskFromNative(nMask);
863 ALOGV("convertAudioPortConfigFromNative OUT mask java %x native %x", jMask, nMask);
864 }
865
866 *jAudioPortConfig = env->NewObject(clazz, methodID,
867 jAudioPort,
868 nAudioPortConfig->sample_rate,
869 jMask,
870 audioFormatFromNative(nAudioPortConfig->format),
871 jAudioGainConfig);
872 if (*jAudioPortConfig == NULL) {
873 ALOGV("convertAudioPortConfigFromNative could not create new port config");
874 jStatus = (jint)AUDIO_JAVA_ERROR;
875 } else {
876 ALOGV("convertAudioPortConfigFromNative OK");
877 }
878
879exit:
880 if (audioportCreated) {
881 env->DeleteLocalRef(jAudioPort);
882 if (jAudioGain != NULL) {
883 env->DeleteLocalRef(jAudioGain);
884 }
885 }
886 if (jAudioGainConfig != NULL) {
887 env->DeleteLocalRef(jAudioGainConfig);
888 }
889 return jStatus;
890}
891
Paul McLean4e5e9e92015-06-17 10:10:11 -0700892static bool hasFormat(int* formats, size_t size, int format) {
893 for (size_t index = 0; index < size; index++) {
894 if (formats[index] == format) {
895 return true; // found
896 }
897 }
898 return false; // not found
899}
900
Eric Laurentb69681c2014-05-19 19:02:51 -0700901static jint convertAudioPortFromNative(JNIEnv *env,
902 jobject *jAudioPort, const struct audio_port *nAudioPort)
903{
904 jint jStatus = (jint)AUDIO_JAVA_SUCCESS;
905 jintArray jSamplingRates = NULL;
906 jintArray jChannelMasks = NULL;
Paul McLeanf29e5f32015-06-15 10:19:22 -0700907 jintArray jChannelIndexMasks = NULL;
Paul McLean4e5e9e92015-06-17 10:10:11 -0700908 int* cFormats = NULL;
Eric Laurentb69681c2014-05-19 19:02:51 -0700909 jintArray jFormats = NULL;
910 jobjectArray jGains = NULL;
911 jobject jHandle = NULL;
Paul McLean10804eb2015-01-28 11:16:35 -0800912 jstring jDeviceName = NULL;
Eric Laurentb69681c2014-05-19 19:02:51 -0700913 bool useInMask;
Paul McLeanf29e5f32015-06-15 10:19:22 -0700914 size_t numPositionMasks = 0;
915 size_t numIndexMasks = 0;
Paul McLean2db94372015-06-18 12:47:34 -0700916 size_t numUniqueFormats = 0;
917
Paul McLean10804eb2015-01-28 11:16:35 -0800918 ALOGV("convertAudioPortFromNative id %d role %d type %d name %s",
919 nAudioPort->id, nAudioPort->role, nAudioPort->type, nAudioPort->name);
Eric Laurentb69681c2014-05-19 19:02:51 -0700920
921 jSamplingRates = env->NewIntArray(nAudioPort->num_sample_rates);
922 if (jSamplingRates == NULL) {
923 jStatus = (jint)AUDIO_JAVA_ERROR;
924 goto exit;
925 }
926 if (nAudioPort->num_sample_rates) {
927 env->SetIntArrayRegion(jSamplingRates, 0, nAudioPort->num_sample_rates,
928 (jint *)nAudioPort->sample_rates);
929 }
930
Paul McLeanf29e5f32015-06-15 10:19:22 -0700931 // count up how many masks are positional and indexed
932 for(size_t index = 0; index < nAudioPort->num_channel_masks; index++) {
933 const audio_channel_mask_t mask = nAudioPort->channel_masks[index];
934 if (audio_channel_mask_get_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
935 numIndexMasks++;
936 } else {
937 numPositionMasks++;
938 }
939 }
940
941 jChannelMasks = env->NewIntArray(numPositionMasks);
Eric Laurentb69681c2014-05-19 19:02:51 -0700942 if (jChannelMasks == NULL) {
943 jStatus = (jint)AUDIO_JAVA_ERROR;
944 goto exit;
945 }
Paul McLeanf29e5f32015-06-15 10:19:22 -0700946 jChannelIndexMasks = env->NewIntArray(numIndexMasks);
947 if (jChannelIndexMasks == NULL) {
948 jStatus = (jint)AUDIO_JAVA_ERROR;
949 goto exit;
950 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700951 useInMask = useInChannelMask(nAudioPort->type, nAudioPort->role);
952
Paul McLeanf29e5f32015-06-15 10:19:22 -0700953 // put the masks in the output arrays
954 for (size_t maskIndex = 0, posMaskIndex = 0, indexedMaskIndex = 0;
955 maskIndex < nAudioPort->num_channel_masks; maskIndex++) {
956 const audio_channel_mask_t mask = nAudioPort->channel_masks[maskIndex];
957 if (audio_channel_mask_get_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
958 jint jMask = audio_channel_mask_get_bits(mask);
959 env->SetIntArrayRegion(jChannelIndexMasks, indexedMaskIndex++, 1, &jMask);
Eric Laurentb69681c2014-05-19 19:02:51 -0700960 } else {
Paul McLeanf29e5f32015-06-15 10:19:22 -0700961 jint jMask = useInMask ? inChannelMaskFromNative(mask)
962 : outChannelMaskFromNative(mask);
963 env->SetIntArrayRegion(jChannelMasks, posMaskIndex++, 1, &jMask);
Eric Laurentb69681c2014-05-19 19:02:51 -0700964 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700965 }
966
Paul McLeanf29e5f32015-06-15 10:19:22 -0700967 // formats
Paul McLean2db94372015-06-18 12:47:34 -0700968 if (nAudioPort->num_formats != 0) {
969 cFormats = new int[nAudioPort->num_formats];
970 for (size_t index = 0; index < nAudioPort->num_formats; index++) {
971 int format = audioFormatFromNative(nAudioPort->formats[index]);
972 if (!hasFormat(cFormats, numUniqueFormats, format)) {
973 cFormats[numUniqueFormats++] = format;
974 }
Paul McLean4e5e9e92015-06-17 10:10:11 -0700975 }
976 }
977 jFormats = env->NewIntArray(numUniqueFormats);
Eric Laurentb69681c2014-05-19 19:02:51 -0700978 if (jFormats == NULL) {
979 jStatus = (jint)AUDIO_JAVA_ERROR;
980 goto exit;
981 }
Paul McLean2db94372015-06-18 12:47:34 -0700982 if (numUniqueFormats != 0) {
983 env->SetIntArrayRegion(jFormats, 0, numUniqueFormats, cFormats);
984 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700985
Paul McLeanf29e5f32015-06-15 10:19:22 -0700986 // gains
Eric Laurentb69681c2014-05-19 19:02:51 -0700987 jGains = env->NewObjectArray(nAudioPort->num_gains,
988 gAudioGainClass, NULL);
989 if (jGains == NULL) {
990 jStatus = (jint)AUDIO_JAVA_ERROR;
991 goto exit;
992 }
Paul McLeanf29e5f32015-06-15 10:19:22 -0700993
Eric Laurentb69681c2014-05-19 19:02:51 -0700994 for (size_t j = 0; j < nAudioPort->num_gains; j++) {
995 audio_channel_mask_t nMask = nAudioPort->gains[j].channel_mask;
Paul McLeanf29e5f32015-06-15 10:19:22 -0700996 jint jMask;
Eric Laurentb69681c2014-05-19 19:02:51 -0700997 if (useInMask) {
998 jMask = inChannelMaskFromNative(nMask);
999 ALOGV("convertAudioPortConfigFromNative IN mask java %x native %x", jMask, nMask);
1000 } else {
1001 jMask = outChannelMaskFromNative(nMask);
1002 ALOGV("convertAudioPortConfigFromNative OUT mask java %x native %x", jMask, nMask);
1003 }
1004
1005 jobject jGain = env->NewObject(gAudioGainClass, gAudioGainCstor,
1006 j,
1007 nAudioPort->gains[j].mode,
1008 jMask,
1009 nAudioPort->gains[j].min_value,
1010 nAudioPort->gains[j].max_value,
1011 nAudioPort->gains[j].default_value,
1012 nAudioPort->gains[j].step_value,
1013 nAudioPort->gains[j].min_ramp_ms,
1014 nAudioPort->gains[j].max_ramp_ms);
1015 if (jGain == NULL) {
1016 jStatus = (jint)AUDIO_JAVA_ERROR;
1017 goto exit;
1018 }
1019 env->SetObjectArrayElement(jGains, j, jGain);
1020 env->DeleteLocalRef(jGain);
1021 }
1022
1023 jHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
1024 nAudioPort->id);
1025 if (jHandle == NULL) {
1026 jStatus = (jint)AUDIO_JAVA_ERROR;
1027 goto exit;
1028 }
1029
Paul McLean10804eb2015-01-28 11:16:35 -08001030 jDeviceName = env->NewStringUTF(nAudioPort->name);
1031
Eric Laurentb69681c2014-05-19 19:02:51 -07001032 if (nAudioPort->type == AUDIO_PORT_TYPE_DEVICE) {
1033 ALOGV("convertAudioPortFromNative is a device %08x", nAudioPort->ext.device.type);
1034 jstring jAddress = env->NewStringUTF(nAudioPort->ext.device.address);
1035 *jAudioPort = env->NewObject(gAudioDevicePortClass, gAudioDevicePortCstor,
Paul McLean10804eb2015-01-28 11:16:35 -08001036 jHandle, jDeviceName,
Paul McLeanf29e5f32015-06-15 10:19:22 -07001037 jSamplingRates, jChannelMasks, jChannelIndexMasks,
1038 jFormats, jGains,
Eric Laurentb69681c2014-05-19 19:02:51 -07001039 nAudioPort->ext.device.type, jAddress);
1040 env->DeleteLocalRef(jAddress);
1041 } else if (nAudioPort->type == AUDIO_PORT_TYPE_MIX) {
1042 ALOGV("convertAudioPortFromNative is a mix");
1043 *jAudioPort = env->NewObject(gAudioMixPortClass, gAudioMixPortCstor,
Eric Laurent4bcdba82015-05-01 11:37:49 -07001044 jHandle, nAudioPort->ext.mix.handle,
1045 nAudioPort->role, jDeviceName,
Paul McLeanf29e5f32015-06-15 10:19:22 -07001046 jSamplingRates, jChannelMasks, jChannelIndexMasks,
Eric Laurentb69681c2014-05-19 19:02:51 -07001047 jFormats, jGains);
1048 } else {
1049 ALOGE("convertAudioPortFromNative unknown nAudioPort type %d", nAudioPort->type);
1050 jStatus = (jint)AUDIO_JAVA_ERROR;
1051 goto exit;
1052 }
1053 if (*jAudioPort == NULL) {
1054 jStatus = (jint)AUDIO_JAVA_ERROR;
1055 goto exit;
1056 }
1057
1058 jobject jAudioPortConfig;
1059 jStatus = convertAudioPortConfigFromNative(env,
1060 *jAudioPort,
1061 &jAudioPortConfig,
1062 &nAudioPort->active_config);
1063 if (jStatus != AUDIO_JAVA_SUCCESS) {
1064 return jStatus;
1065 }
1066
1067 env->SetObjectField(*jAudioPort, gAudioPortFields.mActiveConfig, jAudioPortConfig);
1068
1069exit:
Paul McLean10804eb2015-01-28 11:16:35 -08001070 if (jDeviceName != NULL) {
1071 env->DeleteLocalRef(jDeviceName);
1072 }
Eric Laurentb69681c2014-05-19 19:02:51 -07001073 if (jSamplingRates != NULL) {
1074 env->DeleteLocalRef(jSamplingRates);
1075 }
1076 if (jChannelMasks != NULL) {
1077 env->DeleteLocalRef(jChannelMasks);
1078 }
Paul McLean4e5e9e92015-06-17 10:10:11 -07001079 if (jChannelIndexMasks != NULL) {
1080 env->DeleteLocalRef(jChannelIndexMasks);
1081 }
1082 if (cFormats != NULL) {
1083 delete[] cFormats;
1084 }
Eric Laurentb69681c2014-05-19 19:02:51 -07001085 if (jFormats != NULL) {
1086 env->DeleteLocalRef(jFormats);
1087 }
1088 if (jGains != NULL) {
1089 env->DeleteLocalRef(jGains);
1090 }
1091 if (jHandle != NULL) {
1092 env->DeleteLocalRef(jHandle);
1093 }
1094
1095 return jStatus;
1096}
1097
1098
1099static jint
1100android_media_AudioSystem_listAudioPorts(JNIEnv *env, jobject clazz,
1101 jobject jPorts, jintArray jGeneration)
1102{
1103 ALOGV("listAudioPorts");
1104
1105 if (jPorts == NULL) {
1106 ALOGE("listAudioPorts NULL AudioPort ArrayList");
1107 return (jint)AUDIO_JAVA_BAD_VALUE;
1108 }
1109 if (!env->IsInstanceOf(jPorts, gArrayListClass)) {
1110 ALOGE("listAudioPorts not an arraylist");
1111 return (jint)AUDIO_JAVA_BAD_VALUE;
1112 }
1113
1114 if (jGeneration == NULL || env->GetArrayLength(jGeneration) != 1) {
1115 return (jint)AUDIO_JAVA_BAD_VALUE;
1116 }
1117
1118 status_t status;
1119 unsigned int generation1;
1120 unsigned int generation;
1121 unsigned int numPorts;
1122 jint *nGeneration;
1123 struct audio_port *nPorts = NULL;
1124 int attempts = MAX_PORT_GENERATION_SYNC_ATTEMPTS;
1125
1126 // get the port count and all the ports until they both return the same generation
1127 do {
1128 if (attempts-- < 0) {
1129 status = TIMED_OUT;
1130 break;
1131 }
1132
1133 numPorts = 0;
1134 status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE,
1135 AUDIO_PORT_TYPE_NONE,
1136 &numPorts,
1137 NULL,
1138 &generation1);
1139 if (status != NO_ERROR || numPorts == 0) {
1140 ALOGE_IF(status != NO_ERROR, "AudioSystem::listAudioPorts error %d", status);
1141 break;
1142 }
1143 nPorts = (struct audio_port *)realloc(nPorts, numPorts * sizeof(struct audio_port));
1144
1145 status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE,
1146 AUDIO_PORT_TYPE_NONE,
1147 &numPorts,
1148 nPorts,
1149 &generation);
1150 ALOGV("listAudioPorts AudioSystem::listAudioPorts numPorts %d generation %d generation1 %d",
1151 numPorts, generation, generation1);
1152 } while (generation1 != generation && status == NO_ERROR);
1153
1154 jint jStatus = nativeToJavaStatus(status);
1155 if (jStatus != AUDIO_JAVA_SUCCESS) {
1156 goto exit;
1157 }
1158
1159 nGeneration = env->GetIntArrayElements(jGeneration, NULL);
1160 if (nGeneration == NULL) {
1161 jStatus = (jint)AUDIO_JAVA_ERROR;
1162 goto exit;
1163 }
1164 nGeneration[0] = generation1;
1165 env->ReleaseIntArrayElements(jGeneration, nGeneration, 0);
1166
1167 for (size_t i = 0; i < numPorts; i++) {
1168 jobject jAudioPort;
1169 jStatus = convertAudioPortFromNative(env, &jAudioPort, &nPorts[i]);
1170 if (jStatus != AUDIO_JAVA_SUCCESS) {
1171 goto exit;
1172 }
1173 env->CallBooleanMethod(jPorts, gArrayListMethods.add, jAudioPort);
1174 }
1175
1176exit:
1177 free(nPorts);
1178 return jStatus;
1179}
1180
1181static int
1182android_media_AudioSystem_createAudioPatch(JNIEnv *env, jobject clazz,
1183 jobjectArray jPatches, jobjectArray jSources, jobjectArray jSinks)
1184{
1185 status_t status;
1186 jint jStatus;
1187
1188 ALOGV("createAudioPatch");
1189 if (jPatches == NULL || jSources == NULL || jSinks == NULL) {
1190 return (jint)AUDIO_JAVA_BAD_VALUE;
1191 }
1192
1193 if (env->GetArrayLength(jPatches) != 1) {
1194 return (jint)AUDIO_JAVA_BAD_VALUE;
1195 }
1196 jint numSources = env->GetArrayLength(jSources);
1197 if (numSources == 0 || numSources > AUDIO_PATCH_PORTS_MAX) {
1198 return (jint)AUDIO_JAVA_BAD_VALUE;
1199 }
1200
1201 jint numSinks = env->GetArrayLength(jSinks);
1202 if (numSinks == 0 || numSinks > AUDIO_PATCH_PORTS_MAX) {
1203 return (jint)AUDIO_JAVA_BAD_VALUE;
1204 }
1205
1206 audio_patch_handle_t handle = (audio_patch_handle_t)0;
1207 jobject jPatch = env->GetObjectArrayElement(jPatches, 0);
1208 jobject jPatchHandle = NULL;
1209 if (jPatch != NULL) {
1210 if (!env->IsInstanceOf(jPatch, gAudioPatchClass)) {
1211 return (jint)AUDIO_JAVA_BAD_VALUE;
1212 }
1213 jPatchHandle = env->GetObjectField(jPatch, gAudioPatchFields.mHandle);
1214 handle = (audio_patch_handle_t)env->GetIntField(jPatchHandle, gAudioHandleFields.mId);
1215 }
1216
1217 struct audio_patch nPatch;
1218
1219 nPatch.id = handle;
1220 nPatch.num_sources = 0;
1221 nPatch.num_sinks = 0;
1222 jobject jSource = NULL;
1223 jobject jSink = NULL;
1224
1225 for (jint i = 0; i < numSources; i++) {
1226 jSource = env->GetObjectArrayElement(jSources, i);
1227 if (!env->IsInstanceOf(jSource, gAudioPortConfigClass)) {
1228 jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
1229 goto exit;
1230 }
Eric Laurent6368a7d2014-11-19 12:18:32 -08001231 jStatus = convertAudioPortConfigToNative(env, &nPatch.sources[i], jSource, false);
Eric Laurentb69681c2014-05-19 19:02:51 -07001232 env->DeleteLocalRef(jSource);
1233 jSource = NULL;
1234 if (jStatus != AUDIO_JAVA_SUCCESS) {
1235 goto exit;
1236 }
1237 nPatch.num_sources++;
1238 }
1239
1240 for (jint i = 0; i < numSinks; i++) {
1241 jSink = env->GetObjectArrayElement(jSinks, i);
1242 if (!env->IsInstanceOf(jSink, gAudioPortConfigClass)) {
1243 jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
1244 goto exit;
1245 }
Eric Laurent6368a7d2014-11-19 12:18:32 -08001246 jStatus = convertAudioPortConfigToNative(env, &nPatch.sinks[i], jSink, false);
Eric Laurentb69681c2014-05-19 19:02:51 -07001247 env->DeleteLocalRef(jSink);
1248 jSink = NULL;
1249 if (jStatus != AUDIO_JAVA_SUCCESS) {
1250 goto exit;
1251 }
1252 nPatch.num_sinks++;
1253 }
1254
1255 ALOGV("AudioSystem::createAudioPatch");
1256 status = AudioSystem::createAudioPatch(&nPatch, &handle);
1257 ALOGV("AudioSystem::createAudioPatch() returned %d hande %d", status, handle);
1258
1259 jStatus = nativeToJavaStatus(status);
1260 if (jStatus != AUDIO_JAVA_SUCCESS) {
1261 goto exit;
1262 }
1263
1264 if (jPatchHandle == NULL) {
1265 jPatchHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
1266 handle);
1267 if (jPatchHandle == NULL) {
1268 jStatus = (jint)AUDIO_JAVA_ERROR;
1269 goto exit;
1270 }
1271 jPatch = env->NewObject(gAudioPatchClass, gAudioPatchCstor, jPatchHandle, jSources, jSinks);
1272 if (jPatch == NULL) {
1273 jStatus = (jint)AUDIO_JAVA_ERROR;
1274 goto exit;
1275 }
1276 env->SetObjectArrayElement(jPatches, 0, jPatch);
1277 } else {
1278 env->SetIntField(jPatchHandle, gAudioHandleFields.mId, handle);
1279 }
1280
1281exit:
1282 if (jPatchHandle != NULL) {
1283 env->DeleteLocalRef(jPatchHandle);
1284 }
1285 if (jPatch != NULL) {
1286 env->DeleteLocalRef(jPatch);
1287 }
1288 if (jSource != NULL) {
1289 env->DeleteLocalRef(jSource);
1290 }
1291 if (jSink != NULL) {
1292 env->DeleteLocalRef(jSink);
1293 }
1294 return jStatus;
1295}
1296
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001297static jint
Eric Laurentb69681c2014-05-19 19:02:51 -07001298android_media_AudioSystem_releaseAudioPatch(JNIEnv *env, jobject clazz,
1299 jobject jPatch)
1300{
1301 ALOGV("releaseAudioPatch");
1302 if (jPatch == NULL) {
1303 return (jint)AUDIO_JAVA_BAD_VALUE;
1304 }
1305
1306 audio_patch_handle_t handle = (audio_patch_handle_t)0;
1307 jobject jPatchHandle = NULL;
1308 if (!env->IsInstanceOf(jPatch, gAudioPatchClass)) {
1309 return (jint)AUDIO_JAVA_BAD_VALUE;
1310 }
1311 jPatchHandle = env->GetObjectField(jPatch, gAudioPatchFields.mHandle);
1312 handle = (audio_patch_handle_t)env->GetIntField(jPatchHandle, gAudioHandleFields.mId);
1313 env->DeleteLocalRef(jPatchHandle);
1314
1315 ALOGV("AudioSystem::releaseAudioPatch");
1316 status_t status = AudioSystem::releaseAudioPatch(handle);
1317 ALOGV("AudioSystem::releaseAudioPatch() returned %d", status);
1318 jint jStatus = nativeToJavaStatus(status);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001319 return jStatus;
Eric Laurentb69681c2014-05-19 19:02:51 -07001320}
1321
1322static jint
1323android_media_AudioSystem_listAudioPatches(JNIEnv *env, jobject clazz,
1324 jobject jPatches, jintArray jGeneration)
1325{
1326 ALOGV("listAudioPatches");
1327 if (jPatches == NULL) {
1328 ALOGE("listAudioPatches NULL AudioPatch ArrayList");
1329 return (jint)AUDIO_JAVA_BAD_VALUE;
1330 }
1331 if (!env->IsInstanceOf(jPatches, gArrayListClass)) {
1332 ALOGE("listAudioPatches not an arraylist");
1333 return (jint)AUDIO_JAVA_BAD_VALUE;
1334 }
1335
1336 if (jGeneration == NULL || env->GetArrayLength(jGeneration) != 1) {
1337 return (jint)AUDIO_JAVA_BAD_VALUE;
1338 }
1339
1340 status_t status;
1341 unsigned int generation1;
1342 unsigned int generation;
1343 unsigned int numPatches;
1344 jint *nGeneration;
1345 struct audio_patch *nPatches = NULL;
1346 jobjectArray jSources = NULL;
1347 jobject jSource = NULL;
1348 jobjectArray jSinks = NULL;
1349 jobject jSink = NULL;
1350 jobject jPatch = NULL;
1351 int attempts = MAX_PORT_GENERATION_SYNC_ATTEMPTS;
1352
1353 // get the patch count and all the patches until they both return the same generation
1354 do {
1355 if (attempts-- < 0) {
1356 status = TIMED_OUT;
1357 break;
1358 }
1359
1360 numPatches = 0;
1361 status = AudioSystem::listAudioPatches(&numPatches,
1362 NULL,
1363 &generation1);
1364 if (status != NO_ERROR || numPatches == 0) {
1365 ALOGE_IF(status != NO_ERROR, "listAudioPatches AudioSystem::listAudioPatches error %d",
1366 status);
1367 break;
1368 }
1369 nPatches = (struct audio_patch *)realloc(nPatches, numPatches * sizeof(struct audio_patch));
1370
1371 status = AudioSystem::listAudioPatches(&numPatches,
1372 nPatches,
1373 &generation);
1374 ALOGV("listAudioPatches AudioSystem::listAudioPatches numPatches %d generation %d generation1 %d",
1375 numPatches, generation, generation1);
1376
1377 } while (generation1 != generation && status == NO_ERROR);
1378
1379 jint jStatus = nativeToJavaStatus(status);
1380 if (jStatus != AUDIO_JAVA_SUCCESS) {
1381 goto exit;
1382 }
1383
1384 nGeneration = env->GetIntArrayElements(jGeneration, NULL);
1385 if (nGeneration == NULL) {
1386 jStatus = AUDIO_JAVA_ERROR;
1387 goto exit;
1388 }
1389 nGeneration[0] = generation1;
1390 env->ReleaseIntArrayElements(jGeneration, nGeneration, 0);
1391
1392 for (size_t i = 0; i < numPatches; i++) {
1393 jobject patchHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
1394 nPatches[i].id);
1395 if (patchHandle == NULL) {
1396 jStatus = AUDIO_JAVA_ERROR;
1397 goto exit;
1398 }
Dan Albert46d84442014-11-18 16:07:51 -08001399 ALOGV("listAudioPatches patch %zu num_sources %d num_sinks %d",
Eric Laurentb69681c2014-05-19 19:02:51 -07001400 i, nPatches[i].num_sources, nPatches[i].num_sinks);
1401
1402 env->SetIntField(patchHandle, gAudioHandleFields.mId, nPatches[i].id);
1403
1404 // load sources
1405 jSources = env->NewObjectArray(nPatches[i].num_sources,
1406 gAudioPortConfigClass, NULL);
1407 if (jSources == NULL) {
1408 jStatus = AUDIO_JAVA_ERROR;
1409 goto exit;
1410 }
1411
1412 for (size_t j = 0; j < nPatches[i].num_sources; j++) {
1413 jStatus = convertAudioPortConfigFromNative(env,
1414 NULL,
1415 &jSource,
1416 &nPatches[i].sources[j]);
1417 if (jStatus != AUDIO_JAVA_SUCCESS) {
1418 goto exit;
1419 }
1420 env->SetObjectArrayElement(jSources, j, jSource);
1421 env->DeleteLocalRef(jSource);
1422 jSource = NULL;
Dan Albert46d84442014-11-18 16:07:51 -08001423 ALOGV("listAudioPatches patch %zu source %zu is a %s handle %d",
Eric Laurentb69681c2014-05-19 19:02:51 -07001424 i, j,
1425 nPatches[i].sources[j].type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix",
1426 nPatches[i].sources[j].id);
1427 }
1428 // load sinks
1429 jSinks = env->NewObjectArray(nPatches[i].num_sinks,
1430 gAudioPortConfigClass, NULL);
1431 if (jSinks == NULL) {
1432 jStatus = AUDIO_JAVA_ERROR;
1433 goto exit;
1434 }
1435
1436 for (size_t j = 0; j < nPatches[i].num_sinks; j++) {
1437 jStatus = convertAudioPortConfigFromNative(env,
1438 NULL,
1439 &jSink,
1440 &nPatches[i].sinks[j]);
1441
1442 if (jStatus != AUDIO_JAVA_SUCCESS) {
1443 goto exit;
1444 }
1445 env->SetObjectArrayElement(jSinks, j, jSink);
1446 env->DeleteLocalRef(jSink);
1447 jSink = NULL;
Dan Albert46d84442014-11-18 16:07:51 -08001448 ALOGV("listAudioPatches patch %zu sink %zu is a %s handle %d",
Eric Laurentb69681c2014-05-19 19:02:51 -07001449 i, j,
1450 nPatches[i].sinks[j].type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix",
1451 nPatches[i].sinks[j].id);
1452 }
1453
1454 jPatch = env->NewObject(gAudioPatchClass, gAudioPatchCstor,
1455 patchHandle, jSources, jSinks);
1456 env->DeleteLocalRef(jSources);
1457 jSources = NULL;
1458 env->DeleteLocalRef(jSinks);
1459 jSinks = NULL;
1460 if (jPatch == NULL) {
1461 jStatus = AUDIO_JAVA_ERROR;
1462 goto exit;
1463 }
1464 env->CallBooleanMethod(jPatches, gArrayListMethods.add, jPatch);
1465 env->DeleteLocalRef(jPatch);
1466 jPatch = NULL;
1467 }
1468
1469exit:
1470 if (jSources != NULL) {
1471 env->DeleteLocalRef(jSources);
1472 }
1473 if (jSource != NULL) {
1474 env->DeleteLocalRef(jSource);
1475 }
1476 if (jSinks != NULL) {
1477 env->DeleteLocalRef(jSinks);
1478 }
1479 if (jSink != NULL) {
1480 env->DeleteLocalRef(jSink);
1481 }
1482 if (jPatch != NULL) {
1483 env->DeleteLocalRef(jPatch);
1484 }
1485 free(nPatches);
1486 return jStatus;
1487}
1488
Eric Laurent3a241992014-05-19 19:33:26 -07001489static jint
1490android_media_AudioSystem_setAudioPortConfig(JNIEnv *env, jobject clazz,
1491 jobject jAudioPortConfig)
1492{
1493 ALOGV("setAudioPortConfig");
1494 if (jAudioPortConfig == NULL) {
1495 return AUDIO_JAVA_BAD_VALUE;
1496 }
1497 if (!env->IsInstanceOf(jAudioPortConfig, gAudioPortConfigClass)) {
1498 return AUDIO_JAVA_BAD_VALUE;
1499 }
1500 struct audio_port_config nAudioPortConfig;
Eric Laurent6368a7d2014-11-19 12:18:32 -08001501 jint jStatus = convertAudioPortConfigToNative(env, &nAudioPortConfig, jAudioPortConfig, true);
Eric Laurent3a241992014-05-19 19:33:26 -07001502 if (jStatus != AUDIO_JAVA_SUCCESS) {
1503 return jStatus;
1504 }
1505 status_t status = AudioSystem::setAudioPortConfig(&nAudioPortConfig);
1506 ALOGV("AudioSystem::setAudioPortConfig() returned %d", status);
1507 jStatus = nativeToJavaStatus(status);
1508 return jStatus;
1509}
1510
Eric Laurent700e7342014-05-02 18:33:15 -07001511static void
1512android_media_AudioSystem_eventHandlerSetup(JNIEnv *env, jobject thiz, jobject weak_this)
1513{
1514 ALOGV("eventHandlerSetup");
1515
1516 sp<JNIAudioPortCallback> callback = new JNIAudioPortCallback(env, thiz, weak_this);
1517
Eric Laurent2615afb2015-03-25 14:51:08 -07001518 if (AudioSystem::addAudioPortCallback(callback) == NO_ERROR) {
1519 setJniCallback(env, thiz, callback);
1520 }
Eric Laurent700e7342014-05-02 18:33:15 -07001521}
1522
1523static void
1524android_media_AudioSystem_eventHandlerFinalize(JNIEnv *env, jobject thiz)
1525{
1526 ALOGV("eventHandlerFinalize");
1527
Eric Laurent2615afb2015-03-25 14:51:08 -07001528 sp<JNIAudioPortCallback> callback = setJniCallback(env, thiz, 0);
Eric Laurent700e7342014-05-02 18:33:15 -07001529
Eric Laurent2615afb2015-03-25 14:51:08 -07001530 if (callback != 0) {
1531 AudioSystem::removeAudioPortCallback(callback);
1532 }
Eric Laurent700e7342014-05-02 18:33:15 -07001533}
1534
Eric Laurentb634e1b2014-08-01 14:44:46 -07001535static jint
1536android_media_AudioSystem_getAudioHwSyncForSession(JNIEnv *env, jobject thiz, jint sessionId)
1537{
1538 return (jint)AudioSystem::getAudioHwSyncForSession((audio_session_t)sessionId);
1539}
1540
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001541static void
1542android_media_AudioSystem_registerDynPolicyCallback(JNIEnv *env, jobject thiz)
1543{
1544 AudioSystem::setDynPolicyCallback(android_media_AudioSystem_dyn_policy_callback);
1545}
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001546
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08001547static void
1548android_media_AudioSystem_registerRecordingCallback(JNIEnv *env, jobject thiz)
1549{
1550 AudioSystem::setRecordConfigCallback(android_media_AudioSystem_recording_callback);
1551}
1552
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001553
1554static jint convertAudioMixToNative(JNIEnv *env,
1555 AudioMix *nAudioMix,
1556 const jobject jAudioMix)
1557{
1558 nAudioMix->mMixType = env->GetIntField(jAudioMix, gAudioMixFields.mMixType);
1559 nAudioMix->mRouteFlags = env->GetIntField(jAudioMix, gAudioMixFields.mRouteFlags);
1560
1561 jstring jRegistrationId = (jstring)env->GetObjectField(jAudioMix,
1562 gAudioMixFields.mRegistrationId);
1563 const char *nRegistrationId = env->GetStringUTFChars(jRegistrationId, NULL);
1564 nAudioMix->mRegistrationId = String8(nRegistrationId);
1565 env->ReleaseStringUTFChars(jRegistrationId, nRegistrationId);
1566 env->DeleteLocalRef(jRegistrationId);
1567
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001568 nAudioMix->mCbFlags = env->GetIntField(jAudioMix, gAudioMixFields.mCallbackFlags);
1569
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001570 jobject jFormat = env->GetObjectField(jAudioMix, gAudioMixFields.mFormat);
1571 nAudioMix->mFormat.sample_rate = env->GetIntField(jFormat,
1572 gAudioFormatFields.mSampleRate);
1573 nAudioMix->mFormat.channel_mask = outChannelMaskToNative(env->GetIntField(jFormat,
1574 gAudioFormatFields.mChannelMask));
1575 nAudioMix->mFormat.format = audioFormatToNative(env->GetIntField(jFormat,
1576 gAudioFormatFields.mEncoding));
1577 env->DeleteLocalRef(jFormat);
1578
1579 jobject jRule = env->GetObjectField(jAudioMix, gAudioMixFields.mRule);
1580 jobject jRuleCriteria = env->GetObjectField(jRule, gAudioMixingRuleFields.mCriteria);
1581 env->DeleteLocalRef(jRule);
1582 jobjectArray jCriteria = (jobjectArray)env->CallObjectMethod(jRuleCriteria,
1583 gArrayListMethods.toArray);
1584 env->DeleteLocalRef(jRuleCriteria);
1585
1586 jint numCriteria = env->GetArrayLength(jCriteria);
1587 if (numCriteria > MAX_CRITERIA_PER_MIX) {
1588 numCriteria = MAX_CRITERIA_PER_MIX;
1589 }
1590
1591 for (jint i = 0; i < numCriteria; i++) {
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -08001592 AudioMixMatchCriterion nCriterion;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001593
1594 jobject jCriterion = env->GetObjectArrayElement(jCriteria, i);
1595
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -08001596 nCriterion.mRule = env->GetIntField(jCriterion, gAudioMixMatchCriterionFields.mRule);
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001597
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -08001598 const uint32_t match_rule = nCriterion.mRule & ~RULE_EXCLUSION_MASK;
1599 switch (match_rule) {
1600 case RULE_MATCH_UID:
1601 nCriterion.mValue.mUid = env->GetIntField(jCriterion,
1602 gAudioMixMatchCriterionFields.mIntProp);
1603 break;
1604 case RULE_MATCH_ATTRIBUTE_USAGE:
1605 case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET: {
1606 jobject jAttributes = env->GetObjectField(jCriterion, gAudioMixMatchCriterionFields.mAttr);
1607 if (match_rule == RULE_MATCH_ATTRIBUTE_USAGE) {
1608 nCriterion.mValue.mUsage = (audio_usage_t)env->GetIntField(jAttributes,
1609 gAudioAttributesFields.mUsage);
1610 } else {
1611 nCriterion.mValue.mSource = (audio_source_t)env->GetIntField(jAttributes,
1612 gAudioAttributesFields.mSource);
1613 }
1614 env->DeleteLocalRef(jAttributes);
1615 }
1616 break;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001617 }
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001618
1619 nAudioMix->mCriteria.add(nCriterion);
1620 env->DeleteLocalRef(jCriterion);
1621 }
1622
1623 env->DeleteLocalRef(jCriteria);
1624
1625 return (jint)AUDIO_JAVA_SUCCESS;
1626}
1627
1628static jint
1629android_media_AudioSystem_registerPolicyMixes(JNIEnv *env, jobject clazz,
1630 jobject jMixesList, jboolean registration)
1631{
1632 ALOGV("registerPolicyMixes");
1633
1634 if (jMixesList == NULL) {
1635 return (jint)AUDIO_JAVA_BAD_VALUE;
1636 }
1637 if (!env->IsInstanceOf(jMixesList, gArrayListClass)) {
1638 return (jint)AUDIO_JAVA_BAD_VALUE;
1639 }
1640 jobjectArray jMixes = (jobjectArray)env->CallObjectMethod(jMixesList,
1641 gArrayListMethods.toArray);
1642 jint numMixes = env->GetArrayLength(jMixes);
1643 if (numMixes > MAX_MIXES_PER_POLICY) {
1644 numMixes = MAX_MIXES_PER_POLICY;
1645 }
1646
1647 status_t status;
1648 jint jStatus;
1649 jobject jAudioMix = NULL;
1650 Vector <AudioMix> mixes;
1651 for (jint i = 0; i < numMixes; i++) {
1652 jAudioMix = env->GetObjectArrayElement(jMixes, i);
1653 if (!env->IsInstanceOf(jAudioMix, gAudioMixClass)) {
1654 jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
1655 goto exit;
1656 }
1657 AudioMix mix;
1658 jStatus = convertAudioMixToNative(env, &mix, jAudioMix);
1659 env->DeleteLocalRef(jAudioMix);
1660 jAudioMix = NULL;
1661 if (jStatus != AUDIO_JAVA_SUCCESS) {
1662 goto exit;
1663 }
1664 mixes.add(mix);
1665 }
1666
1667 ALOGV("AudioSystem::registerPolicyMixes numMixes %d registration %d", numMixes, registration);
1668 status = AudioSystem::registerPolicyMixes(mixes, registration);
1669 ALOGV("AudioSystem::registerPolicyMixes() returned %d", status);
1670
1671 jStatus = nativeToJavaStatus(status);
1672 if (jStatus != AUDIO_JAVA_SUCCESS) {
1673 goto exit;
1674 }
1675
1676exit:
1677 if (jAudioMix != NULL) {
1678 env->DeleteLocalRef(jAudioMix);
1679 }
1680 return jStatus;
1681}
1682
Eric Laurent0867bed2015-05-20 14:49:08 -07001683static jint
1684android_media_AudioSystem_systemReady(JNIEnv *env, jobject thiz)
1685{
1686 return nativeToJavaStatus(AudioSystem::systemReady());
1687}
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001688
1689
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001690// ----------------------------------------------------------------------------
1691
Daniel Micay76f6a862015-09-19 17:31:01 -04001692static const JNINativeMethod gMethods[] = {
Eric Laurenta553c252009-07-17 12:17:14 -07001693 {"setParameters", "(Ljava/lang/String;)I", (void *)android_media_AudioSystem_setParameters},
1694 {"getParameters", "(Ljava/lang/String;)Ljava/lang/String;", (void *)android_media_AudioSystem_getParameters},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001695 {"muteMicrophone", "(Z)I", (void *)android_media_AudioSystem_muteMicrophone},
1696 {"isMicrophoneMuted", "()Z", (void *)android_media_AudioSystem_isMicrophoneMuted},
Jean-Michel Trivid6770542012-10-10 12:03:41 -07001697 {"isStreamActive", "(II)Z", (void *)android_media_AudioSystem_isStreamActive},
Jean-Michel Trivi679d5042013-02-04 16:24:09 -08001698 {"isStreamActiveRemotely","(II)Z", (void *)android_media_AudioSystem_isStreamActiveRemotely},
Jean-Michel Trivid6770542012-10-10 12:03:41 -07001699 {"isSourceActive", "(I)Z", (void *)android_media_AudioSystem_isSourceActive},
Jean-Michel Trivi8a21f5d2014-06-05 15:03:52 -07001700 {"newAudioSessionId", "()I", (void *)android_media_AudioSystem_newAudioSessionId},
Paul McLean10804eb2015-01-28 11:16:35 -08001701 {"setDeviceConnectionState", "(IILjava/lang/String;Ljava/lang/String;)I", (void *)android_media_AudioSystem_setDeviceConnectionState},
Eric Laurenta553c252009-07-17 12:17:14 -07001702 {"getDeviceConnectionState", "(ILjava/lang/String;)I", (void *)android_media_AudioSystem_getDeviceConnectionState},
1703 {"setPhoneState", "(I)I", (void *)android_media_AudioSystem_setPhoneState},
Eric Laurenta553c252009-07-17 12:17:14 -07001704 {"setForceUse", "(II)I", (void *)android_media_AudioSystem_setForceUse},
1705 {"getForceUse", "(I)I", (void *)android_media_AudioSystem_getForceUse},
1706 {"initStreamVolume", "(III)I", (void *)android_media_AudioSystem_initStreamVolume},
Eric Laurent9bc8358d2011-11-18 16:43:31 -08001707 {"setStreamVolumeIndex","(III)I", (void *)android_media_AudioSystem_setStreamVolumeIndex},
1708 {"getStreamVolumeIndex","(II)I", (void *)android_media_AudioSystem_getStreamVolumeIndex},
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -04001709 {"setMasterVolume", "(F)I", (void *)android_media_AudioSystem_setMasterVolume},
1710 {"getMasterVolume", "()F", (void *)android_media_AudioSystem_getMasterVolume},
1711 {"setMasterMute", "(Z)I", (void *)android_media_AudioSystem_setMasterMute},
1712 {"getMasterMute", "()Z", (void *)android_media_AudioSystem_getMasterMute},
Andy Hungf04b84d2015-12-18 17:33:27 -08001713 {"setMasterMono", "(Z)I", (void *)android_media_AudioSystem_setMasterMono},
1714 {"getMasterMono", "()Z", (void *)android_media_AudioSystem_getMasterMono},
Glenn Kasten8b4b97a2011-02-04 13:54:26 -08001715 {"getDevicesForStream", "(I)I", (void *)android_media_AudioSystem_getDevicesForStream},
Glenn Kastenc6c43652012-09-24 17:32:30 -07001716 {"getPrimaryOutputSamplingRate", "()I", (void *)android_media_AudioSystem_getPrimaryOutputSamplingRate},
1717 {"getPrimaryOutputFrameCount", "()I", (void *)android_media_AudioSystem_getPrimaryOutputFrameCount},
Oliver Woodman61dcdf32013-06-26 12:43:36 +01001718 {"getOutputLatency", "(I)I", (void *)android_media_AudioSystem_getOutputLatency},
Glenn Kastenfd116ad2013-07-12 17:10:39 -07001719 {"setLowRamDevice", "(Z)I", (void *)android_media_AudioSystem_setLowRamDevice},
Eric Laurentdfb881f2013-07-18 14:41:39 -07001720 {"checkAudioFlinger", "()I", (void *)android_media_AudioSystem_checkAudioFlinger},
Eric Laurentb69681c2014-05-19 19:02:51 -07001721 {"listAudioPorts", "(Ljava/util/ArrayList;[I)I",
1722 (void *)android_media_AudioSystem_listAudioPorts},
1723 {"createAudioPatch", "([Landroid/media/AudioPatch;[Landroid/media/AudioPortConfig;[Landroid/media/AudioPortConfig;)I",
1724 (void *)android_media_AudioSystem_createAudioPatch},
1725 {"releaseAudioPatch", "(Landroid/media/AudioPatch;)I",
1726 (void *)android_media_AudioSystem_releaseAudioPatch},
1727 {"listAudioPatches", "(Ljava/util/ArrayList;[I)I",
1728 (void *)android_media_AudioSystem_listAudioPatches},
Eric Laurent3a241992014-05-19 19:33:26 -07001729 {"setAudioPortConfig", "(Landroid/media/AudioPortConfig;)I",
1730 (void *)android_media_AudioSystem_setAudioPortConfig},
Eric Laurentb634e1b2014-08-01 14:44:46 -07001731 {"getAudioHwSyncForSession", "(I)I",
1732 (void *)android_media_AudioSystem_getAudioHwSyncForSession},
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001733 {"registerPolicyMixes", "(Ljava/util/ArrayList;Z)I",
1734 (void *)android_media_AudioSystem_registerPolicyMixes},
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001735 {"native_register_dynamic_policy_callback", "()V",
1736 (void *)android_media_AudioSystem_registerDynPolicyCallback},
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08001737 {"native_register_recording_callback", "()V",
1738 (void *)android_media_AudioSystem_registerRecordingCallback},
Eric Laurent0867bed2015-05-20 14:49:08 -07001739 {"systemReady", "()I", (void *)android_media_AudioSystem_systemReady},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001740};
1741
Eric Laurentb69681c2014-05-19 19:02:51 -07001742
Daniel Micay76f6a862015-09-19 17:31:01 -04001743static const JNINativeMethod gEventHandlerMethods[] = {
Eric Laurent700e7342014-05-02 18:33:15 -07001744 {"native_setup",
1745 "(Ljava/lang/Object;)V",
1746 (void *)android_media_AudioSystem_eventHandlerSetup},
1747 {"native_finalize",
1748 "()V",
1749 (void *)android_media_AudioSystem_eventHandlerFinalize},
1750};
1751
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001752int register_android_media_AudioSystem(JNIEnv *env)
1753{
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001754 jclass arrayListClass = FindClassOrDie(env, "java/util/ArrayList");
1755 gArrayListClass = MakeGlobalRefOrDie(env, arrayListClass);
1756 gArrayListMethods.add = GetMethodIDOrDie(env, arrayListClass, "add", "(Ljava/lang/Object;)Z");
Eric Laurent09378972014-12-10 10:42:08 -08001757 gArrayListMethods.toArray = GetMethodIDOrDie(env, arrayListClass, "toArray", "()[Ljava/lang/Object;");
Eric Laurentb69681c2014-05-19 19:02:51 -07001758
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001759 jclass audioHandleClass = FindClassOrDie(env, "android/media/AudioHandle");
1760 gAudioHandleClass = MakeGlobalRefOrDie(env, audioHandleClass);
1761 gAudioHandleCstor = GetMethodIDOrDie(env, audioHandleClass, "<init>", "(I)V");
1762 gAudioHandleFields.mId = GetFieldIDOrDie(env, audioHandleClass, "mId", "I");
Eric Laurentb69681c2014-05-19 19:02:51 -07001763
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001764 jclass audioPortClass = FindClassOrDie(env, "android/media/AudioPort");
1765 gAudioPortClass = MakeGlobalRefOrDie(env, audioPortClass);
1766 gAudioPortCstor = GetMethodIDOrDie(env, audioPortClass, "<init>",
Paul McLeanf29e5f32015-06-15 10:19:22 -07001767 "(Landroid/media/AudioHandle;ILjava/lang/String;[I[I[I[I[Landroid/media/AudioGain;)V");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001768 gAudioPortFields.mHandle = GetFieldIDOrDie(env, audioPortClass, "mHandle",
Eric Laurentb69681c2014-05-19 19:02:51 -07001769 "Landroid/media/AudioHandle;");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001770 gAudioPortFields.mRole = GetFieldIDOrDie(env, audioPortClass, "mRole", "I");
1771 gAudioPortFields.mGains = GetFieldIDOrDie(env, audioPortClass, "mGains",
Eric Laurentb69681c2014-05-19 19:02:51 -07001772 "[Landroid/media/AudioGain;");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001773 gAudioPortFields.mActiveConfig = GetFieldIDOrDie(env, audioPortClass, "mActiveConfig",
1774 "Landroid/media/AudioPortConfig;");
Eric Laurentb69681c2014-05-19 19:02:51 -07001775
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001776 jclass audioPortConfigClass = FindClassOrDie(env, "android/media/AudioPortConfig");
1777 gAudioPortConfigClass = MakeGlobalRefOrDie(env, audioPortConfigClass);
1778 gAudioPortConfigCstor = GetMethodIDOrDie(env, audioPortConfigClass, "<init>",
1779 "(Landroid/media/AudioPort;IIILandroid/media/AudioGainConfig;)V");
1780 gAudioPortConfigFields.mPort = GetFieldIDOrDie(env, audioPortConfigClass, "mPort",
Eric Laurentb69681c2014-05-19 19:02:51 -07001781 "Landroid/media/AudioPort;");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001782 gAudioPortConfigFields.mSamplingRate = GetFieldIDOrDie(env, audioPortConfigClass,
Eric Laurentb69681c2014-05-19 19:02:51 -07001783 "mSamplingRate", "I");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001784 gAudioPortConfigFields.mChannelMask = GetFieldIDOrDie(env, audioPortConfigClass,
Eric Laurentb69681c2014-05-19 19:02:51 -07001785 "mChannelMask", "I");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001786 gAudioPortConfigFields.mFormat = GetFieldIDOrDie(env, audioPortConfigClass, "mFormat", "I");
1787 gAudioPortConfigFields.mGain = GetFieldIDOrDie(env, audioPortConfigClass, "mGain",
Eric Laurentb69681c2014-05-19 19:02:51 -07001788 "Landroid/media/AudioGainConfig;");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001789 gAudioPortConfigFields.mConfigMask = GetFieldIDOrDie(env, audioPortConfigClass, "mConfigMask",
1790 "I");
Eric Laurentb69681c2014-05-19 19:02:51 -07001791
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001792 jclass audioDevicePortConfigClass = FindClassOrDie(env, "android/media/AudioDevicePortConfig");
1793 gAudioDevicePortConfigClass = MakeGlobalRefOrDie(env, audioDevicePortConfigClass);
1794 gAudioDevicePortConfigCstor = GetMethodIDOrDie(env, audioDevicePortConfigClass, "<init>",
1795 "(Landroid/media/AudioDevicePort;IIILandroid/media/AudioGainConfig;)V");
Eric Laurentb69681c2014-05-19 19:02:51 -07001796
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001797 jclass audioMixPortConfigClass = FindClassOrDie(env, "android/media/AudioMixPortConfig");
1798 gAudioMixPortConfigClass = MakeGlobalRefOrDie(env, audioMixPortConfigClass);
1799 gAudioMixPortConfigCstor = GetMethodIDOrDie(env, audioMixPortConfigClass, "<init>",
1800 "(Landroid/media/AudioMixPort;IIILandroid/media/AudioGainConfig;)V");
Eric Laurentb69681c2014-05-19 19:02:51 -07001801
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001802 jclass audioDevicePortClass = FindClassOrDie(env, "android/media/AudioDevicePort");
1803 gAudioDevicePortClass = MakeGlobalRefOrDie(env, audioDevicePortClass);
1804 gAudioDevicePortCstor = GetMethodIDOrDie(env, audioDevicePortClass, "<init>",
Paul McLeanf29e5f32015-06-15 10:19:22 -07001805 "(Landroid/media/AudioHandle;Ljava/lang/String;[I[I[I[I[Landroid/media/AudioGain;ILjava/lang/String;)V");
Eric Laurentb69681c2014-05-19 19:02:51 -07001806
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001807 jclass audioMixPortClass = FindClassOrDie(env, "android/media/AudioMixPort");
1808 gAudioMixPortClass = MakeGlobalRefOrDie(env, audioMixPortClass);
1809 gAudioMixPortCstor = GetMethodIDOrDie(env, audioMixPortClass, "<init>",
Paul McLeanf29e5f32015-06-15 10:19:22 -07001810 "(Landroid/media/AudioHandle;IILjava/lang/String;[I[I[I[I[Landroid/media/AudioGain;)V");
Eric Laurentb69681c2014-05-19 19:02:51 -07001811
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001812 jclass audioGainClass = FindClassOrDie(env, "android/media/AudioGain");
1813 gAudioGainClass = MakeGlobalRefOrDie(env, audioGainClass);
1814 gAudioGainCstor = GetMethodIDOrDie(env, audioGainClass, "<init>", "(IIIIIIIII)V");
Eric Laurentb69681c2014-05-19 19:02:51 -07001815
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001816 jclass audioGainConfigClass = FindClassOrDie(env, "android/media/AudioGainConfig");
1817 gAudioGainConfigClass = MakeGlobalRefOrDie(env, audioGainConfigClass);
1818 gAudioGainConfigCstor = GetMethodIDOrDie(env, audioGainConfigClass, "<init>",
Eric Laurentb69681c2014-05-19 19:02:51 -07001819 "(ILandroid/media/AudioGain;II[II)V");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001820 gAudioGainConfigFields.mIndex = GetFieldIDOrDie(env, gAudioGainConfigClass, "mIndex", "I");
1821 gAudioGainConfigFields.mMode = GetFieldIDOrDie(env, audioGainConfigClass, "mMode", "I");
1822 gAudioGainConfigFields.mChannelMask = GetFieldIDOrDie(env, audioGainConfigClass, "mChannelMask",
Eric Laurentb69681c2014-05-19 19:02:51 -07001823 "I");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001824 gAudioGainConfigFields.mValues = GetFieldIDOrDie(env, audioGainConfigClass, "mValues", "[I");
1825 gAudioGainConfigFields.mRampDurationMs = GetFieldIDOrDie(env, audioGainConfigClass,
Eric Laurentb69681c2014-05-19 19:02:51 -07001826 "mRampDurationMs", "I");
1827
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001828 jclass audioPatchClass = FindClassOrDie(env, "android/media/AudioPatch");
1829 gAudioPatchClass = MakeGlobalRefOrDie(env, audioPatchClass);
1830 gAudioPatchCstor = GetMethodIDOrDie(env, audioPatchClass, "<init>",
Eric Laurentb69681c2014-05-19 19:02:51 -07001831"(Landroid/media/AudioHandle;[Landroid/media/AudioPortConfig;[Landroid/media/AudioPortConfig;)V");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001832 gAudioPatchFields.mHandle = GetFieldIDOrDie(env, audioPatchClass, "mHandle",
Eric Laurentb69681c2014-05-19 19:02:51 -07001833 "Landroid/media/AudioHandle;");
1834
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001835 jclass eventHandlerClass = FindClassOrDie(env, kEventHandlerClassPathName);
Eric Laurent2615afb2015-03-25 14:51:08 -07001836 gAudioPortEventHandlerMethods.postEventFromNative = GetStaticMethodIDOrDie(
1837 env, eventHandlerClass, "postEventFromNative",
1838 "(Ljava/lang/Object;IIILjava/lang/Object;)V");
1839 gEventHandlerFields.mJniCallback = GetFieldIDOrDie(env,
1840 eventHandlerClass, "mJniCallback", "J");
Eric Laurent700e7342014-05-02 18:33:15 -07001841
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08001842 gAudioPolicyEventHandlerMethods.postDynPolicyEventFromNative =
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001843 GetStaticMethodIDOrDie(env, env->FindClass(kClassPathName),
1844 "dynamicPolicyCallbackFromNative", "(ILjava/lang/String;I)V");
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08001845 gAudioPolicyEventHandlerMethods.postRecordConfigEventFromNative =
1846 GetStaticMethodIDOrDie(env, env->FindClass(kClassPathName),
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -08001847 "recordingCallbackFromNative", "(III[I)V");
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001848
Eric Laurent09378972014-12-10 10:42:08 -08001849 jclass audioMixClass = FindClassOrDie(env, "android/media/audiopolicy/AudioMix");
1850 gAudioMixClass = MakeGlobalRefOrDie(env, audioMixClass);
1851 gAudioMixFields.mRule = GetFieldIDOrDie(env, audioMixClass, "mRule",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001852 "Landroid/media/audiopolicy/AudioMixingRule;");
Eric Laurent09378972014-12-10 10:42:08 -08001853 gAudioMixFields.mFormat = GetFieldIDOrDie(env, audioMixClass, "mFormat",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001854 "Landroid/media/AudioFormat;");
Eric Laurent09378972014-12-10 10:42:08 -08001855 gAudioMixFields.mRouteFlags = GetFieldIDOrDie(env, audioMixClass, "mRouteFlags", "I");
1856 gAudioMixFields.mRegistrationId = GetFieldIDOrDie(env, audioMixClass, "mRegistrationId",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001857 "Ljava/lang/String;");
Eric Laurent09378972014-12-10 10:42:08 -08001858 gAudioMixFields.mMixType = GetFieldIDOrDie(env, audioMixClass, "mMixType", "I");
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001859 gAudioMixFields.mCallbackFlags = GetFieldIDOrDie(env, audioMixClass, "mCallbackFlags", "I");
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001860
Eric Laurent09378972014-12-10 10:42:08 -08001861 jclass audioFormatClass = FindClassOrDie(env, "android/media/AudioFormat");
1862 gAudioFormatClass = MakeGlobalRefOrDie(env, audioFormatClass);
1863 gAudioFormatFields.mEncoding = GetFieldIDOrDie(env, audioFormatClass, "mEncoding", "I");
1864 gAudioFormatFields.mSampleRate = GetFieldIDOrDie(env, audioFormatClass, "mSampleRate", "I");
1865 gAudioFormatFields.mChannelMask = GetFieldIDOrDie(env, audioFormatClass, "mChannelMask", "I");
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001866
Eric Laurent09378972014-12-10 10:42:08 -08001867 jclass audioMixingRuleClass = FindClassOrDie(env, "android/media/audiopolicy/AudioMixingRule");
1868 gAudioMixingRuleClass = MakeGlobalRefOrDie(env, audioMixingRuleClass);
1869 gAudioMixingRuleFields.mCriteria = GetFieldIDOrDie(env, audioMixingRuleClass, "mCriteria",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001870 "Ljava/util/ArrayList;");
1871
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -08001872 jclass audioMixMatchCriterionClass =
1873 FindClassOrDie(env, "android/media/audiopolicy/AudioMixingRule$AudioMixMatchCriterion");
1874 gAudioMixMatchCriterionClass = MakeGlobalRefOrDie(env,audioMixMatchCriterionClass);
1875 gAudioMixMatchCriterionFields.mAttr = GetFieldIDOrDie(env, audioMixMatchCriterionClass, "mAttr",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001876 "Landroid/media/AudioAttributes;");
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -08001877 gAudioMixMatchCriterionFields.mIntProp = GetFieldIDOrDie(env, audioMixMatchCriterionClass, "mIntProp",
1878 "I");
1879 gAudioMixMatchCriterionFields.mRule = GetFieldIDOrDie(env, audioMixMatchCriterionClass, "mRule",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001880 "I");
1881
Eric Laurent09378972014-12-10 10:42:08 -08001882 jclass audioAttributesClass = FindClassOrDie(env, "android/media/AudioAttributes");
1883 gAudioAttributesClass = MakeGlobalRefOrDie(env, audioAttributesClass);
1884 gAudioAttributesFields.mUsage = GetFieldIDOrDie(env, audioAttributesClass, "mUsage", "I");
1885 gAudioAttributesFields.mSource = GetFieldIDOrDie(env, audioAttributesClass, "mSource", "I");
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001886
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001887 AudioSystem::setErrorCallback(android_media_AudioSystem_error_callback);
Glenn Kasten18db49a2012-03-12 16:29:55 -07001888
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001889 RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
1890 return RegisterMethodsOrDie(env, kEventHandlerClassPathName, gEventHandlerMethods,
1891 NELEM(gEventHandlerMethods));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001892}