blob: ef16ef5055de4f53170d0100fc67a0414cd2c9e9 [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;
Jean-Michel Trivi4ad39882016-03-14 18:46:41 -0700112 jfieldID mDeviceType;
113 jfieldID mDeviceAddress;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -0800114 jfieldID mMixType;
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700115 jfieldID mCallbackFlags;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -0800116} gAudioMixFields;
117
118static jclass gAudioFormatClass;
119static struct {
120 jfieldID mEncoding;
121 jfieldID mSampleRate;
122 jfieldID mChannelMask;
123 // other fields unused by JNI
124} gAudioFormatFields;
125
126static jclass gAudioMixingRuleClass;
127static struct {
128 jfieldID mCriteria;
129 // other fields unused by JNI
130} gAudioMixingRuleFields;
131
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -0800132static jclass gAudioMixMatchCriterionClass;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -0800133static struct {
134 jfieldID mAttr;
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -0800135 jfieldID mIntProp;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -0800136 jfieldID mRule;
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -0800137} gAudioMixMatchCriterionFields;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -0800138
139static jclass gAudioAttributesClass;
140static struct {
141 jfieldID mUsage;
142 jfieldID mSource;
143} gAudioAttributesFields;
144
145
Eric Laurent700e7342014-05-02 18:33:15 -0700146static const char* const kEventHandlerClassPathName =
147 "android/media/AudioPortEventHandler";
Eric Laurent2615afb2015-03-25 14:51:08 -0700148static struct {
149 jfieldID mJniCallback;
150} gEventHandlerFields;
151static struct {
152 jmethodID postEventFromNative;
153} gAudioPortEventHandlerMethods;
154
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700155static struct {
156 jmethodID postDynPolicyEventFromNative;
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800157 jmethodID postRecordConfigEventFromNative;
158} gAudioPolicyEventHandlerMethods;
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700159
Eric Laurent2615afb2015-03-25 14:51:08 -0700160static Mutex gLock;
Eric Laurentb69681c2014-05-19 19:02:51 -0700161
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162enum AudioError {
163 kAudioStatusOk = 0,
164 kAudioStatusError = 1,
165 kAudioStatusMediaServerDied = 100
166};
167
Eric Laurent700e7342014-05-02 18:33:15 -0700168enum {
169 AUDIOPORT_EVENT_PORT_LIST_UPDATED = 1,
170 AUDIOPORT_EVENT_PATCH_LIST_UPDATED = 2,
171 AUDIOPORT_EVENT_SERVICE_DIED = 3,
172};
173
Eric Laurentb69681c2014-05-19 19:02:51 -0700174#define MAX_PORT_GENERATION_SYNC_ATTEMPTS 5
175
Eric Laurent700e7342014-05-02 18:33:15 -0700176// ----------------------------------------------------------------------------
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700177// ref-counted object for audio port callbacks
Eric Laurent700e7342014-05-02 18:33:15 -0700178class JNIAudioPortCallback: public AudioSystem::AudioPortCallback
179{
180public:
181 JNIAudioPortCallback(JNIEnv* env, jobject thiz, jobject weak_thiz);
182 ~JNIAudioPortCallback();
183
184 virtual void onAudioPortListUpdate();
185 virtual void onAudioPatchListUpdate();
186 virtual void onServiceDied();
187
188private:
189 void sendEvent(int event);
190
Eric Laurent2615afb2015-03-25 14:51:08 -0700191 jclass mClass; // Reference to AudioPortEventHandler class
192 jobject mObject; // Weak ref to AudioPortEventHandler Java object to call on
Eric Laurent700e7342014-05-02 18:33:15 -0700193};
194
195JNIAudioPortCallback::JNIAudioPortCallback(JNIEnv* env, jobject thiz, jobject weak_thiz)
196{
197
Eric Laurent2615afb2015-03-25 14:51:08 -0700198 // Hold onto the AudioPortEventHandler class for use in calling the static method
Eric Laurent700e7342014-05-02 18:33:15 -0700199 // that posts events to the application thread.
200 jclass clazz = env->GetObjectClass(thiz);
201 if (clazz == NULL) {
202 ALOGE("Can't find class %s", kEventHandlerClassPathName);
203 return;
204 }
205 mClass = (jclass)env->NewGlobalRef(clazz);
206
Eric Laurent2615afb2015-03-25 14:51:08 -0700207 // We use a weak reference so the AudioPortEventHandler object can be garbage collected.
Eric Laurent700e7342014-05-02 18:33:15 -0700208 // The reference is only used as a proxy for callbacks.
209 mObject = env->NewGlobalRef(weak_thiz);
210}
211
212JNIAudioPortCallback::~JNIAudioPortCallback()
213{
214 // remove global references
215 JNIEnv *env = AndroidRuntime::getJNIEnv();
Eric Laurent449c5882014-11-12 11:07:48 -0800216 if (env == NULL) {
217 return;
218 }
Eric Laurent700e7342014-05-02 18:33:15 -0700219 env->DeleteGlobalRef(mObject);
220 env->DeleteGlobalRef(mClass);
221}
222
223void JNIAudioPortCallback::sendEvent(int event)
224{
225 JNIEnv *env = AndroidRuntime::getJNIEnv();
Eric Laurent449c5882014-11-12 11:07:48 -0800226 if (env == NULL) {
227 return;
228 }
Eric Laurent2615afb2015-03-25 14:51:08 -0700229 env->CallStaticVoidMethod(mClass, gAudioPortEventHandlerMethods.postEventFromNative, mObject,
Eric Laurent700e7342014-05-02 18:33:15 -0700230 event, 0, 0, NULL);
231 if (env->ExceptionCheck()) {
232 ALOGW("An exception occurred while notifying an event.");
233 env->ExceptionClear();
234 }
235}
236
237void JNIAudioPortCallback::onAudioPortListUpdate()
238{
239 sendEvent(AUDIOPORT_EVENT_PORT_LIST_UPDATED);
240}
241
242void JNIAudioPortCallback::onAudioPatchListUpdate()
243{
244 sendEvent(AUDIOPORT_EVENT_PATCH_LIST_UPDATED);
245}
246
247void JNIAudioPortCallback::onServiceDied()
248{
249 sendEvent(AUDIOPORT_EVENT_SERVICE_DIED);
250}
251
Eric Laurent2615afb2015-03-25 14:51:08 -0700252static sp<JNIAudioPortCallback> setJniCallback(JNIEnv* env,
253 jobject thiz,
254 const sp<JNIAudioPortCallback>& callback)
255{
256 Mutex::Autolock l(gLock);
257 sp<JNIAudioPortCallback> old =
258 (JNIAudioPortCallback*)env->GetLongField(thiz, gEventHandlerFields.mJniCallback);
259 if (callback.get()) {
260 callback->incStrong((void*)setJniCallback);
261 }
262 if (old != 0) {
263 old->decStrong((void*)setJniCallback);
264 }
265 env->SetLongField(thiz, gEventHandlerFields.mJniCallback, (jlong)callback.get());
266 return old;
267}
268
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800269static int check_AudioSystem_Command(status_t status)
270{
Eric Laurentdfb881f2013-07-18 14:41:39 -0700271 switch (status) {
272 case DEAD_OBJECT:
273 return kAudioStatusMediaServerDied;
274 case NO_ERROR:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275 return kAudioStatusOk;
Eric Laurentdfb881f2013-07-18 14:41:39 -0700276 default:
277 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800278 }
Eric Laurentdfb881f2013-07-18 14:41:39 -0700279 return kAudioStatusError;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800280}
281
Ashok Bhat075e9a12014-01-06 13:45:09 +0000282static jint
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800283android_media_AudioSystem_muteMicrophone(JNIEnv *env, jobject thiz, jboolean on)
284{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000285 return (jint) check_AudioSystem_Command(AudioSystem::muteMicrophone(on));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286}
287
288static jboolean
289android_media_AudioSystem_isMicrophoneMuted(JNIEnv *env, jobject thiz)
290{
291 bool state = false;
292 AudioSystem::isMicrophoneMuted(&state);
293 return state;
294}
295
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800296static jboolean
Eric Laurent25101b02011-02-02 09:33:30 -0800297android_media_AudioSystem_isStreamActive(JNIEnv *env, jobject thiz, jint stream, jint inPastMs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800298{
299 bool state = false;
Glenn Kastenbc1d77b2012-01-12 16:38:12 -0800300 AudioSystem::isStreamActive((audio_stream_type_t) stream, &state, inPastMs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800301 return state;
302}
303
Jean-Michel Trivid6770542012-10-10 12:03:41 -0700304static jboolean
Jean-Michel Trivi679d5042013-02-04 16:24:09 -0800305android_media_AudioSystem_isStreamActiveRemotely(JNIEnv *env, jobject thiz, jint stream,
306 jint inPastMs)
307{
308 bool state = false;
309 AudioSystem::isStreamActiveRemotely((audio_stream_type_t) stream, &state, inPastMs);
310 return state;
311}
312
313static jboolean
Jean-Michel Trivid6770542012-10-10 12:03:41 -0700314android_media_AudioSystem_isSourceActive(JNIEnv *env, jobject thiz, jint source)
315{
316 bool state = false;
317 AudioSystem::isSourceActive((audio_source_t) source, &state);
318 return state;
319}
320
Ashok Bhat075e9a12014-01-06 13:45:09 +0000321static jint
Jean-Michel Trivi8a21f5d2014-06-05 15:03:52 -0700322android_media_AudioSystem_newAudioSessionId(JNIEnv *env, jobject thiz)
323{
Glenn Kasten211d9052016-02-26 16:22:40 -0800324 return AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
Jean-Michel Trivi8a21f5d2014-06-05 15:03:52 -0700325}
326
327static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700328android_media_AudioSystem_setParameters(JNIEnv *env, jobject thiz, jstring keyValuePairs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800329{
Eric Laurenta553c252009-07-17 12:17:14 -0700330 const jchar* c_keyValuePairs = env->GetStringCritical(keyValuePairs, 0);
331 String8 c_keyValuePairs8;
332 if (keyValuePairs) {
Dan Albert66987492014-11-20 11:41:21 -0800333 c_keyValuePairs8 = String8(
334 reinterpret_cast<const char16_t*>(c_keyValuePairs),
335 env->GetStringLength(keyValuePairs));
Eric Laurenta553c252009-07-17 12:17:14 -0700336 env->ReleaseStringCritical(keyValuePairs, c_keyValuePairs);
337 }
Glenn Kastenc94752a2013-12-19 12:40:33 -0800338 int status = check_AudioSystem_Command(AudioSystem::setParameters(c_keyValuePairs8));
Ashok Bhat075e9a12014-01-06 13:45:09 +0000339 return (jint) status;
Eric Laurenta553c252009-07-17 12:17:14 -0700340}
341
342static jstring
343android_media_AudioSystem_getParameters(JNIEnv *env, jobject thiz, jstring keys)
344{
345 const jchar* c_keys = env->GetStringCritical(keys, 0);
346 String8 c_keys8;
347 if (keys) {
Dan Albert66987492014-11-20 11:41:21 -0800348 c_keys8 = String8(reinterpret_cast<const char16_t*>(c_keys),
349 env->GetStringLength(keys));
Eric Laurenta553c252009-07-17 12:17:14 -0700350 env->ReleaseStringCritical(keys, c_keys);
351 }
Glenn Kastenc94752a2013-12-19 12:40:33 -0800352 return env->NewStringUTF(AudioSystem::getParameters(c_keys8).string());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800353}
354
Glenn Kastened0079d2011-04-04 10:50:50 -0700355static void
356android_media_AudioSystem_error_callback(status_t err)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800357{
Eric Laurent539719a2013-07-18 14:08:00 -0700358 JNIEnv *env = AndroidRuntime::getJNIEnv();
Eric Laurent0e7a4d92010-10-15 12:33:16 -0700359 if (env == NULL) {
360 return;
361 }
362
Glenn Kastened0079d2011-04-04 10:50:50 -0700363 jclass clazz = env->FindClass(kClassPathName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800364
Eric Laurentdfb881f2013-07-18 14:41:39 -0700365 env->CallStaticVoidMethod(clazz, env->GetStaticMethodID(clazz,
366 "errorCallbackFromNative","(I)V"),
367 check_AudioSystem_Command(err));
Viorel Sumanb637ccf2014-05-30 16:51:07 +0300368
369 env->DeleteLocalRef(clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800370}
371
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700372static void
373android_media_AudioSystem_dyn_policy_callback(int event, String8 regId, int val)
374{
375 JNIEnv *env = AndroidRuntime::getJNIEnv();
376 if (env == NULL) {
377 return;
378 }
379
380 jclass clazz = env->FindClass(kClassPathName);
381 const char* zechars = regId.string();
382 jstring zestring = env->NewStringUTF(zechars);
383
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800384 env->CallStaticVoidMethod(clazz, gAudioPolicyEventHandlerMethods.postDynPolicyEventFromNative,
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700385 event, zestring, val);
386
387 env->ReleaseStringUTFChars(zestring, zechars);
388 env->DeleteLocalRef(clazz);
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800389}
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700390
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800391static void
Glenn Kasten33b84042016-03-08 12:02:55 -0800392android_media_AudioSystem_recording_callback(int event, audio_session_t session, int source,
Jean-Michel Trivi8ab72802016-02-25 16:31:45 -0800393 const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig,
394 audio_patch_handle_t patchHandle)
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800395{
396 JNIEnv *env = AndroidRuntime::getJNIEnv();
397 if (env == NULL) {
398 return;
399 }
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800400 if (clientConfig == NULL || deviceConfig == NULL) {
401 ALOGE("Unexpected null client/device configurations in recording callback");
402 return;
403 }
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800404
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800405 // create an array for 2*3 integers to store the record configurations (client + device)
Jean-Michel Trivi8ab72802016-02-25 16:31:45 -0800406 // plus 1 integer for the patch handle
407 const int REC_PARAM_SIZE = 7;
408 jintArray recParamArray = env->NewIntArray(REC_PARAM_SIZE);
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800409 if (recParamArray == NULL) {
410 ALOGE("recording callback: Couldn't allocate int array for configuration data");
411 return;
412 }
Jean-Michel Trivi8ab72802016-02-25 16:31:45 -0800413 jint recParamData[REC_PARAM_SIZE];
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800414 recParamData[0] = (jint) audioFormatFromNative(clientConfig->format);
415 // FIXME this doesn't support index-based masks
416 recParamData[1] = (jint) inChannelMaskFromNative(clientConfig->channel_mask);
417 recParamData[2] = (jint) clientConfig->sample_rate;
418 recParamData[3] = (jint) audioFormatFromNative(deviceConfig->format);
419 // FIXME this doesn't support index-based masks
420 recParamData[4] = (jint) inChannelMaskFromNative(deviceConfig->channel_mask);
421 recParamData[5] = (jint) deviceConfig->sample_rate;
Jean-Michel Trivi8ab72802016-02-25 16:31:45 -0800422 recParamData[6] = (jint) patchHandle;
423 env->SetIntArrayRegion(recParamArray, 0, REC_PARAM_SIZE, recParamData);
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800424
425 // callback into java
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800426 jclass clazz = env->FindClass(kClassPathName);
427 env->CallStaticVoidMethod(clazz,
428 gAudioPolicyEventHandlerMethods.postRecordConfigEventFromNative,
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800429 event, session, source, recParamArray);
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800430 env->DeleteLocalRef(clazz);
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800431
432 env->DeleteLocalRef(recParamArray);
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700433}
434
Ashok Bhat075e9a12014-01-06 13:45:09 +0000435static jint
Paul McLean10804eb2015-01-28 11:16:35 -0800436android_media_AudioSystem_setDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jint state, jstring device_address, jstring device_name)
Eric Laurenta553c252009-07-17 12:17:14 -0700437{
438 const char *c_address = env->GetStringUTFChars(device_address, NULL);
Paul McLean10804eb2015-01-28 11:16:35 -0800439 const char *c_name = env->GetStringUTFChars(device_name, NULL);
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700440 int status = check_AudioSystem_Command(AudioSystem::setDeviceConnectionState(static_cast <audio_devices_t>(device),
441 static_cast <audio_policy_dev_state_t>(state),
Paul McLean10804eb2015-01-28 11:16:35 -0800442 c_address, c_name));
Eric Laurenta553c252009-07-17 12:17:14 -0700443 env->ReleaseStringUTFChars(device_address, c_address);
Paul McLean10804eb2015-01-28 11:16:35 -0800444 env->ReleaseStringUTFChars(device_name, c_name);
Ashok Bhat075e9a12014-01-06 13:45:09 +0000445 return (jint) status;
Eric Laurenta553c252009-07-17 12:17:14 -0700446}
447
Ashok Bhat075e9a12014-01-06 13:45:09 +0000448static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700449android_media_AudioSystem_getDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jstring device_address)
450{
451 const char *c_address = env->GetStringUTFChars(device_address, NULL);
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700452 int state = static_cast <int>(AudioSystem::getDeviceConnectionState(static_cast <audio_devices_t>(device),
Eric Laurenta553c252009-07-17 12:17:14 -0700453 c_address));
454 env->ReleaseStringUTFChars(device_address, c_address);
Ashok Bhat075e9a12014-01-06 13:45:09 +0000455 return (jint) state;
Eric Laurenta553c252009-07-17 12:17:14 -0700456}
457
Ashok Bhat075e9a12014-01-06 13:45:09 +0000458static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700459android_media_AudioSystem_setPhoneState(JNIEnv *env, jobject thiz, jint state)
460{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000461 return (jint) check_AudioSystem_Command(AudioSystem::setPhoneState((audio_mode_t) state));
Eric Laurenta553c252009-07-17 12:17:14 -0700462}
463
Ashok Bhat075e9a12014-01-06 13:45:09 +0000464static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700465android_media_AudioSystem_setForceUse(JNIEnv *env, jobject thiz, jint usage, jint config)
466{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000467 return (jint) check_AudioSystem_Command(AudioSystem::setForceUse(static_cast <audio_policy_force_use_t>(usage),
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700468 static_cast <audio_policy_forced_cfg_t>(config)));
Eric Laurenta553c252009-07-17 12:17:14 -0700469}
470
Ashok Bhat075e9a12014-01-06 13:45:09 +0000471static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700472android_media_AudioSystem_getForceUse(JNIEnv *env, jobject thiz, jint usage)
473{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000474 return static_cast <jint>(AudioSystem::getForceUse(static_cast <audio_policy_force_use_t>(usage)));
Eric Laurenta553c252009-07-17 12:17:14 -0700475}
476
Ashok Bhat075e9a12014-01-06 13:45:09 +0000477static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700478android_media_AudioSystem_initStreamVolume(JNIEnv *env, jobject thiz, jint stream, jint indexMin, jint indexMax)
479{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000480 return (jint) check_AudioSystem_Command(AudioSystem::initStreamVolume(static_cast <audio_stream_type_t>(stream),
Eric Laurenta553c252009-07-17 12:17:14 -0700481 indexMin,
482 indexMax));
483}
484
Ashok Bhat075e9a12014-01-06 13:45:09 +0000485static jint
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800486android_media_AudioSystem_setStreamVolumeIndex(JNIEnv *env,
487 jobject thiz,
488 jint stream,
489 jint index,
490 jint device)
Eric Laurenta553c252009-07-17 12:17:14 -0700491{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000492 return (jint) check_AudioSystem_Command(
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800493 AudioSystem::setStreamVolumeIndex(static_cast <audio_stream_type_t>(stream),
494 index,
495 (audio_devices_t)device));
Eric Laurenta553c252009-07-17 12:17:14 -0700496}
497
Ashok Bhat075e9a12014-01-06 13:45:09 +0000498static jint
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800499android_media_AudioSystem_getStreamVolumeIndex(JNIEnv *env,
500 jobject thiz,
501 jint stream,
502 jint device)
Eric Laurenta553c252009-07-17 12:17:14 -0700503{
504 int index;
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800505 if (AudioSystem::getStreamVolumeIndex(static_cast <audio_stream_type_t>(stream),
506 &index,
507 (audio_devices_t)device)
508 != NO_ERROR) {
Eric Laurenta553c252009-07-17 12:17:14 -0700509 index = -1;
510 }
Ashok Bhat075e9a12014-01-06 13:45:09 +0000511 return (jint) index;
Eric Laurenta553c252009-07-17 12:17:14 -0700512}
513
Ashok Bhat075e9a12014-01-06 13:45:09 +0000514static jint
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400515android_media_AudioSystem_setMasterVolume(JNIEnv *env, jobject thiz, jfloat value)
516{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000517 return (jint) check_AudioSystem_Command(AudioSystem::setMasterVolume(value));
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400518}
519
520static jfloat
521android_media_AudioSystem_getMasterVolume(JNIEnv *env, jobject thiz)
522{
523 float value;
524 if (AudioSystem::getMasterVolume(&value) != NO_ERROR) {
525 value = -1.0;
526 }
527 return value;
528}
529
Ashok Bhat075e9a12014-01-06 13:45:09 +0000530static jint
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400531android_media_AudioSystem_setMasterMute(JNIEnv *env, jobject thiz, jboolean mute)
532{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000533 return (jint) check_AudioSystem_Command(AudioSystem::setMasterMute(mute));
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400534}
535
Vladimir Markoc1bcdbb2014-10-29 20:34:15 +0000536static jboolean
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400537android_media_AudioSystem_getMasterMute(JNIEnv *env, jobject thiz)
538{
539 bool mute;
540 if (AudioSystem::getMasterMute(&mute) != NO_ERROR) {
541 mute = false;
542 }
543 return mute;
544}
545
Glenn Kasten8b4b97a2011-02-04 13:54:26 -0800546static jint
Andy Hungf04b84d2015-12-18 17:33:27 -0800547android_media_AudioSystem_setMasterMono(JNIEnv *env, jobject thiz, jboolean mono)
548{
549 return (jint) check_AudioSystem_Command(AudioSystem::setMasterMono(mono));
550}
551
552static jboolean
553android_media_AudioSystem_getMasterMono(JNIEnv *env, jobject thiz)
554{
555 bool mono;
556 if (AudioSystem::getMasterMono(&mono) != NO_ERROR) {
557 mono = false;
558 }
559 return mono;
560}
561
562static jint
Glenn Kasten8b4b97a2011-02-04 13:54:26 -0800563android_media_AudioSystem_getDevicesForStream(JNIEnv *env, jobject thiz, jint stream)
564{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700565 return (jint) AudioSystem::getDevicesForStream(static_cast <audio_stream_type_t>(stream));
Glenn Kasten8b4b97a2011-02-04 13:54:26 -0800566}
567
Glenn Kastenc6c43652012-09-24 17:32:30 -0700568static jint
569android_media_AudioSystem_getPrimaryOutputSamplingRate(JNIEnv *env, jobject clazz)
570{
571 return (jint) AudioSystem::getPrimaryOutputSamplingRate();
572}
573
574static jint
575android_media_AudioSystem_getPrimaryOutputFrameCount(JNIEnv *env, jobject clazz)
576{
577 return (jint) AudioSystem::getPrimaryOutputFrameCount();
578}
579
Oliver Woodman61dcdf32013-06-26 12:43:36 +0100580static jint
581android_media_AudioSystem_getOutputLatency(JNIEnv *env, jobject clazz, jint stream)
582{
583 uint32_t afLatency;
584 if (AudioSystem::getOutputLatency(&afLatency, static_cast <audio_stream_type_t>(stream))
585 != NO_ERROR) {
586 afLatency = -1;
587 }
588 return (jint) afLatency;
589}
590
Glenn Kastenfd116ad2013-07-12 17:10:39 -0700591static jint
592android_media_AudioSystem_setLowRamDevice(JNIEnv *env, jobject clazz, jboolean isLowRamDevice)
593{
594 return (jint) AudioSystem::setLowRamDevice((bool) isLowRamDevice);
595}
596
Ashok Bhat075e9a12014-01-06 13:45:09 +0000597static jint
Eric Laurentdfb881f2013-07-18 14:41:39 -0700598android_media_AudioSystem_checkAudioFlinger(JNIEnv *env, jobject clazz)
599{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000600 return (jint) check_AudioSystem_Command(AudioSystem::checkAudioFlinger());
Eric Laurentdfb881f2013-07-18 14:41:39 -0700601}
602
Eric Laurentb69681c2014-05-19 19:02:51 -0700603
604static bool useInChannelMask(audio_port_type_t type, audio_port_role_t role)
605{
606 return ((type == AUDIO_PORT_TYPE_DEVICE) && (role == AUDIO_PORT_ROLE_SOURCE)) ||
607 ((type == AUDIO_PORT_TYPE_MIX) && (role == AUDIO_PORT_ROLE_SINK));
608}
609
Eric Laurent3a241992014-05-19 19:33:26 -0700610static void convertAudioGainConfigToNative(JNIEnv *env,
611 struct audio_gain_config *nAudioGainConfig,
612 const jobject jAudioGainConfig,
613 bool useInMask)
614{
615 nAudioGainConfig->index = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mIndex);
616 nAudioGainConfig->mode = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mMode);
617 ALOGV("convertAudioGainConfigToNative got gain index %d", nAudioGainConfig->index);
618 jint jMask = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mChannelMask);
619 audio_channel_mask_t nMask;
620 if (useInMask) {
621 nMask = inChannelMaskToNative(jMask);
622 ALOGV("convertAudioGainConfigToNative IN mask java %x native %x", jMask, nMask);
623 } else {
624 nMask = outChannelMaskToNative(jMask);
625 ALOGV("convertAudioGainConfigToNative OUT mask java %x native %x", jMask, nMask);
626 }
627 nAudioGainConfig->channel_mask = nMask;
628 nAudioGainConfig->ramp_duration_ms = env->GetIntField(jAudioGainConfig,
629 gAudioGainConfigFields.mRampDurationMs);
630 jintArray jValues = (jintArray)env->GetObjectField(jAudioGainConfig,
631 gAudioGainConfigFields.mValues);
632 int *nValues = env->GetIntArrayElements(jValues, NULL);
633 size_t size = env->GetArrayLength(jValues);
634 memcpy(nAudioGainConfig->values, nValues, size * sizeof(int));
635 env->DeleteLocalRef(jValues);
636}
637
638
Eric Laurentb69681c2014-05-19 19:02:51 -0700639static jint convertAudioPortConfigToNative(JNIEnv *env,
640 struct audio_port_config *nAudioPortConfig,
Eric Laurent6368a7d2014-11-19 12:18:32 -0800641 const jobject jAudioPortConfig,
642 bool useConfigMask)
Eric Laurentb69681c2014-05-19 19:02:51 -0700643{
644 jobject jAudioPort = env->GetObjectField(jAudioPortConfig, gAudioPortConfigFields.mPort);
645 jobject jHandle = env->GetObjectField(jAudioPort, gAudioPortFields.mHandle);
646 nAudioPortConfig->id = env->GetIntField(jHandle, gAudioHandleFields.mId);
647 nAudioPortConfig->role = (audio_port_role_t)env->GetIntField(jAudioPort,
648 gAudioPortFields.mRole);
649 if (env->IsInstanceOf(jAudioPort, gAudioDevicePortClass)) {
650 nAudioPortConfig->type = AUDIO_PORT_TYPE_DEVICE;
651 } else if (env->IsInstanceOf(jAudioPort, gAudioMixPortClass)) {
652 nAudioPortConfig->type = AUDIO_PORT_TYPE_MIX;
653 } else {
654 env->DeleteLocalRef(jAudioPort);
655 env->DeleteLocalRef(jHandle);
656 return (jint)AUDIO_JAVA_ERROR;
657 }
658 ALOGV("convertAudioPortConfigToNative handle %d role %d type %d",
659 nAudioPortConfig->id, nAudioPortConfig->role, nAudioPortConfig->type);
660
Eric Laurent6368a7d2014-11-19 12:18:32 -0800661 unsigned int configMask = 0;
662
Eric Laurentb69681c2014-05-19 19:02:51 -0700663 nAudioPortConfig->sample_rate = env->GetIntField(jAudioPortConfig,
664 gAudioPortConfigFields.mSamplingRate);
Eric Laurent6368a7d2014-11-19 12:18:32 -0800665 if (nAudioPortConfig->sample_rate != 0) {
666 configMask |= AUDIO_PORT_CONFIG_SAMPLE_RATE;
667 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700668
669 bool useInMask = useInChannelMask(nAudioPortConfig->type, nAudioPortConfig->role);
670 audio_channel_mask_t nMask;
671 jint jMask = env->GetIntField(jAudioPortConfig,
672 gAudioPortConfigFields.mChannelMask);
673 if (useInMask) {
674 nMask = inChannelMaskToNative(jMask);
675 ALOGV("convertAudioPortConfigToNative IN mask java %x native %x", jMask, nMask);
676 } else {
677 nMask = outChannelMaskToNative(jMask);
678 ALOGV("convertAudioPortConfigToNative OUT mask java %x native %x", jMask, nMask);
679 }
680 nAudioPortConfig->channel_mask = nMask;
Eric Laurent6368a7d2014-11-19 12:18:32 -0800681 if (nAudioPortConfig->channel_mask != AUDIO_CHANNEL_NONE) {
682 configMask |= AUDIO_PORT_CONFIG_CHANNEL_MASK;
683 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700684
685 jint jFormat = env->GetIntField(jAudioPortConfig, gAudioPortConfigFields.mFormat);
686 audio_format_t nFormat = audioFormatToNative(jFormat);
687 ALOGV("convertAudioPortConfigToNative format %d native %d", jFormat, nFormat);
688 nAudioPortConfig->format = nFormat;
Eric Laurent6368a7d2014-11-19 12:18:32 -0800689 if (nAudioPortConfig->format != AUDIO_FORMAT_DEFAULT &&
690 nAudioPortConfig->format != AUDIO_FORMAT_INVALID) {
691 configMask |= AUDIO_PORT_CONFIG_FORMAT;
692 }
693
Eric Laurentb69681c2014-05-19 19:02:51 -0700694 jobject jGain = env->GetObjectField(jAudioPortConfig, gAudioPortConfigFields.mGain);
695 if (jGain != NULL) {
Eric Laurent3a241992014-05-19 19:33:26 -0700696 convertAudioGainConfigToNative(env, &nAudioPortConfig->gain, jGain, useInMask);
Eric Laurentb69681c2014-05-19 19:02:51 -0700697 env->DeleteLocalRef(jGain);
Eric Laurent6368a7d2014-11-19 12:18:32 -0800698 configMask |= AUDIO_PORT_CONFIG_GAIN;
Eric Laurentb69681c2014-05-19 19:02:51 -0700699 } else {
700 ALOGV("convertAudioPortConfigToNative no gain");
701 nAudioPortConfig->gain.index = -1;
702 }
Eric Laurent6368a7d2014-11-19 12:18:32 -0800703 if (useConfigMask) {
704 nAudioPortConfig->config_mask = env->GetIntField(jAudioPortConfig,
705 gAudioPortConfigFields.mConfigMask);
706 } else {
707 nAudioPortConfig->config_mask = configMask;
708 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700709 env->DeleteLocalRef(jAudioPort);
710 env->DeleteLocalRef(jHandle);
711 return (jint)AUDIO_JAVA_SUCCESS;
712}
713
714static jint convertAudioPortConfigFromNative(JNIEnv *env,
715 jobject jAudioPort,
716 jobject *jAudioPortConfig,
717 const struct audio_port_config *nAudioPortConfig)
718{
719 jint jStatus = AUDIO_JAVA_SUCCESS;
720 jobject jAudioGainConfig = NULL;
721 jobject jAudioGain = NULL;
722 jintArray jGainValues;
723 bool audioportCreated = false;
724
725 ALOGV("convertAudioPortConfigFromNative jAudioPort %p", jAudioPort);
726
727 if (jAudioPort == NULL) {
728 jobject jHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
729 nAudioPortConfig->id);
730
731 ALOGV("convertAudioPortConfigFromNative handle %d is a %s", nAudioPortConfig->id,
732 nAudioPortConfig->type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix");
733
734 if (jHandle == NULL) {
735 return (jint)AUDIO_JAVA_ERROR;
736 }
737 // create dummy port and port config objects with just the correct handle
738 // and configuration data. The actual AudioPortConfig objects will be
739 // constructed by java code with correct class type (device, mix etc...)
740 // and reference to AudioPort instance in this client
741 jAudioPort = env->NewObject(gAudioPortClass, gAudioPortCstor,
Paul McLeanf29e5f32015-06-15 10:19:22 -0700742 jHandle, // handle
743 0, // role
744 NULL, // name
745 NULL, // samplingRates
746 NULL, // channelMasks
747 NULL, // channelIndexMasks
748 NULL, // formats
749 NULL); // gains
Eric Laurentb69681c2014-05-19 19:02:51 -0700750 env->DeleteLocalRef(jHandle);
751 if (jAudioPort == NULL) {
752 return (jint)AUDIO_JAVA_ERROR;
753 }
754 ALOGV("convertAudioPortConfigFromNative jAudioPort created for handle %d",
755 nAudioPortConfig->id);
756
757 audioportCreated = true;
758 }
759
760 bool useInMask = useInChannelMask(nAudioPortConfig->type, nAudioPortConfig->role);
761
762 audio_channel_mask_t nMask;
763 jint jMask;
764
765 int gainIndex = nAudioPortConfig->gain.index;
766 if (gainIndex >= 0) {
767 ALOGV("convertAudioPortConfigFromNative gain found with index %d mode %x",
768 gainIndex, nAudioPortConfig->gain.mode);
769 if (audioportCreated) {
770 ALOGV("convertAudioPortConfigFromNative creating gain");
771 jAudioGain = env->NewObject(gAudioGainClass, gAudioGainCstor,
772 gainIndex,
773 0,
774 0,
775 0,
776 0,
777 0,
778 0,
779 0,
780 0);
781 if (jAudioGain == NULL) {
782 ALOGV("convertAudioPortConfigFromNative creating gain FAILED");
783 jStatus = (jint)AUDIO_JAVA_ERROR;
784 goto exit;
785 }
786 } else {
787 ALOGV("convertAudioPortConfigFromNative reading gain from port");
788 jobjectArray jGains = (jobjectArray)env->GetObjectField(jAudioPort,
789 gAudioPortFields.mGains);
790 if (jGains == NULL) {
791 ALOGV("convertAudioPortConfigFromNative could not get gains from port");
792 jStatus = (jint)AUDIO_JAVA_ERROR;
793 goto exit;
794 }
795 jAudioGain = env->GetObjectArrayElement(jGains, gainIndex);
796 env->DeleteLocalRef(jGains);
797 if (jAudioGain == NULL) {
798 ALOGV("convertAudioPortConfigFromNative could not get gain at index %d", gainIndex);
799 jStatus = (jint)AUDIO_JAVA_ERROR;
800 goto exit;
801 }
802 }
Eric Laurent0078c7c2014-06-04 09:49:52 -0700803 int numValues;
804 if (useInMask) {
805 numValues = audio_channel_count_from_in_mask(nAudioPortConfig->gain.channel_mask);
806 } else {
807 numValues = audio_channel_count_from_out_mask(nAudioPortConfig->gain.channel_mask);
808 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700809 jGainValues = env->NewIntArray(numValues);
810 if (jGainValues == NULL) {
811 ALOGV("convertAudioPortConfigFromNative could not create gain values %d", numValues);
812 jStatus = (jint)AUDIO_JAVA_ERROR;
813 goto exit;
814 }
815 env->SetIntArrayRegion(jGainValues, 0, numValues,
816 nAudioPortConfig->gain.values);
817
818 nMask = nAudioPortConfig->gain.channel_mask;
819 if (useInMask) {
820 jMask = inChannelMaskFromNative(nMask);
821 ALOGV("convertAudioPortConfigFromNative IN mask java %x native %x", jMask, nMask);
822 } else {
823 jMask = outChannelMaskFromNative(nMask);
824 ALOGV("convertAudioPortConfigFromNative OUT mask java %x native %x", jMask, nMask);
825 }
826
827 jAudioGainConfig = env->NewObject(gAudioGainConfigClass,
828 gAudioGainConfigCstor,
829 gainIndex,
830 jAudioGain,
831 nAudioPortConfig->gain.mode,
832 jMask,
833 jGainValues,
834 nAudioPortConfig->gain.ramp_duration_ms);
835 env->DeleteLocalRef(jGainValues);
836 if (jAudioGainConfig == NULL) {
837 ALOGV("convertAudioPortConfigFromNative could not create gain config");
838 jStatus = (jint)AUDIO_JAVA_ERROR;
839 goto exit;
840 }
841 }
842 jclass clazz;
843 jmethodID methodID;
844 if (audioportCreated) {
845 clazz = gAudioPortConfigClass;
846 methodID = gAudioPortConfigCstor;
847 ALOGV("convertAudioPortConfigFromNative building a generic port config");
848 } else {
849 if (env->IsInstanceOf(jAudioPort, gAudioDevicePortClass)) {
850 clazz = gAudioDevicePortConfigClass;
851 methodID = gAudioDevicePortConfigCstor;
852 ALOGV("convertAudioPortConfigFromNative building a device config");
853 } else if (env->IsInstanceOf(jAudioPort, gAudioMixPortClass)) {
854 clazz = gAudioMixPortConfigClass;
855 methodID = gAudioMixPortConfigCstor;
856 ALOGV("convertAudioPortConfigFromNative building a mix config");
857 } else {
858 jStatus = (jint)AUDIO_JAVA_ERROR;
859 goto exit;
860 }
861 }
862 nMask = nAudioPortConfig->channel_mask;
863 if (useInMask) {
864 jMask = inChannelMaskFromNative(nMask);
865 ALOGV("convertAudioPortConfigFromNative IN mask java %x native %x", jMask, nMask);
866 } else {
867 jMask = outChannelMaskFromNative(nMask);
868 ALOGV("convertAudioPortConfigFromNative OUT mask java %x native %x", jMask, nMask);
869 }
870
871 *jAudioPortConfig = env->NewObject(clazz, methodID,
872 jAudioPort,
873 nAudioPortConfig->sample_rate,
874 jMask,
875 audioFormatFromNative(nAudioPortConfig->format),
876 jAudioGainConfig);
877 if (*jAudioPortConfig == NULL) {
878 ALOGV("convertAudioPortConfigFromNative could not create new port config");
879 jStatus = (jint)AUDIO_JAVA_ERROR;
880 } else {
881 ALOGV("convertAudioPortConfigFromNative OK");
882 }
883
884exit:
885 if (audioportCreated) {
886 env->DeleteLocalRef(jAudioPort);
887 if (jAudioGain != NULL) {
888 env->DeleteLocalRef(jAudioGain);
889 }
890 }
891 if (jAudioGainConfig != NULL) {
892 env->DeleteLocalRef(jAudioGainConfig);
893 }
894 return jStatus;
895}
896
Paul McLean4e5e9e92015-06-17 10:10:11 -0700897static bool hasFormat(int* formats, size_t size, int format) {
898 for (size_t index = 0; index < size; index++) {
899 if (formats[index] == format) {
900 return true; // found
901 }
902 }
903 return false; // not found
904}
905
Eric Laurentb69681c2014-05-19 19:02:51 -0700906static jint convertAudioPortFromNative(JNIEnv *env,
907 jobject *jAudioPort, const struct audio_port *nAudioPort)
908{
909 jint jStatus = (jint)AUDIO_JAVA_SUCCESS;
910 jintArray jSamplingRates = NULL;
911 jintArray jChannelMasks = NULL;
Paul McLeanf29e5f32015-06-15 10:19:22 -0700912 jintArray jChannelIndexMasks = NULL;
Paul McLean4e5e9e92015-06-17 10:10:11 -0700913 int* cFormats = NULL;
Eric Laurentb69681c2014-05-19 19:02:51 -0700914 jintArray jFormats = NULL;
915 jobjectArray jGains = NULL;
916 jobject jHandle = NULL;
Paul McLean10804eb2015-01-28 11:16:35 -0800917 jstring jDeviceName = NULL;
Eric Laurentb69681c2014-05-19 19:02:51 -0700918 bool useInMask;
Paul McLeanf29e5f32015-06-15 10:19:22 -0700919 size_t numPositionMasks = 0;
920 size_t numIndexMasks = 0;
Paul McLean2db94372015-06-18 12:47:34 -0700921 size_t numUniqueFormats = 0;
922
Paul McLean10804eb2015-01-28 11:16:35 -0800923 ALOGV("convertAudioPortFromNative id %d role %d type %d name %s",
924 nAudioPort->id, nAudioPort->role, nAudioPort->type, nAudioPort->name);
Eric Laurentb69681c2014-05-19 19:02:51 -0700925
926 jSamplingRates = env->NewIntArray(nAudioPort->num_sample_rates);
927 if (jSamplingRates == NULL) {
928 jStatus = (jint)AUDIO_JAVA_ERROR;
929 goto exit;
930 }
931 if (nAudioPort->num_sample_rates) {
932 env->SetIntArrayRegion(jSamplingRates, 0, nAudioPort->num_sample_rates,
933 (jint *)nAudioPort->sample_rates);
934 }
935
Paul McLeanf29e5f32015-06-15 10:19:22 -0700936 // count up how many masks are positional and indexed
937 for(size_t index = 0; index < nAudioPort->num_channel_masks; index++) {
938 const audio_channel_mask_t mask = nAudioPort->channel_masks[index];
939 if (audio_channel_mask_get_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
940 numIndexMasks++;
941 } else {
942 numPositionMasks++;
943 }
944 }
945
946 jChannelMasks = env->NewIntArray(numPositionMasks);
Eric Laurentb69681c2014-05-19 19:02:51 -0700947 if (jChannelMasks == NULL) {
948 jStatus = (jint)AUDIO_JAVA_ERROR;
949 goto exit;
950 }
Paul McLeanf29e5f32015-06-15 10:19:22 -0700951 jChannelIndexMasks = env->NewIntArray(numIndexMasks);
952 if (jChannelIndexMasks == NULL) {
953 jStatus = (jint)AUDIO_JAVA_ERROR;
954 goto exit;
955 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700956 useInMask = useInChannelMask(nAudioPort->type, nAudioPort->role);
957
Paul McLeanf29e5f32015-06-15 10:19:22 -0700958 // put the masks in the output arrays
959 for (size_t maskIndex = 0, posMaskIndex = 0, indexedMaskIndex = 0;
960 maskIndex < nAudioPort->num_channel_masks; maskIndex++) {
961 const audio_channel_mask_t mask = nAudioPort->channel_masks[maskIndex];
962 if (audio_channel_mask_get_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
963 jint jMask = audio_channel_mask_get_bits(mask);
964 env->SetIntArrayRegion(jChannelIndexMasks, indexedMaskIndex++, 1, &jMask);
Eric Laurentb69681c2014-05-19 19:02:51 -0700965 } else {
Paul McLeanf29e5f32015-06-15 10:19:22 -0700966 jint jMask = useInMask ? inChannelMaskFromNative(mask)
967 : outChannelMaskFromNative(mask);
968 env->SetIntArrayRegion(jChannelMasks, posMaskIndex++, 1, &jMask);
Eric Laurentb69681c2014-05-19 19:02:51 -0700969 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700970 }
971
Paul McLeanf29e5f32015-06-15 10:19:22 -0700972 // formats
Paul McLean2db94372015-06-18 12:47:34 -0700973 if (nAudioPort->num_formats != 0) {
974 cFormats = new int[nAudioPort->num_formats];
975 for (size_t index = 0; index < nAudioPort->num_formats; index++) {
976 int format = audioFormatFromNative(nAudioPort->formats[index]);
977 if (!hasFormat(cFormats, numUniqueFormats, format)) {
978 cFormats[numUniqueFormats++] = format;
979 }
Paul McLean4e5e9e92015-06-17 10:10:11 -0700980 }
981 }
982 jFormats = env->NewIntArray(numUniqueFormats);
Eric Laurentb69681c2014-05-19 19:02:51 -0700983 if (jFormats == NULL) {
984 jStatus = (jint)AUDIO_JAVA_ERROR;
985 goto exit;
986 }
Paul McLean2db94372015-06-18 12:47:34 -0700987 if (numUniqueFormats != 0) {
988 env->SetIntArrayRegion(jFormats, 0, numUniqueFormats, cFormats);
989 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700990
Paul McLeanf29e5f32015-06-15 10:19:22 -0700991 // gains
Eric Laurentb69681c2014-05-19 19:02:51 -0700992 jGains = env->NewObjectArray(nAudioPort->num_gains,
993 gAudioGainClass, NULL);
994 if (jGains == NULL) {
995 jStatus = (jint)AUDIO_JAVA_ERROR;
996 goto exit;
997 }
Paul McLeanf29e5f32015-06-15 10:19:22 -0700998
Eric Laurentb69681c2014-05-19 19:02:51 -0700999 for (size_t j = 0; j < nAudioPort->num_gains; j++) {
1000 audio_channel_mask_t nMask = nAudioPort->gains[j].channel_mask;
Paul McLeanf29e5f32015-06-15 10:19:22 -07001001 jint jMask;
Eric Laurentb69681c2014-05-19 19:02:51 -07001002 if (useInMask) {
1003 jMask = inChannelMaskFromNative(nMask);
1004 ALOGV("convertAudioPortConfigFromNative IN mask java %x native %x", jMask, nMask);
1005 } else {
1006 jMask = outChannelMaskFromNative(nMask);
1007 ALOGV("convertAudioPortConfigFromNative OUT mask java %x native %x", jMask, nMask);
1008 }
1009
1010 jobject jGain = env->NewObject(gAudioGainClass, gAudioGainCstor,
1011 j,
1012 nAudioPort->gains[j].mode,
1013 jMask,
1014 nAudioPort->gains[j].min_value,
1015 nAudioPort->gains[j].max_value,
1016 nAudioPort->gains[j].default_value,
1017 nAudioPort->gains[j].step_value,
1018 nAudioPort->gains[j].min_ramp_ms,
1019 nAudioPort->gains[j].max_ramp_ms);
1020 if (jGain == NULL) {
1021 jStatus = (jint)AUDIO_JAVA_ERROR;
1022 goto exit;
1023 }
1024 env->SetObjectArrayElement(jGains, j, jGain);
1025 env->DeleteLocalRef(jGain);
1026 }
1027
1028 jHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
1029 nAudioPort->id);
1030 if (jHandle == NULL) {
1031 jStatus = (jint)AUDIO_JAVA_ERROR;
1032 goto exit;
1033 }
1034
Paul McLean10804eb2015-01-28 11:16:35 -08001035 jDeviceName = env->NewStringUTF(nAudioPort->name);
1036
Eric Laurentb69681c2014-05-19 19:02:51 -07001037 if (nAudioPort->type == AUDIO_PORT_TYPE_DEVICE) {
1038 ALOGV("convertAudioPortFromNative is a device %08x", nAudioPort->ext.device.type);
1039 jstring jAddress = env->NewStringUTF(nAudioPort->ext.device.address);
1040 *jAudioPort = env->NewObject(gAudioDevicePortClass, gAudioDevicePortCstor,
Paul McLean10804eb2015-01-28 11:16:35 -08001041 jHandle, jDeviceName,
Paul McLeanf29e5f32015-06-15 10:19:22 -07001042 jSamplingRates, jChannelMasks, jChannelIndexMasks,
1043 jFormats, jGains,
Eric Laurentb69681c2014-05-19 19:02:51 -07001044 nAudioPort->ext.device.type, jAddress);
1045 env->DeleteLocalRef(jAddress);
1046 } else if (nAudioPort->type == AUDIO_PORT_TYPE_MIX) {
1047 ALOGV("convertAudioPortFromNative is a mix");
1048 *jAudioPort = env->NewObject(gAudioMixPortClass, gAudioMixPortCstor,
Eric Laurent4bcdba82015-05-01 11:37:49 -07001049 jHandle, nAudioPort->ext.mix.handle,
1050 nAudioPort->role, jDeviceName,
Paul McLeanf29e5f32015-06-15 10:19:22 -07001051 jSamplingRates, jChannelMasks, jChannelIndexMasks,
Eric Laurentb69681c2014-05-19 19:02:51 -07001052 jFormats, jGains);
1053 } else {
1054 ALOGE("convertAudioPortFromNative unknown nAudioPort type %d", nAudioPort->type);
1055 jStatus = (jint)AUDIO_JAVA_ERROR;
1056 goto exit;
1057 }
1058 if (*jAudioPort == NULL) {
1059 jStatus = (jint)AUDIO_JAVA_ERROR;
1060 goto exit;
1061 }
1062
1063 jobject jAudioPortConfig;
1064 jStatus = convertAudioPortConfigFromNative(env,
1065 *jAudioPort,
1066 &jAudioPortConfig,
1067 &nAudioPort->active_config);
1068 if (jStatus != AUDIO_JAVA_SUCCESS) {
1069 return jStatus;
1070 }
1071
1072 env->SetObjectField(*jAudioPort, gAudioPortFields.mActiveConfig, jAudioPortConfig);
1073
1074exit:
Paul McLean10804eb2015-01-28 11:16:35 -08001075 if (jDeviceName != NULL) {
1076 env->DeleteLocalRef(jDeviceName);
1077 }
Eric Laurentb69681c2014-05-19 19:02:51 -07001078 if (jSamplingRates != NULL) {
1079 env->DeleteLocalRef(jSamplingRates);
1080 }
1081 if (jChannelMasks != NULL) {
1082 env->DeleteLocalRef(jChannelMasks);
1083 }
Paul McLean4e5e9e92015-06-17 10:10:11 -07001084 if (jChannelIndexMasks != NULL) {
1085 env->DeleteLocalRef(jChannelIndexMasks);
1086 }
1087 if (cFormats != NULL) {
1088 delete[] cFormats;
1089 }
Eric Laurentb69681c2014-05-19 19:02:51 -07001090 if (jFormats != NULL) {
1091 env->DeleteLocalRef(jFormats);
1092 }
1093 if (jGains != NULL) {
1094 env->DeleteLocalRef(jGains);
1095 }
1096 if (jHandle != NULL) {
1097 env->DeleteLocalRef(jHandle);
1098 }
1099
1100 return jStatus;
1101}
1102
1103
1104static jint
1105android_media_AudioSystem_listAudioPorts(JNIEnv *env, jobject clazz,
1106 jobject jPorts, jintArray jGeneration)
1107{
1108 ALOGV("listAudioPorts");
1109
1110 if (jPorts == NULL) {
1111 ALOGE("listAudioPorts NULL AudioPort ArrayList");
1112 return (jint)AUDIO_JAVA_BAD_VALUE;
1113 }
1114 if (!env->IsInstanceOf(jPorts, gArrayListClass)) {
1115 ALOGE("listAudioPorts not an arraylist");
1116 return (jint)AUDIO_JAVA_BAD_VALUE;
1117 }
1118
1119 if (jGeneration == NULL || env->GetArrayLength(jGeneration) != 1) {
1120 return (jint)AUDIO_JAVA_BAD_VALUE;
1121 }
1122
1123 status_t status;
1124 unsigned int generation1;
1125 unsigned int generation;
1126 unsigned int numPorts;
1127 jint *nGeneration;
1128 struct audio_port *nPorts = NULL;
1129 int attempts = MAX_PORT_GENERATION_SYNC_ATTEMPTS;
Eric Laurentb36d1042016-04-14 18:00:38 -07001130 jint jStatus;
Eric Laurentb69681c2014-05-19 19:02:51 -07001131
1132 // get the port count and all the ports until they both return the same generation
1133 do {
1134 if (attempts-- < 0) {
1135 status = TIMED_OUT;
1136 break;
1137 }
1138
1139 numPorts = 0;
1140 status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE,
1141 AUDIO_PORT_TYPE_NONE,
1142 &numPorts,
1143 NULL,
1144 &generation1);
Eric Laurentb36d1042016-04-14 18:00:38 -07001145 if (status != NO_ERROR) {
Eric Laurentb69681c2014-05-19 19:02:51 -07001146 ALOGE_IF(status != NO_ERROR, "AudioSystem::listAudioPorts error %d", status);
1147 break;
1148 }
Eric Laurentb36d1042016-04-14 18:00:38 -07001149 if (numPorts == 0) {
1150 jStatus = (jint)AUDIO_JAVA_SUCCESS;
1151 goto exit;
1152 }
Eric Laurentb69681c2014-05-19 19:02:51 -07001153 nPorts = (struct audio_port *)realloc(nPorts, numPorts * sizeof(struct audio_port));
1154
1155 status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE,
1156 AUDIO_PORT_TYPE_NONE,
1157 &numPorts,
1158 nPorts,
1159 &generation);
1160 ALOGV("listAudioPorts AudioSystem::listAudioPorts numPorts %d generation %d generation1 %d",
1161 numPorts, generation, generation1);
1162 } while (generation1 != generation && status == NO_ERROR);
1163
Eric Laurentb36d1042016-04-14 18:00:38 -07001164 jStatus = nativeToJavaStatus(status);
Eric Laurentb69681c2014-05-19 19:02:51 -07001165 if (jStatus != AUDIO_JAVA_SUCCESS) {
1166 goto exit;
1167 }
1168
Eric Laurentb69681c2014-05-19 19:02:51 -07001169 for (size_t i = 0; i < numPorts; i++) {
1170 jobject jAudioPort;
1171 jStatus = convertAudioPortFromNative(env, &jAudioPort, &nPorts[i]);
1172 if (jStatus != AUDIO_JAVA_SUCCESS) {
1173 goto exit;
1174 }
1175 env->CallBooleanMethod(jPorts, gArrayListMethods.add, jAudioPort);
1176 }
1177
1178exit:
Eric Laurentb36d1042016-04-14 18:00:38 -07001179 nGeneration = env->GetIntArrayElements(jGeneration, NULL);
1180 if (nGeneration == NULL) {
1181 jStatus = (jint)AUDIO_JAVA_ERROR;
1182 } else {
1183 nGeneration[0] = generation1;
1184 env->ReleaseIntArrayElements(jGeneration, nGeneration, 0);
1185 }
Eric Laurentb69681c2014-05-19 19:02:51 -07001186 free(nPorts);
1187 return jStatus;
1188}
1189
1190static int
1191android_media_AudioSystem_createAudioPatch(JNIEnv *env, jobject clazz,
1192 jobjectArray jPatches, jobjectArray jSources, jobjectArray jSinks)
1193{
1194 status_t status;
1195 jint jStatus;
1196
1197 ALOGV("createAudioPatch");
1198 if (jPatches == NULL || jSources == NULL || jSinks == NULL) {
1199 return (jint)AUDIO_JAVA_BAD_VALUE;
1200 }
1201
1202 if (env->GetArrayLength(jPatches) != 1) {
1203 return (jint)AUDIO_JAVA_BAD_VALUE;
1204 }
1205 jint numSources = env->GetArrayLength(jSources);
1206 if (numSources == 0 || numSources > AUDIO_PATCH_PORTS_MAX) {
1207 return (jint)AUDIO_JAVA_BAD_VALUE;
1208 }
1209
1210 jint numSinks = env->GetArrayLength(jSinks);
1211 if (numSinks == 0 || numSinks > AUDIO_PATCH_PORTS_MAX) {
1212 return (jint)AUDIO_JAVA_BAD_VALUE;
1213 }
1214
1215 audio_patch_handle_t handle = (audio_patch_handle_t)0;
1216 jobject jPatch = env->GetObjectArrayElement(jPatches, 0);
1217 jobject jPatchHandle = NULL;
1218 if (jPatch != NULL) {
1219 if (!env->IsInstanceOf(jPatch, gAudioPatchClass)) {
1220 return (jint)AUDIO_JAVA_BAD_VALUE;
1221 }
1222 jPatchHandle = env->GetObjectField(jPatch, gAudioPatchFields.mHandle);
1223 handle = (audio_patch_handle_t)env->GetIntField(jPatchHandle, gAudioHandleFields.mId);
1224 }
1225
1226 struct audio_patch nPatch;
1227
1228 nPatch.id = handle;
1229 nPatch.num_sources = 0;
1230 nPatch.num_sinks = 0;
1231 jobject jSource = NULL;
1232 jobject jSink = NULL;
1233
1234 for (jint i = 0; i < numSources; i++) {
1235 jSource = env->GetObjectArrayElement(jSources, i);
1236 if (!env->IsInstanceOf(jSource, gAudioPortConfigClass)) {
1237 jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
1238 goto exit;
1239 }
Eric Laurent6368a7d2014-11-19 12:18:32 -08001240 jStatus = convertAudioPortConfigToNative(env, &nPatch.sources[i], jSource, false);
Eric Laurentb69681c2014-05-19 19:02:51 -07001241 env->DeleteLocalRef(jSource);
1242 jSource = NULL;
1243 if (jStatus != AUDIO_JAVA_SUCCESS) {
1244 goto exit;
1245 }
1246 nPatch.num_sources++;
1247 }
1248
1249 for (jint i = 0; i < numSinks; i++) {
1250 jSink = env->GetObjectArrayElement(jSinks, i);
1251 if (!env->IsInstanceOf(jSink, gAudioPortConfigClass)) {
1252 jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
1253 goto exit;
1254 }
Eric Laurent6368a7d2014-11-19 12:18:32 -08001255 jStatus = convertAudioPortConfigToNative(env, &nPatch.sinks[i], jSink, false);
Eric Laurentb69681c2014-05-19 19:02:51 -07001256 env->DeleteLocalRef(jSink);
1257 jSink = NULL;
1258 if (jStatus != AUDIO_JAVA_SUCCESS) {
1259 goto exit;
1260 }
1261 nPatch.num_sinks++;
1262 }
1263
1264 ALOGV("AudioSystem::createAudioPatch");
1265 status = AudioSystem::createAudioPatch(&nPatch, &handle);
1266 ALOGV("AudioSystem::createAudioPatch() returned %d hande %d", status, handle);
1267
1268 jStatus = nativeToJavaStatus(status);
1269 if (jStatus != AUDIO_JAVA_SUCCESS) {
1270 goto exit;
1271 }
1272
1273 if (jPatchHandle == NULL) {
1274 jPatchHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
1275 handle);
1276 if (jPatchHandle == NULL) {
1277 jStatus = (jint)AUDIO_JAVA_ERROR;
1278 goto exit;
1279 }
1280 jPatch = env->NewObject(gAudioPatchClass, gAudioPatchCstor, jPatchHandle, jSources, jSinks);
1281 if (jPatch == NULL) {
1282 jStatus = (jint)AUDIO_JAVA_ERROR;
1283 goto exit;
1284 }
1285 env->SetObjectArrayElement(jPatches, 0, jPatch);
1286 } else {
1287 env->SetIntField(jPatchHandle, gAudioHandleFields.mId, handle);
1288 }
1289
1290exit:
1291 if (jPatchHandle != NULL) {
1292 env->DeleteLocalRef(jPatchHandle);
1293 }
1294 if (jPatch != NULL) {
1295 env->DeleteLocalRef(jPatch);
1296 }
1297 if (jSource != NULL) {
1298 env->DeleteLocalRef(jSource);
1299 }
1300 if (jSink != NULL) {
1301 env->DeleteLocalRef(jSink);
1302 }
1303 return jStatus;
1304}
1305
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001306static jint
Eric Laurentb69681c2014-05-19 19:02:51 -07001307android_media_AudioSystem_releaseAudioPatch(JNIEnv *env, jobject clazz,
1308 jobject jPatch)
1309{
1310 ALOGV("releaseAudioPatch");
1311 if (jPatch == NULL) {
1312 return (jint)AUDIO_JAVA_BAD_VALUE;
1313 }
1314
1315 audio_patch_handle_t handle = (audio_patch_handle_t)0;
1316 jobject jPatchHandle = NULL;
1317 if (!env->IsInstanceOf(jPatch, gAudioPatchClass)) {
1318 return (jint)AUDIO_JAVA_BAD_VALUE;
1319 }
1320 jPatchHandle = env->GetObjectField(jPatch, gAudioPatchFields.mHandle);
1321 handle = (audio_patch_handle_t)env->GetIntField(jPatchHandle, gAudioHandleFields.mId);
1322 env->DeleteLocalRef(jPatchHandle);
1323
1324 ALOGV("AudioSystem::releaseAudioPatch");
1325 status_t status = AudioSystem::releaseAudioPatch(handle);
1326 ALOGV("AudioSystem::releaseAudioPatch() returned %d", status);
1327 jint jStatus = nativeToJavaStatus(status);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001328 return jStatus;
Eric Laurentb69681c2014-05-19 19:02:51 -07001329}
1330
1331static jint
1332android_media_AudioSystem_listAudioPatches(JNIEnv *env, jobject clazz,
1333 jobject jPatches, jintArray jGeneration)
1334{
1335 ALOGV("listAudioPatches");
1336 if (jPatches == NULL) {
1337 ALOGE("listAudioPatches NULL AudioPatch ArrayList");
1338 return (jint)AUDIO_JAVA_BAD_VALUE;
1339 }
1340 if (!env->IsInstanceOf(jPatches, gArrayListClass)) {
1341 ALOGE("listAudioPatches not an arraylist");
1342 return (jint)AUDIO_JAVA_BAD_VALUE;
1343 }
1344
1345 if (jGeneration == NULL || env->GetArrayLength(jGeneration) != 1) {
1346 return (jint)AUDIO_JAVA_BAD_VALUE;
1347 }
1348
1349 status_t status;
1350 unsigned int generation1;
1351 unsigned int generation;
1352 unsigned int numPatches;
1353 jint *nGeneration;
1354 struct audio_patch *nPatches = NULL;
1355 jobjectArray jSources = NULL;
1356 jobject jSource = NULL;
1357 jobjectArray jSinks = NULL;
1358 jobject jSink = NULL;
1359 jobject jPatch = NULL;
1360 int attempts = MAX_PORT_GENERATION_SYNC_ATTEMPTS;
Eric Laurentb36d1042016-04-14 18:00:38 -07001361 jint jStatus;
Eric Laurentb69681c2014-05-19 19:02:51 -07001362
1363 // get the patch count and all the patches until they both return the same generation
1364 do {
1365 if (attempts-- < 0) {
1366 status = TIMED_OUT;
1367 break;
1368 }
1369
1370 numPatches = 0;
1371 status = AudioSystem::listAudioPatches(&numPatches,
1372 NULL,
1373 &generation1);
Eric Laurentb36d1042016-04-14 18:00:38 -07001374 if (status != NO_ERROR) {
Eric Laurentb69681c2014-05-19 19:02:51 -07001375 ALOGE_IF(status != NO_ERROR, "listAudioPatches AudioSystem::listAudioPatches error %d",
1376 status);
1377 break;
1378 }
Eric Laurentb36d1042016-04-14 18:00:38 -07001379 if (numPatches == 0) {
1380 jStatus = (jint)AUDIO_JAVA_SUCCESS;
1381 goto exit;
1382 }
1383
Eric Laurentb69681c2014-05-19 19:02:51 -07001384 nPatches = (struct audio_patch *)realloc(nPatches, numPatches * sizeof(struct audio_patch));
1385
1386 status = AudioSystem::listAudioPatches(&numPatches,
1387 nPatches,
1388 &generation);
1389 ALOGV("listAudioPatches AudioSystem::listAudioPatches numPatches %d generation %d generation1 %d",
1390 numPatches, generation, generation1);
1391
1392 } while (generation1 != generation && status == NO_ERROR);
1393
Eric Laurentb36d1042016-04-14 18:00:38 -07001394 jStatus = nativeToJavaStatus(status);
Eric Laurentb69681c2014-05-19 19:02:51 -07001395 if (jStatus != AUDIO_JAVA_SUCCESS) {
1396 goto exit;
1397 }
1398
Eric Laurentb69681c2014-05-19 19:02:51 -07001399 for (size_t i = 0; i < numPatches; i++) {
1400 jobject patchHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
1401 nPatches[i].id);
1402 if (patchHandle == NULL) {
1403 jStatus = AUDIO_JAVA_ERROR;
1404 goto exit;
1405 }
Dan Albert46d84442014-11-18 16:07:51 -08001406 ALOGV("listAudioPatches patch %zu num_sources %d num_sinks %d",
Eric Laurentb69681c2014-05-19 19:02:51 -07001407 i, nPatches[i].num_sources, nPatches[i].num_sinks);
1408
1409 env->SetIntField(patchHandle, gAudioHandleFields.mId, nPatches[i].id);
1410
1411 // load sources
1412 jSources = env->NewObjectArray(nPatches[i].num_sources,
1413 gAudioPortConfigClass, NULL);
1414 if (jSources == NULL) {
1415 jStatus = AUDIO_JAVA_ERROR;
1416 goto exit;
1417 }
1418
1419 for (size_t j = 0; j < nPatches[i].num_sources; j++) {
1420 jStatus = convertAudioPortConfigFromNative(env,
1421 NULL,
1422 &jSource,
1423 &nPatches[i].sources[j]);
1424 if (jStatus != AUDIO_JAVA_SUCCESS) {
1425 goto exit;
1426 }
1427 env->SetObjectArrayElement(jSources, j, jSource);
1428 env->DeleteLocalRef(jSource);
1429 jSource = NULL;
Dan Albert46d84442014-11-18 16:07:51 -08001430 ALOGV("listAudioPatches patch %zu source %zu is a %s handle %d",
Eric Laurentb69681c2014-05-19 19:02:51 -07001431 i, j,
1432 nPatches[i].sources[j].type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix",
1433 nPatches[i].sources[j].id);
1434 }
1435 // load sinks
1436 jSinks = env->NewObjectArray(nPatches[i].num_sinks,
1437 gAudioPortConfigClass, NULL);
1438 if (jSinks == NULL) {
1439 jStatus = AUDIO_JAVA_ERROR;
1440 goto exit;
1441 }
1442
1443 for (size_t j = 0; j < nPatches[i].num_sinks; j++) {
1444 jStatus = convertAudioPortConfigFromNative(env,
1445 NULL,
1446 &jSink,
1447 &nPatches[i].sinks[j]);
1448
1449 if (jStatus != AUDIO_JAVA_SUCCESS) {
1450 goto exit;
1451 }
1452 env->SetObjectArrayElement(jSinks, j, jSink);
1453 env->DeleteLocalRef(jSink);
1454 jSink = NULL;
Dan Albert46d84442014-11-18 16:07:51 -08001455 ALOGV("listAudioPatches patch %zu sink %zu is a %s handle %d",
Eric Laurentb69681c2014-05-19 19:02:51 -07001456 i, j,
1457 nPatches[i].sinks[j].type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix",
1458 nPatches[i].sinks[j].id);
1459 }
1460
1461 jPatch = env->NewObject(gAudioPatchClass, gAudioPatchCstor,
1462 patchHandle, jSources, jSinks);
1463 env->DeleteLocalRef(jSources);
1464 jSources = NULL;
1465 env->DeleteLocalRef(jSinks);
1466 jSinks = NULL;
1467 if (jPatch == NULL) {
1468 jStatus = AUDIO_JAVA_ERROR;
1469 goto exit;
1470 }
1471 env->CallBooleanMethod(jPatches, gArrayListMethods.add, jPatch);
1472 env->DeleteLocalRef(jPatch);
1473 jPatch = NULL;
1474 }
1475
1476exit:
Eric Laurentb36d1042016-04-14 18:00:38 -07001477
1478 nGeneration = env->GetIntArrayElements(jGeneration, NULL);
1479 if (nGeneration == NULL) {
1480 jStatus = AUDIO_JAVA_ERROR;
1481 } else {
1482 nGeneration[0] = generation1;
1483 env->ReleaseIntArrayElements(jGeneration, nGeneration, 0);
1484 }
1485
Eric Laurentb69681c2014-05-19 19:02:51 -07001486 if (jSources != NULL) {
1487 env->DeleteLocalRef(jSources);
1488 }
1489 if (jSource != NULL) {
1490 env->DeleteLocalRef(jSource);
1491 }
1492 if (jSinks != NULL) {
1493 env->DeleteLocalRef(jSinks);
1494 }
1495 if (jSink != NULL) {
1496 env->DeleteLocalRef(jSink);
1497 }
1498 if (jPatch != NULL) {
1499 env->DeleteLocalRef(jPatch);
1500 }
1501 free(nPatches);
1502 return jStatus;
1503}
1504
Eric Laurent3a241992014-05-19 19:33:26 -07001505static jint
1506android_media_AudioSystem_setAudioPortConfig(JNIEnv *env, jobject clazz,
1507 jobject jAudioPortConfig)
1508{
1509 ALOGV("setAudioPortConfig");
1510 if (jAudioPortConfig == NULL) {
1511 return AUDIO_JAVA_BAD_VALUE;
1512 }
1513 if (!env->IsInstanceOf(jAudioPortConfig, gAudioPortConfigClass)) {
1514 return AUDIO_JAVA_BAD_VALUE;
1515 }
1516 struct audio_port_config nAudioPortConfig;
Eric Laurent6368a7d2014-11-19 12:18:32 -08001517 jint jStatus = convertAudioPortConfigToNative(env, &nAudioPortConfig, jAudioPortConfig, true);
Eric Laurent3a241992014-05-19 19:33:26 -07001518 if (jStatus != AUDIO_JAVA_SUCCESS) {
1519 return jStatus;
1520 }
1521 status_t status = AudioSystem::setAudioPortConfig(&nAudioPortConfig);
1522 ALOGV("AudioSystem::setAudioPortConfig() returned %d", status);
1523 jStatus = nativeToJavaStatus(status);
1524 return jStatus;
1525}
1526
Eric Laurent700e7342014-05-02 18:33:15 -07001527static void
1528android_media_AudioSystem_eventHandlerSetup(JNIEnv *env, jobject thiz, jobject weak_this)
1529{
1530 ALOGV("eventHandlerSetup");
1531
1532 sp<JNIAudioPortCallback> callback = new JNIAudioPortCallback(env, thiz, weak_this);
1533
Eric Laurent2615afb2015-03-25 14:51:08 -07001534 if (AudioSystem::addAudioPortCallback(callback) == NO_ERROR) {
1535 setJniCallback(env, thiz, callback);
1536 }
Eric Laurent700e7342014-05-02 18:33:15 -07001537}
1538
1539static void
1540android_media_AudioSystem_eventHandlerFinalize(JNIEnv *env, jobject thiz)
1541{
1542 ALOGV("eventHandlerFinalize");
1543
Eric Laurent2615afb2015-03-25 14:51:08 -07001544 sp<JNIAudioPortCallback> callback = setJniCallback(env, thiz, 0);
Eric Laurent700e7342014-05-02 18:33:15 -07001545
Eric Laurent2615afb2015-03-25 14:51:08 -07001546 if (callback != 0) {
1547 AudioSystem::removeAudioPortCallback(callback);
1548 }
Eric Laurent700e7342014-05-02 18:33:15 -07001549}
1550
Eric Laurentb634e1b2014-08-01 14:44:46 -07001551static jint
1552android_media_AudioSystem_getAudioHwSyncForSession(JNIEnv *env, jobject thiz, jint sessionId)
1553{
Glenn Kasten33b84042016-03-08 12:02:55 -08001554 return (jint) AudioSystem::getAudioHwSyncForSession((audio_session_t) sessionId);
Eric Laurentb634e1b2014-08-01 14:44:46 -07001555}
1556
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001557static void
1558android_media_AudioSystem_registerDynPolicyCallback(JNIEnv *env, jobject thiz)
1559{
1560 AudioSystem::setDynPolicyCallback(android_media_AudioSystem_dyn_policy_callback);
1561}
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001562
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08001563static void
1564android_media_AudioSystem_registerRecordingCallback(JNIEnv *env, jobject thiz)
1565{
1566 AudioSystem::setRecordConfigCallback(android_media_AudioSystem_recording_callback);
1567}
1568
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001569
1570static jint convertAudioMixToNative(JNIEnv *env,
1571 AudioMix *nAudioMix,
1572 const jobject jAudioMix)
1573{
1574 nAudioMix->mMixType = env->GetIntField(jAudioMix, gAudioMixFields.mMixType);
1575 nAudioMix->mRouteFlags = env->GetIntField(jAudioMix, gAudioMixFields.mRouteFlags);
Jean-Michel Trivi4ad39882016-03-14 18:46:41 -07001576 nAudioMix->mDeviceType = (audio_devices_t)
1577 env->GetIntField(jAudioMix, gAudioMixFields.mDeviceType);
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001578
Jean-Michel Trivi4ad39882016-03-14 18:46:41 -07001579 jstring jDeviceAddress = (jstring)env->GetObjectField(jAudioMix,
1580 gAudioMixFields.mDeviceAddress);
1581 const char *nDeviceAddress = env->GetStringUTFChars(jDeviceAddress, NULL);
1582 nAudioMix->mDeviceAddress = String8(nDeviceAddress);
1583 env->ReleaseStringUTFChars(jDeviceAddress, nDeviceAddress);
1584 env->DeleteLocalRef(jDeviceAddress);
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001585
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001586 nAudioMix->mCbFlags = env->GetIntField(jAudioMix, gAudioMixFields.mCallbackFlags);
1587
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001588 jobject jFormat = env->GetObjectField(jAudioMix, gAudioMixFields.mFormat);
1589 nAudioMix->mFormat.sample_rate = env->GetIntField(jFormat,
1590 gAudioFormatFields.mSampleRate);
1591 nAudioMix->mFormat.channel_mask = outChannelMaskToNative(env->GetIntField(jFormat,
1592 gAudioFormatFields.mChannelMask));
1593 nAudioMix->mFormat.format = audioFormatToNative(env->GetIntField(jFormat,
1594 gAudioFormatFields.mEncoding));
1595 env->DeleteLocalRef(jFormat);
1596
1597 jobject jRule = env->GetObjectField(jAudioMix, gAudioMixFields.mRule);
1598 jobject jRuleCriteria = env->GetObjectField(jRule, gAudioMixingRuleFields.mCriteria);
1599 env->DeleteLocalRef(jRule);
1600 jobjectArray jCriteria = (jobjectArray)env->CallObjectMethod(jRuleCriteria,
1601 gArrayListMethods.toArray);
1602 env->DeleteLocalRef(jRuleCriteria);
1603
1604 jint numCriteria = env->GetArrayLength(jCriteria);
1605 if (numCriteria > MAX_CRITERIA_PER_MIX) {
1606 numCriteria = MAX_CRITERIA_PER_MIX;
1607 }
1608
1609 for (jint i = 0; i < numCriteria; i++) {
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -08001610 AudioMixMatchCriterion nCriterion;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001611
1612 jobject jCriterion = env->GetObjectArrayElement(jCriteria, i);
1613
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -08001614 nCriterion.mRule = env->GetIntField(jCriterion, gAudioMixMatchCriterionFields.mRule);
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001615
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -08001616 const uint32_t match_rule = nCriterion.mRule & ~RULE_EXCLUSION_MASK;
1617 switch (match_rule) {
1618 case RULE_MATCH_UID:
1619 nCriterion.mValue.mUid = env->GetIntField(jCriterion,
1620 gAudioMixMatchCriterionFields.mIntProp);
1621 break;
1622 case RULE_MATCH_ATTRIBUTE_USAGE:
1623 case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET: {
1624 jobject jAttributes = env->GetObjectField(jCriterion, gAudioMixMatchCriterionFields.mAttr);
1625 if (match_rule == RULE_MATCH_ATTRIBUTE_USAGE) {
1626 nCriterion.mValue.mUsage = (audio_usage_t)env->GetIntField(jAttributes,
1627 gAudioAttributesFields.mUsage);
1628 } else {
1629 nCriterion.mValue.mSource = (audio_source_t)env->GetIntField(jAttributes,
1630 gAudioAttributesFields.mSource);
1631 }
1632 env->DeleteLocalRef(jAttributes);
1633 }
1634 break;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001635 }
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001636
1637 nAudioMix->mCriteria.add(nCriterion);
1638 env->DeleteLocalRef(jCriterion);
1639 }
1640
1641 env->DeleteLocalRef(jCriteria);
1642
1643 return (jint)AUDIO_JAVA_SUCCESS;
1644}
1645
1646static jint
1647android_media_AudioSystem_registerPolicyMixes(JNIEnv *env, jobject clazz,
1648 jobject jMixesList, jboolean registration)
1649{
1650 ALOGV("registerPolicyMixes");
1651
1652 if (jMixesList == NULL) {
1653 return (jint)AUDIO_JAVA_BAD_VALUE;
1654 }
1655 if (!env->IsInstanceOf(jMixesList, gArrayListClass)) {
1656 return (jint)AUDIO_JAVA_BAD_VALUE;
1657 }
1658 jobjectArray jMixes = (jobjectArray)env->CallObjectMethod(jMixesList,
1659 gArrayListMethods.toArray);
1660 jint numMixes = env->GetArrayLength(jMixes);
1661 if (numMixes > MAX_MIXES_PER_POLICY) {
1662 numMixes = MAX_MIXES_PER_POLICY;
1663 }
1664
1665 status_t status;
1666 jint jStatus;
1667 jobject jAudioMix = NULL;
1668 Vector <AudioMix> mixes;
1669 for (jint i = 0; i < numMixes; i++) {
1670 jAudioMix = env->GetObjectArrayElement(jMixes, i);
1671 if (!env->IsInstanceOf(jAudioMix, gAudioMixClass)) {
1672 jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
1673 goto exit;
1674 }
1675 AudioMix mix;
1676 jStatus = convertAudioMixToNative(env, &mix, jAudioMix);
1677 env->DeleteLocalRef(jAudioMix);
1678 jAudioMix = NULL;
1679 if (jStatus != AUDIO_JAVA_SUCCESS) {
1680 goto exit;
1681 }
1682 mixes.add(mix);
1683 }
1684
1685 ALOGV("AudioSystem::registerPolicyMixes numMixes %d registration %d", numMixes, registration);
1686 status = AudioSystem::registerPolicyMixes(mixes, registration);
1687 ALOGV("AudioSystem::registerPolicyMixes() returned %d", status);
1688
1689 jStatus = nativeToJavaStatus(status);
1690 if (jStatus != AUDIO_JAVA_SUCCESS) {
1691 goto exit;
1692 }
1693
1694exit:
1695 if (jAudioMix != NULL) {
1696 env->DeleteLocalRef(jAudioMix);
1697 }
1698 return jStatus;
1699}
1700
Eric Laurent0867bed2015-05-20 14:49:08 -07001701static jint
1702android_media_AudioSystem_systemReady(JNIEnv *env, jobject thiz)
1703{
1704 return nativeToJavaStatus(AudioSystem::systemReady());
1705}
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001706
1707
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001708// ----------------------------------------------------------------------------
1709
Daniel Micay76f6a862015-09-19 17:31:01 -04001710static const JNINativeMethod gMethods[] = {
Eric Laurenta553c252009-07-17 12:17:14 -07001711 {"setParameters", "(Ljava/lang/String;)I", (void *)android_media_AudioSystem_setParameters},
1712 {"getParameters", "(Ljava/lang/String;)Ljava/lang/String;", (void *)android_media_AudioSystem_getParameters},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001713 {"muteMicrophone", "(Z)I", (void *)android_media_AudioSystem_muteMicrophone},
1714 {"isMicrophoneMuted", "()Z", (void *)android_media_AudioSystem_isMicrophoneMuted},
Jean-Michel Trivid6770542012-10-10 12:03:41 -07001715 {"isStreamActive", "(II)Z", (void *)android_media_AudioSystem_isStreamActive},
Jean-Michel Trivi679d5042013-02-04 16:24:09 -08001716 {"isStreamActiveRemotely","(II)Z", (void *)android_media_AudioSystem_isStreamActiveRemotely},
Jean-Michel Trivid6770542012-10-10 12:03:41 -07001717 {"isSourceActive", "(I)Z", (void *)android_media_AudioSystem_isSourceActive},
Jean-Michel Trivi8a21f5d2014-06-05 15:03:52 -07001718 {"newAudioSessionId", "()I", (void *)android_media_AudioSystem_newAudioSessionId},
Paul McLean10804eb2015-01-28 11:16:35 -08001719 {"setDeviceConnectionState", "(IILjava/lang/String;Ljava/lang/String;)I", (void *)android_media_AudioSystem_setDeviceConnectionState},
Eric Laurenta553c252009-07-17 12:17:14 -07001720 {"getDeviceConnectionState", "(ILjava/lang/String;)I", (void *)android_media_AudioSystem_getDeviceConnectionState},
1721 {"setPhoneState", "(I)I", (void *)android_media_AudioSystem_setPhoneState},
Eric Laurenta553c252009-07-17 12:17:14 -07001722 {"setForceUse", "(II)I", (void *)android_media_AudioSystem_setForceUse},
1723 {"getForceUse", "(I)I", (void *)android_media_AudioSystem_getForceUse},
1724 {"initStreamVolume", "(III)I", (void *)android_media_AudioSystem_initStreamVolume},
Eric Laurent9bc8358d2011-11-18 16:43:31 -08001725 {"setStreamVolumeIndex","(III)I", (void *)android_media_AudioSystem_setStreamVolumeIndex},
1726 {"getStreamVolumeIndex","(II)I", (void *)android_media_AudioSystem_getStreamVolumeIndex},
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -04001727 {"setMasterVolume", "(F)I", (void *)android_media_AudioSystem_setMasterVolume},
1728 {"getMasterVolume", "()F", (void *)android_media_AudioSystem_getMasterVolume},
1729 {"setMasterMute", "(Z)I", (void *)android_media_AudioSystem_setMasterMute},
1730 {"getMasterMute", "()Z", (void *)android_media_AudioSystem_getMasterMute},
Andy Hungf04b84d2015-12-18 17:33:27 -08001731 {"setMasterMono", "(Z)I", (void *)android_media_AudioSystem_setMasterMono},
1732 {"getMasterMono", "()Z", (void *)android_media_AudioSystem_getMasterMono},
Glenn Kasten8b4b97a2011-02-04 13:54:26 -08001733 {"getDevicesForStream", "(I)I", (void *)android_media_AudioSystem_getDevicesForStream},
Glenn Kastenc6c43652012-09-24 17:32:30 -07001734 {"getPrimaryOutputSamplingRate", "()I", (void *)android_media_AudioSystem_getPrimaryOutputSamplingRate},
1735 {"getPrimaryOutputFrameCount", "()I", (void *)android_media_AudioSystem_getPrimaryOutputFrameCount},
Oliver Woodman61dcdf32013-06-26 12:43:36 +01001736 {"getOutputLatency", "(I)I", (void *)android_media_AudioSystem_getOutputLatency},
Glenn Kastenfd116ad2013-07-12 17:10:39 -07001737 {"setLowRamDevice", "(Z)I", (void *)android_media_AudioSystem_setLowRamDevice},
Eric Laurentdfb881f2013-07-18 14:41:39 -07001738 {"checkAudioFlinger", "()I", (void *)android_media_AudioSystem_checkAudioFlinger},
Eric Laurentb69681c2014-05-19 19:02:51 -07001739 {"listAudioPorts", "(Ljava/util/ArrayList;[I)I",
1740 (void *)android_media_AudioSystem_listAudioPorts},
1741 {"createAudioPatch", "([Landroid/media/AudioPatch;[Landroid/media/AudioPortConfig;[Landroid/media/AudioPortConfig;)I",
1742 (void *)android_media_AudioSystem_createAudioPatch},
1743 {"releaseAudioPatch", "(Landroid/media/AudioPatch;)I",
1744 (void *)android_media_AudioSystem_releaseAudioPatch},
1745 {"listAudioPatches", "(Ljava/util/ArrayList;[I)I",
1746 (void *)android_media_AudioSystem_listAudioPatches},
Eric Laurent3a241992014-05-19 19:33:26 -07001747 {"setAudioPortConfig", "(Landroid/media/AudioPortConfig;)I",
1748 (void *)android_media_AudioSystem_setAudioPortConfig},
Eric Laurentb634e1b2014-08-01 14:44:46 -07001749 {"getAudioHwSyncForSession", "(I)I",
1750 (void *)android_media_AudioSystem_getAudioHwSyncForSession},
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001751 {"registerPolicyMixes", "(Ljava/util/ArrayList;Z)I",
1752 (void *)android_media_AudioSystem_registerPolicyMixes},
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001753 {"native_register_dynamic_policy_callback", "()V",
1754 (void *)android_media_AudioSystem_registerDynPolicyCallback},
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08001755 {"native_register_recording_callback", "()V",
1756 (void *)android_media_AudioSystem_registerRecordingCallback},
Eric Laurent0867bed2015-05-20 14:49:08 -07001757 {"systemReady", "()I", (void *)android_media_AudioSystem_systemReady},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001758};
1759
Eric Laurentb69681c2014-05-19 19:02:51 -07001760
Daniel Micay76f6a862015-09-19 17:31:01 -04001761static const JNINativeMethod gEventHandlerMethods[] = {
Eric Laurent700e7342014-05-02 18:33:15 -07001762 {"native_setup",
1763 "(Ljava/lang/Object;)V",
1764 (void *)android_media_AudioSystem_eventHandlerSetup},
1765 {"native_finalize",
1766 "()V",
1767 (void *)android_media_AudioSystem_eventHandlerFinalize},
1768};
1769
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001770int register_android_media_AudioSystem(JNIEnv *env)
1771{
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001772 jclass arrayListClass = FindClassOrDie(env, "java/util/ArrayList");
1773 gArrayListClass = MakeGlobalRefOrDie(env, arrayListClass);
1774 gArrayListMethods.add = GetMethodIDOrDie(env, arrayListClass, "add", "(Ljava/lang/Object;)Z");
Eric Laurent09378972014-12-10 10:42:08 -08001775 gArrayListMethods.toArray = GetMethodIDOrDie(env, arrayListClass, "toArray", "()[Ljava/lang/Object;");
Eric Laurentb69681c2014-05-19 19:02:51 -07001776
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001777 jclass audioHandleClass = FindClassOrDie(env, "android/media/AudioHandle");
1778 gAudioHandleClass = MakeGlobalRefOrDie(env, audioHandleClass);
1779 gAudioHandleCstor = GetMethodIDOrDie(env, audioHandleClass, "<init>", "(I)V");
1780 gAudioHandleFields.mId = GetFieldIDOrDie(env, audioHandleClass, "mId", "I");
Eric Laurentb69681c2014-05-19 19:02:51 -07001781
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001782 jclass audioPortClass = FindClassOrDie(env, "android/media/AudioPort");
1783 gAudioPortClass = MakeGlobalRefOrDie(env, audioPortClass);
1784 gAudioPortCstor = GetMethodIDOrDie(env, audioPortClass, "<init>",
Paul McLeanf29e5f32015-06-15 10:19:22 -07001785 "(Landroid/media/AudioHandle;ILjava/lang/String;[I[I[I[I[Landroid/media/AudioGain;)V");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001786 gAudioPortFields.mHandle = GetFieldIDOrDie(env, audioPortClass, "mHandle",
Eric Laurentb69681c2014-05-19 19:02:51 -07001787 "Landroid/media/AudioHandle;");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001788 gAudioPortFields.mRole = GetFieldIDOrDie(env, audioPortClass, "mRole", "I");
1789 gAudioPortFields.mGains = GetFieldIDOrDie(env, audioPortClass, "mGains",
Eric Laurentb69681c2014-05-19 19:02:51 -07001790 "[Landroid/media/AudioGain;");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001791 gAudioPortFields.mActiveConfig = GetFieldIDOrDie(env, audioPortClass, "mActiveConfig",
1792 "Landroid/media/AudioPortConfig;");
Eric Laurentb69681c2014-05-19 19:02:51 -07001793
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001794 jclass audioPortConfigClass = FindClassOrDie(env, "android/media/AudioPortConfig");
1795 gAudioPortConfigClass = MakeGlobalRefOrDie(env, audioPortConfigClass);
1796 gAudioPortConfigCstor = GetMethodIDOrDie(env, audioPortConfigClass, "<init>",
1797 "(Landroid/media/AudioPort;IIILandroid/media/AudioGainConfig;)V");
1798 gAudioPortConfigFields.mPort = GetFieldIDOrDie(env, audioPortConfigClass, "mPort",
Eric Laurentb69681c2014-05-19 19:02:51 -07001799 "Landroid/media/AudioPort;");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001800 gAudioPortConfigFields.mSamplingRate = GetFieldIDOrDie(env, audioPortConfigClass,
Eric Laurentb69681c2014-05-19 19:02:51 -07001801 "mSamplingRate", "I");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001802 gAudioPortConfigFields.mChannelMask = GetFieldIDOrDie(env, audioPortConfigClass,
Eric Laurentb69681c2014-05-19 19:02:51 -07001803 "mChannelMask", "I");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001804 gAudioPortConfigFields.mFormat = GetFieldIDOrDie(env, audioPortConfigClass, "mFormat", "I");
1805 gAudioPortConfigFields.mGain = GetFieldIDOrDie(env, audioPortConfigClass, "mGain",
Eric Laurentb69681c2014-05-19 19:02:51 -07001806 "Landroid/media/AudioGainConfig;");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001807 gAudioPortConfigFields.mConfigMask = GetFieldIDOrDie(env, audioPortConfigClass, "mConfigMask",
1808 "I");
Eric Laurentb69681c2014-05-19 19:02:51 -07001809
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001810 jclass audioDevicePortConfigClass = FindClassOrDie(env, "android/media/AudioDevicePortConfig");
1811 gAudioDevicePortConfigClass = MakeGlobalRefOrDie(env, audioDevicePortConfigClass);
1812 gAudioDevicePortConfigCstor = GetMethodIDOrDie(env, audioDevicePortConfigClass, "<init>",
1813 "(Landroid/media/AudioDevicePort;IIILandroid/media/AudioGainConfig;)V");
Eric Laurentb69681c2014-05-19 19:02:51 -07001814
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001815 jclass audioMixPortConfigClass = FindClassOrDie(env, "android/media/AudioMixPortConfig");
1816 gAudioMixPortConfigClass = MakeGlobalRefOrDie(env, audioMixPortConfigClass);
1817 gAudioMixPortConfigCstor = GetMethodIDOrDie(env, audioMixPortConfigClass, "<init>",
1818 "(Landroid/media/AudioMixPort;IIILandroid/media/AudioGainConfig;)V");
Eric Laurentb69681c2014-05-19 19:02:51 -07001819
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001820 jclass audioDevicePortClass = FindClassOrDie(env, "android/media/AudioDevicePort");
1821 gAudioDevicePortClass = MakeGlobalRefOrDie(env, audioDevicePortClass);
1822 gAudioDevicePortCstor = GetMethodIDOrDie(env, audioDevicePortClass, "<init>",
Paul McLeanf29e5f32015-06-15 10:19:22 -07001823 "(Landroid/media/AudioHandle;Ljava/lang/String;[I[I[I[I[Landroid/media/AudioGain;ILjava/lang/String;)V");
Eric Laurentb69681c2014-05-19 19:02:51 -07001824
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001825 jclass audioMixPortClass = FindClassOrDie(env, "android/media/AudioMixPort");
1826 gAudioMixPortClass = MakeGlobalRefOrDie(env, audioMixPortClass);
1827 gAudioMixPortCstor = GetMethodIDOrDie(env, audioMixPortClass, "<init>",
Paul McLeanf29e5f32015-06-15 10:19:22 -07001828 "(Landroid/media/AudioHandle;IILjava/lang/String;[I[I[I[I[Landroid/media/AudioGain;)V");
Eric Laurentb69681c2014-05-19 19:02:51 -07001829
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001830 jclass audioGainClass = FindClassOrDie(env, "android/media/AudioGain");
1831 gAudioGainClass = MakeGlobalRefOrDie(env, audioGainClass);
1832 gAudioGainCstor = GetMethodIDOrDie(env, audioGainClass, "<init>", "(IIIIIIIII)V");
Eric Laurentb69681c2014-05-19 19:02:51 -07001833
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001834 jclass audioGainConfigClass = FindClassOrDie(env, "android/media/AudioGainConfig");
1835 gAudioGainConfigClass = MakeGlobalRefOrDie(env, audioGainConfigClass);
1836 gAudioGainConfigCstor = GetMethodIDOrDie(env, audioGainConfigClass, "<init>",
Eric Laurentb69681c2014-05-19 19:02:51 -07001837 "(ILandroid/media/AudioGain;II[II)V");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001838 gAudioGainConfigFields.mIndex = GetFieldIDOrDie(env, gAudioGainConfigClass, "mIndex", "I");
1839 gAudioGainConfigFields.mMode = GetFieldIDOrDie(env, audioGainConfigClass, "mMode", "I");
1840 gAudioGainConfigFields.mChannelMask = GetFieldIDOrDie(env, audioGainConfigClass, "mChannelMask",
Eric Laurentb69681c2014-05-19 19:02:51 -07001841 "I");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001842 gAudioGainConfigFields.mValues = GetFieldIDOrDie(env, audioGainConfigClass, "mValues", "[I");
1843 gAudioGainConfigFields.mRampDurationMs = GetFieldIDOrDie(env, audioGainConfigClass,
Eric Laurentb69681c2014-05-19 19:02:51 -07001844 "mRampDurationMs", "I");
1845
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001846 jclass audioPatchClass = FindClassOrDie(env, "android/media/AudioPatch");
1847 gAudioPatchClass = MakeGlobalRefOrDie(env, audioPatchClass);
1848 gAudioPatchCstor = GetMethodIDOrDie(env, audioPatchClass, "<init>",
Eric Laurentb69681c2014-05-19 19:02:51 -07001849"(Landroid/media/AudioHandle;[Landroid/media/AudioPortConfig;[Landroid/media/AudioPortConfig;)V");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001850 gAudioPatchFields.mHandle = GetFieldIDOrDie(env, audioPatchClass, "mHandle",
Eric Laurentb69681c2014-05-19 19:02:51 -07001851 "Landroid/media/AudioHandle;");
1852
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001853 jclass eventHandlerClass = FindClassOrDie(env, kEventHandlerClassPathName);
Eric Laurent2615afb2015-03-25 14:51:08 -07001854 gAudioPortEventHandlerMethods.postEventFromNative = GetStaticMethodIDOrDie(
1855 env, eventHandlerClass, "postEventFromNative",
1856 "(Ljava/lang/Object;IIILjava/lang/Object;)V");
1857 gEventHandlerFields.mJniCallback = GetFieldIDOrDie(env,
1858 eventHandlerClass, "mJniCallback", "J");
Eric Laurent700e7342014-05-02 18:33:15 -07001859
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08001860 gAudioPolicyEventHandlerMethods.postDynPolicyEventFromNative =
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001861 GetStaticMethodIDOrDie(env, env->FindClass(kClassPathName),
1862 "dynamicPolicyCallbackFromNative", "(ILjava/lang/String;I)V");
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08001863 gAudioPolicyEventHandlerMethods.postRecordConfigEventFromNative =
1864 GetStaticMethodIDOrDie(env, env->FindClass(kClassPathName),
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -08001865 "recordingCallbackFromNative", "(III[I)V");
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001866
Eric Laurent09378972014-12-10 10:42:08 -08001867 jclass audioMixClass = FindClassOrDie(env, "android/media/audiopolicy/AudioMix");
1868 gAudioMixClass = MakeGlobalRefOrDie(env, audioMixClass);
1869 gAudioMixFields.mRule = GetFieldIDOrDie(env, audioMixClass, "mRule",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001870 "Landroid/media/audiopolicy/AudioMixingRule;");
Eric Laurent09378972014-12-10 10:42:08 -08001871 gAudioMixFields.mFormat = GetFieldIDOrDie(env, audioMixClass, "mFormat",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001872 "Landroid/media/AudioFormat;");
Eric Laurent09378972014-12-10 10:42:08 -08001873 gAudioMixFields.mRouteFlags = GetFieldIDOrDie(env, audioMixClass, "mRouteFlags", "I");
Jean-Michel Trivi4ad39882016-03-14 18:46:41 -07001874 gAudioMixFields.mDeviceType = GetFieldIDOrDie(env, audioMixClass, "mDeviceSystemType", "I");
1875 gAudioMixFields.mDeviceAddress = GetFieldIDOrDie(env, audioMixClass, "mDeviceAddress",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001876 "Ljava/lang/String;");
Eric Laurent09378972014-12-10 10:42:08 -08001877 gAudioMixFields.mMixType = GetFieldIDOrDie(env, audioMixClass, "mMixType", "I");
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001878 gAudioMixFields.mCallbackFlags = GetFieldIDOrDie(env, audioMixClass, "mCallbackFlags", "I");
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001879
Eric Laurent09378972014-12-10 10:42:08 -08001880 jclass audioFormatClass = FindClassOrDie(env, "android/media/AudioFormat");
1881 gAudioFormatClass = MakeGlobalRefOrDie(env, audioFormatClass);
1882 gAudioFormatFields.mEncoding = GetFieldIDOrDie(env, audioFormatClass, "mEncoding", "I");
1883 gAudioFormatFields.mSampleRate = GetFieldIDOrDie(env, audioFormatClass, "mSampleRate", "I");
1884 gAudioFormatFields.mChannelMask = GetFieldIDOrDie(env, audioFormatClass, "mChannelMask", "I");
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001885
Eric Laurent09378972014-12-10 10:42:08 -08001886 jclass audioMixingRuleClass = FindClassOrDie(env, "android/media/audiopolicy/AudioMixingRule");
1887 gAudioMixingRuleClass = MakeGlobalRefOrDie(env, audioMixingRuleClass);
1888 gAudioMixingRuleFields.mCriteria = GetFieldIDOrDie(env, audioMixingRuleClass, "mCriteria",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001889 "Ljava/util/ArrayList;");
1890
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -08001891 jclass audioMixMatchCriterionClass =
1892 FindClassOrDie(env, "android/media/audiopolicy/AudioMixingRule$AudioMixMatchCriterion");
1893 gAudioMixMatchCriterionClass = MakeGlobalRefOrDie(env,audioMixMatchCriterionClass);
1894 gAudioMixMatchCriterionFields.mAttr = GetFieldIDOrDie(env, audioMixMatchCriterionClass, "mAttr",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001895 "Landroid/media/AudioAttributes;");
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -08001896 gAudioMixMatchCriterionFields.mIntProp = GetFieldIDOrDie(env, audioMixMatchCriterionClass, "mIntProp",
1897 "I");
1898 gAudioMixMatchCriterionFields.mRule = GetFieldIDOrDie(env, audioMixMatchCriterionClass, "mRule",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001899 "I");
1900
Eric Laurent09378972014-12-10 10:42:08 -08001901 jclass audioAttributesClass = FindClassOrDie(env, "android/media/AudioAttributes");
1902 gAudioAttributesClass = MakeGlobalRefOrDie(env, audioAttributesClass);
1903 gAudioAttributesFields.mUsage = GetFieldIDOrDie(env, audioAttributesClass, "mUsage", "I");
1904 gAudioAttributesFields.mSource = GetFieldIDOrDie(env, audioAttributesClass, "mSource", "I");
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001905
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001906 AudioSystem::setErrorCallback(android_media_AudioSystem_error_callback);
Glenn Kasten18db49a2012-03-12 16:29:55 -07001907
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001908 RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
1909 return RegisterMethodsOrDie(env, kEventHandlerClassPathName, gEventHandlerMethods,
1910 NELEM(gEventHandlerMethods));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001911}