blob: 1eb01110091963127df882ef744d0a9553cdd27b [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{
Glenn Kasten211d9052016-02-26 16:22:40 -0800323 return AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
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,
Jean-Michel Trivi8ab72802016-02-25 16:31:45 -0800392 const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig,
393 audio_patch_handle_t patchHandle)
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800394{
395 JNIEnv *env = AndroidRuntime::getJNIEnv();
396 if (env == NULL) {
397 return;
398 }
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800399 if (clientConfig == NULL || deviceConfig == NULL) {
400 ALOGE("Unexpected null client/device configurations in recording callback");
401 return;
402 }
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800403
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800404 // create an array for 2*3 integers to store the record configurations (client + device)
Jean-Michel Trivi8ab72802016-02-25 16:31:45 -0800405 // plus 1 integer for the patch handle
406 const int REC_PARAM_SIZE = 7;
407 jintArray recParamArray = env->NewIntArray(REC_PARAM_SIZE);
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800408 if (recParamArray == NULL) {
409 ALOGE("recording callback: Couldn't allocate int array for configuration data");
410 return;
411 }
Jean-Michel Trivi8ab72802016-02-25 16:31:45 -0800412 jint recParamData[REC_PARAM_SIZE];
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800413 recParamData[0] = (jint) audioFormatFromNative(clientConfig->format);
414 // FIXME this doesn't support index-based masks
415 recParamData[1] = (jint) inChannelMaskFromNative(clientConfig->channel_mask);
416 recParamData[2] = (jint) clientConfig->sample_rate;
417 recParamData[3] = (jint) audioFormatFromNative(deviceConfig->format);
418 // FIXME this doesn't support index-based masks
419 recParamData[4] = (jint) inChannelMaskFromNative(deviceConfig->channel_mask);
420 recParamData[5] = (jint) deviceConfig->sample_rate;
Jean-Michel Trivi8ab72802016-02-25 16:31:45 -0800421 recParamData[6] = (jint) patchHandle;
422 env->SetIntArrayRegion(recParamArray, 0, REC_PARAM_SIZE, recParamData);
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800423
424 // callback into java
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800425 jclass clazz = env->FindClass(kClassPathName);
426 env->CallStaticVoidMethod(clazz,
427 gAudioPolicyEventHandlerMethods.postRecordConfigEventFromNative,
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800428 event, session, source, recParamArray);
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800429 env->DeleteLocalRef(clazz);
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800430
431 env->DeleteLocalRef(recParamArray);
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700432}
433
Ashok Bhat075e9a12014-01-06 13:45:09 +0000434static jint
Paul McLean10804eb2015-01-28 11:16:35 -0800435android_media_AudioSystem_setDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jint state, jstring device_address, jstring device_name)
Eric Laurenta553c252009-07-17 12:17:14 -0700436{
437 const char *c_address = env->GetStringUTFChars(device_address, NULL);
Paul McLean10804eb2015-01-28 11:16:35 -0800438 const char *c_name = env->GetStringUTFChars(device_name, NULL);
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700439 int status = check_AudioSystem_Command(AudioSystem::setDeviceConnectionState(static_cast <audio_devices_t>(device),
440 static_cast <audio_policy_dev_state_t>(state),
Paul McLean10804eb2015-01-28 11:16:35 -0800441 c_address, c_name));
Eric Laurenta553c252009-07-17 12:17:14 -0700442 env->ReleaseStringUTFChars(device_address, c_address);
Paul McLean10804eb2015-01-28 11:16:35 -0800443 env->ReleaseStringUTFChars(device_name, c_name);
Ashok Bhat075e9a12014-01-06 13:45:09 +0000444 return (jint) status;
Eric Laurenta553c252009-07-17 12:17:14 -0700445}
446
Ashok Bhat075e9a12014-01-06 13:45:09 +0000447static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700448android_media_AudioSystem_getDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jstring device_address)
449{
450 const char *c_address = env->GetStringUTFChars(device_address, NULL);
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700451 int state = static_cast <int>(AudioSystem::getDeviceConnectionState(static_cast <audio_devices_t>(device),
Eric Laurenta553c252009-07-17 12:17:14 -0700452 c_address));
453 env->ReleaseStringUTFChars(device_address, c_address);
Ashok Bhat075e9a12014-01-06 13:45:09 +0000454 return (jint) state;
Eric Laurenta553c252009-07-17 12:17:14 -0700455}
456
Ashok Bhat075e9a12014-01-06 13:45:09 +0000457static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700458android_media_AudioSystem_setPhoneState(JNIEnv *env, jobject thiz, jint state)
459{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000460 return (jint) check_AudioSystem_Command(AudioSystem::setPhoneState((audio_mode_t) state));
Eric Laurenta553c252009-07-17 12:17:14 -0700461}
462
Ashok Bhat075e9a12014-01-06 13:45:09 +0000463static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700464android_media_AudioSystem_setForceUse(JNIEnv *env, jobject thiz, jint usage, jint config)
465{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000466 return (jint) check_AudioSystem_Command(AudioSystem::setForceUse(static_cast <audio_policy_force_use_t>(usage),
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700467 static_cast <audio_policy_forced_cfg_t>(config)));
Eric Laurenta553c252009-07-17 12:17:14 -0700468}
469
Ashok Bhat075e9a12014-01-06 13:45:09 +0000470static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700471android_media_AudioSystem_getForceUse(JNIEnv *env, jobject thiz, jint usage)
472{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000473 return static_cast <jint>(AudioSystem::getForceUse(static_cast <audio_policy_force_use_t>(usage)));
Eric Laurenta553c252009-07-17 12:17:14 -0700474}
475
Ashok Bhat075e9a12014-01-06 13:45:09 +0000476static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700477android_media_AudioSystem_initStreamVolume(JNIEnv *env, jobject thiz, jint stream, jint indexMin, jint indexMax)
478{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000479 return (jint) check_AudioSystem_Command(AudioSystem::initStreamVolume(static_cast <audio_stream_type_t>(stream),
Eric Laurenta553c252009-07-17 12:17:14 -0700480 indexMin,
481 indexMax));
482}
483
Ashok Bhat075e9a12014-01-06 13:45:09 +0000484static jint
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800485android_media_AudioSystem_setStreamVolumeIndex(JNIEnv *env,
486 jobject thiz,
487 jint stream,
488 jint index,
489 jint device)
Eric Laurenta553c252009-07-17 12:17:14 -0700490{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000491 return (jint) check_AudioSystem_Command(
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800492 AudioSystem::setStreamVolumeIndex(static_cast <audio_stream_type_t>(stream),
493 index,
494 (audio_devices_t)device));
Eric Laurenta553c252009-07-17 12:17:14 -0700495}
496
Ashok Bhat075e9a12014-01-06 13:45:09 +0000497static jint
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800498android_media_AudioSystem_getStreamVolumeIndex(JNIEnv *env,
499 jobject thiz,
500 jint stream,
501 jint device)
Eric Laurenta553c252009-07-17 12:17:14 -0700502{
503 int index;
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800504 if (AudioSystem::getStreamVolumeIndex(static_cast <audio_stream_type_t>(stream),
505 &index,
506 (audio_devices_t)device)
507 != NO_ERROR) {
Eric Laurenta553c252009-07-17 12:17:14 -0700508 index = -1;
509 }
Ashok Bhat075e9a12014-01-06 13:45:09 +0000510 return (jint) index;
Eric Laurenta553c252009-07-17 12:17:14 -0700511}
512
Ashok Bhat075e9a12014-01-06 13:45:09 +0000513static jint
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400514android_media_AudioSystem_setMasterVolume(JNIEnv *env, jobject thiz, jfloat value)
515{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000516 return (jint) check_AudioSystem_Command(AudioSystem::setMasterVolume(value));
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400517}
518
519static jfloat
520android_media_AudioSystem_getMasterVolume(JNIEnv *env, jobject thiz)
521{
522 float value;
523 if (AudioSystem::getMasterVolume(&value) != NO_ERROR) {
524 value = -1.0;
525 }
526 return value;
527}
528
Ashok Bhat075e9a12014-01-06 13:45:09 +0000529static jint
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400530android_media_AudioSystem_setMasterMute(JNIEnv *env, jobject thiz, jboolean mute)
531{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000532 return (jint) check_AudioSystem_Command(AudioSystem::setMasterMute(mute));
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400533}
534
Vladimir Markoc1bcdbb2014-10-29 20:34:15 +0000535static jboolean
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400536android_media_AudioSystem_getMasterMute(JNIEnv *env, jobject thiz)
537{
538 bool mute;
539 if (AudioSystem::getMasterMute(&mute) != NO_ERROR) {
540 mute = false;
541 }
542 return mute;
543}
544
Glenn Kasten8b4b97a2011-02-04 13:54:26 -0800545static jint
Andy Hungf04b84d2015-12-18 17:33:27 -0800546android_media_AudioSystem_setMasterMono(JNIEnv *env, jobject thiz, jboolean mono)
547{
548 return (jint) check_AudioSystem_Command(AudioSystem::setMasterMono(mono));
549}
550
551static jboolean
552android_media_AudioSystem_getMasterMono(JNIEnv *env, jobject thiz)
553{
554 bool mono;
555 if (AudioSystem::getMasterMono(&mono) != NO_ERROR) {
556 mono = false;
557 }
558 return mono;
559}
560
561static jint
Glenn Kasten8b4b97a2011-02-04 13:54:26 -0800562android_media_AudioSystem_getDevicesForStream(JNIEnv *env, jobject thiz, jint stream)
563{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700564 return (jint) AudioSystem::getDevicesForStream(static_cast <audio_stream_type_t>(stream));
Glenn Kasten8b4b97a2011-02-04 13:54:26 -0800565}
566
Glenn Kastenc6c43652012-09-24 17:32:30 -0700567static jint
568android_media_AudioSystem_getPrimaryOutputSamplingRate(JNIEnv *env, jobject clazz)
569{
570 return (jint) AudioSystem::getPrimaryOutputSamplingRate();
571}
572
573static jint
574android_media_AudioSystem_getPrimaryOutputFrameCount(JNIEnv *env, jobject clazz)
575{
576 return (jint) AudioSystem::getPrimaryOutputFrameCount();
577}
578
Oliver Woodman61dcdf32013-06-26 12:43:36 +0100579static jint
580android_media_AudioSystem_getOutputLatency(JNIEnv *env, jobject clazz, jint stream)
581{
582 uint32_t afLatency;
583 if (AudioSystem::getOutputLatency(&afLatency, static_cast <audio_stream_type_t>(stream))
584 != NO_ERROR) {
585 afLatency = -1;
586 }
587 return (jint) afLatency;
588}
589
Glenn Kastenfd116ad2013-07-12 17:10:39 -0700590static jint
591android_media_AudioSystem_setLowRamDevice(JNIEnv *env, jobject clazz, jboolean isLowRamDevice)
592{
593 return (jint) AudioSystem::setLowRamDevice((bool) isLowRamDevice);
594}
595
Ashok Bhat075e9a12014-01-06 13:45:09 +0000596static jint
Eric Laurentdfb881f2013-07-18 14:41:39 -0700597android_media_AudioSystem_checkAudioFlinger(JNIEnv *env, jobject clazz)
598{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000599 return (jint) check_AudioSystem_Command(AudioSystem::checkAudioFlinger());
Eric Laurentdfb881f2013-07-18 14:41:39 -0700600}
601
Eric Laurentb69681c2014-05-19 19:02:51 -0700602
603static bool useInChannelMask(audio_port_type_t type, audio_port_role_t role)
604{
605 return ((type == AUDIO_PORT_TYPE_DEVICE) && (role == AUDIO_PORT_ROLE_SOURCE)) ||
606 ((type == AUDIO_PORT_TYPE_MIX) && (role == AUDIO_PORT_ROLE_SINK));
607}
608
Eric Laurent3a241992014-05-19 19:33:26 -0700609static void convertAudioGainConfigToNative(JNIEnv *env,
610 struct audio_gain_config *nAudioGainConfig,
611 const jobject jAudioGainConfig,
612 bool useInMask)
613{
614 nAudioGainConfig->index = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mIndex);
615 nAudioGainConfig->mode = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mMode);
616 ALOGV("convertAudioGainConfigToNative got gain index %d", nAudioGainConfig->index);
617 jint jMask = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mChannelMask);
618 audio_channel_mask_t nMask;
619 if (useInMask) {
620 nMask = inChannelMaskToNative(jMask);
621 ALOGV("convertAudioGainConfigToNative IN mask java %x native %x", jMask, nMask);
622 } else {
623 nMask = outChannelMaskToNative(jMask);
624 ALOGV("convertAudioGainConfigToNative OUT mask java %x native %x", jMask, nMask);
625 }
626 nAudioGainConfig->channel_mask = nMask;
627 nAudioGainConfig->ramp_duration_ms = env->GetIntField(jAudioGainConfig,
628 gAudioGainConfigFields.mRampDurationMs);
629 jintArray jValues = (jintArray)env->GetObjectField(jAudioGainConfig,
630 gAudioGainConfigFields.mValues);
631 int *nValues = env->GetIntArrayElements(jValues, NULL);
632 size_t size = env->GetArrayLength(jValues);
633 memcpy(nAudioGainConfig->values, nValues, size * sizeof(int));
634 env->DeleteLocalRef(jValues);
635}
636
637
Eric Laurentb69681c2014-05-19 19:02:51 -0700638static jint convertAudioPortConfigToNative(JNIEnv *env,
639 struct audio_port_config *nAudioPortConfig,
Eric Laurent6368a7d2014-11-19 12:18:32 -0800640 const jobject jAudioPortConfig,
641 bool useConfigMask)
Eric Laurentb69681c2014-05-19 19:02:51 -0700642{
643 jobject jAudioPort = env->GetObjectField(jAudioPortConfig, gAudioPortConfigFields.mPort);
644 jobject jHandle = env->GetObjectField(jAudioPort, gAudioPortFields.mHandle);
645 nAudioPortConfig->id = env->GetIntField(jHandle, gAudioHandleFields.mId);
646 nAudioPortConfig->role = (audio_port_role_t)env->GetIntField(jAudioPort,
647 gAudioPortFields.mRole);
648 if (env->IsInstanceOf(jAudioPort, gAudioDevicePortClass)) {
649 nAudioPortConfig->type = AUDIO_PORT_TYPE_DEVICE;
650 } else if (env->IsInstanceOf(jAudioPort, gAudioMixPortClass)) {
651 nAudioPortConfig->type = AUDIO_PORT_TYPE_MIX;
652 } else {
653 env->DeleteLocalRef(jAudioPort);
654 env->DeleteLocalRef(jHandle);
655 return (jint)AUDIO_JAVA_ERROR;
656 }
657 ALOGV("convertAudioPortConfigToNative handle %d role %d type %d",
658 nAudioPortConfig->id, nAudioPortConfig->role, nAudioPortConfig->type);
659
Eric Laurent6368a7d2014-11-19 12:18:32 -0800660 unsigned int configMask = 0;
661
Eric Laurentb69681c2014-05-19 19:02:51 -0700662 nAudioPortConfig->sample_rate = env->GetIntField(jAudioPortConfig,
663 gAudioPortConfigFields.mSamplingRate);
Eric Laurent6368a7d2014-11-19 12:18:32 -0800664 if (nAudioPortConfig->sample_rate != 0) {
665 configMask |= AUDIO_PORT_CONFIG_SAMPLE_RATE;
666 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700667
668 bool useInMask = useInChannelMask(nAudioPortConfig->type, nAudioPortConfig->role);
669 audio_channel_mask_t nMask;
670 jint jMask = env->GetIntField(jAudioPortConfig,
671 gAudioPortConfigFields.mChannelMask);
672 if (useInMask) {
673 nMask = inChannelMaskToNative(jMask);
674 ALOGV("convertAudioPortConfigToNative IN mask java %x native %x", jMask, nMask);
675 } else {
676 nMask = outChannelMaskToNative(jMask);
677 ALOGV("convertAudioPortConfigToNative OUT mask java %x native %x", jMask, nMask);
678 }
679 nAudioPortConfig->channel_mask = nMask;
Eric Laurent6368a7d2014-11-19 12:18:32 -0800680 if (nAudioPortConfig->channel_mask != AUDIO_CHANNEL_NONE) {
681 configMask |= AUDIO_PORT_CONFIG_CHANNEL_MASK;
682 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700683
684 jint jFormat = env->GetIntField(jAudioPortConfig, gAudioPortConfigFields.mFormat);
685 audio_format_t nFormat = audioFormatToNative(jFormat);
686 ALOGV("convertAudioPortConfigToNative format %d native %d", jFormat, nFormat);
687 nAudioPortConfig->format = nFormat;
Eric Laurent6368a7d2014-11-19 12:18:32 -0800688 if (nAudioPortConfig->format != AUDIO_FORMAT_DEFAULT &&
689 nAudioPortConfig->format != AUDIO_FORMAT_INVALID) {
690 configMask |= AUDIO_PORT_CONFIG_FORMAT;
691 }
692
Eric Laurentb69681c2014-05-19 19:02:51 -0700693 jobject jGain = env->GetObjectField(jAudioPortConfig, gAudioPortConfigFields.mGain);
694 if (jGain != NULL) {
Eric Laurent3a241992014-05-19 19:33:26 -0700695 convertAudioGainConfigToNative(env, &nAudioPortConfig->gain, jGain, useInMask);
Eric Laurentb69681c2014-05-19 19:02:51 -0700696 env->DeleteLocalRef(jGain);
Eric Laurent6368a7d2014-11-19 12:18:32 -0800697 configMask |= AUDIO_PORT_CONFIG_GAIN;
Eric Laurentb69681c2014-05-19 19:02:51 -0700698 } else {
699 ALOGV("convertAudioPortConfigToNative no gain");
700 nAudioPortConfig->gain.index = -1;
701 }
Eric Laurent6368a7d2014-11-19 12:18:32 -0800702 if (useConfigMask) {
703 nAudioPortConfig->config_mask = env->GetIntField(jAudioPortConfig,
704 gAudioPortConfigFields.mConfigMask);
705 } else {
706 nAudioPortConfig->config_mask = configMask;
707 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700708 env->DeleteLocalRef(jAudioPort);
709 env->DeleteLocalRef(jHandle);
710 return (jint)AUDIO_JAVA_SUCCESS;
711}
712
713static jint convertAudioPortConfigFromNative(JNIEnv *env,
714 jobject jAudioPort,
715 jobject *jAudioPortConfig,
716 const struct audio_port_config *nAudioPortConfig)
717{
718 jint jStatus = AUDIO_JAVA_SUCCESS;
719 jobject jAudioGainConfig = NULL;
720 jobject jAudioGain = NULL;
721 jintArray jGainValues;
722 bool audioportCreated = false;
723
724 ALOGV("convertAudioPortConfigFromNative jAudioPort %p", jAudioPort);
725
726 if (jAudioPort == NULL) {
727 jobject jHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
728 nAudioPortConfig->id);
729
730 ALOGV("convertAudioPortConfigFromNative handle %d is a %s", nAudioPortConfig->id,
731 nAudioPortConfig->type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix");
732
733 if (jHandle == NULL) {
734 return (jint)AUDIO_JAVA_ERROR;
735 }
736 // create dummy port and port config objects with just the correct handle
737 // and configuration data. The actual AudioPortConfig objects will be
738 // constructed by java code with correct class type (device, mix etc...)
739 // and reference to AudioPort instance in this client
740 jAudioPort = env->NewObject(gAudioPortClass, gAudioPortCstor,
Paul McLeanf29e5f32015-06-15 10:19:22 -0700741 jHandle, // handle
742 0, // role
743 NULL, // name
744 NULL, // samplingRates
745 NULL, // channelMasks
746 NULL, // channelIndexMasks
747 NULL, // formats
748 NULL); // gains
Eric Laurentb69681c2014-05-19 19:02:51 -0700749 env->DeleteLocalRef(jHandle);
750 if (jAudioPort == NULL) {
751 return (jint)AUDIO_JAVA_ERROR;
752 }
753 ALOGV("convertAudioPortConfigFromNative jAudioPort created for handle %d",
754 nAudioPortConfig->id);
755
756 audioportCreated = true;
757 }
758
759 bool useInMask = useInChannelMask(nAudioPortConfig->type, nAudioPortConfig->role);
760
761 audio_channel_mask_t nMask;
762 jint jMask;
763
764 int gainIndex = nAudioPortConfig->gain.index;
765 if (gainIndex >= 0) {
766 ALOGV("convertAudioPortConfigFromNative gain found with index %d mode %x",
767 gainIndex, nAudioPortConfig->gain.mode);
768 if (audioportCreated) {
769 ALOGV("convertAudioPortConfigFromNative creating gain");
770 jAudioGain = env->NewObject(gAudioGainClass, gAudioGainCstor,
771 gainIndex,
772 0,
773 0,
774 0,
775 0,
776 0,
777 0,
778 0,
779 0);
780 if (jAudioGain == NULL) {
781 ALOGV("convertAudioPortConfigFromNative creating gain FAILED");
782 jStatus = (jint)AUDIO_JAVA_ERROR;
783 goto exit;
784 }
785 } else {
786 ALOGV("convertAudioPortConfigFromNative reading gain from port");
787 jobjectArray jGains = (jobjectArray)env->GetObjectField(jAudioPort,
788 gAudioPortFields.mGains);
789 if (jGains == NULL) {
790 ALOGV("convertAudioPortConfigFromNative could not get gains from port");
791 jStatus = (jint)AUDIO_JAVA_ERROR;
792 goto exit;
793 }
794 jAudioGain = env->GetObjectArrayElement(jGains, gainIndex);
795 env->DeleteLocalRef(jGains);
796 if (jAudioGain == NULL) {
797 ALOGV("convertAudioPortConfigFromNative could not get gain at index %d", gainIndex);
798 jStatus = (jint)AUDIO_JAVA_ERROR;
799 goto exit;
800 }
801 }
Eric Laurent0078c7c2014-06-04 09:49:52 -0700802 int numValues;
803 if (useInMask) {
804 numValues = audio_channel_count_from_in_mask(nAudioPortConfig->gain.channel_mask);
805 } else {
806 numValues = audio_channel_count_from_out_mask(nAudioPortConfig->gain.channel_mask);
807 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700808 jGainValues = env->NewIntArray(numValues);
809 if (jGainValues == NULL) {
810 ALOGV("convertAudioPortConfigFromNative could not create gain values %d", numValues);
811 jStatus = (jint)AUDIO_JAVA_ERROR;
812 goto exit;
813 }
814 env->SetIntArrayRegion(jGainValues, 0, numValues,
815 nAudioPortConfig->gain.values);
816
817 nMask = nAudioPortConfig->gain.channel_mask;
818 if (useInMask) {
819 jMask = inChannelMaskFromNative(nMask);
820 ALOGV("convertAudioPortConfigFromNative IN mask java %x native %x", jMask, nMask);
821 } else {
822 jMask = outChannelMaskFromNative(nMask);
823 ALOGV("convertAudioPortConfigFromNative OUT mask java %x native %x", jMask, nMask);
824 }
825
826 jAudioGainConfig = env->NewObject(gAudioGainConfigClass,
827 gAudioGainConfigCstor,
828 gainIndex,
829 jAudioGain,
830 nAudioPortConfig->gain.mode,
831 jMask,
832 jGainValues,
833 nAudioPortConfig->gain.ramp_duration_ms);
834 env->DeleteLocalRef(jGainValues);
835 if (jAudioGainConfig == NULL) {
836 ALOGV("convertAudioPortConfigFromNative could not create gain config");
837 jStatus = (jint)AUDIO_JAVA_ERROR;
838 goto exit;
839 }
840 }
841 jclass clazz;
842 jmethodID methodID;
843 if (audioportCreated) {
844 clazz = gAudioPortConfigClass;
845 methodID = gAudioPortConfigCstor;
846 ALOGV("convertAudioPortConfigFromNative building a generic port config");
847 } else {
848 if (env->IsInstanceOf(jAudioPort, gAudioDevicePortClass)) {
849 clazz = gAudioDevicePortConfigClass;
850 methodID = gAudioDevicePortConfigCstor;
851 ALOGV("convertAudioPortConfigFromNative building a device config");
852 } else if (env->IsInstanceOf(jAudioPort, gAudioMixPortClass)) {
853 clazz = gAudioMixPortConfigClass;
854 methodID = gAudioMixPortConfigCstor;
855 ALOGV("convertAudioPortConfigFromNative building a mix config");
856 } else {
857 jStatus = (jint)AUDIO_JAVA_ERROR;
858 goto exit;
859 }
860 }
861 nMask = nAudioPortConfig->channel_mask;
862 if (useInMask) {
863 jMask = inChannelMaskFromNative(nMask);
864 ALOGV("convertAudioPortConfigFromNative IN mask java %x native %x", jMask, nMask);
865 } else {
866 jMask = outChannelMaskFromNative(nMask);
867 ALOGV("convertAudioPortConfigFromNative OUT mask java %x native %x", jMask, nMask);
868 }
869
870 *jAudioPortConfig = env->NewObject(clazz, methodID,
871 jAudioPort,
872 nAudioPortConfig->sample_rate,
873 jMask,
874 audioFormatFromNative(nAudioPortConfig->format),
875 jAudioGainConfig);
876 if (*jAudioPortConfig == NULL) {
877 ALOGV("convertAudioPortConfigFromNative could not create new port config");
878 jStatus = (jint)AUDIO_JAVA_ERROR;
879 } else {
880 ALOGV("convertAudioPortConfigFromNative OK");
881 }
882
883exit:
884 if (audioportCreated) {
885 env->DeleteLocalRef(jAudioPort);
886 if (jAudioGain != NULL) {
887 env->DeleteLocalRef(jAudioGain);
888 }
889 }
890 if (jAudioGainConfig != NULL) {
891 env->DeleteLocalRef(jAudioGainConfig);
892 }
893 return jStatus;
894}
895
Paul McLean4e5e9e92015-06-17 10:10:11 -0700896static bool hasFormat(int* formats, size_t size, int format) {
897 for (size_t index = 0; index < size; index++) {
898 if (formats[index] == format) {
899 return true; // found
900 }
901 }
902 return false; // not found
903}
904
Eric Laurentb69681c2014-05-19 19:02:51 -0700905static jint convertAudioPortFromNative(JNIEnv *env,
906 jobject *jAudioPort, const struct audio_port *nAudioPort)
907{
908 jint jStatus = (jint)AUDIO_JAVA_SUCCESS;
909 jintArray jSamplingRates = NULL;
910 jintArray jChannelMasks = NULL;
Paul McLeanf29e5f32015-06-15 10:19:22 -0700911 jintArray jChannelIndexMasks = NULL;
Paul McLean4e5e9e92015-06-17 10:10:11 -0700912 int* cFormats = NULL;
Eric Laurentb69681c2014-05-19 19:02:51 -0700913 jintArray jFormats = NULL;
914 jobjectArray jGains = NULL;
915 jobject jHandle = NULL;
Paul McLean10804eb2015-01-28 11:16:35 -0800916 jstring jDeviceName = NULL;
Eric Laurentb69681c2014-05-19 19:02:51 -0700917 bool useInMask;
Paul McLeanf29e5f32015-06-15 10:19:22 -0700918 size_t numPositionMasks = 0;
919 size_t numIndexMasks = 0;
Paul McLean2db94372015-06-18 12:47:34 -0700920 size_t numUniqueFormats = 0;
921
Paul McLean10804eb2015-01-28 11:16:35 -0800922 ALOGV("convertAudioPortFromNative id %d role %d type %d name %s",
923 nAudioPort->id, nAudioPort->role, nAudioPort->type, nAudioPort->name);
Eric Laurentb69681c2014-05-19 19:02:51 -0700924
925 jSamplingRates = env->NewIntArray(nAudioPort->num_sample_rates);
926 if (jSamplingRates == NULL) {
927 jStatus = (jint)AUDIO_JAVA_ERROR;
928 goto exit;
929 }
930 if (nAudioPort->num_sample_rates) {
931 env->SetIntArrayRegion(jSamplingRates, 0, nAudioPort->num_sample_rates,
932 (jint *)nAudioPort->sample_rates);
933 }
934
Paul McLeanf29e5f32015-06-15 10:19:22 -0700935 // count up how many masks are positional and indexed
936 for(size_t index = 0; index < nAudioPort->num_channel_masks; index++) {
937 const audio_channel_mask_t mask = nAudioPort->channel_masks[index];
938 if (audio_channel_mask_get_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
939 numIndexMasks++;
940 } else {
941 numPositionMasks++;
942 }
943 }
944
945 jChannelMasks = env->NewIntArray(numPositionMasks);
Eric Laurentb69681c2014-05-19 19:02:51 -0700946 if (jChannelMasks == NULL) {
947 jStatus = (jint)AUDIO_JAVA_ERROR;
948 goto exit;
949 }
Paul McLeanf29e5f32015-06-15 10:19:22 -0700950 jChannelIndexMasks = env->NewIntArray(numIndexMasks);
951 if (jChannelIndexMasks == NULL) {
952 jStatus = (jint)AUDIO_JAVA_ERROR;
953 goto exit;
954 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700955 useInMask = useInChannelMask(nAudioPort->type, nAudioPort->role);
956
Paul McLeanf29e5f32015-06-15 10:19:22 -0700957 // put the masks in the output arrays
958 for (size_t maskIndex = 0, posMaskIndex = 0, indexedMaskIndex = 0;
959 maskIndex < nAudioPort->num_channel_masks; maskIndex++) {
960 const audio_channel_mask_t mask = nAudioPort->channel_masks[maskIndex];
961 if (audio_channel_mask_get_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
962 jint jMask = audio_channel_mask_get_bits(mask);
963 env->SetIntArrayRegion(jChannelIndexMasks, indexedMaskIndex++, 1, &jMask);
Eric Laurentb69681c2014-05-19 19:02:51 -0700964 } else {
Paul McLeanf29e5f32015-06-15 10:19:22 -0700965 jint jMask = useInMask ? inChannelMaskFromNative(mask)
966 : outChannelMaskFromNative(mask);
967 env->SetIntArrayRegion(jChannelMasks, posMaskIndex++, 1, &jMask);
Eric Laurentb69681c2014-05-19 19:02:51 -0700968 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700969 }
970
Paul McLeanf29e5f32015-06-15 10:19:22 -0700971 // formats
Paul McLean2db94372015-06-18 12:47:34 -0700972 if (nAudioPort->num_formats != 0) {
973 cFormats = new int[nAudioPort->num_formats];
974 for (size_t index = 0; index < nAudioPort->num_formats; index++) {
975 int format = audioFormatFromNative(nAudioPort->formats[index]);
976 if (!hasFormat(cFormats, numUniqueFormats, format)) {
977 cFormats[numUniqueFormats++] = format;
978 }
Paul McLean4e5e9e92015-06-17 10:10:11 -0700979 }
980 }
981 jFormats = env->NewIntArray(numUniqueFormats);
Eric Laurentb69681c2014-05-19 19:02:51 -0700982 if (jFormats == NULL) {
983 jStatus = (jint)AUDIO_JAVA_ERROR;
984 goto exit;
985 }
Paul McLean2db94372015-06-18 12:47:34 -0700986 if (numUniqueFormats != 0) {
987 env->SetIntArrayRegion(jFormats, 0, numUniqueFormats, cFormats);
988 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700989
Paul McLeanf29e5f32015-06-15 10:19:22 -0700990 // gains
Eric Laurentb69681c2014-05-19 19:02:51 -0700991 jGains = env->NewObjectArray(nAudioPort->num_gains,
992 gAudioGainClass, NULL);
993 if (jGains == NULL) {
994 jStatus = (jint)AUDIO_JAVA_ERROR;
995 goto exit;
996 }
Paul McLeanf29e5f32015-06-15 10:19:22 -0700997
Eric Laurentb69681c2014-05-19 19:02:51 -0700998 for (size_t j = 0; j < nAudioPort->num_gains; j++) {
999 audio_channel_mask_t nMask = nAudioPort->gains[j].channel_mask;
Paul McLeanf29e5f32015-06-15 10:19:22 -07001000 jint jMask;
Eric Laurentb69681c2014-05-19 19:02:51 -07001001 if (useInMask) {
1002 jMask = inChannelMaskFromNative(nMask);
1003 ALOGV("convertAudioPortConfigFromNative IN mask java %x native %x", jMask, nMask);
1004 } else {
1005 jMask = outChannelMaskFromNative(nMask);
1006 ALOGV("convertAudioPortConfigFromNative OUT mask java %x native %x", jMask, nMask);
1007 }
1008
1009 jobject jGain = env->NewObject(gAudioGainClass, gAudioGainCstor,
1010 j,
1011 nAudioPort->gains[j].mode,
1012 jMask,
1013 nAudioPort->gains[j].min_value,
1014 nAudioPort->gains[j].max_value,
1015 nAudioPort->gains[j].default_value,
1016 nAudioPort->gains[j].step_value,
1017 nAudioPort->gains[j].min_ramp_ms,
1018 nAudioPort->gains[j].max_ramp_ms);
1019 if (jGain == NULL) {
1020 jStatus = (jint)AUDIO_JAVA_ERROR;
1021 goto exit;
1022 }
1023 env->SetObjectArrayElement(jGains, j, jGain);
1024 env->DeleteLocalRef(jGain);
1025 }
1026
1027 jHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
1028 nAudioPort->id);
1029 if (jHandle == NULL) {
1030 jStatus = (jint)AUDIO_JAVA_ERROR;
1031 goto exit;
1032 }
1033
Paul McLean10804eb2015-01-28 11:16:35 -08001034 jDeviceName = env->NewStringUTF(nAudioPort->name);
1035
Eric Laurentb69681c2014-05-19 19:02:51 -07001036 if (nAudioPort->type == AUDIO_PORT_TYPE_DEVICE) {
1037 ALOGV("convertAudioPortFromNative is a device %08x", nAudioPort->ext.device.type);
1038 jstring jAddress = env->NewStringUTF(nAudioPort->ext.device.address);
1039 *jAudioPort = env->NewObject(gAudioDevicePortClass, gAudioDevicePortCstor,
Paul McLean10804eb2015-01-28 11:16:35 -08001040 jHandle, jDeviceName,
Paul McLeanf29e5f32015-06-15 10:19:22 -07001041 jSamplingRates, jChannelMasks, jChannelIndexMasks,
1042 jFormats, jGains,
Eric Laurentb69681c2014-05-19 19:02:51 -07001043 nAudioPort->ext.device.type, jAddress);
1044 env->DeleteLocalRef(jAddress);
1045 } else if (nAudioPort->type == AUDIO_PORT_TYPE_MIX) {
1046 ALOGV("convertAudioPortFromNative is a mix");
1047 *jAudioPort = env->NewObject(gAudioMixPortClass, gAudioMixPortCstor,
Eric Laurent4bcdba82015-05-01 11:37:49 -07001048 jHandle, nAudioPort->ext.mix.handle,
1049 nAudioPort->role, jDeviceName,
Paul McLeanf29e5f32015-06-15 10:19:22 -07001050 jSamplingRates, jChannelMasks, jChannelIndexMasks,
Eric Laurentb69681c2014-05-19 19:02:51 -07001051 jFormats, jGains);
1052 } else {
1053 ALOGE("convertAudioPortFromNative unknown nAudioPort type %d", nAudioPort->type);
1054 jStatus = (jint)AUDIO_JAVA_ERROR;
1055 goto exit;
1056 }
1057 if (*jAudioPort == NULL) {
1058 jStatus = (jint)AUDIO_JAVA_ERROR;
1059 goto exit;
1060 }
1061
1062 jobject jAudioPortConfig;
1063 jStatus = convertAudioPortConfigFromNative(env,
1064 *jAudioPort,
1065 &jAudioPortConfig,
1066 &nAudioPort->active_config);
1067 if (jStatus != AUDIO_JAVA_SUCCESS) {
1068 return jStatus;
1069 }
1070
1071 env->SetObjectField(*jAudioPort, gAudioPortFields.mActiveConfig, jAudioPortConfig);
1072
1073exit:
Paul McLean10804eb2015-01-28 11:16:35 -08001074 if (jDeviceName != NULL) {
1075 env->DeleteLocalRef(jDeviceName);
1076 }
Eric Laurentb69681c2014-05-19 19:02:51 -07001077 if (jSamplingRates != NULL) {
1078 env->DeleteLocalRef(jSamplingRates);
1079 }
1080 if (jChannelMasks != NULL) {
1081 env->DeleteLocalRef(jChannelMasks);
1082 }
Paul McLean4e5e9e92015-06-17 10:10:11 -07001083 if (jChannelIndexMasks != NULL) {
1084 env->DeleteLocalRef(jChannelIndexMasks);
1085 }
1086 if (cFormats != NULL) {
1087 delete[] cFormats;
1088 }
Eric Laurentb69681c2014-05-19 19:02:51 -07001089 if (jFormats != NULL) {
1090 env->DeleteLocalRef(jFormats);
1091 }
1092 if (jGains != NULL) {
1093 env->DeleteLocalRef(jGains);
1094 }
1095 if (jHandle != NULL) {
1096 env->DeleteLocalRef(jHandle);
1097 }
1098
1099 return jStatus;
1100}
1101
1102
1103static jint
1104android_media_AudioSystem_listAudioPorts(JNIEnv *env, jobject clazz,
1105 jobject jPorts, jintArray jGeneration)
1106{
1107 ALOGV("listAudioPorts");
1108
1109 if (jPorts == NULL) {
1110 ALOGE("listAudioPorts NULL AudioPort ArrayList");
1111 return (jint)AUDIO_JAVA_BAD_VALUE;
1112 }
1113 if (!env->IsInstanceOf(jPorts, gArrayListClass)) {
1114 ALOGE("listAudioPorts not an arraylist");
1115 return (jint)AUDIO_JAVA_BAD_VALUE;
1116 }
1117
1118 if (jGeneration == NULL || env->GetArrayLength(jGeneration) != 1) {
1119 return (jint)AUDIO_JAVA_BAD_VALUE;
1120 }
1121
1122 status_t status;
1123 unsigned int generation1;
1124 unsigned int generation;
1125 unsigned int numPorts;
1126 jint *nGeneration;
1127 struct audio_port *nPorts = NULL;
1128 int attempts = MAX_PORT_GENERATION_SYNC_ATTEMPTS;
1129
1130 // get the port count and all the ports until they both return the same generation
1131 do {
1132 if (attempts-- < 0) {
1133 status = TIMED_OUT;
1134 break;
1135 }
1136
1137 numPorts = 0;
1138 status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE,
1139 AUDIO_PORT_TYPE_NONE,
1140 &numPorts,
1141 NULL,
1142 &generation1);
1143 if (status != NO_ERROR || numPorts == 0) {
1144 ALOGE_IF(status != NO_ERROR, "AudioSystem::listAudioPorts error %d", status);
1145 break;
1146 }
1147 nPorts = (struct audio_port *)realloc(nPorts, numPorts * sizeof(struct audio_port));
1148
1149 status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE,
1150 AUDIO_PORT_TYPE_NONE,
1151 &numPorts,
1152 nPorts,
1153 &generation);
1154 ALOGV("listAudioPorts AudioSystem::listAudioPorts numPorts %d generation %d generation1 %d",
1155 numPorts, generation, generation1);
1156 } while (generation1 != generation && status == NO_ERROR);
1157
1158 jint jStatus = nativeToJavaStatus(status);
1159 if (jStatus != AUDIO_JAVA_SUCCESS) {
1160 goto exit;
1161 }
1162
1163 nGeneration = env->GetIntArrayElements(jGeneration, NULL);
1164 if (nGeneration == NULL) {
1165 jStatus = (jint)AUDIO_JAVA_ERROR;
1166 goto exit;
1167 }
1168 nGeneration[0] = generation1;
1169 env->ReleaseIntArrayElements(jGeneration, nGeneration, 0);
1170
1171 for (size_t i = 0; i < numPorts; i++) {
1172 jobject jAudioPort;
1173 jStatus = convertAudioPortFromNative(env, &jAudioPort, &nPorts[i]);
1174 if (jStatus != AUDIO_JAVA_SUCCESS) {
1175 goto exit;
1176 }
1177 env->CallBooleanMethod(jPorts, gArrayListMethods.add, jAudioPort);
1178 }
1179
1180exit:
1181 free(nPorts);
1182 return jStatus;
1183}
1184
1185static int
1186android_media_AudioSystem_createAudioPatch(JNIEnv *env, jobject clazz,
1187 jobjectArray jPatches, jobjectArray jSources, jobjectArray jSinks)
1188{
1189 status_t status;
1190 jint jStatus;
1191
1192 ALOGV("createAudioPatch");
1193 if (jPatches == NULL || jSources == NULL || jSinks == NULL) {
1194 return (jint)AUDIO_JAVA_BAD_VALUE;
1195 }
1196
1197 if (env->GetArrayLength(jPatches) != 1) {
1198 return (jint)AUDIO_JAVA_BAD_VALUE;
1199 }
1200 jint numSources = env->GetArrayLength(jSources);
1201 if (numSources == 0 || numSources > AUDIO_PATCH_PORTS_MAX) {
1202 return (jint)AUDIO_JAVA_BAD_VALUE;
1203 }
1204
1205 jint numSinks = env->GetArrayLength(jSinks);
1206 if (numSinks == 0 || numSinks > AUDIO_PATCH_PORTS_MAX) {
1207 return (jint)AUDIO_JAVA_BAD_VALUE;
1208 }
1209
1210 audio_patch_handle_t handle = (audio_patch_handle_t)0;
1211 jobject jPatch = env->GetObjectArrayElement(jPatches, 0);
1212 jobject jPatchHandle = NULL;
1213 if (jPatch != NULL) {
1214 if (!env->IsInstanceOf(jPatch, gAudioPatchClass)) {
1215 return (jint)AUDIO_JAVA_BAD_VALUE;
1216 }
1217 jPatchHandle = env->GetObjectField(jPatch, gAudioPatchFields.mHandle);
1218 handle = (audio_patch_handle_t)env->GetIntField(jPatchHandle, gAudioHandleFields.mId);
1219 }
1220
1221 struct audio_patch nPatch;
1222
1223 nPatch.id = handle;
1224 nPatch.num_sources = 0;
1225 nPatch.num_sinks = 0;
1226 jobject jSource = NULL;
1227 jobject jSink = NULL;
1228
1229 for (jint i = 0; i < numSources; i++) {
1230 jSource = env->GetObjectArrayElement(jSources, i);
1231 if (!env->IsInstanceOf(jSource, gAudioPortConfigClass)) {
1232 jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
1233 goto exit;
1234 }
Eric Laurent6368a7d2014-11-19 12:18:32 -08001235 jStatus = convertAudioPortConfigToNative(env, &nPatch.sources[i], jSource, false);
Eric Laurentb69681c2014-05-19 19:02:51 -07001236 env->DeleteLocalRef(jSource);
1237 jSource = NULL;
1238 if (jStatus != AUDIO_JAVA_SUCCESS) {
1239 goto exit;
1240 }
1241 nPatch.num_sources++;
1242 }
1243
1244 for (jint i = 0; i < numSinks; i++) {
1245 jSink = env->GetObjectArrayElement(jSinks, i);
1246 if (!env->IsInstanceOf(jSink, gAudioPortConfigClass)) {
1247 jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
1248 goto exit;
1249 }
Eric Laurent6368a7d2014-11-19 12:18:32 -08001250 jStatus = convertAudioPortConfigToNative(env, &nPatch.sinks[i], jSink, false);
Eric Laurentb69681c2014-05-19 19:02:51 -07001251 env->DeleteLocalRef(jSink);
1252 jSink = NULL;
1253 if (jStatus != AUDIO_JAVA_SUCCESS) {
1254 goto exit;
1255 }
1256 nPatch.num_sinks++;
1257 }
1258
1259 ALOGV("AudioSystem::createAudioPatch");
1260 status = AudioSystem::createAudioPatch(&nPatch, &handle);
1261 ALOGV("AudioSystem::createAudioPatch() returned %d hande %d", status, handle);
1262
1263 jStatus = nativeToJavaStatus(status);
1264 if (jStatus != AUDIO_JAVA_SUCCESS) {
1265 goto exit;
1266 }
1267
1268 if (jPatchHandle == NULL) {
1269 jPatchHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
1270 handle);
1271 if (jPatchHandle == NULL) {
1272 jStatus = (jint)AUDIO_JAVA_ERROR;
1273 goto exit;
1274 }
1275 jPatch = env->NewObject(gAudioPatchClass, gAudioPatchCstor, jPatchHandle, jSources, jSinks);
1276 if (jPatch == NULL) {
1277 jStatus = (jint)AUDIO_JAVA_ERROR;
1278 goto exit;
1279 }
1280 env->SetObjectArrayElement(jPatches, 0, jPatch);
1281 } else {
1282 env->SetIntField(jPatchHandle, gAudioHandleFields.mId, handle);
1283 }
1284
1285exit:
1286 if (jPatchHandle != NULL) {
1287 env->DeleteLocalRef(jPatchHandle);
1288 }
1289 if (jPatch != NULL) {
1290 env->DeleteLocalRef(jPatch);
1291 }
1292 if (jSource != NULL) {
1293 env->DeleteLocalRef(jSource);
1294 }
1295 if (jSink != NULL) {
1296 env->DeleteLocalRef(jSink);
1297 }
1298 return jStatus;
1299}
1300
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001301static jint
Eric Laurentb69681c2014-05-19 19:02:51 -07001302android_media_AudioSystem_releaseAudioPatch(JNIEnv *env, jobject clazz,
1303 jobject jPatch)
1304{
1305 ALOGV("releaseAudioPatch");
1306 if (jPatch == NULL) {
1307 return (jint)AUDIO_JAVA_BAD_VALUE;
1308 }
1309
1310 audio_patch_handle_t handle = (audio_patch_handle_t)0;
1311 jobject jPatchHandle = NULL;
1312 if (!env->IsInstanceOf(jPatch, gAudioPatchClass)) {
1313 return (jint)AUDIO_JAVA_BAD_VALUE;
1314 }
1315 jPatchHandle = env->GetObjectField(jPatch, gAudioPatchFields.mHandle);
1316 handle = (audio_patch_handle_t)env->GetIntField(jPatchHandle, gAudioHandleFields.mId);
1317 env->DeleteLocalRef(jPatchHandle);
1318
1319 ALOGV("AudioSystem::releaseAudioPatch");
1320 status_t status = AudioSystem::releaseAudioPatch(handle);
1321 ALOGV("AudioSystem::releaseAudioPatch() returned %d", status);
1322 jint jStatus = nativeToJavaStatus(status);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001323 return jStatus;
Eric Laurentb69681c2014-05-19 19:02:51 -07001324}
1325
1326static jint
1327android_media_AudioSystem_listAudioPatches(JNIEnv *env, jobject clazz,
1328 jobject jPatches, jintArray jGeneration)
1329{
1330 ALOGV("listAudioPatches");
1331 if (jPatches == NULL) {
1332 ALOGE("listAudioPatches NULL AudioPatch ArrayList");
1333 return (jint)AUDIO_JAVA_BAD_VALUE;
1334 }
1335 if (!env->IsInstanceOf(jPatches, gArrayListClass)) {
1336 ALOGE("listAudioPatches not an arraylist");
1337 return (jint)AUDIO_JAVA_BAD_VALUE;
1338 }
1339
1340 if (jGeneration == NULL || env->GetArrayLength(jGeneration) != 1) {
1341 return (jint)AUDIO_JAVA_BAD_VALUE;
1342 }
1343
1344 status_t status;
1345 unsigned int generation1;
1346 unsigned int generation;
1347 unsigned int numPatches;
1348 jint *nGeneration;
1349 struct audio_patch *nPatches = NULL;
1350 jobjectArray jSources = NULL;
1351 jobject jSource = NULL;
1352 jobjectArray jSinks = NULL;
1353 jobject jSink = NULL;
1354 jobject jPatch = NULL;
1355 int attempts = MAX_PORT_GENERATION_SYNC_ATTEMPTS;
1356
1357 // get the patch count and all the patches until they both return the same generation
1358 do {
1359 if (attempts-- < 0) {
1360 status = TIMED_OUT;
1361 break;
1362 }
1363
1364 numPatches = 0;
1365 status = AudioSystem::listAudioPatches(&numPatches,
1366 NULL,
1367 &generation1);
1368 if (status != NO_ERROR || numPatches == 0) {
1369 ALOGE_IF(status != NO_ERROR, "listAudioPatches AudioSystem::listAudioPatches error %d",
1370 status);
1371 break;
1372 }
1373 nPatches = (struct audio_patch *)realloc(nPatches, numPatches * sizeof(struct audio_patch));
1374
1375 status = AudioSystem::listAudioPatches(&numPatches,
1376 nPatches,
1377 &generation);
1378 ALOGV("listAudioPatches AudioSystem::listAudioPatches numPatches %d generation %d generation1 %d",
1379 numPatches, generation, generation1);
1380
1381 } while (generation1 != generation && status == NO_ERROR);
1382
1383 jint jStatus = nativeToJavaStatus(status);
1384 if (jStatus != AUDIO_JAVA_SUCCESS) {
1385 goto exit;
1386 }
1387
1388 nGeneration = env->GetIntArrayElements(jGeneration, NULL);
1389 if (nGeneration == NULL) {
1390 jStatus = AUDIO_JAVA_ERROR;
1391 goto exit;
1392 }
1393 nGeneration[0] = generation1;
1394 env->ReleaseIntArrayElements(jGeneration, nGeneration, 0);
1395
1396 for (size_t i = 0; i < numPatches; i++) {
1397 jobject patchHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
1398 nPatches[i].id);
1399 if (patchHandle == NULL) {
1400 jStatus = AUDIO_JAVA_ERROR;
1401 goto exit;
1402 }
Dan Albert46d84442014-11-18 16:07:51 -08001403 ALOGV("listAudioPatches patch %zu num_sources %d num_sinks %d",
Eric Laurentb69681c2014-05-19 19:02:51 -07001404 i, nPatches[i].num_sources, nPatches[i].num_sinks);
1405
1406 env->SetIntField(patchHandle, gAudioHandleFields.mId, nPatches[i].id);
1407
1408 // load sources
1409 jSources = env->NewObjectArray(nPatches[i].num_sources,
1410 gAudioPortConfigClass, NULL);
1411 if (jSources == NULL) {
1412 jStatus = AUDIO_JAVA_ERROR;
1413 goto exit;
1414 }
1415
1416 for (size_t j = 0; j < nPatches[i].num_sources; j++) {
1417 jStatus = convertAudioPortConfigFromNative(env,
1418 NULL,
1419 &jSource,
1420 &nPatches[i].sources[j]);
1421 if (jStatus != AUDIO_JAVA_SUCCESS) {
1422 goto exit;
1423 }
1424 env->SetObjectArrayElement(jSources, j, jSource);
1425 env->DeleteLocalRef(jSource);
1426 jSource = NULL;
Dan Albert46d84442014-11-18 16:07:51 -08001427 ALOGV("listAudioPatches patch %zu source %zu is a %s handle %d",
Eric Laurentb69681c2014-05-19 19:02:51 -07001428 i, j,
1429 nPatches[i].sources[j].type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix",
1430 nPatches[i].sources[j].id);
1431 }
1432 // load sinks
1433 jSinks = env->NewObjectArray(nPatches[i].num_sinks,
1434 gAudioPortConfigClass, NULL);
1435 if (jSinks == NULL) {
1436 jStatus = AUDIO_JAVA_ERROR;
1437 goto exit;
1438 }
1439
1440 for (size_t j = 0; j < nPatches[i].num_sinks; j++) {
1441 jStatus = convertAudioPortConfigFromNative(env,
1442 NULL,
1443 &jSink,
1444 &nPatches[i].sinks[j]);
1445
1446 if (jStatus != AUDIO_JAVA_SUCCESS) {
1447 goto exit;
1448 }
1449 env->SetObjectArrayElement(jSinks, j, jSink);
1450 env->DeleteLocalRef(jSink);
1451 jSink = NULL;
Dan Albert46d84442014-11-18 16:07:51 -08001452 ALOGV("listAudioPatches patch %zu sink %zu is a %s handle %d",
Eric Laurentb69681c2014-05-19 19:02:51 -07001453 i, j,
1454 nPatches[i].sinks[j].type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix",
1455 nPatches[i].sinks[j].id);
1456 }
1457
1458 jPatch = env->NewObject(gAudioPatchClass, gAudioPatchCstor,
1459 patchHandle, jSources, jSinks);
1460 env->DeleteLocalRef(jSources);
1461 jSources = NULL;
1462 env->DeleteLocalRef(jSinks);
1463 jSinks = NULL;
1464 if (jPatch == NULL) {
1465 jStatus = AUDIO_JAVA_ERROR;
1466 goto exit;
1467 }
1468 env->CallBooleanMethod(jPatches, gArrayListMethods.add, jPatch);
1469 env->DeleteLocalRef(jPatch);
1470 jPatch = NULL;
1471 }
1472
1473exit:
1474 if (jSources != NULL) {
1475 env->DeleteLocalRef(jSources);
1476 }
1477 if (jSource != NULL) {
1478 env->DeleteLocalRef(jSource);
1479 }
1480 if (jSinks != NULL) {
1481 env->DeleteLocalRef(jSinks);
1482 }
1483 if (jSink != NULL) {
1484 env->DeleteLocalRef(jSink);
1485 }
1486 if (jPatch != NULL) {
1487 env->DeleteLocalRef(jPatch);
1488 }
1489 free(nPatches);
1490 return jStatus;
1491}
1492
Eric Laurent3a241992014-05-19 19:33:26 -07001493static jint
1494android_media_AudioSystem_setAudioPortConfig(JNIEnv *env, jobject clazz,
1495 jobject jAudioPortConfig)
1496{
1497 ALOGV("setAudioPortConfig");
1498 if (jAudioPortConfig == NULL) {
1499 return AUDIO_JAVA_BAD_VALUE;
1500 }
1501 if (!env->IsInstanceOf(jAudioPortConfig, gAudioPortConfigClass)) {
1502 return AUDIO_JAVA_BAD_VALUE;
1503 }
1504 struct audio_port_config nAudioPortConfig;
Eric Laurent6368a7d2014-11-19 12:18:32 -08001505 jint jStatus = convertAudioPortConfigToNative(env, &nAudioPortConfig, jAudioPortConfig, true);
Eric Laurent3a241992014-05-19 19:33:26 -07001506 if (jStatus != AUDIO_JAVA_SUCCESS) {
1507 return jStatus;
1508 }
1509 status_t status = AudioSystem::setAudioPortConfig(&nAudioPortConfig);
1510 ALOGV("AudioSystem::setAudioPortConfig() returned %d", status);
1511 jStatus = nativeToJavaStatus(status);
1512 return jStatus;
1513}
1514
Eric Laurent700e7342014-05-02 18:33:15 -07001515static void
1516android_media_AudioSystem_eventHandlerSetup(JNIEnv *env, jobject thiz, jobject weak_this)
1517{
1518 ALOGV("eventHandlerSetup");
1519
1520 sp<JNIAudioPortCallback> callback = new JNIAudioPortCallback(env, thiz, weak_this);
1521
Eric Laurent2615afb2015-03-25 14:51:08 -07001522 if (AudioSystem::addAudioPortCallback(callback) == NO_ERROR) {
1523 setJniCallback(env, thiz, callback);
1524 }
Eric Laurent700e7342014-05-02 18:33:15 -07001525}
1526
1527static void
1528android_media_AudioSystem_eventHandlerFinalize(JNIEnv *env, jobject thiz)
1529{
1530 ALOGV("eventHandlerFinalize");
1531
Eric Laurent2615afb2015-03-25 14:51:08 -07001532 sp<JNIAudioPortCallback> callback = setJniCallback(env, thiz, 0);
Eric Laurent700e7342014-05-02 18:33:15 -07001533
Eric Laurent2615afb2015-03-25 14:51:08 -07001534 if (callback != 0) {
1535 AudioSystem::removeAudioPortCallback(callback);
1536 }
Eric Laurent700e7342014-05-02 18:33:15 -07001537}
1538
Eric Laurentb634e1b2014-08-01 14:44:46 -07001539static jint
1540android_media_AudioSystem_getAudioHwSyncForSession(JNIEnv *env, jobject thiz, jint sessionId)
1541{
1542 return (jint)AudioSystem::getAudioHwSyncForSession((audio_session_t)sessionId);
1543}
1544
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001545static void
1546android_media_AudioSystem_registerDynPolicyCallback(JNIEnv *env, jobject thiz)
1547{
1548 AudioSystem::setDynPolicyCallback(android_media_AudioSystem_dyn_policy_callback);
1549}
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001550
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08001551static void
1552android_media_AudioSystem_registerRecordingCallback(JNIEnv *env, jobject thiz)
1553{
1554 AudioSystem::setRecordConfigCallback(android_media_AudioSystem_recording_callback);
1555}
1556
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001557
1558static jint convertAudioMixToNative(JNIEnv *env,
1559 AudioMix *nAudioMix,
1560 const jobject jAudioMix)
1561{
1562 nAudioMix->mMixType = env->GetIntField(jAudioMix, gAudioMixFields.mMixType);
1563 nAudioMix->mRouteFlags = env->GetIntField(jAudioMix, gAudioMixFields.mRouteFlags);
1564
1565 jstring jRegistrationId = (jstring)env->GetObjectField(jAudioMix,
1566 gAudioMixFields.mRegistrationId);
1567 const char *nRegistrationId = env->GetStringUTFChars(jRegistrationId, NULL);
1568 nAudioMix->mRegistrationId = String8(nRegistrationId);
1569 env->ReleaseStringUTFChars(jRegistrationId, nRegistrationId);
1570 env->DeleteLocalRef(jRegistrationId);
1571
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001572 nAudioMix->mCbFlags = env->GetIntField(jAudioMix, gAudioMixFields.mCallbackFlags);
1573
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001574 jobject jFormat = env->GetObjectField(jAudioMix, gAudioMixFields.mFormat);
1575 nAudioMix->mFormat.sample_rate = env->GetIntField(jFormat,
1576 gAudioFormatFields.mSampleRate);
1577 nAudioMix->mFormat.channel_mask = outChannelMaskToNative(env->GetIntField(jFormat,
1578 gAudioFormatFields.mChannelMask));
1579 nAudioMix->mFormat.format = audioFormatToNative(env->GetIntField(jFormat,
1580 gAudioFormatFields.mEncoding));
1581 env->DeleteLocalRef(jFormat);
1582
1583 jobject jRule = env->GetObjectField(jAudioMix, gAudioMixFields.mRule);
1584 jobject jRuleCriteria = env->GetObjectField(jRule, gAudioMixingRuleFields.mCriteria);
1585 env->DeleteLocalRef(jRule);
1586 jobjectArray jCriteria = (jobjectArray)env->CallObjectMethod(jRuleCriteria,
1587 gArrayListMethods.toArray);
1588 env->DeleteLocalRef(jRuleCriteria);
1589
1590 jint numCriteria = env->GetArrayLength(jCriteria);
1591 if (numCriteria > MAX_CRITERIA_PER_MIX) {
1592 numCriteria = MAX_CRITERIA_PER_MIX;
1593 }
1594
1595 for (jint i = 0; i < numCriteria; i++) {
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -08001596 AudioMixMatchCriterion nCriterion;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001597
1598 jobject jCriterion = env->GetObjectArrayElement(jCriteria, i);
1599
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -08001600 nCriterion.mRule = env->GetIntField(jCriterion, gAudioMixMatchCriterionFields.mRule);
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001601
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -08001602 const uint32_t match_rule = nCriterion.mRule & ~RULE_EXCLUSION_MASK;
1603 switch (match_rule) {
1604 case RULE_MATCH_UID:
1605 nCriterion.mValue.mUid = env->GetIntField(jCriterion,
1606 gAudioMixMatchCriterionFields.mIntProp);
1607 break;
1608 case RULE_MATCH_ATTRIBUTE_USAGE:
1609 case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET: {
1610 jobject jAttributes = env->GetObjectField(jCriterion, gAudioMixMatchCriterionFields.mAttr);
1611 if (match_rule == RULE_MATCH_ATTRIBUTE_USAGE) {
1612 nCriterion.mValue.mUsage = (audio_usage_t)env->GetIntField(jAttributes,
1613 gAudioAttributesFields.mUsage);
1614 } else {
1615 nCriterion.mValue.mSource = (audio_source_t)env->GetIntField(jAttributes,
1616 gAudioAttributesFields.mSource);
1617 }
1618 env->DeleteLocalRef(jAttributes);
1619 }
1620 break;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001621 }
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001622
1623 nAudioMix->mCriteria.add(nCriterion);
1624 env->DeleteLocalRef(jCriterion);
1625 }
1626
1627 env->DeleteLocalRef(jCriteria);
1628
1629 return (jint)AUDIO_JAVA_SUCCESS;
1630}
1631
1632static jint
1633android_media_AudioSystem_registerPolicyMixes(JNIEnv *env, jobject clazz,
1634 jobject jMixesList, jboolean registration)
1635{
1636 ALOGV("registerPolicyMixes");
1637
1638 if (jMixesList == NULL) {
1639 return (jint)AUDIO_JAVA_BAD_VALUE;
1640 }
1641 if (!env->IsInstanceOf(jMixesList, gArrayListClass)) {
1642 return (jint)AUDIO_JAVA_BAD_VALUE;
1643 }
1644 jobjectArray jMixes = (jobjectArray)env->CallObjectMethod(jMixesList,
1645 gArrayListMethods.toArray);
1646 jint numMixes = env->GetArrayLength(jMixes);
1647 if (numMixes > MAX_MIXES_PER_POLICY) {
1648 numMixes = MAX_MIXES_PER_POLICY;
1649 }
1650
1651 status_t status;
1652 jint jStatus;
1653 jobject jAudioMix = NULL;
1654 Vector <AudioMix> mixes;
1655 for (jint i = 0; i < numMixes; i++) {
1656 jAudioMix = env->GetObjectArrayElement(jMixes, i);
1657 if (!env->IsInstanceOf(jAudioMix, gAudioMixClass)) {
1658 jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
1659 goto exit;
1660 }
1661 AudioMix mix;
1662 jStatus = convertAudioMixToNative(env, &mix, jAudioMix);
1663 env->DeleteLocalRef(jAudioMix);
1664 jAudioMix = NULL;
1665 if (jStatus != AUDIO_JAVA_SUCCESS) {
1666 goto exit;
1667 }
1668 mixes.add(mix);
1669 }
1670
1671 ALOGV("AudioSystem::registerPolicyMixes numMixes %d registration %d", numMixes, registration);
1672 status = AudioSystem::registerPolicyMixes(mixes, registration);
1673 ALOGV("AudioSystem::registerPolicyMixes() returned %d", status);
1674
1675 jStatus = nativeToJavaStatus(status);
1676 if (jStatus != AUDIO_JAVA_SUCCESS) {
1677 goto exit;
1678 }
1679
1680exit:
1681 if (jAudioMix != NULL) {
1682 env->DeleteLocalRef(jAudioMix);
1683 }
1684 return jStatus;
1685}
1686
Eric Laurent0867bed2015-05-20 14:49:08 -07001687static jint
1688android_media_AudioSystem_systemReady(JNIEnv *env, jobject thiz)
1689{
1690 return nativeToJavaStatus(AudioSystem::systemReady());
1691}
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001692
1693
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001694// ----------------------------------------------------------------------------
1695
Daniel Micay76f6a862015-09-19 17:31:01 -04001696static const JNINativeMethod gMethods[] = {
Eric Laurenta553c252009-07-17 12:17:14 -07001697 {"setParameters", "(Ljava/lang/String;)I", (void *)android_media_AudioSystem_setParameters},
1698 {"getParameters", "(Ljava/lang/String;)Ljava/lang/String;", (void *)android_media_AudioSystem_getParameters},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001699 {"muteMicrophone", "(Z)I", (void *)android_media_AudioSystem_muteMicrophone},
1700 {"isMicrophoneMuted", "()Z", (void *)android_media_AudioSystem_isMicrophoneMuted},
Jean-Michel Trivid6770542012-10-10 12:03:41 -07001701 {"isStreamActive", "(II)Z", (void *)android_media_AudioSystem_isStreamActive},
Jean-Michel Trivi679d5042013-02-04 16:24:09 -08001702 {"isStreamActiveRemotely","(II)Z", (void *)android_media_AudioSystem_isStreamActiveRemotely},
Jean-Michel Trivid6770542012-10-10 12:03:41 -07001703 {"isSourceActive", "(I)Z", (void *)android_media_AudioSystem_isSourceActive},
Jean-Michel Trivi8a21f5d2014-06-05 15:03:52 -07001704 {"newAudioSessionId", "()I", (void *)android_media_AudioSystem_newAudioSessionId},
Paul McLean10804eb2015-01-28 11:16:35 -08001705 {"setDeviceConnectionState", "(IILjava/lang/String;Ljava/lang/String;)I", (void *)android_media_AudioSystem_setDeviceConnectionState},
Eric Laurenta553c252009-07-17 12:17:14 -07001706 {"getDeviceConnectionState", "(ILjava/lang/String;)I", (void *)android_media_AudioSystem_getDeviceConnectionState},
1707 {"setPhoneState", "(I)I", (void *)android_media_AudioSystem_setPhoneState},
Eric Laurenta553c252009-07-17 12:17:14 -07001708 {"setForceUse", "(II)I", (void *)android_media_AudioSystem_setForceUse},
1709 {"getForceUse", "(I)I", (void *)android_media_AudioSystem_getForceUse},
1710 {"initStreamVolume", "(III)I", (void *)android_media_AudioSystem_initStreamVolume},
Eric Laurent9bc8358d2011-11-18 16:43:31 -08001711 {"setStreamVolumeIndex","(III)I", (void *)android_media_AudioSystem_setStreamVolumeIndex},
1712 {"getStreamVolumeIndex","(II)I", (void *)android_media_AudioSystem_getStreamVolumeIndex},
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -04001713 {"setMasterVolume", "(F)I", (void *)android_media_AudioSystem_setMasterVolume},
1714 {"getMasterVolume", "()F", (void *)android_media_AudioSystem_getMasterVolume},
1715 {"setMasterMute", "(Z)I", (void *)android_media_AudioSystem_setMasterMute},
1716 {"getMasterMute", "()Z", (void *)android_media_AudioSystem_getMasterMute},
Andy Hungf04b84d2015-12-18 17:33:27 -08001717 {"setMasterMono", "(Z)I", (void *)android_media_AudioSystem_setMasterMono},
1718 {"getMasterMono", "()Z", (void *)android_media_AudioSystem_getMasterMono},
Glenn Kasten8b4b97a2011-02-04 13:54:26 -08001719 {"getDevicesForStream", "(I)I", (void *)android_media_AudioSystem_getDevicesForStream},
Glenn Kastenc6c43652012-09-24 17:32:30 -07001720 {"getPrimaryOutputSamplingRate", "()I", (void *)android_media_AudioSystem_getPrimaryOutputSamplingRate},
1721 {"getPrimaryOutputFrameCount", "()I", (void *)android_media_AudioSystem_getPrimaryOutputFrameCount},
Oliver Woodman61dcdf32013-06-26 12:43:36 +01001722 {"getOutputLatency", "(I)I", (void *)android_media_AudioSystem_getOutputLatency},
Glenn Kastenfd116ad2013-07-12 17:10:39 -07001723 {"setLowRamDevice", "(Z)I", (void *)android_media_AudioSystem_setLowRamDevice},
Eric Laurentdfb881f2013-07-18 14:41:39 -07001724 {"checkAudioFlinger", "()I", (void *)android_media_AudioSystem_checkAudioFlinger},
Eric Laurentb69681c2014-05-19 19:02:51 -07001725 {"listAudioPorts", "(Ljava/util/ArrayList;[I)I",
1726 (void *)android_media_AudioSystem_listAudioPorts},
1727 {"createAudioPatch", "([Landroid/media/AudioPatch;[Landroid/media/AudioPortConfig;[Landroid/media/AudioPortConfig;)I",
1728 (void *)android_media_AudioSystem_createAudioPatch},
1729 {"releaseAudioPatch", "(Landroid/media/AudioPatch;)I",
1730 (void *)android_media_AudioSystem_releaseAudioPatch},
1731 {"listAudioPatches", "(Ljava/util/ArrayList;[I)I",
1732 (void *)android_media_AudioSystem_listAudioPatches},
Eric Laurent3a241992014-05-19 19:33:26 -07001733 {"setAudioPortConfig", "(Landroid/media/AudioPortConfig;)I",
1734 (void *)android_media_AudioSystem_setAudioPortConfig},
Eric Laurentb634e1b2014-08-01 14:44:46 -07001735 {"getAudioHwSyncForSession", "(I)I",
1736 (void *)android_media_AudioSystem_getAudioHwSyncForSession},
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001737 {"registerPolicyMixes", "(Ljava/util/ArrayList;Z)I",
1738 (void *)android_media_AudioSystem_registerPolicyMixes},
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001739 {"native_register_dynamic_policy_callback", "()V",
1740 (void *)android_media_AudioSystem_registerDynPolicyCallback},
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08001741 {"native_register_recording_callback", "()V",
1742 (void *)android_media_AudioSystem_registerRecordingCallback},
Eric Laurent0867bed2015-05-20 14:49:08 -07001743 {"systemReady", "()I", (void *)android_media_AudioSystem_systemReady},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001744};
1745
Eric Laurentb69681c2014-05-19 19:02:51 -07001746
Daniel Micay76f6a862015-09-19 17:31:01 -04001747static const JNINativeMethod gEventHandlerMethods[] = {
Eric Laurent700e7342014-05-02 18:33:15 -07001748 {"native_setup",
1749 "(Ljava/lang/Object;)V",
1750 (void *)android_media_AudioSystem_eventHandlerSetup},
1751 {"native_finalize",
1752 "()V",
1753 (void *)android_media_AudioSystem_eventHandlerFinalize},
1754};
1755
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001756int register_android_media_AudioSystem(JNIEnv *env)
1757{
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001758 jclass arrayListClass = FindClassOrDie(env, "java/util/ArrayList");
1759 gArrayListClass = MakeGlobalRefOrDie(env, arrayListClass);
1760 gArrayListMethods.add = GetMethodIDOrDie(env, arrayListClass, "add", "(Ljava/lang/Object;)Z");
Eric Laurent09378972014-12-10 10:42:08 -08001761 gArrayListMethods.toArray = GetMethodIDOrDie(env, arrayListClass, "toArray", "()[Ljava/lang/Object;");
Eric Laurentb69681c2014-05-19 19:02:51 -07001762
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001763 jclass audioHandleClass = FindClassOrDie(env, "android/media/AudioHandle");
1764 gAudioHandleClass = MakeGlobalRefOrDie(env, audioHandleClass);
1765 gAudioHandleCstor = GetMethodIDOrDie(env, audioHandleClass, "<init>", "(I)V");
1766 gAudioHandleFields.mId = GetFieldIDOrDie(env, audioHandleClass, "mId", "I");
Eric Laurentb69681c2014-05-19 19:02:51 -07001767
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001768 jclass audioPortClass = FindClassOrDie(env, "android/media/AudioPort");
1769 gAudioPortClass = MakeGlobalRefOrDie(env, audioPortClass);
1770 gAudioPortCstor = GetMethodIDOrDie(env, audioPortClass, "<init>",
Paul McLeanf29e5f32015-06-15 10:19:22 -07001771 "(Landroid/media/AudioHandle;ILjava/lang/String;[I[I[I[I[Landroid/media/AudioGain;)V");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001772 gAudioPortFields.mHandle = GetFieldIDOrDie(env, audioPortClass, "mHandle",
Eric Laurentb69681c2014-05-19 19:02:51 -07001773 "Landroid/media/AudioHandle;");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001774 gAudioPortFields.mRole = GetFieldIDOrDie(env, audioPortClass, "mRole", "I");
1775 gAudioPortFields.mGains = GetFieldIDOrDie(env, audioPortClass, "mGains",
Eric Laurentb69681c2014-05-19 19:02:51 -07001776 "[Landroid/media/AudioGain;");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001777 gAudioPortFields.mActiveConfig = GetFieldIDOrDie(env, audioPortClass, "mActiveConfig",
1778 "Landroid/media/AudioPortConfig;");
Eric Laurentb69681c2014-05-19 19:02:51 -07001779
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001780 jclass audioPortConfigClass = FindClassOrDie(env, "android/media/AudioPortConfig");
1781 gAudioPortConfigClass = MakeGlobalRefOrDie(env, audioPortConfigClass);
1782 gAudioPortConfigCstor = GetMethodIDOrDie(env, audioPortConfigClass, "<init>",
1783 "(Landroid/media/AudioPort;IIILandroid/media/AudioGainConfig;)V");
1784 gAudioPortConfigFields.mPort = GetFieldIDOrDie(env, audioPortConfigClass, "mPort",
Eric Laurentb69681c2014-05-19 19:02:51 -07001785 "Landroid/media/AudioPort;");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001786 gAudioPortConfigFields.mSamplingRate = GetFieldIDOrDie(env, audioPortConfigClass,
Eric Laurentb69681c2014-05-19 19:02:51 -07001787 "mSamplingRate", "I");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001788 gAudioPortConfigFields.mChannelMask = GetFieldIDOrDie(env, audioPortConfigClass,
Eric Laurentb69681c2014-05-19 19:02:51 -07001789 "mChannelMask", "I");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001790 gAudioPortConfigFields.mFormat = GetFieldIDOrDie(env, audioPortConfigClass, "mFormat", "I");
1791 gAudioPortConfigFields.mGain = GetFieldIDOrDie(env, audioPortConfigClass, "mGain",
Eric Laurentb69681c2014-05-19 19:02:51 -07001792 "Landroid/media/AudioGainConfig;");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001793 gAudioPortConfigFields.mConfigMask = GetFieldIDOrDie(env, audioPortConfigClass, "mConfigMask",
1794 "I");
Eric Laurentb69681c2014-05-19 19:02:51 -07001795
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001796 jclass audioDevicePortConfigClass = FindClassOrDie(env, "android/media/AudioDevicePortConfig");
1797 gAudioDevicePortConfigClass = MakeGlobalRefOrDie(env, audioDevicePortConfigClass);
1798 gAudioDevicePortConfigCstor = GetMethodIDOrDie(env, audioDevicePortConfigClass, "<init>",
1799 "(Landroid/media/AudioDevicePort;IIILandroid/media/AudioGainConfig;)V");
Eric Laurentb69681c2014-05-19 19:02:51 -07001800
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001801 jclass audioMixPortConfigClass = FindClassOrDie(env, "android/media/AudioMixPortConfig");
1802 gAudioMixPortConfigClass = MakeGlobalRefOrDie(env, audioMixPortConfigClass);
1803 gAudioMixPortConfigCstor = GetMethodIDOrDie(env, audioMixPortConfigClass, "<init>",
1804 "(Landroid/media/AudioMixPort;IIILandroid/media/AudioGainConfig;)V");
Eric Laurentb69681c2014-05-19 19:02:51 -07001805
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001806 jclass audioDevicePortClass = FindClassOrDie(env, "android/media/AudioDevicePort");
1807 gAudioDevicePortClass = MakeGlobalRefOrDie(env, audioDevicePortClass);
1808 gAudioDevicePortCstor = GetMethodIDOrDie(env, audioDevicePortClass, "<init>",
Paul McLeanf29e5f32015-06-15 10:19:22 -07001809 "(Landroid/media/AudioHandle;Ljava/lang/String;[I[I[I[I[Landroid/media/AudioGain;ILjava/lang/String;)V");
Eric Laurentb69681c2014-05-19 19:02:51 -07001810
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001811 jclass audioMixPortClass = FindClassOrDie(env, "android/media/AudioMixPort");
1812 gAudioMixPortClass = MakeGlobalRefOrDie(env, audioMixPortClass);
1813 gAudioMixPortCstor = GetMethodIDOrDie(env, audioMixPortClass, "<init>",
Paul McLeanf29e5f32015-06-15 10:19:22 -07001814 "(Landroid/media/AudioHandle;IILjava/lang/String;[I[I[I[I[Landroid/media/AudioGain;)V");
Eric Laurentb69681c2014-05-19 19:02:51 -07001815
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001816 jclass audioGainClass = FindClassOrDie(env, "android/media/AudioGain");
1817 gAudioGainClass = MakeGlobalRefOrDie(env, audioGainClass);
1818 gAudioGainCstor = GetMethodIDOrDie(env, audioGainClass, "<init>", "(IIIIIIIII)V");
Eric Laurentb69681c2014-05-19 19:02:51 -07001819
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001820 jclass audioGainConfigClass = FindClassOrDie(env, "android/media/AudioGainConfig");
1821 gAudioGainConfigClass = MakeGlobalRefOrDie(env, audioGainConfigClass);
1822 gAudioGainConfigCstor = GetMethodIDOrDie(env, audioGainConfigClass, "<init>",
Eric Laurentb69681c2014-05-19 19:02:51 -07001823 "(ILandroid/media/AudioGain;II[II)V");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001824 gAudioGainConfigFields.mIndex = GetFieldIDOrDie(env, gAudioGainConfigClass, "mIndex", "I");
1825 gAudioGainConfigFields.mMode = GetFieldIDOrDie(env, audioGainConfigClass, "mMode", "I");
1826 gAudioGainConfigFields.mChannelMask = GetFieldIDOrDie(env, audioGainConfigClass, "mChannelMask",
Eric Laurentb69681c2014-05-19 19:02:51 -07001827 "I");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001828 gAudioGainConfigFields.mValues = GetFieldIDOrDie(env, audioGainConfigClass, "mValues", "[I");
1829 gAudioGainConfigFields.mRampDurationMs = GetFieldIDOrDie(env, audioGainConfigClass,
Eric Laurentb69681c2014-05-19 19:02:51 -07001830 "mRampDurationMs", "I");
1831
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001832 jclass audioPatchClass = FindClassOrDie(env, "android/media/AudioPatch");
1833 gAudioPatchClass = MakeGlobalRefOrDie(env, audioPatchClass);
1834 gAudioPatchCstor = GetMethodIDOrDie(env, audioPatchClass, "<init>",
Eric Laurentb69681c2014-05-19 19:02:51 -07001835"(Landroid/media/AudioHandle;[Landroid/media/AudioPortConfig;[Landroid/media/AudioPortConfig;)V");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001836 gAudioPatchFields.mHandle = GetFieldIDOrDie(env, audioPatchClass, "mHandle",
Eric Laurentb69681c2014-05-19 19:02:51 -07001837 "Landroid/media/AudioHandle;");
1838
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001839 jclass eventHandlerClass = FindClassOrDie(env, kEventHandlerClassPathName);
Eric Laurent2615afb2015-03-25 14:51:08 -07001840 gAudioPortEventHandlerMethods.postEventFromNative = GetStaticMethodIDOrDie(
1841 env, eventHandlerClass, "postEventFromNative",
1842 "(Ljava/lang/Object;IIILjava/lang/Object;)V");
1843 gEventHandlerFields.mJniCallback = GetFieldIDOrDie(env,
1844 eventHandlerClass, "mJniCallback", "J");
Eric Laurent700e7342014-05-02 18:33:15 -07001845
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08001846 gAudioPolicyEventHandlerMethods.postDynPolicyEventFromNative =
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001847 GetStaticMethodIDOrDie(env, env->FindClass(kClassPathName),
1848 "dynamicPolicyCallbackFromNative", "(ILjava/lang/String;I)V");
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08001849 gAudioPolicyEventHandlerMethods.postRecordConfigEventFromNative =
1850 GetStaticMethodIDOrDie(env, env->FindClass(kClassPathName),
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -08001851 "recordingCallbackFromNative", "(III[I)V");
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001852
Eric Laurent09378972014-12-10 10:42:08 -08001853 jclass audioMixClass = FindClassOrDie(env, "android/media/audiopolicy/AudioMix");
1854 gAudioMixClass = MakeGlobalRefOrDie(env, audioMixClass);
1855 gAudioMixFields.mRule = GetFieldIDOrDie(env, audioMixClass, "mRule",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001856 "Landroid/media/audiopolicy/AudioMixingRule;");
Eric Laurent09378972014-12-10 10:42:08 -08001857 gAudioMixFields.mFormat = GetFieldIDOrDie(env, audioMixClass, "mFormat",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001858 "Landroid/media/AudioFormat;");
Eric Laurent09378972014-12-10 10:42:08 -08001859 gAudioMixFields.mRouteFlags = GetFieldIDOrDie(env, audioMixClass, "mRouteFlags", "I");
1860 gAudioMixFields.mRegistrationId = GetFieldIDOrDie(env, audioMixClass, "mRegistrationId",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001861 "Ljava/lang/String;");
Eric Laurent09378972014-12-10 10:42:08 -08001862 gAudioMixFields.mMixType = GetFieldIDOrDie(env, audioMixClass, "mMixType", "I");
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001863 gAudioMixFields.mCallbackFlags = GetFieldIDOrDie(env, audioMixClass, "mCallbackFlags", "I");
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001864
Eric Laurent09378972014-12-10 10:42:08 -08001865 jclass audioFormatClass = FindClassOrDie(env, "android/media/AudioFormat");
1866 gAudioFormatClass = MakeGlobalRefOrDie(env, audioFormatClass);
1867 gAudioFormatFields.mEncoding = GetFieldIDOrDie(env, audioFormatClass, "mEncoding", "I");
1868 gAudioFormatFields.mSampleRate = GetFieldIDOrDie(env, audioFormatClass, "mSampleRate", "I");
1869 gAudioFormatFields.mChannelMask = GetFieldIDOrDie(env, audioFormatClass, "mChannelMask", "I");
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001870
Eric Laurent09378972014-12-10 10:42:08 -08001871 jclass audioMixingRuleClass = FindClassOrDie(env, "android/media/audiopolicy/AudioMixingRule");
1872 gAudioMixingRuleClass = MakeGlobalRefOrDie(env, audioMixingRuleClass);
1873 gAudioMixingRuleFields.mCriteria = GetFieldIDOrDie(env, audioMixingRuleClass, "mCriteria",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001874 "Ljava/util/ArrayList;");
1875
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -08001876 jclass audioMixMatchCriterionClass =
1877 FindClassOrDie(env, "android/media/audiopolicy/AudioMixingRule$AudioMixMatchCriterion");
1878 gAudioMixMatchCriterionClass = MakeGlobalRefOrDie(env,audioMixMatchCriterionClass);
1879 gAudioMixMatchCriterionFields.mAttr = GetFieldIDOrDie(env, audioMixMatchCriterionClass, "mAttr",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001880 "Landroid/media/AudioAttributes;");
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -08001881 gAudioMixMatchCriterionFields.mIntProp = GetFieldIDOrDie(env, audioMixMatchCriterionClass, "mIntProp",
1882 "I");
1883 gAudioMixMatchCriterionFields.mRule = GetFieldIDOrDie(env, audioMixMatchCriterionClass, "mRule",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001884 "I");
1885
Eric Laurent09378972014-12-10 10:42:08 -08001886 jclass audioAttributesClass = FindClassOrDie(env, "android/media/AudioAttributes");
1887 gAudioAttributesClass = MakeGlobalRefOrDie(env, audioAttributesClass);
1888 gAudioAttributesFields.mUsage = GetFieldIDOrDie(env, audioAttributesClass, "mUsage", "I");
1889 gAudioAttributesFields.mSource = GetFieldIDOrDie(env, audioAttributesClass, "mSource", "I");
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001890
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001891 AudioSystem::setErrorCallback(android_media_AudioSystem_error_callback);
Glenn Kasten18db49a2012-03-12 16:29:55 -07001892
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001893 RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
1894 return RegisterMethodsOrDie(env, kEventHandlerClassPathName, gEventHandlerMethods,
1895 NELEM(gEventHandlerMethods));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001896}