blob: ab5e15d95ac46b99f94f67d1c8a252812610ff3b [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
Andy Hung737d9fb2016-08-16 18:38:49 -070023#include <sstream>
jiabinc0f49442018-01-05 10:23:50 -080024#include <vector>
Glenn Kastenc81d31c2012-03-13 14:46:23 -070025#include <jni.h>
Steven Moreland2279b252017-07-19 09:50:45 -070026#include <nativehelper/JNIHelp.h>
Andreas Gampeed6b9df2014-11-20 22:02:20 -080027#include "core_jni_helpers.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028
29#include <media/AudioSystem.h>
Eric Laurent7f5eb9f2014-12-01 19:36:30 -080030#include <media/AudioPolicy.h>
jiabinc0f49442018-01-05 10:23:50 -080031#include <media/MicrophoneInfo.h>
Andy Hung737d9fb2016-08-16 18:38:49 -070032#include <nativehelper/ScopedLocalRef.h>
Dima Zavin34bb4192011-05-11 14:15:23 -070033#include <system/audio.h>
Dima Zavin290029d2011-06-13 18:16:26 -070034#include <system/audio_policy.h>
Eric Laurentb69681c2014-05-19 19:02:51 -070035#include "android_media_AudioFormat.h"
36#include "android_media_AudioErrors.h"
jiabinc0f49442018-01-05 10:23:50 -080037#include "android_media_MicrophoneInfo.h"
Dima Zavin24fc2fb2011-04-19 22:30:36 -070038
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039// ----------------------------------------------------------------------------
40
41using namespace android;
42
Glenn Kastened0079d2011-04-04 10:50:50 -070043static const char* const kClassPathName = "android/media/AudioSystem";
44
Eric Laurentb69681c2014-05-19 19:02:51 -070045static jclass gArrayListClass;
46static struct {
47 jmethodID add;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -080048 jmethodID toArray;
Eric Laurentb69681c2014-05-19 19:02:51 -070049} gArrayListMethods;
50
51static jclass gAudioHandleClass;
52static jmethodID gAudioHandleCstor;
53static struct {
54 jfieldID mId;
55} gAudioHandleFields;
56
57static jclass gAudioPortClass;
58static jmethodID gAudioPortCstor;
59static struct {
60 jfieldID mHandle;
61 jfieldID mRole;
62 jfieldID mGains;
63 jfieldID mActiveConfig;
64 // other fields unused by JNI
65} gAudioPortFields;
66
67static jclass gAudioPortConfigClass;
68static jmethodID gAudioPortConfigCstor;
69static struct {
70 jfieldID mPort;
71 jfieldID mSamplingRate;
72 jfieldID mChannelMask;
73 jfieldID mFormat;
74 jfieldID mGain;
Eric Laurent3a241992014-05-19 19:33:26 -070075 jfieldID mConfigMask;
Eric Laurentb69681c2014-05-19 19:02:51 -070076} gAudioPortConfigFields;
77
78static jclass gAudioDevicePortClass;
79static jmethodID gAudioDevicePortCstor;
80
81static jclass gAudioDevicePortConfigClass;
82static jmethodID gAudioDevicePortConfigCstor;
83
84static jclass gAudioMixPortClass;
85static jmethodID gAudioMixPortCstor;
86
87static jclass gAudioMixPortConfigClass;
88static jmethodID gAudioMixPortConfigCstor;
89
90static jclass gAudioGainClass;
91static jmethodID gAudioGainCstor;
92
93static jclass gAudioGainConfigClass;
94static jmethodID gAudioGainConfigCstor;
95static struct {
96 jfieldID mIndex;
97 jfieldID mMode;
98 jfieldID mChannelMask;
99 jfieldID mValues;
100 jfieldID mRampDurationMs;
101 // other fields unused by JNI
102} gAudioGainConfigFields;
103
104static jclass gAudioPatchClass;
105static jmethodID gAudioPatchCstor;
106static struct {
107 jfieldID mHandle;
108 // other fields unused by JNI
109} gAudioPatchFields;
110
Eric Laurent7f5eb9f2014-12-01 19:36:30 -0800111static jclass gAudioMixClass;
112static struct {
113 jfieldID mRule;
114 jfieldID mFormat;
115 jfieldID mRouteFlags;
Jean-Michel Trivi4ad39882016-03-14 18:46:41 -0700116 jfieldID mDeviceType;
117 jfieldID mDeviceAddress;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -0800118 jfieldID mMixType;
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700119 jfieldID mCallbackFlags;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -0800120} gAudioMixFields;
121
122static jclass gAudioFormatClass;
123static struct {
124 jfieldID mEncoding;
125 jfieldID mSampleRate;
126 jfieldID mChannelMask;
127 // other fields unused by JNI
128} gAudioFormatFields;
129
130static jclass gAudioMixingRuleClass;
131static struct {
132 jfieldID mCriteria;
133 // other fields unused by JNI
134} gAudioMixingRuleFields;
135
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -0800136static jclass gAudioMixMatchCriterionClass;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -0800137static struct {
138 jfieldID mAttr;
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -0800139 jfieldID mIntProp;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -0800140 jfieldID mRule;
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -0800141} gAudioMixMatchCriterionFields;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -0800142
143static jclass gAudioAttributesClass;
144static struct {
145 jfieldID mUsage;
146 jfieldID mSource;
147} gAudioAttributesFields;
148
Eric Laurent700e7342014-05-02 18:33:15 -0700149static const char* const kEventHandlerClassPathName =
150 "android/media/AudioPortEventHandler";
Eric Laurent2615afb2015-03-25 14:51:08 -0700151static struct {
152 jfieldID mJniCallback;
153} gEventHandlerFields;
154static struct {
155 jmethodID postEventFromNative;
156} gAudioPortEventHandlerMethods;
157
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700158static struct {
159 jmethodID postDynPolicyEventFromNative;
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800160 jmethodID postRecordConfigEventFromNative;
161} gAudioPolicyEventHandlerMethods;
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700162
Eric Laurent2615afb2015-03-25 14:51:08 -0700163static Mutex gLock;
Eric Laurentb69681c2014-05-19 19:02:51 -0700164
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800165enum AudioError {
166 kAudioStatusOk = 0,
167 kAudioStatusError = 1,
168 kAudioStatusMediaServerDied = 100
169};
170
Eric Laurent700e7342014-05-02 18:33:15 -0700171enum {
172 AUDIOPORT_EVENT_PORT_LIST_UPDATED = 1,
173 AUDIOPORT_EVENT_PATCH_LIST_UPDATED = 2,
174 AUDIOPORT_EVENT_SERVICE_DIED = 3,
175};
176
Eric Laurentb69681c2014-05-19 19:02:51 -0700177#define MAX_PORT_GENERATION_SYNC_ATTEMPTS 5
178
Eric Laurent700e7342014-05-02 18:33:15 -0700179// ----------------------------------------------------------------------------
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700180// ref-counted object for audio port callbacks
Eric Laurent700e7342014-05-02 18:33:15 -0700181class JNIAudioPortCallback: public AudioSystem::AudioPortCallback
182{
183public:
184 JNIAudioPortCallback(JNIEnv* env, jobject thiz, jobject weak_thiz);
185 ~JNIAudioPortCallback();
186
187 virtual void onAudioPortListUpdate();
188 virtual void onAudioPatchListUpdate();
189 virtual void onServiceDied();
190
191private:
192 void sendEvent(int event);
193
Eric Laurent2615afb2015-03-25 14:51:08 -0700194 jclass mClass; // Reference to AudioPortEventHandler class
195 jobject mObject; // Weak ref to AudioPortEventHandler Java object to call on
Eric Laurent700e7342014-05-02 18:33:15 -0700196};
197
198JNIAudioPortCallback::JNIAudioPortCallback(JNIEnv* env, jobject thiz, jobject weak_thiz)
199{
200
Eric Laurent2615afb2015-03-25 14:51:08 -0700201 // Hold onto the AudioPortEventHandler class for use in calling the static method
Eric Laurent700e7342014-05-02 18:33:15 -0700202 // that posts events to the application thread.
203 jclass clazz = env->GetObjectClass(thiz);
204 if (clazz == NULL) {
205 ALOGE("Can't find class %s", kEventHandlerClassPathName);
206 return;
207 }
208 mClass = (jclass)env->NewGlobalRef(clazz);
209
Eric Laurent2615afb2015-03-25 14:51:08 -0700210 // We use a weak reference so the AudioPortEventHandler object can be garbage collected.
Eric Laurent700e7342014-05-02 18:33:15 -0700211 // The reference is only used as a proxy for callbacks.
212 mObject = env->NewGlobalRef(weak_thiz);
213}
214
215JNIAudioPortCallback::~JNIAudioPortCallback()
216{
217 // remove global references
218 JNIEnv *env = AndroidRuntime::getJNIEnv();
Eric Laurent449c5882014-11-12 11:07:48 -0800219 if (env == NULL) {
220 return;
221 }
Eric Laurent700e7342014-05-02 18:33:15 -0700222 env->DeleteGlobalRef(mObject);
223 env->DeleteGlobalRef(mClass);
224}
225
226void JNIAudioPortCallback::sendEvent(int event)
227{
228 JNIEnv *env = AndroidRuntime::getJNIEnv();
Eric Laurent449c5882014-11-12 11:07:48 -0800229 if (env == NULL) {
230 return;
231 }
Eric Laurent2615afb2015-03-25 14:51:08 -0700232 env->CallStaticVoidMethod(mClass, gAudioPortEventHandlerMethods.postEventFromNative, mObject,
Eric Laurent700e7342014-05-02 18:33:15 -0700233 event, 0, 0, NULL);
234 if (env->ExceptionCheck()) {
235 ALOGW("An exception occurred while notifying an event.");
236 env->ExceptionClear();
237 }
238}
239
240void JNIAudioPortCallback::onAudioPortListUpdate()
241{
242 sendEvent(AUDIOPORT_EVENT_PORT_LIST_UPDATED);
243}
244
245void JNIAudioPortCallback::onAudioPatchListUpdate()
246{
247 sendEvent(AUDIOPORT_EVENT_PATCH_LIST_UPDATED);
248}
249
250void JNIAudioPortCallback::onServiceDied()
251{
252 sendEvent(AUDIOPORT_EVENT_SERVICE_DIED);
253}
254
Eric Laurent2615afb2015-03-25 14:51:08 -0700255static sp<JNIAudioPortCallback> setJniCallback(JNIEnv* env,
256 jobject thiz,
257 const sp<JNIAudioPortCallback>& callback)
258{
259 Mutex::Autolock l(gLock);
260 sp<JNIAudioPortCallback> old =
261 (JNIAudioPortCallback*)env->GetLongField(thiz, gEventHandlerFields.mJniCallback);
262 if (callback.get()) {
263 callback->incStrong((void*)setJniCallback);
264 }
265 if (old != 0) {
266 old->decStrong((void*)setJniCallback);
267 }
268 env->SetLongField(thiz, gEventHandlerFields.mJniCallback, (jlong)callback.get());
269 return old;
270}
271
Mikhail Naganov5caa57d2018-04-02 10:35:45 -0700272#define check_AudioSystem_Command(status) _check_AudioSystem_Command(__func__, (status))
273
274static int _check_AudioSystem_Command(const char* caller, status_t status)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275{
Mikhail Naganov5caa57d2018-04-02 10:35:45 -0700276 ALOGE_IF(status, "Command failed for %s: %d", caller, status);
Eric Laurentdfb881f2013-07-18 14:41:39 -0700277 switch (status) {
278 case DEAD_OBJECT:
279 return kAudioStatusMediaServerDied;
280 case NO_ERROR:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800281 return kAudioStatusOk;
Eric Laurentdfb881f2013-07-18 14:41:39 -0700282 default:
283 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800284 }
Eric Laurentdfb881f2013-07-18 14:41:39 -0700285 return kAudioStatusError;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286}
287
Ashok Bhat075e9a12014-01-06 13:45:09 +0000288static jint
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800289android_media_AudioSystem_muteMicrophone(JNIEnv *env, jobject thiz, jboolean on)
290{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000291 return (jint) check_AudioSystem_Command(AudioSystem::muteMicrophone(on));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800292}
293
294static jboolean
295android_media_AudioSystem_isMicrophoneMuted(JNIEnv *env, jobject thiz)
296{
297 bool state = false;
298 AudioSystem::isMicrophoneMuted(&state);
299 return state;
300}
301
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800302static jboolean
Eric Laurent25101b02011-02-02 09:33:30 -0800303android_media_AudioSystem_isStreamActive(JNIEnv *env, jobject thiz, jint stream, jint inPastMs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800304{
305 bool state = false;
Glenn Kastenbc1d77b2012-01-12 16:38:12 -0800306 AudioSystem::isStreamActive((audio_stream_type_t) stream, &state, inPastMs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800307 return state;
308}
309
Jean-Michel Trivid6770542012-10-10 12:03:41 -0700310static jboolean
Jean-Michel Trivi679d5042013-02-04 16:24:09 -0800311android_media_AudioSystem_isStreamActiveRemotely(JNIEnv *env, jobject thiz, jint stream,
312 jint inPastMs)
313{
314 bool state = false;
315 AudioSystem::isStreamActiveRemotely((audio_stream_type_t) stream, &state, inPastMs);
316 return state;
317}
318
319static jboolean
Jean-Michel Trivid6770542012-10-10 12:03:41 -0700320android_media_AudioSystem_isSourceActive(JNIEnv *env, jobject thiz, jint source)
321{
322 bool state = false;
323 AudioSystem::isSourceActive((audio_source_t) source, &state);
324 return state;
325}
326
Ashok Bhat075e9a12014-01-06 13:45:09 +0000327static jint
Jean-Michel Trivi8a21f5d2014-06-05 15:03:52 -0700328android_media_AudioSystem_newAudioSessionId(JNIEnv *env, jobject thiz)
329{
Glenn Kasten211d9052016-02-26 16:22:40 -0800330 return AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
Jean-Michel Trivi8a21f5d2014-06-05 15:03:52 -0700331}
332
333static jint
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -0800334android_media_AudioSystem_newAudioPlayerId(JNIEnv *env, jobject thiz)
335{
336 return AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_PLAYER);
337}
338
339static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700340android_media_AudioSystem_setParameters(JNIEnv *env, jobject thiz, jstring keyValuePairs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800341{
Eric Laurenta553c252009-07-17 12:17:14 -0700342 const jchar* c_keyValuePairs = env->GetStringCritical(keyValuePairs, 0);
343 String8 c_keyValuePairs8;
344 if (keyValuePairs) {
Dan Albert66987492014-11-20 11:41:21 -0800345 c_keyValuePairs8 = String8(
346 reinterpret_cast<const char16_t*>(c_keyValuePairs),
347 env->GetStringLength(keyValuePairs));
Eric Laurenta553c252009-07-17 12:17:14 -0700348 env->ReleaseStringCritical(keyValuePairs, c_keyValuePairs);
349 }
Glenn Kastenc94752a2013-12-19 12:40:33 -0800350 int status = check_AudioSystem_Command(AudioSystem::setParameters(c_keyValuePairs8));
Ashok Bhat075e9a12014-01-06 13:45:09 +0000351 return (jint) status;
Eric Laurenta553c252009-07-17 12:17:14 -0700352}
353
354static jstring
355android_media_AudioSystem_getParameters(JNIEnv *env, jobject thiz, jstring keys)
356{
357 const jchar* c_keys = env->GetStringCritical(keys, 0);
358 String8 c_keys8;
359 if (keys) {
Dan Albert66987492014-11-20 11:41:21 -0800360 c_keys8 = String8(reinterpret_cast<const char16_t*>(c_keys),
361 env->GetStringLength(keys));
Eric Laurenta553c252009-07-17 12:17:14 -0700362 env->ReleaseStringCritical(keys, c_keys);
363 }
Glenn Kastenc94752a2013-12-19 12:40:33 -0800364 return env->NewStringUTF(AudioSystem::getParameters(c_keys8).string());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800365}
366
Glenn Kastened0079d2011-04-04 10:50:50 -0700367static void
368android_media_AudioSystem_error_callback(status_t err)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800369{
Eric Laurent539719a2013-07-18 14:08:00 -0700370 JNIEnv *env = AndroidRuntime::getJNIEnv();
Eric Laurent0e7a4d92010-10-15 12:33:16 -0700371 if (env == NULL) {
372 return;
373 }
374
Glenn Kastened0079d2011-04-04 10:50:50 -0700375 jclass clazz = env->FindClass(kClassPathName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800376
Eric Laurentdfb881f2013-07-18 14:41:39 -0700377 env->CallStaticVoidMethod(clazz, env->GetStaticMethodID(clazz,
378 "errorCallbackFromNative","(I)V"),
379 check_AudioSystem_Command(err));
Viorel Sumanb637ccf2014-05-30 16:51:07 +0300380
381 env->DeleteLocalRef(clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800382}
383
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700384static void
385android_media_AudioSystem_dyn_policy_callback(int event, String8 regId, int val)
386{
387 JNIEnv *env = AndroidRuntime::getJNIEnv();
388 if (env == NULL) {
389 return;
390 }
391
392 jclass clazz = env->FindClass(kClassPathName);
393 const char* zechars = regId.string();
394 jstring zestring = env->NewStringUTF(zechars);
395
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800396 env->CallStaticVoidMethod(clazz, gAudioPolicyEventHandlerMethods.postDynPolicyEventFromNative,
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700397 event, zestring, val);
398
399 env->ReleaseStringUTFChars(zestring, zechars);
400 env->DeleteLocalRef(clazz);
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800401}
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700402
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800403static void
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -0800404android_media_AudioSystem_recording_callback(int event, const record_client_info_t *clientInfo,
Jean-Michel Trivi8ab72802016-02-25 16:31:45 -0800405 const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig,
406 audio_patch_handle_t patchHandle)
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800407{
408 JNIEnv *env = AndroidRuntime::getJNIEnv();
409 if (env == NULL) {
410 return;
411 }
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -0800412 if (clientInfo == NULL || clientConfig == NULL || deviceConfig == NULL) {
413 ALOGE("Unexpected null client/device info or configurations in recording callback");
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800414 return;
415 }
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800416
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800417 // create an array for 2*3 integers to store the record configurations (client + device)
Jean-Michel Trivi8ab72802016-02-25 16:31:45 -0800418 // plus 1 integer for the patch handle
419 const int REC_PARAM_SIZE = 7;
420 jintArray recParamArray = env->NewIntArray(REC_PARAM_SIZE);
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800421 if (recParamArray == NULL) {
422 ALOGE("recording callback: Couldn't allocate int array for configuration data");
423 return;
424 }
Jean-Michel Trivi8ab72802016-02-25 16:31:45 -0800425 jint recParamData[REC_PARAM_SIZE];
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800426 recParamData[0] = (jint) audioFormatFromNative(clientConfig->format);
427 // FIXME this doesn't support index-based masks
428 recParamData[1] = (jint) inChannelMaskFromNative(clientConfig->channel_mask);
429 recParamData[2] = (jint) clientConfig->sample_rate;
430 recParamData[3] = (jint) audioFormatFromNative(deviceConfig->format);
431 // FIXME this doesn't support index-based masks
432 recParamData[4] = (jint) inChannelMaskFromNative(deviceConfig->channel_mask);
433 recParamData[5] = (jint) deviceConfig->sample_rate;
Jean-Michel Trivi8ab72802016-02-25 16:31:45 -0800434 recParamData[6] = (jint) patchHandle;
435 env->SetIntArrayRegion(recParamArray, 0, REC_PARAM_SIZE, recParamData);
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800436
437 // callback into java
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800438 jclass clazz = env->FindClass(kClassPathName);
439 env->CallStaticVoidMethod(clazz,
440 gAudioPolicyEventHandlerMethods.postRecordConfigEventFromNative,
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -0800441 event, (jint) clientInfo->uid, clientInfo->session, clientInfo->source, recParamArray);
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800442 env->DeleteLocalRef(clazz);
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800443
444 env->DeleteLocalRef(recParamArray);
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700445}
446
Ashok Bhat075e9a12014-01-06 13:45:09 +0000447static jint
Paul McLean10804eb2015-01-28 11:16:35 -0800448android_media_AudioSystem_setDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jint state, jstring device_address, jstring device_name)
Eric Laurenta553c252009-07-17 12:17:14 -0700449{
450 const char *c_address = env->GetStringUTFChars(device_address, NULL);
Paul McLean10804eb2015-01-28 11:16:35 -0800451 const char *c_name = env->GetStringUTFChars(device_name, NULL);
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700452 int status = check_AudioSystem_Command(AudioSystem::setDeviceConnectionState(static_cast <audio_devices_t>(device),
453 static_cast <audio_policy_dev_state_t>(state),
Paul McLean10804eb2015-01-28 11:16:35 -0800454 c_address, c_name));
Eric Laurenta553c252009-07-17 12:17:14 -0700455 env->ReleaseStringUTFChars(device_address, c_address);
Paul McLean10804eb2015-01-28 11:16:35 -0800456 env->ReleaseStringUTFChars(device_name, c_name);
Ashok Bhat075e9a12014-01-06 13:45:09 +0000457 return (jint) status;
Eric Laurenta553c252009-07-17 12:17:14 -0700458}
459
Ashok Bhat075e9a12014-01-06 13:45:09 +0000460static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700461android_media_AudioSystem_getDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jstring device_address)
462{
463 const char *c_address = env->GetStringUTFChars(device_address, NULL);
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700464 int state = static_cast <int>(AudioSystem::getDeviceConnectionState(static_cast <audio_devices_t>(device),
Eric Laurenta553c252009-07-17 12:17:14 -0700465 c_address));
466 env->ReleaseStringUTFChars(device_address, c_address);
Ashok Bhat075e9a12014-01-06 13:45:09 +0000467 return (jint) state;
Eric Laurenta553c252009-07-17 12:17:14 -0700468}
469
Ashok Bhat075e9a12014-01-06 13:45:09 +0000470static jint
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -0800471android_media_AudioSystem_handleDeviceConfigChange(JNIEnv *env, jobject thiz, jint device, jstring device_address, jstring device_name)
472{
473 const char *c_address = env->GetStringUTFChars(device_address, NULL);
474 const char *c_name = env->GetStringUTFChars(device_name, NULL);
475 int status = check_AudioSystem_Command(AudioSystem::handleDeviceConfigChange(static_cast <audio_devices_t>(device),
476 c_address, c_name));
477 env->ReleaseStringUTFChars(device_address, c_address);
478 env->ReleaseStringUTFChars(device_name, c_name);
479 return (jint) status;
480}
481
482static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700483android_media_AudioSystem_setPhoneState(JNIEnv *env, jobject thiz, jint state)
484{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000485 return (jint) check_AudioSystem_Command(AudioSystem::setPhoneState((audio_mode_t) state));
Eric Laurenta553c252009-07-17 12:17:14 -0700486}
487
Ashok Bhat075e9a12014-01-06 13:45:09 +0000488static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700489android_media_AudioSystem_setForceUse(JNIEnv *env, jobject thiz, jint usage, jint config)
490{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000491 return (jint) check_AudioSystem_Command(AudioSystem::setForceUse(static_cast <audio_policy_force_use_t>(usage),
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700492 static_cast <audio_policy_forced_cfg_t>(config)));
Eric Laurenta553c252009-07-17 12:17:14 -0700493}
494
Ashok Bhat075e9a12014-01-06 13:45:09 +0000495static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700496android_media_AudioSystem_getForceUse(JNIEnv *env, jobject thiz, jint usage)
497{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000498 return static_cast <jint>(AudioSystem::getForceUse(static_cast <audio_policy_force_use_t>(usage)));
Eric Laurenta553c252009-07-17 12:17:14 -0700499}
500
Ashok Bhat075e9a12014-01-06 13:45:09 +0000501static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700502android_media_AudioSystem_initStreamVolume(JNIEnv *env, jobject thiz, jint stream, jint indexMin, jint indexMax)
503{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000504 return (jint) check_AudioSystem_Command(AudioSystem::initStreamVolume(static_cast <audio_stream_type_t>(stream),
Eric Laurenta553c252009-07-17 12:17:14 -0700505 indexMin,
506 indexMax));
507}
508
Ashok Bhat075e9a12014-01-06 13:45:09 +0000509static jint
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800510android_media_AudioSystem_setStreamVolumeIndex(JNIEnv *env,
511 jobject thiz,
512 jint stream,
513 jint index,
514 jint device)
Eric Laurenta553c252009-07-17 12:17:14 -0700515{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000516 return (jint) check_AudioSystem_Command(
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800517 AudioSystem::setStreamVolumeIndex(static_cast <audio_stream_type_t>(stream),
518 index,
519 (audio_devices_t)device));
Eric Laurenta553c252009-07-17 12:17:14 -0700520}
521
Ashok Bhat075e9a12014-01-06 13:45:09 +0000522static jint
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800523android_media_AudioSystem_getStreamVolumeIndex(JNIEnv *env,
524 jobject thiz,
525 jint stream,
526 jint device)
Eric Laurenta553c252009-07-17 12:17:14 -0700527{
528 int index;
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800529 if (AudioSystem::getStreamVolumeIndex(static_cast <audio_stream_type_t>(stream),
530 &index,
531 (audio_devices_t)device)
532 != NO_ERROR) {
Eric Laurenta553c252009-07-17 12:17:14 -0700533 index = -1;
534 }
Ashok Bhat075e9a12014-01-06 13:45:09 +0000535 return (jint) index;
Eric Laurenta553c252009-07-17 12:17:14 -0700536}
537
Ashok Bhat075e9a12014-01-06 13:45:09 +0000538static jint
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400539android_media_AudioSystem_setMasterVolume(JNIEnv *env, jobject thiz, jfloat value)
540{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000541 return (jint) check_AudioSystem_Command(AudioSystem::setMasterVolume(value));
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400542}
543
544static jfloat
545android_media_AudioSystem_getMasterVolume(JNIEnv *env, jobject thiz)
546{
547 float value;
548 if (AudioSystem::getMasterVolume(&value) != NO_ERROR) {
549 value = -1.0;
550 }
551 return value;
552}
553
Ashok Bhat075e9a12014-01-06 13:45:09 +0000554static jint
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400555android_media_AudioSystem_setMasterMute(JNIEnv *env, jobject thiz, jboolean mute)
556{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000557 return (jint) check_AudioSystem_Command(AudioSystem::setMasterMute(mute));
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400558}
559
Vladimir Markoc1bcdbb2014-10-29 20:34:15 +0000560static jboolean
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400561android_media_AudioSystem_getMasterMute(JNIEnv *env, jobject thiz)
562{
563 bool mute;
564 if (AudioSystem::getMasterMute(&mute) != NO_ERROR) {
565 mute = false;
566 }
567 return mute;
568}
569
Glenn Kasten8b4b97a2011-02-04 13:54:26 -0800570static jint
Andy Hungf04b84d2015-12-18 17:33:27 -0800571android_media_AudioSystem_setMasterMono(JNIEnv *env, jobject thiz, jboolean mono)
572{
573 return (jint) check_AudioSystem_Command(AudioSystem::setMasterMono(mono));
574}
575
576static jboolean
577android_media_AudioSystem_getMasterMono(JNIEnv *env, jobject thiz)
578{
579 bool mono;
580 if (AudioSystem::getMasterMono(&mono) != NO_ERROR) {
581 mono = false;
582 }
583 return mono;
584}
585
586static jint
Glenn Kasten8b4b97a2011-02-04 13:54:26 -0800587android_media_AudioSystem_getDevicesForStream(JNIEnv *env, jobject thiz, jint stream)
588{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700589 return (jint) AudioSystem::getDevicesForStream(static_cast <audio_stream_type_t>(stream));
Glenn Kasten8b4b97a2011-02-04 13:54:26 -0800590}
591
Glenn Kastenc6c43652012-09-24 17:32:30 -0700592static jint
593android_media_AudioSystem_getPrimaryOutputSamplingRate(JNIEnv *env, jobject clazz)
594{
595 return (jint) AudioSystem::getPrimaryOutputSamplingRate();
596}
597
598static jint
599android_media_AudioSystem_getPrimaryOutputFrameCount(JNIEnv *env, jobject clazz)
600{
601 return (jint) AudioSystem::getPrimaryOutputFrameCount();
602}
603
Oliver Woodman61dcdf32013-06-26 12:43:36 +0100604static jint
605android_media_AudioSystem_getOutputLatency(JNIEnv *env, jobject clazz, jint stream)
606{
607 uint32_t afLatency;
608 if (AudioSystem::getOutputLatency(&afLatency, static_cast <audio_stream_type_t>(stream))
609 != NO_ERROR) {
610 afLatency = -1;
611 }
612 return (jint) afLatency;
613}
614
Glenn Kastenfd116ad2013-07-12 17:10:39 -0700615static jint
Andy Hung79583582018-01-23 13:58:02 -0800616android_media_AudioSystem_setLowRamDevice(
617 JNIEnv *env, jobject clazz, jboolean isLowRamDevice, jlong totalMemory)
Glenn Kastenfd116ad2013-07-12 17:10:39 -0700618{
Andy Hung79583582018-01-23 13:58:02 -0800619 return (jint) AudioSystem::setLowRamDevice((bool) isLowRamDevice, (int64_t) totalMemory);
Glenn Kastenfd116ad2013-07-12 17:10:39 -0700620}
621
Ashok Bhat075e9a12014-01-06 13:45:09 +0000622static jint
Eric Laurentdfb881f2013-07-18 14:41:39 -0700623android_media_AudioSystem_checkAudioFlinger(JNIEnv *env, jobject clazz)
624{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000625 return (jint) check_AudioSystem_Command(AudioSystem::checkAudioFlinger());
Eric Laurentdfb881f2013-07-18 14:41:39 -0700626}
627
Eric Laurentb69681c2014-05-19 19:02:51 -0700628
629static bool useInChannelMask(audio_port_type_t type, audio_port_role_t role)
630{
631 return ((type == AUDIO_PORT_TYPE_DEVICE) && (role == AUDIO_PORT_ROLE_SOURCE)) ||
632 ((type == AUDIO_PORT_TYPE_MIX) && (role == AUDIO_PORT_ROLE_SINK));
633}
634
Eric Laurent3a241992014-05-19 19:33:26 -0700635static void convertAudioGainConfigToNative(JNIEnv *env,
636 struct audio_gain_config *nAudioGainConfig,
637 const jobject jAudioGainConfig,
638 bool useInMask)
639{
640 nAudioGainConfig->index = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mIndex);
641 nAudioGainConfig->mode = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mMode);
642 ALOGV("convertAudioGainConfigToNative got gain index %d", nAudioGainConfig->index);
643 jint jMask = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mChannelMask);
644 audio_channel_mask_t nMask;
645 if (useInMask) {
646 nMask = inChannelMaskToNative(jMask);
647 ALOGV("convertAudioGainConfigToNative IN mask java %x native %x", jMask, nMask);
648 } else {
649 nMask = outChannelMaskToNative(jMask);
650 ALOGV("convertAudioGainConfigToNative OUT mask java %x native %x", jMask, nMask);
651 }
652 nAudioGainConfig->channel_mask = nMask;
653 nAudioGainConfig->ramp_duration_ms = env->GetIntField(jAudioGainConfig,
654 gAudioGainConfigFields.mRampDurationMs);
655 jintArray jValues = (jintArray)env->GetObjectField(jAudioGainConfig,
656 gAudioGainConfigFields.mValues);
657 int *nValues = env->GetIntArrayElements(jValues, NULL);
658 size_t size = env->GetArrayLength(jValues);
659 memcpy(nAudioGainConfig->values, nValues, size * sizeof(int));
660 env->DeleteLocalRef(jValues);
661}
662
663
Eric Laurentb69681c2014-05-19 19:02:51 -0700664static jint convertAudioPortConfigToNative(JNIEnv *env,
665 struct audio_port_config *nAudioPortConfig,
Eric Laurent6368a7d2014-11-19 12:18:32 -0800666 const jobject jAudioPortConfig,
667 bool useConfigMask)
Eric Laurentb69681c2014-05-19 19:02:51 -0700668{
669 jobject jAudioPort = env->GetObjectField(jAudioPortConfig, gAudioPortConfigFields.mPort);
670 jobject jHandle = env->GetObjectField(jAudioPort, gAudioPortFields.mHandle);
671 nAudioPortConfig->id = env->GetIntField(jHandle, gAudioHandleFields.mId);
672 nAudioPortConfig->role = (audio_port_role_t)env->GetIntField(jAudioPort,
673 gAudioPortFields.mRole);
674 if (env->IsInstanceOf(jAudioPort, gAudioDevicePortClass)) {
675 nAudioPortConfig->type = AUDIO_PORT_TYPE_DEVICE;
676 } else if (env->IsInstanceOf(jAudioPort, gAudioMixPortClass)) {
677 nAudioPortConfig->type = AUDIO_PORT_TYPE_MIX;
678 } else {
679 env->DeleteLocalRef(jAudioPort);
680 env->DeleteLocalRef(jHandle);
681 return (jint)AUDIO_JAVA_ERROR;
682 }
683 ALOGV("convertAudioPortConfigToNative handle %d role %d type %d",
684 nAudioPortConfig->id, nAudioPortConfig->role, nAudioPortConfig->type);
685
Eric Laurent6368a7d2014-11-19 12:18:32 -0800686 unsigned int configMask = 0;
687
Eric Laurentb69681c2014-05-19 19:02:51 -0700688 nAudioPortConfig->sample_rate = env->GetIntField(jAudioPortConfig,
689 gAudioPortConfigFields.mSamplingRate);
Eric Laurent6368a7d2014-11-19 12:18:32 -0800690 if (nAudioPortConfig->sample_rate != 0) {
691 configMask |= AUDIO_PORT_CONFIG_SAMPLE_RATE;
692 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700693
694 bool useInMask = useInChannelMask(nAudioPortConfig->type, nAudioPortConfig->role);
695 audio_channel_mask_t nMask;
696 jint jMask = env->GetIntField(jAudioPortConfig,
697 gAudioPortConfigFields.mChannelMask);
698 if (useInMask) {
699 nMask = inChannelMaskToNative(jMask);
700 ALOGV("convertAudioPortConfigToNative IN mask java %x native %x", jMask, nMask);
701 } else {
702 nMask = outChannelMaskToNative(jMask);
703 ALOGV("convertAudioPortConfigToNative OUT mask java %x native %x", jMask, nMask);
704 }
705 nAudioPortConfig->channel_mask = nMask;
Eric Laurent6368a7d2014-11-19 12:18:32 -0800706 if (nAudioPortConfig->channel_mask != AUDIO_CHANNEL_NONE) {
707 configMask |= AUDIO_PORT_CONFIG_CHANNEL_MASK;
708 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700709
710 jint jFormat = env->GetIntField(jAudioPortConfig, gAudioPortConfigFields.mFormat);
711 audio_format_t nFormat = audioFormatToNative(jFormat);
712 ALOGV("convertAudioPortConfigToNative format %d native %d", jFormat, nFormat);
713 nAudioPortConfig->format = nFormat;
Eric Laurent6368a7d2014-11-19 12:18:32 -0800714 if (nAudioPortConfig->format != AUDIO_FORMAT_DEFAULT &&
715 nAudioPortConfig->format != AUDIO_FORMAT_INVALID) {
716 configMask |= AUDIO_PORT_CONFIG_FORMAT;
717 }
718
Eric Laurentb69681c2014-05-19 19:02:51 -0700719 jobject jGain = env->GetObjectField(jAudioPortConfig, gAudioPortConfigFields.mGain);
720 if (jGain != NULL) {
Eric Laurent3a241992014-05-19 19:33:26 -0700721 convertAudioGainConfigToNative(env, &nAudioPortConfig->gain, jGain, useInMask);
Eric Laurentb69681c2014-05-19 19:02:51 -0700722 env->DeleteLocalRef(jGain);
Eric Laurent6368a7d2014-11-19 12:18:32 -0800723 configMask |= AUDIO_PORT_CONFIG_GAIN;
Eric Laurentb69681c2014-05-19 19:02:51 -0700724 } else {
725 ALOGV("convertAudioPortConfigToNative no gain");
726 nAudioPortConfig->gain.index = -1;
727 }
Eric Laurent6368a7d2014-11-19 12:18:32 -0800728 if (useConfigMask) {
729 nAudioPortConfig->config_mask = env->GetIntField(jAudioPortConfig,
730 gAudioPortConfigFields.mConfigMask);
731 } else {
732 nAudioPortConfig->config_mask = configMask;
733 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700734 env->DeleteLocalRef(jAudioPort);
735 env->DeleteLocalRef(jHandle);
736 return (jint)AUDIO_JAVA_SUCCESS;
737}
738
739static jint convertAudioPortConfigFromNative(JNIEnv *env,
740 jobject jAudioPort,
741 jobject *jAudioPortConfig,
742 const struct audio_port_config *nAudioPortConfig)
743{
744 jint jStatus = AUDIO_JAVA_SUCCESS;
745 jobject jAudioGainConfig = NULL;
746 jobject jAudioGain = NULL;
747 jintArray jGainValues;
748 bool audioportCreated = false;
749
750 ALOGV("convertAudioPortConfigFromNative jAudioPort %p", jAudioPort);
751
752 if (jAudioPort == NULL) {
753 jobject jHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
754 nAudioPortConfig->id);
755
756 ALOGV("convertAudioPortConfigFromNative handle %d is a %s", nAudioPortConfig->id,
757 nAudioPortConfig->type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix");
758
759 if (jHandle == NULL) {
760 return (jint)AUDIO_JAVA_ERROR;
761 }
762 // create dummy port and port config objects with just the correct handle
763 // and configuration data. The actual AudioPortConfig objects will be
764 // constructed by java code with correct class type (device, mix etc...)
765 // and reference to AudioPort instance in this client
766 jAudioPort = env->NewObject(gAudioPortClass, gAudioPortCstor,
Paul McLeanf29e5f32015-06-15 10:19:22 -0700767 jHandle, // handle
768 0, // role
769 NULL, // name
770 NULL, // samplingRates
771 NULL, // channelMasks
772 NULL, // channelIndexMasks
773 NULL, // formats
774 NULL); // gains
Eric Laurentb69681c2014-05-19 19:02:51 -0700775 env->DeleteLocalRef(jHandle);
776 if (jAudioPort == NULL) {
777 return (jint)AUDIO_JAVA_ERROR;
778 }
779 ALOGV("convertAudioPortConfigFromNative jAudioPort created for handle %d",
780 nAudioPortConfig->id);
781
782 audioportCreated = true;
783 }
784
785 bool useInMask = useInChannelMask(nAudioPortConfig->type, nAudioPortConfig->role);
786
787 audio_channel_mask_t nMask;
788 jint jMask;
789
790 int gainIndex = nAudioPortConfig->gain.index;
791 if (gainIndex >= 0) {
792 ALOGV("convertAudioPortConfigFromNative gain found with index %d mode %x",
793 gainIndex, nAudioPortConfig->gain.mode);
794 if (audioportCreated) {
795 ALOGV("convertAudioPortConfigFromNative creating gain");
796 jAudioGain = env->NewObject(gAudioGainClass, gAudioGainCstor,
797 gainIndex,
798 0,
799 0,
800 0,
801 0,
802 0,
803 0,
804 0,
805 0);
806 if (jAudioGain == NULL) {
807 ALOGV("convertAudioPortConfigFromNative creating gain FAILED");
808 jStatus = (jint)AUDIO_JAVA_ERROR;
809 goto exit;
810 }
811 } else {
812 ALOGV("convertAudioPortConfigFromNative reading gain from port");
813 jobjectArray jGains = (jobjectArray)env->GetObjectField(jAudioPort,
814 gAudioPortFields.mGains);
815 if (jGains == NULL) {
816 ALOGV("convertAudioPortConfigFromNative could not get gains from port");
817 jStatus = (jint)AUDIO_JAVA_ERROR;
818 goto exit;
819 }
820 jAudioGain = env->GetObjectArrayElement(jGains, gainIndex);
821 env->DeleteLocalRef(jGains);
822 if (jAudioGain == NULL) {
823 ALOGV("convertAudioPortConfigFromNative could not get gain at index %d", gainIndex);
824 jStatus = (jint)AUDIO_JAVA_ERROR;
825 goto exit;
826 }
827 }
Eric Laurent0078c7c2014-06-04 09:49:52 -0700828 int numValues;
829 if (useInMask) {
830 numValues = audio_channel_count_from_in_mask(nAudioPortConfig->gain.channel_mask);
831 } else {
832 numValues = audio_channel_count_from_out_mask(nAudioPortConfig->gain.channel_mask);
833 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700834 jGainValues = env->NewIntArray(numValues);
835 if (jGainValues == NULL) {
836 ALOGV("convertAudioPortConfigFromNative could not create gain values %d", numValues);
837 jStatus = (jint)AUDIO_JAVA_ERROR;
838 goto exit;
839 }
840 env->SetIntArrayRegion(jGainValues, 0, numValues,
841 nAudioPortConfig->gain.values);
842
843 nMask = nAudioPortConfig->gain.channel_mask;
844 if (useInMask) {
845 jMask = inChannelMaskFromNative(nMask);
846 ALOGV("convertAudioPortConfigFromNative IN mask java %x native %x", jMask, nMask);
847 } else {
848 jMask = outChannelMaskFromNative(nMask);
849 ALOGV("convertAudioPortConfigFromNative OUT mask java %x native %x", jMask, nMask);
850 }
851
852 jAudioGainConfig = env->NewObject(gAudioGainConfigClass,
853 gAudioGainConfigCstor,
854 gainIndex,
855 jAudioGain,
856 nAudioPortConfig->gain.mode,
857 jMask,
858 jGainValues,
859 nAudioPortConfig->gain.ramp_duration_ms);
860 env->DeleteLocalRef(jGainValues);
861 if (jAudioGainConfig == NULL) {
862 ALOGV("convertAudioPortConfigFromNative could not create gain config");
863 jStatus = (jint)AUDIO_JAVA_ERROR;
864 goto exit;
865 }
866 }
867 jclass clazz;
868 jmethodID methodID;
869 if (audioportCreated) {
870 clazz = gAudioPortConfigClass;
871 methodID = gAudioPortConfigCstor;
872 ALOGV("convertAudioPortConfigFromNative building a generic port config");
873 } else {
874 if (env->IsInstanceOf(jAudioPort, gAudioDevicePortClass)) {
875 clazz = gAudioDevicePortConfigClass;
876 methodID = gAudioDevicePortConfigCstor;
877 ALOGV("convertAudioPortConfigFromNative building a device config");
878 } else if (env->IsInstanceOf(jAudioPort, gAudioMixPortClass)) {
879 clazz = gAudioMixPortConfigClass;
880 methodID = gAudioMixPortConfigCstor;
881 ALOGV("convertAudioPortConfigFromNative building a mix config");
882 } else {
883 jStatus = (jint)AUDIO_JAVA_ERROR;
884 goto exit;
885 }
886 }
887 nMask = nAudioPortConfig->channel_mask;
888 if (useInMask) {
889 jMask = inChannelMaskFromNative(nMask);
890 ALOGV("convertAudioPortConfigFromNative IN mask java %x native %x", jMask, nMask);
891 } else {
892 jMask = outChannelMaskFromNative(nMask);
893 ALOGV("convertAudioPortConfigFromNative OUT mask java %x native %x", jMask, nMask);
894 }
895
896 *jAudioPortConfig = env->NewObject(clazz, methodID,
897 jAudioPort,
898 nAudioPortConfig->sample_rate,
899 jMask,
900 audioFormatFromNative(nAudioPortConfig->format),
901 jAudioGainConfig);
902 if (*jAudioPortConfig == NULL) {
903 ALOGV("convertAudioPortConfigFromNative could not create new port config");
904 jStatus = (jint)AUDIO_JAVA_ERROR;
905 } else {
906 ALOGV("convertAudioPortConfigFromNative OK");
907 }
908
909exit:
910 if (audioportCreated) {
911 env->DeleteLocalRef(jAudioPort);
912 if (jAudioGain != NULL) {
913 env->DeleteLocalRef(jAudioGain);
914 }
915 }
916 if (jAudioGainConfig != NULL) {
917 env->DeleteLocalRef(jAudioGainConfig);
918 }
919 return jStatus;
920}
921
Paul McLean4e5e9e92015-06-17 10:10:11 -0700922static bool hasFormat(int* formats, size_t size, int format) {
923 for (size_t index = 0; index < size; index++) {
924 if (formats[index] == format) {
925 return true; // found
926 }
927 }
928 return false; // not found
929}
930
Andy Hung737d9fb2016-08-16 18:38:49 -0700931// TODO: pull out to separate file
932template <typename T, size_t N>
933static constexpr size_t array_size(const T (&)[N]) {
934 return N;
935}
936
Eric Laurentb69681c2014-05-19 19:02:51 -0700937static jint convertAudioPortFromNative(JNIEnv *env,
938 jobject *jAudioPort, const struct audio_port *nAudioPort)
939{
940 jint jStatus = (jint)AUDIO_JAVA_SUCCESS;
941 jintArray jSamplingRates = NULL;
942 jintArray jChannelMasks = NULL;
Paul McLeanf29e5f32015-06-15 10:19:22 -0700943 jintArray jChannelIndexMasks = NULL;
Paul McLean4e5e9e92015-06-17 10:10:11 -0700944 int* cFormats = NULL;
Eric Laurentb69681c2014-05-19 19:02:51 -0700945 jintArray jFormats = NULL;
946 jobjectArray jGains = NULL;
947 jobject jHandle = NULL;
Paul McLean10804eb2015-01-28 11:16:35 -0800948 jstring jDeviceName = NULL;
Eric Laurentb69681c2014-05-19 19:02:51 -0700949 bool useInMask;
Paul McLeanf29e5f32015-06-15 10:19:22 -0700950 size_t numPositionMasks = 0;
951 size_t numIndexMasks = 0;
Paul McLean2db94372015-06-18 12:47:34 -0700952 size_t numUniqueFormats = 0;
953
Paul McLean10804eb2015-01-28 11:16:35 -0800954 ALOGV("convertAudioPortFromNative id %d role %d type %d name %s",
955 nAudioPort->id, nAudioPort->role, nAudioPort->type, nAudioPort->name);
Eric Laurentb69681c2014-05-19 19:02:51 -0700956
Andy Hung737d9fb2016-08-16 18:38:49 -0700957 // Verify audio port array count info.
958 if (nAudioPort->num_sample_rates > array_size(nAudioPort->sample_rates)
959 || nAudioPort->num_channel_masks > array_size(nAudioPort->channel_masks)
960 || nAudioPort->num_formats > array_size(nAudioPort->formats)
961 || nAudioPort->num_gains > array_size(nAudioPort->gains)) {
962
963 std::stringstream ss;
964 ss << "convertAudioPortFromNative array count out of bounds:"
965 << " num_sample_rates " << nAudioPort->num_sample_rates
966 << " num_channel_masks " << nAudioPort->num_channel_masks
967 << " num_formats " << nAudioPort->num_formats
968 << " num_gains " << nAudioPort->num_gains
969 ;
970 std::string s = ss.str();
971
972 // Prefer to log through Java wtf instead of native ALOGE.
973 ScopedLocalRef<jclass> jLogClass(env, env->FindClass("android/util/Log"));
974 jmethodID jWtfId = (jLogClass.get() == nullptr)
975 ? nullptr
976 : env->GetStaticMethodID(jLogClass.get(), "wtf",
977 "(Ljava/lang/String;Ljava/lang/String;)I");
978 if (jWtfId != nullptr) {
979 ScopedLocalRef<jstring> jMessage(env, env->NewStringUTF(s.c_str()));
980 ScopedLocalRef<jstring> jTag(env, env->NewStringUTF(LOG_TAG));
981 (void)env->CallStaticIntMethod(jLogClass.get(), jWtfId, jTag.get(), jMessage.get());
982 } else {
983 ALOGE("%s", s.c_str());
984 }
985 jStatus = (jint)AUDIO_JAVA_ERROR;
986 goto exit;
987 }
988
Eric Laurentb69681c2014-05-19 19:02:51 -0700989 jSamplingRates = env->NewIntArray(nAudioPort->num_sample_rates);
990 if (jSamplingRates == NULL) {
991 jStatus = (jint)AUDIO_JAVA_ERROR;
992 goto exit;
993 }
994 if (nAudioPort->num_sample_rates) {
995 env->SetIntArrayRegion(jSamplingRates, 0, nAudioPort->num_sample_rates,
996 (jint *)nAudioPort->sample_rates);
997 }
998
Paul McLeanf29e5f32015-06-15 10:19:22 -0700999 // count up how many masks are positional and indexed
1000 for(size_t index = 0; index < nAudioPort->num_channel_masks; index++) {
1001 const audio_channel_mask_t mask = nAudioPort->channel_masks[index];
1002 if (audio_channel_mask_get_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
1003 numIndexMasks++;
1004 } else {
1005 numPositionMasks++;
1006 }
1007 }
1008
1009 jChannelMasks = env->NewIntArray(numPositionMasks);
Eric Laurentb69681c2014-05-19 19:02:51 -07001010 if (jChannelMasks == NULL) {
1011 jStatus = (jint)AUDIO_JAVA_ERROR;
1012 goto exit;
1013 }
Paul McLeanf29e5f32015-06-15 10:19:22 -07001014 jChannelIndexMasks = env->NewIntArray(numIndexMasks);
1015 if (jChannelIndexMasks == NULL) {
1016 jStatus = (jint)AUDIO_JAVA_ERROR;
1017 goto exit;
1018 }
Eric Laurentb69681c2014-05-19 19:02:51 -07001019 useInMask = useInChannelMask(nAudioPort->type, nAudioPort->role);
1020
Paul McLeanf29e5f32015-06-15 10:19:22 -07001021 // put the masks in the output arrays
1022 for (size_t maskIndex = 0, posMaskIndex = 0, indexedMaskIndex = 0;
1023 maskIndex < nAudioPort->num_channel_masks; maskIndex++) {
1024 const audio_channel_mask_t mask = nAudioPort->channel_masks[maskIndex];
1025 if (audio_channel_mask_get_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
1026 jint jMask = audio_channel_mask_get_bits(mask);
1027 env->SetIntArrayRegion(jChannelIndexMasks, indexedMaskIndex++, 1, &jMask);
Eric Laurentb69681c2014-05-19 19:02:51 -07001028 } else {
Paul McLeanf29e5f32015-06-15 10:19:22 -07001029 jint jMask = useInMask ? inChannelMaskFromNative(mask)
1030 : outChannelMaskFromNative(mask);
1031 env->SetIntArrayRegion(jChannelMasks, posMaskIndex++, 1, &jMask);
Eric Laurentb69681c2014-05-19 19:02:51 -07001032 }
Eric Laurentb69681c2014-05-19 19:02:51 -07001033 }
1034
Paul McLeanf29e5f32015-06-15 10:19:22 -07001035 // formats
Paul McLean2db94372015-06-18 12:47:34 -07001036 if (nAudioPort->num_formats != 0) {
1037 cFormats = new int[nAudioPort->num_formats];
1038 for (size_t index = 0; index < nAudioPort->num_formats; index++) {
1039 int format = audioFormatFromNative(nAudioPort->formats[index]);
1040 if (!hasFormat(cFormats, numUniqueFormats, format)) {
1041 cFormats[numUniqueFormats++] = format;
1042 }
Paul McLean4e5e9e92015-06-17 10:10:11 -07001043 }
1044 }
1045 jFormats = env->NewIntArray(numUniqueFormats);
Eric Laurentb69681c2014-05-19 19:02:51 -07001046 if (jFormats == NULL) {
1047 jStatus = (jint)AUDIO_JAVA_ERROR;
1048 goto exit;
1049 }
Paul McLean2db94372015-06-18 12:47:34 -07001050 if (numUniqueFormats != 0) {
1051 env->SetIntArrayRegion(jFormats, 0, numUniqueFormats, cFormats);
1052 }
Eric Laurentb69681c2014-05-19 19:02:51 -07001053
Paul McLeanf29e5f32015-06-15 10:19:22 -07001054 // gains
Eric Laurentb69681c2014-05-19 19:02:51 -07001055 jGains = env->NewObjectArray(nAudioPort->num_gains,
1056 gAudioGainClass, NULL);
1057 if (jGains == NULL) {
1058 jStatus = (jint)AUDIO_JAVA_ERROR;
1059 goto exit;
1060 }
Paul McLeanf29e5f32015-06-15 10:19:22 -07001061
Eric Laurentb69681c2014-05-19 19:02:51 -07001062 for (size_t j = 0; j < nAudioPort->num_gains; j++) {
1063 audio_channel_mask_t nMask = nAudioPort->gains[j].channel_mask;
Paul McLeanf29e5f32015-06-15 10:19:22 -07001064 jint jMask;
Eric Laurentb69681c2014-05-19 19:02:51 -07001065 if (useInMask) {
1066 jMask = inChannelMaskFromNative(nMask);
1067 ALOGV("convertAudioPortConfigFromNative IN mask java %x native %x", jMask, nMask);
1068 } else {
1069 jMask = outChannelMaskFromNative(nMask);
1070 ALOGV("convertAudioPortConfigFromNative OUT mask java %x native %x", jMask, nMask);
1071 }
1072
1073 jobject jGain = env->NewObject(gAudioGainClass, gAudioGainCstor,
1074 j,
1075 nAudioPort->gains[j].mode,
1076 jMask,
1077 nAudioPort->gains[j].min_value,
1078 nAudioPort->gains[j].max_value,
1079 nAudioPort->gains[j].default_value,
1080 nAudioPort->gains[j].step_value,
1081 nAudioPort->gains[j].min_ramp_ms,
1082 nAudioPort->gains[j].max_ramp_ms);
1083 if (jGain == NULL) {
1084 jStatus = (jint)AUDIO_JAVA_ERROR;
1085 goto exit;
1086 }
1087 env->SetObjectArrayElement(jGains, j, jGain);
1088 env->DeleteLocalRef(jGain);
1089 }
1090
1091 jHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
1092 nAudioPort->id);
1093 if (jHandle == NULL) {
1094 jStatus = (jint)AUDIO_JAVA_ERROR;
1095 goto exit;
1096 }
1097
Paul McLean10804eb2015-01-28 11:16:35 -08001098 jDeviceName = env->NewStringUTF(nAudioPort->name);
1099
Eric Laurentb69681c2014-05-19 19:02:51 -07001100 if (nAudioPort->type == AUDIO_PORT_TYPE_DEVICE) {
1101 ALOGV("convertAudioPortFromNative is a device %08x", nAudioPort->ext.device.type);
1102 jstring jAddress = env->NewStringUTF(nAudioPort->ext.device.address);
1103 *jAudioPort = env->NewObject(gAudioDevicePortClass, gAudioDevicePortCstor,
Paul McLean10804eb2015-01-28 11:16:35 -08001104 jHandle, jDeviceName,
Paul McLeanf29e5f32015-06-15 10:19:22 -07001105 jSamplingRates, jChannelMasks, jChannelIndexMasks,
1106 jFormats, jGains,
Eric Laurentb69681c2014-05-19 19:02:51 -07001107 nAudioPort->ext.device.type, jAddress);
1108 env->DeleteLocalRef(jAddress);
1109 } else if (nAudioPort->type == AUDIO_PORT_TYPE_MIX) {
1110 ALOGV("convertAudioPortFromNative is a mix");
1111 *jAudioPort = env->NewObject(gAudioMixPortClass, gAudioMixPortCstor,
Eric Laurent4bcdba82015-05-01 11:37:49 -07001112 jHandle, nAudioPort->ext.mix.handle,
1113 nAudioPort->role, jDeviceName,
Paul McLeanf29e5f32015-06-15 10:19:22 -07001114 jSamplingRates, jChannelMasks, jChannelIndexMasks,
Eric Laurentb69681c2014-05-19 19:02:51 -07001115 jFormats, jGains);
1116 } else {
1117 ALOGE("convertAudioPortFromNative unknown nAudioPort type %d", nAudioPort->type);
1118 jStatus = (jint)AUDIO_JAVA_ERROR;
1119 goto exit;
1120 }
1121 if (*jAudioPort == NULL) {
1122 jStatus = (jint)AUDIO_JAVA_ERROR;
1123 goto exit;
1124 }
1125
1126 jobject jAudioPortConfig;
1127 jStatus = convertAudioPortConfigFromNative(env,
1128 *jAudioPort,
1129 &jAudioPortConfig,
1130 &nAudioPort->active_config);
1131 if (jStatus != AUDIO_JAVA_SUCCESS) {
Andy Hung737d9fb2016-08-16 18:38:49 -07001132 goto exit;
Eric Laurentb69681c2014-05-19 19:02:51 -07001133 }
1134
1135 env->SetObjectField(*jAudioPort, gAudioPortFields.mActiveConfig, jAudioPortConfig);
1136
1137exit:
Paul McLean10804eb2015-01-28 11:16:35 -08001138 if (jDeviceName != NULL) {
1139 env->DeleteLocalRef(jDeviceName);
1140 }
Eric Laurentb69681c2014-05-19 19:02:51 -07001141 if (jSamplingRates != NULL) {
1142 env->DeleteLocalRef(jSamplingRates);
1143 }
1144 if (jChannelMasks != NULL) {
1145 env->DeleteLocalRef(jChannelMasks);
1146 }
Paul McLean4e5e9e92015-06-17 10:10:11 -07001147 if (jChannelIndexMasks != NULL) {
1148 env->DeleteLocalRef(jChannelIndexMasks);
1149 }
1150 if (cFormats != NULL) {
1151 delete[] cFormats;
1152 }
Eric Laurentb69681c2014-05-19 19:02:51 -07001153 if (jFormats != NULL) {
1154 env->DeleteLocalRef(jFormats);
1155 }
1156 if (jGains != NULL) {
1157 env->DeleteLocalRef(jGains);
1158 }
1159 if (jHandle != NULL) {
1160 env->DeleteLocalRef(jHandle);
1161 }
1162
1163 return jStatus;
1164}
1165
Eric Laurentb69681c2014-05-19 19:02:51 -07001166static jint
1167android_media_AudioSystem_listAudioPorts(JNIEnv *env, jobject clazz,
1168 jobject jPorts, jintArray jGeneration)
1169{
1170 ALOGV("listAudioPorts");
1171
1172 if (jPorts == NULL) {
1173 ALOGE("listAudioPorts NULL AudioPort ArrayList");
1174 return (jint)AUDIO_JAVA_BAD_VALUE;
1175 }
1176 if (!env->IsInstanceOf(jPorts, gArrayListClass)) {
1177 ALOGE("listAudioPorts not an arraylist");
1178 return (jint)AUDIO_JAVA_BAD_VALUE;
1179 }
1180
1181 if (jGeneration == NULL || env->GetArrayLength(jGeneration) != 1) {
1182 return (jint)AUDIO_JAVA_BAD_VALUE;
1183 }
1184
1185 status_t status;
1186 unsigned int generation1;
1187 unsigned int generation;
1188 unsigned int numPorts;
1189 jint *nGeneration;
1190 struct audio_port *nPorts = NULL;
1191 int attempts = MAX_PORT_GENERATION_SYNC_ATTEMPTS;
Eric Laurentb36d1042016-04-14 18:00:38 -07001192 jint jStatus;
Eric Laurentb69681c2014-05-19 19:02:51 -07001193
1194 // get the port count and all the ports until they both return the same generation
1195 do {
1196 if (attempts-- < 0) {
1197 status = TIMED_OUT;
1198 break;
1199 }
1200
1201 numPorts = 0;
1202 status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE,
1203 AUDIO_PORT_TYPE_NONE,
1204 &numPorts,
1205 NULL,
1206 &generation1);
Eric Laurentb36d1042016-04-14 18:00:38 -07001207 if (status != NO_ERROR) {
Eric Laurentb69681c2014-05-19 19:02:51 -07001208 ALOGE_IF(status != NO_ERROR, "AudioSystem::listAudioPorts error %d", status);
1209 break;
1210 }
Eric Laurentb36d1042016-04-14 18:00:38 -07001211 if (numPorts == 0) {
1212 jStatus = (jint)AUDIO_JAVA_SUCCESS;
1213 goto exit;
1214 }
Eric Laurentb69681c2014-05-19 19:02:51 -07001215 nPorts = (struct audio_port *)realloc(nPorts, numPorts * sizeof(struct audio_port));
1216
1217 status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE,
1218 AUDIO_PORT_TYPE_NONE,
1219 &numPorts,
1220 nPorts,
1221 &generation);
1222 ALOGV("listAudioPorts AudioSystem::listAudioPorts numPorts %d generation %d generation1 %d",
1223 numPorts, generation, generation1);
1224 } while (generation1 != generation && status == NO_ERROR);
1225
Eric Laurentb36d1042016-04-14 18:00:38 -07001226 jStatus = nativeToJavaStatus(status);
Eric Laurentb69681c2014-05-19 19:02:51 -07001227 if (jStatus != AUDIO_JAVA_SUCCESS) {
1228 goto exit;
1229 }
1230
Eric Laurentb69681c2014-05-19 19:02:51 -07001231 for (size_t i = 0; i < numPorts; i++) {
1232 jobject jAudioPort;
1233 jStatus = convertAudioPortFromNative(env, &jAudioPort, &nPorts[i]);
1234 if (jStatus != AUDIO_JAVA_SUCCESS) {
1235 goto exit;
1236 }
1237 env->CallBooleanMethod(jPorts, gArrayListMethods.add, jAudioPort);
1238 }
1239
1240exit:
Eric Laurentb36d1042016-04-14 18:00:38 -07001241 nGeneration = env->GetIntArrayElements(jGeneration, NULL);
1242 if (nGeneration == NULL) {
1243 jStatus = (jint)AUDIO_JAVA_ERROR;
1244 } else {
1245 nGeneration[0] = generation1;
1246 env->ReleaseIntArrayElements(jGeneration, nGeneration, 0);
1247 }
Eric Laurentb69681c2014-05-19 19:02:51 -07001248 free(nPorts);
1249 return jStatus;
1250}
1251
1252static int
1253android_media_AudioSystem_createAudioPatch(JNIEnv *env, jobject clazz,
1254 jobjectArray jPatches, jobjectArray jSources, jobjectArray jSinks)
1255{
1256 status_t status;
1257 jint jStatus;
1258
1259 ALOGV("createAudioPatch");
1260 if (jPatches == NULL || jSources == NULL || jSinks == NULL) {
1261 return (jint)AUDIO_JAVA_BAD_VALUE;
1262 }
1263
1264 if (env->GetArrayLength(jPatches) != 1) {
1265 return (jint)AUDIO_JAVA_BAD_VALUE;
1266 }
1267 jint numSources = env->GetArrayLength(jSources);
1268 if (numSources == 0 || numSources > AUDIO_PATCH_PORTS_MAX) {
1269 return (jint)AUDIO_JAVA_BAD_VALUE;
1270 }
1271
1272 jint numSinks = env->GetArrayLength(jSinks);
1273 if (numSinks == 0 || numSinks > AUDIO_PATCH_PORTS_MAX) {
1274 return (jint)AUDIO_JAVA_BAD_VALUE;
1275 }
1276
1277 audio_patch_handle_t handle = (audio_patch_handle_t)0;
1278 jobject jPatch = env->GetObjectArrayElement(jPatches, 0);
1279 jobject jPatchHandle = NULL;
1280 if (jPatch != NULL) {
1281 if (!env->IsInstanceOf(jPatch, gAudioPatchClass)) {
1282 return (jint)AUDIO_JAVA_BAD_VALUE;
1283 }
1284 jPatchHandle = env->GetObjectField(jPatch, gAudioPatchFields.mHandle);
1285 handle = (audio_patch_handle_t)env->GetIntField(jPatchHandle, gAudioHandleFields.mId);
1286 }
1287
1288 struct audio_patch nPatch;
1289
1290 nPatch.id = handle;
1291 nPatch.num_sources = 0;
1292 nPatch.num_sinks = 0;
1293 jobject jSource = NULL;
1294 jobject jSink = NULL;
1295
1296 for (jint i = 0; i < numSources; i++) {
1297 jSource = env->GetObjectArrayElement(jSources, i);
1298 if (!env->IsInstanceOf(jSource, gAudioPortConfigClass)) {
1299 jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
1300 goto exit;
1301 }
Eric Laurent6368a7d2014-11-19 12:18:32 -08001302 jStatus = convertAudioPortConfigToNative(env, &nPatch.sources[i], jSource, false);
Eric Laurentb69681c2014-05-19 19:02:51 -07001303 env->DeleteLocalRef(jSource);
1304 jSource = NULL;
1305 if (jStatus != AUDIO_JAVA_SUCCESS) {
1306 goto exit;
1307 }
1308 nPatch.num_sources++;
1309 }
1310
1311 for (jint i = 0; i < numSinks; i++) {
1312 jSink = env->GetObjectArrayElement(jSinks, i);
1313 if (!env->IsInstanceOf(jSink, gAudioPortConfigClass)) {
1314 jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
1315 goto exit;
1316 }
Eric Laurent6368a7d2014-11-19 12:18:32 -08001317 jStatus = convertAudioPortConfigToNative(env, &nPatch.sinks[i], jSink, false);
Eric Laurentb69681c2014-05-19 19:02:51 -07001318 env->DeleteLocalRef(jSink);
1319 jSink = NULL;
1320 if (jStatus != AUDIO_JAVA_SUCCESS) {
1321 goto exit;
1322 }
1323 nPatch.num_sinks++;
1324 }
1325
1326 ALOGV("AudioSystem::createAudioPatch");
1327 status = AudioSystem::createAudioPatch(&nPatch, &handle);
1328 ALOGV("AudioSystem::createAudioPatch() returned %d hande %d", status, handle);
1329
1330 jStatus = nativeToJavaStatus(status);
1331 if (jStatus != AUDIO_JAVA_SUCCESS) {
1332 goto exit;
1333 }
1334
1335 if (jPatchHandle == NULL) {
1336 jPatchHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
1337 handle);
1338 if (jPatchHandle == NULL) {
1339 jStatus = (jint)AUDIO_JAVA_ERROR;
1340 goto exit;
1341 }
1342 jPatch = env->NewObject(gAudioPatchClass, gAudioPatchCstor, jPatchHandle, jSources, jSinks);
1343 if (jPatch == NULL) {
1344 jStatus = (jint)AUDIO_JAVA_ERROR;
1345 goto exit;
1346 }
1347 env->SetObjectArrayElement(jPatches, 0, jPatch);
1348 } else {
1349 env->SetIntField(jPatchHandle, gAudioHandleFields.mId, handle);
1350 }
1351
1352exit:
1353 if (jPatchHandle != NULL) {
1354 env->DeleteLocalRef(jPatchHandle);
1355 }
1356 if (jPatch != NULL) {
1357 env->DeleteLocalRef(jPatch);
1358 }
1359 if (jSource != NULL) {
1360 env->DeleteLocalRef(jSource);
1361 }
1362 if (jSink != NULL) {
1363 env->DeleteLocalRef(jSink);
1364 }
1365 return jStatus;
1366}
1367
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001368static jint
Eric Laurentb69681c2014-05-19 19:02:51 -07001369android_media_AudioSystem_releaseAudioPatch(JNIEnv *env, jobject clazz,
1370 jobject jPatch)
1371{
1372 ALOGV("releaseAudioPatch");
1373 if (jPatch == NULL) {
1374 return (jint)AUDIO_JAVA_BAD_VALUE;
1375 }
1376
1377 audio_patch_handle_t handle = (audio_patch_handle_t)0;
1378 jobject jPatchHandle = NULL;
1379 if (!env->IsInstanceOf(jPatch, gAudioPatchClass)) {
1380 return (jint)AUDIO_JAVA_BAD_VALUE;
1381 }
1382 jPatchHandle = env->GetObjectField(jPatch, gAudioPatchFields.mHandle);
1383 handle = (audio_patch_handle_t)env->GetIntField(jPatchHandle, gAudioHandleFields.mId);
1384 env->DeleteLocalRef(jPatchHandle);
1385
1386 ALOGV("AudioSystem::releaseAudioPatch");
1387 status_t status = AudioSystem::releaseAudioPatch(handle);
1388 ALOGV("AudioSystem::releaseAudioPatch() returned %d", status);
1389 jint jStatus = nativeToJavaStatus(status);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001390 return jStatus;
Eric Laurentb69681c2014-05-19 19:02:51 -07001391}
1392
1393static jint
1394android_media_AudioSystem_listAudioPatches(JNIEnv *env, jobject clazz,
1395 jobject jPatches, jintArray jGeneration)
1396{
1397 ALOGV("listAudioPatches");
1398 if (jPatches == NULL) {
1399 ALOGE("listAudioPatches NULL AudioPatch ArrayList");
1400 return (jint)AUDIO_JAVA_BAD_VALUE;
1401 }
1402 if (!env->IsInstanceOf(jPatches, gArrayListClass)) {
1403 ALOGE("listAudioPatches not an arraylist");
1404 return (jint)AUDIO_JAVA_BAD_VALUE;
1405 }
1406
1407 if (jGeneration == NULL || env->GetArrayLength(jGeneration) != 1) {
1408 return (jint)AUDIO_JAVA_BAD_VALUE;
1409 }
1410
1411 status_t status;
1412 unsigned int generation1;
1413 unsigned int generation;
1414 unsigned int numPatches;
1415 jint *nGeneration;
1416 struct audio_patch *nPatches = NULL;
1417 jobjectArray jSources = NULL;
1418 jobject jSource = NULL;
1419 jobjectArray jSinks = NULL;
1420 jobject jSink = NULL;
1421 jobject jPatch = NULL;
1422 int attempts = MAX_PORT_GENERATION_SYNC_ATTEMPTS;
Eric Laurentb36d1042016-04-14 18:00:38 -07001423 jint jStatus;
Eric Laurentb69681c2014-05-19 19:02:51 -07001424
1425 // get the patch count and all the patches until they both return the same generation
1426 do {
1427 if (attempts-- < 0) {
1428 status = TIMED_OUT;
1429 break;
1430 }
1431
1432 numPatches = 0;
1433 status = AudioSystem::listAudioPatches(&numPatches,
1434 NULL,
1435 &generation1);
Eric Laurentb36d1042016-04-14 18:00:38 -07001436 if (status != NO_ERROR) {
Eric Laurentb69681c2014-05-19 19:02:51 -07001437 ALOGE_IF(status != NO_ERROR, "listAudioPatches AudioSystem::listAudioPatches error %d",
1438 status);
1439 break;
1440 }
Eric Laurentb36d1042016-04-14 18:00:38 -07001441 if (numPatches == 0) {
1442 jStatus = (jint)AUDIO_JAVA_SUCCESS;
1443 goto exit;
1444 }
1445
Eric Laurentb69681c2014-05-19 19:02:51 -07001446 nPatches = (struct audio_patch *)realloc(nPatches, numPatches * sizeof(struct audio_patch));
1447
1448 status = AudioSystem::listAudioPatches(&numPatches,
1449 nPatches,
1450 &generation);
1451 ALOGV("listAudioPatches AudioSystem::listAudioPatches numPatches %d generation %d generation1 %d",
1452 numPatches, generation, generation1);
1453
1454 } while (generation1 != generation && status == NO_ERROR);
1455
Eric Laurentb36d1042016-04-14 18:00:38 -07001456 jStatus = nativeToJavaStatus(status);
Eric Laurentb69681c2014-05-19 19:02:51 -07001457 if (jStatus != AUDIO_JAVA_SUCCESS) {
1458 goto exit;
1459 }
1460
Eric Laurentb69681c2014-05-19 19:02:51 -07001461 for (size_t i = 0; i < numPatches; i++) {
1462 jobject patchHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
1463 nPatches[i].id);
1464 if (patchHandle == NULL) {
1465 jStatus = AUDIO_JAVA_ERROR;
1466 goto exit;
1467 }
Dan Albert46d84442014-11-18 16:07:51 -08001468 ALOGV("listAudioPatches patch %zu num_sources %d num_sinks %d",
Eric Laurentb69681c2014-05-19 19:02:51 -07001469 i, nPatches[i].num_sources, nPatches[i].num_sinks);
1470
1471 env->SetIntField(patchHandle, gAudioHandleFields.mId, nPatches[i].id);
1472
1473 // load sources
1474 jSources = env->NewObjectArray(nPatches[i].num_sources,
1475 gAudioPortConfigClass, NULL);
1476 if (jSources == NULL) {
1477 jStatus = AUDIO_JAVA_ERROR;
1478 goto exit;
1479 }
1480
1481 for (size_t j = 0; j < nPatches[i].num_sources; j++) {
1482 jStatus = convertAudioPortConfigFromNative(env,
1483 NULL,
1484 &jSource,
1485 &nPatches[i].sources[j]);
1486 if (jStatus != AUDIO_JAVA_SUCCESS) {
1487 goto exit;
1488 }
1489 env->SetObjectArrayElement(jSources, j, jSource);
1490 env->DeleteLocalRef(jSource);
1491 jSource = NULL;
Dan Albert46d84442014-11-18 16:07:51 -08001492 ALOGV("listAudioPatches patch %zu source %zu is a %s handle %d",
Eric Laurentb69681c2014-05-19 19:02:51 -07001493 i, j,
1494 nPatches[i].sources[j].type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix",
1495 nPatches[i].sources[j].id);
1496 }
1497 // load sinks
1498 jSinks = env->NewObjectArray(nPatches[i].num_sinks,
1499 gAudioPortConfigClass, NULL);
1500 if (jSinks == NULL) {
1501 jStatus = AUDIO_JAVA_ERROR;
1502 goto exit;
1503 }
1504
1505 for (size_t j = 0; j < nPatches[i].num_sinks; j++) {
1506 jStatus = convertAudioPortConfigFromNative(env,
1507 NULL,
1508 &jSink,
1509 &nPatches[i].sinks[j]);
1510
1511 if (jStatus != AUDIO_JAVA_SUCCESS) {
1512 goto exit;
1513 }
1514 env->SetObjectArrayElement(jSinks, j, jSink);
1515 env->DeleteLocalRef(jSink);
1516 jSink = NULL;
Dan Albert46d84442014-11-18 16:07:51 -08001517 ALOGV("listAudioPatches patch %zu sink %zu is a %s handle %d",
Eric Laurentb69681c2014-05-19 19:02:51 -07001518 i, j,
1519 nPatches[i].sinks[j].type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix",
1520 nPatches[i].sinks[j].id);
1521 }
1522
1523 jPatch = env->NewObject(gAudioPatchClass, gAudioPatchCstor,
1524 patchHandle, jSources, jSinks);
1525 env->DeleteLocalRef(jSources);
1526 jSources = NULL;
1527 env->DeleteLocalRef(jSinks);
1528 jSinks = NULL;
1529 if (jPatch == NULL) {
1530 jStatus = AUDIO_JAVA_ERROR;
1531 goto exit;
1532 }
1533 env->CallBooleanMethod(jPatches, gArrayListMethods.add, jPatch);
1534 env->DeleteLocalRef(jPatch);
1535 jPatch = NULL;
1536 }
1537
1538exit:
Eric Laurentb36d1042016-04-14 18:00:38 -07001539
1540 nGeneration = env->GetIntArrayElements(jGeneration, NULL);
1541 if (nGeneration == NULL) {
1542 jStatus = AUDIO_JAVA_ERROR;
1543 } else {
1544 nGeneration[0] = generation1;
1545 env->ReleaseIntArrayElements(jGeneration, nGeneration, 0);
1546 }
1547
Eric Laurentb69681c2014-05-19 19:02:51 -07001548 if (jSources != NULL) {
1549 env->DeleteLocalRef(jSources);
1550 }
1551 if (jSource != NULL) {
1552 env->DeleteLocalRef(jSource);
1553 }
1554 if (jSinks != NULL) {
1555 env->DeleteLocalRef(jSinks);
1556 }
1557 if (jSink != NULL) {
1558 env->DeleteLocalRef(jSink);
1559 }
1560 if (jPatch != NULL) {
1561 env->DeleteLocalRef(jPatch);
1562 }
1563 free(nPatches);
1564 return jStatus;
1565}
1566
Eric Laurent3a241992014-05-19 19:33:26 -07001567static jint
1568android_media_AudioSystem_setAudioPortConfig(JNIEnv *env, jobject clazz,
1569 jobject jAudioPortConfig)
1570{
1571 ALOGV("setAudioPortConfig");
1572 if (jAudioPortConfig == NULL) {
1573 return AUDIO_JAVA_BAD_VALUE;
1574 }
1575 if (!env->IsInstanceOf(jAudioPortConfig, gAudioPortConfigClass)) {
1576 return AUDIO_JAVA_BAD_VALUE;
1577 }
1578 struct audio_port_config nAudioPortConfig;
Eric Laurent6368a7d2014-11-19 12:18:32 -08001579 jint jStatus = convertAudioPortConfigToNative(env, &nAudioPortConfig, jAudioPortConfig, true);
Eric Laurent3a241992014-05-19 19:33:26 -07001580 if (jStatus != AUDIO_JAVA_SUCCESS) {
1581 return jStatus;
1582 }
1583 status_t status = AudioSystem::setAudioPortConfig(&nAudioPortConfig);
1584 ALOGV("AudioSystem::setAudioPortConfig() returned %d", status);
1585 jStatus = nativeToJavaStatus(status);
1586 return jStatus;
1587}
1588
Eric Laurent700e7342014-05-02 18:33:15 -07001589static void
1590android_media_AudioSystem_eventHandlerSetup(JNIEnv *env, jobject thiz, jobject weak_this)
1591{
1592 ALOGV("eventHandlerSetup");
1593
1594 sp<JNIAudioPortCallback> callback = new JNIAudioPortCallback(env, thiz, weak_this);
1595
Eric Laurent2615afb2015-03-25 14:51:08 -07001596 if (AudioSystem::addAudioPortCallback(callback) == NO_ERROR) {
1597 setJniCallback(env, thiz, callback);
1598 }
Eric Laurent700e7342014-05-02 18:33:15 -07001599}
1600
1601static void
1602android_media_AudioSystem_eventHandlerFinalize(JNIEnv *env, jobject thiz)
1603{
1604 ALOGV("eventHandlerFinalize");
1605
Eric Laurent2615afb2015-03-25 14:51:08 -07001606 sp<JNIAudioPortCallback> callback = setJniCallback(env, thiz, 0);
Eric Laurent700e7342014-05-02 18:33:15 -07001607
Eric Laurent2615afb2015-03-25 14:51:08 -07001608 if (callback != 0) {
1609 AudioSystem::removeAudioPortCallback(callback);
1610 }
Eric Laurent700e7342014-05-02 18:33:15 -07001611}
1612
Eric Laurentb634e1b2014-08-01 14:44:46 -07001613static jint
1614android_media_AudioSystem_getAudioHwSyncForSession(JNIEnv *env, jobject thiz, jint sessionId)
1615{
Glenn Kasten33b84042016-03-08 12:02:55 -08001616 return (jint) AudioSystem::getAudioHwSyncForSession((audio_session_t) sessionId);
Eric Laurentb634e1b2014-08-01 14:44:46 -07001617}
1618
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001619static void
1620android_media_AudioSystem_registerDynPolicyCallback(JNIEnv *env, jobject thiz)
1621{
1622 AudioSystem::setDynPolicyCallback(android_media_AudioSystem_dyn_policy_callback);
1623}
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001624
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08001625static void
1626android_media_AudioSystem_registerRecordingCallback(JNIEnv *env, jobject thiz)
1627{
1628 AudioSystem::setRecordConfigCallback(android_media_AudioSystem_recording_callback);
1629}
1630
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001631
1632static jint convertAudioMixToNative(JNIEnv *env,
1633 AudioMix *nAudioMix,
1634 const jobject jAudioMix)
1635{
1636 nAudioMix->mMixType = env->GetIntField(jAudioMix, gAudioMixFields.mMixType);
1637 nAudioMix->mRouteFlags = env->GetIntField(jAudioMix, gAudioMixFields.mRouteFlags);
Jean-Michel Trivi4ad39882016-03-14 18:46:41 -07001638 nAudioMix->mDeviceType = (audio_devices_t)
1639 env->GetIntField(jAudioMix, gAudioMixFields.mDeviceType);
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001640
Jean-Michel Trivi4ad39882016-03-14 18:46:41 -07001641 jstring jDeviceAddress = (jstring)env->GetObjectField(jAudioMix,
1642 gAudioMixFields.mDeviceAddress);
1643 const char *nDeviceAddress = env->GetStringUTFChars(jDeviceAddress, NULL);
1644 nAudioMix->mDeviceAddress = String8(nDeviceAddress);
1645 env->ReleaseStringUTFChars(jDeviceAddress, nDeviceAddress);
1646 env->DeleteLocalRef(jDeviceAddress);
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001647
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001648 nAudioMix->mCbFlags = env->GetIntField(jAudioMix, gAudioMixFields.mCallbackFlags);
1649
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001650 jobject jFormat = env->GetObjectField(jAudioMix, gAudioMixFields.mFormat);
1651 nAudioMix->mFormat.sample_rate = env->GetIntField(jFormat,
1652 gAudioFormatFields.mSampleRate);
1653 nAudioMix->mFormat.channel_mask = outChannelMaskToNative(env->GetIntField(jFormat,
1654 gAudioFormatFields.mChannelMask));
1655 nAudioMix->mFormat.format = audioFormatToNative(env->GetIntField(jFormat,
1656 gAudioFormatFields.mEncoding));
1657 env->DeleteLocalRef(jFormat);
1658
1659 jobject jRule = env->GetObjectField(jAudioMix, gAudioMixFields.mRule);
1660 jobject jRuleCriteria = env->GetObjectField(jRule, gAudioMixingRuleFields.mCriteria);
1661 env->DeleteLocalRef(jRule);
1662 jobjectArray jCriteria = (jobjectArray)env->CallObjectMethod(jRuleCriteria,
1663 gArrayListMethods.toArray);
1664 env->DeleteLocalRef(jRuleCriteria);
1665
1666 jint numCriteria = env->GetArrayLength(jCriteria);
1667 if (numCriteria > MAX_CRITERIA_PER_MIX) {
1668 numCriteria = MAX_CRITERIA_PER_MIX;
1669 }
1670
1671 for (jint i = 0; i < numCriteria; i++) {
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -08001672 AudioMixMatchCriterion nCriterion;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001673
1674 jobject jCriterion = env->GetObjectArrayElement(jCriteria, i);
1675
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -08001676 nCriterion.mRule = env->GetIntField(jCriterion, gAudioMixMatchCriterionFields.mRule);
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001677
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -08001678 const uint32_t match_rule = nCriterion.mRule & ~RULE_EXCLUSION_MASK;
1679 switch (match_rule) {
1680 case RULE_MATCH_UID:
1681 nCriterion.mValue.mUid = env->GetIntField(jCriterion,
1682 gAudioMixMatchCriterionFields.mIntProp);
1683 break;
1684 case RULE_MATCH_ATTRIBUTE_USAGE:
1685 case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET: {
1686 jobject jAttributes = env->GetObjectField(jCriterion, gAudioMixMatchCriterionFields.mAttr);
1687 if (match_rule == RULE_MATCH_ATTRIBUTE_USAGE) {
1688 nCriterion.mValue.mUsage = (audio_usage_t)env->GetIntField(jAttributes,
1689 gAudioAttributesFields.mUsage);
1690 } else {
1691 nCriterion.mValue.mSource = (audio_source_t)env->GetIntField(jAttributes,
1692 gAudioAttributesFields.mSource);
1693 }
1694 env->DeleteLocalRef(jAttributes);
1695 }
1696 break;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001697 }
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001698
1699 nAudioMix->mCriteria.add(nCriterion);
1700 env->DeleteLocalRef(jCriterion);
1701 }
1702
1703 env->DeleteLocalRef(jCriteria);
1704
1705 return (jint)AUDIO_JAVA_SUCCESS;
1706}
1707
1708static jint
1709android_media_AudioSystem_registerPolicyMixes(JNIEnv *env, jobject clazz,
1710 jobject jMixesList, jboolean registration)
1711{
1712 ALOGV("registerPolicyMixes");
1713
1714 if (jMixesList == NULL) {
1715 return (jint)AUDIO_JAVA_BAD_VALUE;
1716 }
1717 if (!env->IsInstanceOf(jMixesList, gArrayListClass)) {
1718 return (jint)AUDIO_JAVA_BAD_VALUE;
1719 }
1720 jobjectArray jMixes = (jobjectArray)env->CallObjectMethod(jMixesList,
1721 gArrayListMethods.toArray);
1722 jint numMixes = env->GetArrayLength(jMixes);
1723 if (numMixes > MAX_MIXES_PER_POLICY) {
1724 numMixes = MAX_MIXES_PER_POLICY;
1725 }
1726
1727 status_t status;
1728 jint jStatus;
1729 jobject jAudioMix = NULL;
1730 Vector <AudioMix> mixes;
1731 for (jint i = 0; i < numMixes; i++) {
1732 jAudioMix = env->GetObjectArrayElement(jMixes, i);
1733 if (!env->IsInstanceOf(jAudioMix, gAudioMixClass)) {
1734 jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
1735 goto exit;
1736 }
1737 AudioMix mix;
1738 jStatus = convertAudioMixToNative(env, &mix, jAudioMix);
1739 env->DeleteLocalRef(jAudioMix);
1740 jAudioMix = NULL;
1741 if (jStatus != AUDIO_JAVA_SUCCESS) {
1742 goto exit;
1743 }
1744 mixes.add(mix);
1745 }
1746
1747 ALOGV("AudioSystem::registerPolicyMixes numMixes %d registration %d", numMixes, registration);
1748 status = AudioSystem::registerPolicyMixes(mixes, registration);
1749 ALOGV("AudioSystem::registerPolicyMixes() returned %d", status);
1750
1751 jStatus = nativeToJavaStatus(status);
1752 if (jStatus != AUDIO_JAVA_SUCCESS) {
1753 goto exit;
1754 }
1755
1756exit:
1757 if (jAudioMix != NULL) {
1758 env->DeleteLocalRef(jAudioMix);
1759 }
1760 return jStatus;
1761}
1762
Eric Laurent0867bed2015-05-20 14:49:08 -07001763static jint
1764android_media_AudioSystem_systemReady(JNIEnv *env, jobject thiz)
1765{
1766 return nativeToJavaStatus(AudioSystem::systemReady());
1767}
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001768
Eric Laurenteab40d12017-06-09 12:45:21 -07001769static jfloat
1770android_media_AudioSystem_getStreamVolumeDB(JNIEnv *env, jobject thiz,
1771 jint stream, jint index, jint device)
1772{
1773 return (jfloat)AudioSystem::getStreamVolumeDB((audio_stream_type_t)stream,
1774 (int)index,
1775 (audio_devices_t)device);
1776}
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001777
Jean-Michel Trivi980d38f2018-01-08 15:43:35 -08001778static jboolean
1779android_media_AudioSystem_isOffloadSupported(JNIEnv *env, jobject thiz,
1780 jint encoding, jint sampleRate, jint channelMask, jint channelIndexMask)
1781{
1782 audio_offload_info_t format = AUDIO_INFO_INITIALIZER;
1783 format.format = (audio_format_t) audioFormatToNative(encoding);
1784 format.sample_rate = (uint32_t) sampleRate;
1785 format.channel_mask = nativeChannelMaskFromJavaChannelMasks(channelMask, channelIndexMask);
1786 format.stream_type = AUDIO_STREAM_MUSIC;
1787 format.has_video = false;
1788 format.is_streaming = false;
1789 // offload duration unknown at this point:
1790 // client side code cannot access "audio.offload.min.duration.secs" property to make a query
1791 // agnostic of duration, so using acceptable estimate of 2mn
1792 format.duration_us = 120 * 1000000;
1793 return AudioSystem::isOffloadSupported(format);
1794}
1795
jiabinc0f49442018-01-05 10:23:50 -08001796static jint
1797android_media_AudioSystem_getMicrophones(JNIEnv *env, jobject thiz, jobject jMicrophonesInfo)
1798{
1799 ALOGV("getMicrophones");
1800
1801 if (jMicrophonesInfo == NULL) {
1802 ALOGE("jMicrophonesInfo NULL MicrophoneInfo ArrayList");
1803 return (jint)AUDIO_JAVA_BAD_VALUE;
1804 }
1805 if (!env->IsInstanceOf(jMicrophonesInfo, gArrayListClass)) {
1806 ALOGE("getMicrophones not an arraylist");
1807 return (jint)AUDIO_JAVA_BAD_VALUE;
1808 }
1809
1810 jint jStatus;
1811 std::vector<media::MicrophoneInfo> microphones;
1812 status_t status = AudioSystem::getMicrophones(&microphones);
1813 if (status != NO_ERROR) {
1814 ALOGE_IF(status != NO_ERROR, "AudioSystem::getMicrophones error %d", status);
1815 jStatus = nativeToJavaStatus(status);
1816 return jStatus;
1817 }
1818 if (microphones.size() == 0) {
1819 jStatus = (jint)AUDIO_JAVA_SUCCESS;
1820 return jStatus;
1821 }
1822 for (size_t i = 0; i < microphones.size(); i++) {
1823 jobject jMicrophoneInfo;
1824 jStatus = convertMicrophoneInfoFromNative(env, &jMicrophoneInfo, &microphones[i]);
1825 if (jStatus != AUDIO_JAVA_SUCCESS) {
1826 return jStatus;
1827 }
1828 env->CallBooleanMethod(jMicrophonesInfo, gArrayListMethods.add, jMicrophoneInfo);
1829 env->DeleteLocalRef(jMicrophoneInfo);
1830 }
1831
1832 return jStatus;
1833}
1834
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001835// ----------------------------------------------------------------------------
1836
Daniel Micay76f6a862015-09-19 17:31:01 -04001837static const JNINativeMethod gMethods[] = {
Eric Laurenta553c252009-07-17 12:17:14 -07001838 {"setParameters", "(Ljava/lang/String;)I", (void *)android_media_AudioSystem_setParameters},
1839 {"getParameters", "(Ljava/lang/String;)Ljava/lang/String;", (void *)android_media_AudioSystem_getParameters},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001840 {"muteMicrophone", "(Z)I", (void *)android_media_AudioSystem_muteMicrophone},
1841 {"isMicrophoneMuted", "()Z", (void *)android_media_AudioSystem_isMicrophoneMuted},
Jean-Michel Trivid6770542012-10-10 12:03:41 -07001842 {"isStreamActive", "(II)Z", (void *)android_media_AudioSystem_isStreamActive},
Jean-Michel Trivi679d5042013-02-04 16:24:09 -08001843 {"isStreamActiveRemotely","(II)Z", (void *)android_media_AudioSystem_isStreamActiveRemotely},
Jean-Michel Trivid6770542012-10-10 12:03:41 -07001844 {"isSourceActive", "(I)Z", (void *)android_media_AudioSystem_isSourceActive},
Jean-Michel Trivi8a21f5d2014-06-05 15:03:52 -07001845 {"newAudioSessionId", "()I", (void *)android_media_AudioSystem_newAudioSessionId},
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08001846 {"newAudioPlayerId", "()I", (void *)android_media_AudioSystem_newAudioPlayerId},
Paul McLean10804eb2015-01-28 11:16:35 -08001847 {"setDeviceConnectionState", "(IILjava/lang/String;Ljava/lang/String;)I", (void *)android_media_AudioSystem_setDeviceConnectionState},
Eric Laurenta553c252009-07-17 12:17:14 -07001848 {"getDeviceConnectionState", "(ILjava/lang/String;)I", (void *)android_media_AudioSystem_getDeviceConnectionState},
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08001849 {"handleDeviceConfigChange", "(ILjava/lang/String;Ljava/lang/String;)I", (void *)android_media_AudioSystem_handleDeviceConfigChange},
Eric Laurenta553c252009-07-17 12:17:14 -07001850 {"setPhoneState", "(I)I", (void *)android_media_AudioSystem_setPhoneState},
Eric Laurenta553c252009-07-17 12:17:14 -07001851 {"setForceUse", "(II)I", (void *)android_media_AudioSystem_setForceUse},
1852 {"getForceUse", "(I)I", (void *)android_media_AudioSystem_getForceUse},
1853 {"initStreamVolume", "(III)I", (void *)android_media_AudioSystem_initStreamVolume},
Eric Laurent9bc8358d2011-11-18 16:43:31 -08001854 {"setStreamVolumeIndex","(III)I", (void *)android_media_AudioSystem_setStreamVolumeIndex},
1855 {"getStreamVolumeIndex","(II)I", (void *)android_media_AudioSystem_getStreamVolumeIndex},
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -04001856 {"setMasterVolume", "(F)I", (void *)android_media_AudioSystem_setMasterVolume},
1857 {"getMasterVolume", "()F", (void *)android_media_AudioSystem_getMasterVolume},
1858 {"setMasterMute", "(Z)I", (void *)android_media_AudioSystem_setMasterMute},
1859 {"getMasterMute", "()Z", (void *)android_media_AudioSystem_getMasterMute},
Andy Hungf04b84d2015-12-18 17:33:27 -08001860 {"setMasterMono", "(Z)I", (void *)android_media_AudioSystem_setMasterMono},
1861 {"getMasterMono", "()Z", (void *)android_media_AudioSystem_getMasterMono},
Glenn Kasten8b4b97a2011-02-04 13:54:26 -08001862 {"getDevicesForStream", "(I)I", (void *)android_media_AudioSystem_getDevicesForStream},
Glenn Kastenc6c43652012-09-24 17:32:30 -07001863 {"getPrimaryOutputSamplingRate", "()I", (void *)android_media_AudioSystem_getPrimaryOutputSamplingRate},
1864 {"getPrimaryOutputFrameCount", "()I", (void *)android_media_AudioSystem_getPrimaryOutputFrameCount},
Oliver Woodman61dcdf32013-06-26 12:43:36 +01001865 {"getOutputLatency", "(I)I", (void *)android_media_AudioSystem_getOutputLatency},
Andy Hung79583582018-01-23 13:58:02 -08001866 {"setLowRamDevice", "(ZJ)I", (void *)android_media_AudioSystem_setLowRamDevice},
Eric Laurentdfb881f2013-07-18 14:41:39 -07001867 {"checkAudioFlinger", "()I", (void *)android_media_AudioSystem_checkAudioFlinger},
Eric Laurentb69681c2014-05-19 19:02:51 -07001868 {"listAudioPorts", "(Ljava/util/ArrayList;[I)I",
1869 (void *)android_media_AudioSystem_listAudioPorts},
1870 {"createAudioPatch", "([Landroid/media/AudioPatch;[Landroid/media/AudioPortConfig;[Landroid/media/AudioPortConfig;)I",
1871 (void *)android_media_AudioSystem_createAudioPatch},
1872 {"releaseAudioPatch", "(Landroid/media/AudioPatch;)I",
1873 (void *)android_media_AudioSystem_releaseAudioPatch},
1874 {"listAudioPatches", "(Ljava/util/ArrayList;[I)I",
1875 (void *)android_media_AudioSystem_listAudioPatches},
Eric Laurent3a241992014-05-19 19:33:26 -07001876 {"setAudioPortConfig", "(Landroid/media/AudioPortConfig;)I",
1877 (void *)android_media_AudioSystem_setAudioPortConfig},
Eric Laurentb634e1b2014-08-01 14:44:46 -07001878 {"getAudioHwSyncForSession", "(I)I",
1879 (void *)android_media_AudioSystem_getAudioHwSyncForSession},
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001880 {"registerPolicyMixes", "(Ljava/util/ArrayList;Z)I",
1881 (void *)android_media_AudioSystem_registerPolicyMixes},
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001882 {"native_register_dynamic_policy_callback", "()V",
1883 (void *)android_media_AudioSystem_registerDynPolicyCallback},
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08001884 {"native_register_recording_callback", "()V",
1885 (void *)android_media_AudioSystem_registerRecordingCallback},
Eric Laurent0867bed2015-05-20 14:49:08 -07001886 {"systemReady", "()I", (void *)android_media_AudioSystem_systemReady},
Eric Laurenteab40d12017-06-09 12:45:21 -07001887 {"getStreamVolumeDB", "(III)F", (void *)android_media_AudioSystem_getStreamVolumeDB},
Jean-Michel Trivi980d38f2018-01-08 15:43:35 -08001888 {"native_is_offload_supported", "(IIII)Z", (void *)android_media_AudioSystem_isOffloadSupported},
jiabinc0f49442018-01-05 10:23:50 -08001889 {"getMicrophones", "(Ljava/util/ArrayList;)I", (void *)android_media_AudioSystem_getMicrophones},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001890};
1891
Eric Laurentb69681c2014-05-19 19:02:51 -07001892
Daniel Micay76f6a862015-09-19 17:31:01 -04001893static const JNINativeMethod gEventHandlerMethods[] = {
Eric Laurent700e7342014-05-02 18:33:15 -07001894 {"native_setup",
1895 "(Ljava/lang/Object;)V",
1896 (void *)android_media_AudioSystem_eventHandlerSetup},
1897 {"native_finalize",
1898 "()V",
1899 (void *)android_media_AudioSystem_eventHandlerFinalize},
1900};
1901
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001902int register_android_media_AudioSystem(JNIEnv *env)
1903{
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001904 jclass arrayListClass = FindClassOrDie(env, "java/util/ArrayList");
1905 gArrayListClass = MakeGlobalRefOrDie(env, arrayListClass);
1906 gArrayListMethods.add = GetMethodIDOrDie(env, arrayListClass, "add", "(Ljava/lang/Object;)Z");
Eric Laurent09378972014-12-10 10:42:08 -08001907 gArrayListMethods.toArray = GetMethodIDOrDie(env, arrayListClass, "toArray", "()[Ljava/lang/Object;");
Eric Laurentb69681c2014-05-19 19:02:51 -07001908
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001909 jclass audioHandleClass = FindClassOrDie(env, "android/media/AudioHandle");
1910 gAudioHandleClass = MakeGlobalRefOrDie(env, audioHandleClass);
1911 gAudioHandleCstor = GetMethodIDOrDie(env, audioHandleClass, "<init>", "(I)V");
1912 gAudioHandleFields.mId = GetFieldIDOrDie(env, audioHandleClass, "mId", "I");
Eric Laurentb69681c2014-05-19 19:02:51 -07001913
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001914 jclass audioPortClass = FindClassOrDie(env, "android/media/AudioPort");
1915 gAudioPortClass = MakeGlobalRefOrDie(env, audioPortClass);
1916 gAudioPortCstor = GetMethodIDOrDie(env, audioPortClass, "<init>",
Paul McLeanf29e5f32015-06-15 10:19:22 -07001917 "(Landroid/media/AudioHandle;ILjava/lang/String;[I[I[I[I[Landroid/media/AudioGain;)V");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001918 gAudioPortFields.mHandle = GetFieldIDOrDie(env, audioPortClass, "mHandle",
Eric Laurentb69681c2014-05-19 19:02:51 -07001919 "Landroid/media/AudioHandle;");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001920 gAudioPortFields.mRole = GetFieldIDOrDie(env, audioPortClass, "mRole", "I");
1921 gAudioPortFields.mGains = GetFieldIDOrDie(env, audioPortClass, "mGains",
Eric Laurentb69681c2014-05-19 19:02:51 -07001922 "[Landroid/media/AudioGain;");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001923 gAudioPortFields.mActiveConfig = GetFieldIDOrDie(env, audioPortClass, "mActiveConfig",
1924 "Landroid/media/AudioPortConfig;");
Eric Laurentb69681c2014-05-19 19:02:51 -07001925
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001926 jclass audioPortConfigClass = FindClassOrDie(env, "android/media/AudioPortConfig");
1927 gAudioPortConfigClass = MakeGlobalRefOrDie(env, audioPortConfigClass);
1928 gAudioPortConfigCstor = GetMethodIDOrDie(env, audioPortConfigClass, "<init>",
1929 "(Landroid/media/AudioPort;IIILandroid/media/AudioGainConfig;)V");
1930 gAudioPortConfigFields.mPort = GetFieldIDOrDie(env, audioPortConfigClass, "mPort",
Eric Laurentb69681c2014-05-19 19:02:51 -07001931 "Landroid/media/AudioPort;");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001932 gAudioPortConfigFields.mSamplingRate = GetFieldIDOrDie(env, audioPortConfigClass,
Eric Laurentb69681c2014-05-19 19:02:51 -07001933 "mSamplingRate", "I");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001934 gAudioPortConfigFields.mChannelMask = GetFieldIDOrDie(env, audioPortConfigClass,
Eric Laurentb69681c2014-05-19 19:02:51 -07001935 "mChannelMask", "I");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001936 gAudioPortConfigFields.mFormat = GetFieldIDOrDie(env, audioPortConfigClass, "mFormat", "I");
1937 gAudioPortConfigFields.mGain = GetFieldIDOrDie(env, audioPortConfigClass, "mGain",
Eric Laurentb69681c2014-05-19 19:02:51 -07001938 "Landroid/media/AudioGainConfig;");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001939 gAudioPortConfigFields.mConfigMask = GetFieldIDOrDie(env, audioPortConfigClass, "mConfigMask",
1940 "I");
Eric Laurentb69681c2014-05-19 19:02:51 -07001941
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001942 jclass audioDevicePortConfigClass = FindClassOrDie(env, "android/media/AudioDevicePortConfig");
1943 gAudioDevicePortConfigClass = MakeGlobalRefOrDie(env, audioDevicePortConfigClass);
1944 gAudioDevicePortConfigCstor = GetMethodIDOrDie(env, audioDevicePortConfigClass, "<init>",
1945 "(Landroid/media/AudioDevicePort;IIILandroid/media/AudioGainConfig;)V");
Eric Laurentb69681c2014-05-19 19:02:51 -07001946
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001947 jclass audioMixPortConfigClass = FindClassOrDie(env, "android/media/AudioMixPortConfig");
1948 gAudioMixPortConfigClass = MakeGlobalRefOrDie(env, audioMixPortConfigClass);
1949 gAudioMixPortConfigCstor = GetMethodIDOrDie(env, audioMixPortConfigClass, "<init>",
1950 "(Landroid/media/AudioMixPort;IIILandroid/media/AudioGainConfig;)V");
Eric Laurentb69681c2014-05-19 19:02:51 -07001951
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001952 jclass audioDevicePortClass = FindClassOrDie(env, "android/media/AudioDevicePort");
1953 gAudioDevicePortClass = MakeGlobalRefOrDie(env, audioDevicePortClass);
1954 gAudioDevicePortCstor = GetMethodIDOrDie(env, audioDevicePortClass, "<init>",
Paul McLeanf29e5f32015-06-15 10:19:22 -07001955 "(Landroid/media/AudioHandle;Ljava/lang/String;[I[I[I[I[Landroid/media/AudioGain;ILjava/lang/String;)V");
Eric Laurentb69681c2014-05-19 19:02:51 -07001956
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001957 jclass audioMixPortClass = FindClassOrDie(env, "android/media/AudioMixPort");
1958 gAudioMixPortClass = MakeGlobalRefOrDie(env, audioMixPortClass);
1959 gAudioMixPortCstor = GetMethodIDOrDie(env, audioMixPortClass, "<init>",
Paul McLeanf29e5f32015-06-15 10:19:22 -07001960 "(Landroid/media/AudioHandle;IILjava/lang/String;[I[I[I[I[Landroid/media/AudioGain;)V");
Eric Laurentb69681c2014-05-19 19:02:51 -07001961
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001962 jclass audioGainClass = FindClassOrDie(env, "android/media/AudioGain");
1963 gAudioGainClass = MakeGlobalRefOrDie(env, audioGainClass);
1964 gAudioGainCstor = GetMethodIDOrDie(env, audioGainClass, "<init>", "(IIIIIIIII)V");
Eric Laurentb69681c2014-05-19 19:02:51 -07001965
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001966 jclass audioGainConfigClass = FindClassOrDie(env, "android/media/AudioGainConfig");
1967 gAudioGainConfigClass = MakeGlobalRefOrDie(env, audioGainConfigClass);
1968 gAudioGainConfigCstor = GetMethodIDOrDie(env, audioGainConfigClass, "<init>",
Eric Laurentb69681c2014-05-19 19:02:51 -07001969 "(ILandroid/media/AudioGain;II[II)V");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001970 gAudioGainConfigFields.mIndex = GetFieldIDOrDie(env, gAudioGainConfigClass, "mIndex", "I");
1971 gAudioGainConfigFields.mMode = GetFieldIDOrDie(env, audioGainConfigClass, "mMode", "I");
1972 gAudioGainConfigFields.mChannelMask = GetFieldIDOrDie(env, audioGainConfigClass, "mChannelMask",
Eric Laurentb69681c2014-05-19 19:02:51 -07001973 "I");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001974 gAudioGainConfigFields.mValues = GetFieldIDOrDie(env, audioGainConfigClass, "mValues", "[I");
1975 gAudioGainConfigFields.mRampDurationMs = GetFieldIDOrDie(env, audioGainConfigClass,
Eric Laurentb69681c2014-05-19 19:02:51 -07001976 "mRampDurationMs", "I");
1977
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001978 jclass audioPatchClass = FindClassOrDie(env, "android/media/AudioPatch");
1979 gAudioPatchClass = MakeGlobalRefOrDie(env, audioPatchClass);
1980 gAudioPatchCstor = GetMethodIDOrDie(env, audioPatchClass, "<init>",
Eric Laurentb69681c2014-05-19 19:02:51 -07001981"(Landroid/media/AudioHandle;[Landroid/media/AudioPortConfig;[Landroid/media/AudioPortConfig;)V");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001982 gAudioPatchFields.mHandle = GetFieldIDOrDie(env, audioPatchClass, "mHandle",
Eric Laurentb69681c2014-05-19 19:02:51 -07001983 "Landroid/media/AudioHandle;");
1984
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001985 jclass eventHandlerClass = FindClassOrDie(env, kEventHandlerClassPathName);
Eric Laurent2615afb2015-03-25 14:51:08 -07001986 gAudioPortEventHandlerMethods.postEventFromNative = GetStaticMethodIDOrDie(
1987 env, eventHandlerClass, "postEventFromNative",
1988 "(Ljava/lang/Object;IIILjava/lang/Object;)V");
1989 gEventHandlerFields.mJniCallback = GetFieldIDOrDie(env,
1990 eventHandlerClass, "mJniCallback", "J");
Eric Laurent700e7342014-05-02 18:33:15 -07001991
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08001992 gAudioPolicyEventHandlerMethods.postDynPolicyEventFromNative =
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001993 GetStaticMethodIDOrDie(env, env->FindClass(kClassPathName),
1994 "dynamicPolicyCallbackFromNative", "(ILjava/lang/String;I)V");
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08001995 gAudioPolicyEventHandlerMethods.postRecordConfigEventFromNative =
1996 GetStaticMethodIDOrDie(env, env->FindClass(kClassPathName),
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -08001997 "recordingCallbackFromNative", "(IIII[I)V");
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001998
Eric Laurent09378972014-12-10 10:42:08 -08001999 jclass audioMixClass = FindClassOrDie(env, "android/media/audiopolicy/AudioMix");
2000 gAudioMixClass = MakeGlobalRefOrDie(env, audioMixClass);
2001 gAudioMixFields.mRule = GetFieldIDOrDie(env, audioMixClass, "mRule",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08002002 "Landroid/media/audiopolicy/AudioMixingRule;");
Eric Laurent09378972014-12-10 10:42:08 -08002003 gAudioMixFields.mFormat = GetFieldIDOrDie(env, audioMixClass, "mFormat",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08002004 "Landroid/media/AudioFormat;");
Eric Laurent09378972014-12-10 10:42:08 -08002005 gAudioMixFields.mRouteFlags = GetFieldIDOrDie(env, audioMixClass, "mRouteFlags", "I");
Jean-Michel Trivi4ad39882016-03-14 18:46:41 -07002006 gAudioMixFields.mDeviceType = GetFieldIDOrDie(env, audioMixClass, "mDeviceSystemType", "I");
2007 gAudioMixFields.mDeviceAddress = GetFieldIDOrDie(env, audioMixClass, "mDeviceAddress",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08002008 "Ljava/lang/String;");
Eric Laurent09378972014-12-10 10:42:08 -08002009 gAudioMixFields.mMixType = GetFieldIDOrDie(env, audioMixClass, "mMixType", "I");
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07002010 gAudioMixFields.mCallbackFlags = GetFieldIDOrDie(env, audioMixClass, "mCallbackFlags", "I");
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08002011
Eric Laurent09378972014-12-10 10:42:08 -08002012 jclass audioFormatClass = FindClassOrDie(env, "android/media/AudioFormat");
2013 gAudioFormatClass = MakeGlobalRefOrDie(env, audioFormatClass);
2014 gAudioFormatFields.mEncoding = GetFieldIDOrDie(env, audioFormatClass, "mEncoding", "I");
2015 gAudioFormatFields.mSampleRate = GetFieldIDOrDie(env, audioFormatClass, "mSampleRate", "I");
2016 gAudioFormatFields.mChannelMask = GetFieldIDOrDie(env, audioFormatClass, "mChannelMask", "I");
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08002017
Eric Laurent09378972014-12-10 10:42:08 -08002018 jclass audioMixingRuleClass = FindClassOrDie(env, "android/media/audiopolicy/AudioMixingRule");
2019 gAudioMixingRuleClass = MakeGlobalRefOrDie(env, audioMixingRuleClass);
2020 gAudioMixingRuleFields.mCriteria = GetFieldIDOrDie(env, audioMixingRuleClass, "mCriteria",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08002021 "Ljava/util/ArrayList;");
2022
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -08002023 jclass audioMixMatchCriterionClass =
2024 FindClassOrDie(env, "android/media/audiopolicy/AudioMixingRule$AudioMixMatchCriterion");
2025 gAudioMixMatchCriterionClass = MakeGlobalRefOrDie(env,audioMixMatchCriterionClass);
2026 gAudioMixMatchCriterionFields.mAttr = GetFieldIDOrDie(env, audioMixMatchCriterionClass, "mAttr",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08002027 "Landroid/media/AudioAttributes;");
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -08002028 gAudioMixMatchCriterionFields.mIntProp = GetFieldIDOrDie(env, audioMixMatchCriterionClass, "mIntProp",
2029 "I");
2030 gAudioMixMatchCriterionFields.mRule = GetFieldIDOrDie(env, audioMixMatchCriterionClass, "mRule",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08002031 "I");
2032
Eric Laurent09378972014-12-10 10:42:08 -08002033 jclass audioAttributesClass = FindClassOrDie(env, "android/media/AudioAttributes");
2034 gAudioAttributesClass = MakeGlobalRefOrDie(env, audioAttributesClass);
2035 gAudioAttributesFields.mUsage = GetFieldIDOrDie(env, audioAttributesClass, "mUsage", "I");
2036 gAudioAttributesFields.mSource = GetFieldIDOrDie(env, audioAttributesClass, "mSource", "I");
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08002037
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002038 AudioSystem::setErrorCallback(android_media_AudioSystem_error_callback);
Glenn Kasten18db49a2012-03-12 16:29:55 -07002039
Andreas Gampeed6b9df2014-11-20 22:02:20 -08002040 RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
2041 return RegisterMethodsOrDie(env, kEventHandlerClassPathName, gEventHandlerMethods,
2042 NELEM(gEventHandlerMethods));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002043}