blob: 376a7971767798fca917840b8c064678b492bf38 [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>
Glenn Kastenc81d31c2012-03-13 14:46:23 -070024#include <jni.h>
Steven Moreland2279b252017-07-19 09:50:45 -070025#include <nativehelper/JNIHelp.h>
Andreas Gampeed6b9df2014-11-20 22:02:20 -080026#include "core_jni_helpers.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027
28#include <media/AudioSystem.h>
Eric Laurent7f5eb9f2014-12-01 19:36:30 -080029#include <media/AudioPolicy.h>
Andy Hung737d9fb2016-08-16 18:38:49 -070030#include <nativehelper/ScopedLocalRef.h>
Dima Zavin34bb4192011-05-11 14:15:23 -070031#include <system/audio.h>
Dima Zavin290029d2011-06-13 18:16:26 -070032#include <system/audio_policy.h>
Eric Laurentb69681c2014-05-19 19:02:51 -070033#include "android_media_AudioFormat.h"
34#include "android_media_AudioErrors.h"
Dima Zavin24fc2fb2011-04-19 22:30:36 -070035
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036// ----------------------------------------------------------------------------
37
38using namespace android;
39
Glenn Kastened0079d2011-04-04 10:50:50 -070040static const char* const kClassPathName = "android/media/AudioSystem";
41
Eric Laurentb69681c2014-05-19 19:02:51 -070042static jclass gArrayListClass;
43static struct {
44 jmethodID add;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -080045 jmethodID toArray;
Eric Laurentb69681c2014-05-19 19:02:51 -070046} gArrayListMethods;
47
48static jclass gAudioHandleClass;
49static jmethodID gAudioHandleCstor;
50static struct {
51 jfieldID mId;
52} gAudioHandleFields;
53
54static jclass gAudioPortClass;
55static jmethodID gAudioPortCstor;
56static struct {
57 jfieldID mHandle;
58 jfieldID mRole;
59 jfieldID mGains;
60 jfieldID mActiveConfig;
61 // other fields unused by JNI
62} gAudioPortFields;
63
64static jclass gAudioPortConfigClass;
65static jmethodID gAudioPortConfigCstor;
66static struct {
67 jfieldID mPort;
68 jfieldID mSamplingRate;
69 jfieldID mChannelMask;
70 jfieldID mFormat;
71 jfieldID mGain;
Eric Laurent3a241992014-05-19 19:33:26 -070072 jfieldID mConfigMask;
Eric Laurentb69681c2014-05-19 19:02:51 -070073} gAudioPortConfigFields;
74
75static jclass gAudioDevicePortClass;
76static jmethodID gAudioDevicePortCstor;
77
78static jclass gAudioDevicePortConfigClass;
79static jmethodID gAudioDevicePortConfigCstor;
80
81static jclass gAudioMixPortClass;
82static jmethodID gAudioMixPortCstor;
83
84static jclass gAudioMixPortConfigClass;
85static jmethodID gAudioMixPortConfigCstor;
86
87static jclass gAudioGainClass;
88static jmethodID gAudioGainCstor;
89
90static jclass gAudioGainConfigClass;
91static jmethodID gAudioGainConfigCstor;
92static struct {
93 jfieldID mIndex;
94 jfieldID mMode;
95 jfieldID mChannelMask;
96 jfieldID mValues;
97 jfieldID mRampDurationMs;
98 // other fields unused by JNI
99} gAudioGainConfigFields;
100
101static jclass gAudioPatchClass;
102static jmethodID gAudioPatchCstor;
103static struct {
104 jfieldID mHandle;
105 // other fields unused by JNI
106} gAudioPatchFields;
107
Eric Laurent7f5eb9f2014-12-01 19:36:30 -0800108static jclass gAudioMixClass;
109static struct {
110 jfieldID mRule;
111 jfieldID mFormat;
112 jfieldID mRouteFlags;
Jean-Michel Trivi4ad39882016-03-14 18:46:41 -0700113 jfieldID mDeviceType;
114 jfieldID mDeviceAddress;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -0800115 jfieldID mMixType;
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700116 jfieldID mCallbackFlags;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -0800117} gAudioMixFields;
118
119static jclass gAudioFormatClass;
120static struct {
121 jfieldID mEncoding;
122 jfieldID mSampleRate;
123 jfieldID mChannelMask;
124 // other fields unused by JNI
125} gAudioFormatFields;
126
127static jclass gAudioMixingRuleClass;
128static struct {
129 jfieldID mCriteria;
130 // other fields unused by JNI
131} gAudioMixingRuleFields;
132
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -0800133static jclass gAudioMixMatchCriterionClass;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -0800134static struct {
135 jfieldID mAttr;
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -0800136 jfieldID mIntProp;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -0800137 jfieldID mRule;
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -0800138} gAudioMixMatchCriterionFields;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -0800139
140static jclass gAudioAttributesClass;
141static struct {
142 jfieldID mUsage;
143 jfieldID mSource;
144} gAudioAttributesFields;
145
146
Eric Laurent700e7342014-05-02 18:33:15 -0700147static const char* const kEventHandlerClassPathName =
148 "android/media/AudioPortEventHandler";
Eric Laurent2615afb2015-03-25 14:51:08 -0700149static struct {
150 jfieldID mJniCallback;
151} gEventHandlerFields;
152static struct {
153 jmethodID postEventFromNative;
154} gAudioPortEventHandlerMethods;
155
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700156static struct {
157 jmethodID postDynPolicyEventFromNative;
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800158 jmethodID postRecordConfigEventFromNative;
159} gAudioPolicyEventHandlerMethods;
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700160
Eric Laurent2615afb2015-03-25 14:51:08 -0700161static Mutex gLock;
Eric Laurentb69681c2014-05-19 19:02:51 -0700162
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800163enum AudioError {
164 kAudioStatusOk = 0,
165 kAudioStatusError = 1,
166 kAudioStatusMediaServerDied = 100
167};
168
Eric Laurent700e7342014-05-02 18:33:15 -0700169enum {
170 AUDIOPORT_EVENT_PORT_LIST_UPDATED = 1,
171 AUDIOPORT_EVENT_PATCH_LIST_UPDATED = 2,
172 AUDIOPORT_EVENT_SERVICE_DIED = 3,
173};
174
Eric Laurentb69681c2014-05-19 19:02:51 -0700175#define MAX_PORT_GENERATION_SYNC_ATTEMPTS 5
176
Eric Laurent700e7342014-05-02 18:33:15 -0700177// ----------------------------------------------------------------------------
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700178// ref-counted object for audio port callbacks
Eric Laurent700e7342014-05-02 18:33:15 -0700179class JNIAudioPortCallback: public AudioSystem::AudioPortCallback
180{
181public:
182 JNIAudioPortCallback(JNIEnv* env, jobject thiz, jobject weak_thiz);
183 ~JNIAudioPortCallback();
184
185 virtual void onAudioPortListUpdate();
186 virtual void onAudioPatchListUpdate();
187 virtual void onServiceDied();
188
189private:
190 void sendEvent(int event);
191
Eric Laurent2615afb2015-03-25 14:51:08 -0700192 jclass mClass; // Reference to AudioPortEventHandler class
193 jobject mObject; // Weak ref to AudioPortEventHandler Java object to call on
Eric Laurent700e7342014-05-02 18:33:15 -0700194};
195
196JNIAudioPortCallback::JNIAudioPortCallback(JNIEnv* env, jobject thiz, jobject weak_thiz)
197{
198
Eric Laurent2615afb2015-03-25 14:51:08 -0700199 // Hold onto the AudioPortEventHandler class for use in calling the static method
Eric Laurent700e7342014-05-02 18:33:15 -0700200 // that posts events to the application thread.
201 jclass clazz = env->GetObjectClass(thiz);
202 if (clazz == NULL) {
203 ALOGE("Can't find class %s", kEventHandlerClassPathName);
204 return;
205 }
206 mClass = (jclass)env->NewGlobalRef(clazz);
207
Eric Laurent2615afb2015-03-25 14:51:08 -0700208 // We use a weak reference so the AudioPortEventHandler object can be garbage collected.
Eric Laurent700e7342014-05-02 18:33:15 -0700209 // The reference is only used as a proxy for callbacks.
210 mObject = env->NewGlobalRef(weak_thiz);
211}
212
213JNIAudioPortCallback::~JNIAudioPortCallback()
214{
215 // remove global references
216 JNIEnv *env = AndroidRuntime::getJNIEnv();
Eric Laurent449c5882014-11-12 11:07:48 -0800217 if (env == NULL) {
218 return;
219 }
Eric Laurent700e7342014-05-02 18:33:15 -0700220 env->DeleteGlobalRef(mObject);
221 env->DeleteGlobalRef(mClass);
222}
223
224void JNIAudioPortCallback::sendEvent(int event)
225{
226 JNIEnv *env = AndroidRuntime::getJNIEnv();
Eric Laurent449c5882014-11-12 11:07:48 -0800227 if (env == NULL) {
228 return;
229 }
Eric Laurent2615afb2015-03-25 14:51:08 -0700230 env->CallStaticVoidMethod(mClass, gAudioPortEventHandlerMethods.postEventFromNative, mObject,
Eric Laurent700e7342014-05-02 18:33:15 -0700231 event, 0, 0, NULL);
232 if (env->ExceptionCheck()) {
233 ALOGW("An exception occurred while notifying an event.");
234 env->ExceptionClear();
235 }
236}
237
238void JNIAudioPortCallback::onAudioPortListUpdate()
239{
240 sendEvent(AUDIOPORT_EVENT_PORT_LIST_UPDATED);
241}
242
243void JNIAudioPortCallback::onAudioPatchListUpdate()
244{
245 sendEvent(AUDIOPORT_EVENT_PATCH_LIST_UPDATED);
246}
247
248void JNIAudioPortCallback::onServiceDied()
249{
250 sendEvent(AUDIOPORT_EVENT_SERVICE_DIED);
251}
252
Eric Laurent2615afb2015-03-25 14:51:08 -0700253static sp<JNIAudioPortCallback> setJniCallback(JNIEnv* env,
254 jobject thiz,
255 const sp<JNIAudioPortCallback>& callback)
256{
257 Mutex::Autolock l(gLock);
258 sp<JNIAudioPortCallback> old =
259 (JNIAudioPortCallback*)env->GetLongField(thiz, gEventHandlerFields.mJniCallback);
260 if (callback.get()) {
261 callback->incStrong((void*)setJniCallback);
262 }
263 if (old != 0) {
264 old->decStrong((void*)setJniCallback);
265 }
266 env->SetLongField(thiz, gEventHandlerFields.mJniCallback, (jlong)callback.get());
267 return old;
268}
269
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800270static int check_AudioSystem_Command(status_t status)
271{
Eric Laurentdfb881f2013-07-18 14:41:39 -0700272 switch (status) {
273 case DEAD_OBJECT:
274 return kAudioStatusMediaServerDied;
275 case NO_ERROR:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800276 return kAudioStatusOk;
Eric Laurentdfb881f2013-07-18 14:41:39 -0700277 default:
278 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279 }
Eric Laurentdfb881f2013-07-18 14:41:39 -0700280 return kAudioStatusError;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800281}
282
Ashok Bhat075e9a12014-01-06 13:45:09 +0000283static jint
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800284android_media_AudioSystem_muteMicrophone(JNIEnv *env, jobject thiz, jboolean on)
285{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000286 return (jint) check_AudioSystem_Command(AudioSystem::muteMicrophone(on));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800287}
288
289static jboolean
290android_media_AudioSystem_isMicrophoneMuted(JNIEnv *env, jobject thiz)
291{
292 bool state = false;
293 AudioSystem::isMicrophoneMuted(&state);
294 return state;
295}
296
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800297static jboolean
Eric Laurent25101b02011-02-02 09:33:30 -0800298android_media_AudioSystem_isStreamActive(JNIEnv *env, jobject thiz, jint stream, jint inPastMs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800299{
300 bool state = false;
Glenn Kastenbc1d77b2012-01-12 16:38:12 -0800301 AudioSystem::isStreamActive((audio_stream_type_t) stream, &state, inPastMs);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800302 return state;
303}
304
Jean-Michel Trivid6770542012-10-10 12:03:41 -0700305static jboolean
Jean-Michel Trivi679d5042013-02-04 16:24:09 -0800306android_media_AudioSystem_isStreamActiveRemotely(JNIEnv *env, jobject thiz, jint stream,
307 jint inPastMs)
308{
309 bool state = false;
310 AudioSystem::isStreamActiveRemotely((audio_stream_type_t) stream, &state, inPastMs);
311 return state;
312}
313
314static jboolean
Jean-Michel Trivid6770542012-10-10 12:03:41 -0700315android_media_AudioSystem_isSourceActive(JNIEnv *env, jobject thiz, jint source)
316{
317 bool state = false;
318 AudioSystem::isSourceActive((audio_source_t) source, &state);
319 return state;
320}
321
Ashok Bhat075e9a12014-01-06 13:45:09 +0000322static jint
Jean-Michel Trivi8a21f5d2014-06-05 15:03:52 -0700323android_media_AudioSystem_newAudioSessionId(JNIEnv *env, jobject thiz)
324{
Glenn Kasten211d9052016-02-26 16:22:40 -0800325 return AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
Jean-Michel Trivi8a21f5d2014-06-05 15:03:52 -0700326}
327
328static jint
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -0800329android_media_AudioSystem_newAudioPlayerId(JNIEnv *env, jobject thiz)
330{
331 return AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_PLAYER);
332}
333
334static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700335android_media_AudioSystem_setParameters(JNIEnv *env, jobject thiz, jstring keyValuePairs)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800336{
Eric Laurenta553c252009-07-17 12:17:14 -0700337 const jchar* c_keyValuePairs = env->GetStringCritical(keyValuePairs, 0);
338 String8 c_keyValuePairs8;
339 if (keyValuePairs) {
Dan Albert66987492014-11-20 11:41:21 -0800340 c_keyValuePairs8 = String8(
341 reinterpret_cast<const char16_t*>(c_keyValuePairs),
342 env->GetStringLength(keyValuePairs));
Eric Laurenta553c252009-07-17 12:17:14 -0700343 env->ReleaseStringCritical(keyValuePairs, c_keyValuePairs);
344 }
Glenn Kastenc94752a2013-12-19 12:40:33 -0800345 int status = check_AudioSystem_Command(AudioSystem::setParameters(c_keyValuePairs8));
Ashok Bhat075e9a12014-01-06 13:45:09 +0000346 return (jint) status;
Eric Laurenta553c252009-07-17 12:17:14 -0700347}
348
349static jstring
350android_media_AudioSystem_getParameters(JNIEnv *env, jobject thiz, jstring keys)
351{
352 const jchar* c_keys = env->GetStringCritical(keys, 0);
353 String8 c_keys8;
354 if (keys) {
Dan Albert66987492014-11-20 11:41:21 -0800355 c_keys8 = String8(reinterpret_cast<const char16_t*>(c_keys),
356 env->GetStringLength(keys));
Eric Laurenta553c252009-07-17 12:17:14 -0700357 env->ReleaseStringCritical(keys, c_keys);
358 }
Glenn Kastenc94752a2013-12-19 12:40:33 -0800359 return env->NewStringUTF(AudioSystem::getParameters(c_keys8).string());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800360}
361
Glenn Kastened0079d2011-04-04 10:50:50 -0700362static void
363android_media_AudioSystem_error_callback(status_t err)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800364{
Eric Laurent539719a2013-07-18 14:08:00 -0700365 JNIEnv *env = AndroidRuntime::getJNIEnv();
Eric Laurent0e7a4d92010-10-15 12:33:16 -0700366 if (env == NULL) {
367 return;
368 }
369
Glenn Kastened0079d2011-04-04 10:50:50 -0700370 jclass clazz = env->FindClass(kClassPathName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800371
Eric Laurentdfb881f2013-07-18 14:41:39 -0700372 env->CallStaticVoidMethod(clazz, env->GetStaticMethodID(clazz,
373 "errorCallbackFromNative","(I)V"),
374 check_AudioSystem_Command(err));
Viorel Sumanb637ccf2014-05-30 16:51:07 +0300375
376 env->DeleteLocalRef(clazz);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800377}
378
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700379static void
380android_media_AudioSystem_dyn_policy_callback(int event, String8 regId, int val)
381{
382 JNIEnv *env = AndroidRuntime::getJNIEnv();
383 if (env == NULL) {
384 return;
385 }
386
387 jclass clazz = env->FindClass(kClassPathName);
388 const char* zechars = regId.string();
389 jstring zestring = env->NewStringUTF(zechars);
390
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800391 env->CallStaticVoidMethod(clazz, gAudioPolicyEventHandlerMethods.postDynPolicyEventFromNative,
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700392 event, zestring, val);
393
394 env->ReleaseStringUTFChars(zestring, zechars);
395 env->DeleteLocalRef(clazz);
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800396}
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700397
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800398static void
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -0800399android_media_AudioSystem_recording_callback(int event, const record_client_info_t *clientInfo,
Jean-Michel Trivi8ab72802016-02-25 16:31:45 -0800400 const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig,
401 audio_patch_handle_t patchHandle)
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800402{
403 JNIEnv *env = AndroidRuntime::getJNIEnv();
404 if (env == NULL) {
405 return;
406 }
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -0800407 if (clientInfo == NULL || clientConfig == NULL || deviceConfig == NULL) {
408 ALOGE("Unexpected null client/device info or configurations in recording callback");
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800409 return;
410 }
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800411
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800412 // create an array for 2*3 integers to store the record configurations (client + device)
Jean-Michel Trivi8ab72802016-02-25 16:31:45 -0800413 // plus 1 integer for the patch handle
414 const int REC_PARAM_SIZE = 7;
415 jintArray recParamArray = env->NewIntArray(REC_PARAM_SIZE);
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800416 if (recParamArray == NULL) {
417 ALOGE("recording callback: Couldn't allocate int array for configuration data");
418 return;
419 }
Jean-Michel Trivi8ab72802016-02-25 16:31:45 -0800420 jint recParamData[REC_PARAM_SIZE];
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800421 recParamData[0] = (jint) audioFormatFromNative(clientConfig->format);
422 // FIXME this doesn't support index-based masks
423 recParamData[1] = (jint) inChannelMaskFromNative(clientConfig->channel_mask);
424 recParamData[2] = (jint) clientConfig->sample_rate;
425 recParamData[3] = (jint) audioFormatFromNative(deviceConfig->format);
426 // FIXME this doesn't support index-based masks
427 recParamData[4] = (jint) inChannelMaskFromNative(deviceConfig->channel_mask);
428 recParamData[5] = (jint) deviceConfig->sample_rate;
Jean-Michel Trivi8ab72802016-02-25 16:31:45 -0800429 recParamData[6] = (jint) patchHandle;
430 env->SetIntArrayRegion(recParamArray, 0, REC_PARAM_SIZE, recParamData);
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800431
432 // callback into java
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800433 jclass clazz = env->FindClass(kClassPathName);
434 env->CallStaticVoidMethod(clazz,
435 gAudioPolicyEventHandlerMethods.postRecordConfigEventFromNative,
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -0800436 event, (jint) clientInfo->uid, clientInfo->session, clientInfo->source, recParamArray);
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -0800437 env->DeleteLocalRef(clazz);
Jean-Michel Trivi33fd8162016-02-22 10:52:41 -0800438
439 env->DeleteLocalRef(recParamArray);
Jean-Michel Trivi5a561092015-04-23 18:48:08 -0700440}
441
Ashok Bhat075e9a12014-01-06 13:45:09 +0000442static jint
Paul McLean10804eb2015-01-28 11:16:35 -0800443android_media_AudioSystem_setDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jint state, jstring device_address, jstring device_name)
Eric Laurenta553c252009-07-17 12:17:14 -0700444{
445 const char *c_address = env->GetStringUTFChars(device_address, NULL);
Paul McLean10804eb2015-01-28 11:16:35 -0800446 const char *c_name = env->GetStringUTFChars(device_name, NULL);
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700447 int status = check_AudioSystem_Command(AudioSystem::setDeviceConnectionState(static_cast <audio_devices_t>(device),
448 static_cast <audio_policy_dev_state_t>(state),
Paul McLean10804eb2015-01-28 11:16:35 -0800449 c_address, c_name));
Eric Laurenta553c252009-07-17 12:17:14 -0700450 env->ReleaseStringUTFChars(device_address, c_address);
Paul McLean10804eb2015-01-28 11:16:35 -0800451 env->ReleaseStringUTFChars(device_name, c_name);
Ashok Bhat075e9a12014-01-06 13:45:09 +0000452 return (jint) status;
Eric Laurenta553c252009-07-17 12:17:14 -0700453}
454
Ashok Bhat075e9a12014-01-06 13:45:09 +0000455static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700456android_media_AudioSystem_getDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jstring device_address)
457{
458 const char *c_address = env->GetStringUTFChars(device_address, NULL);
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700459 int state = static_cast <int>(AudioSystem::getDeviceConnectionState(static_cast <audio_devices_t>(device),
Eric Laurenta553c252009-07-17 12:17:14 -0700460 c_address));
461 env->ReleaseStringUTFChars(device_address, c_address);
Ashok Bhat075e9a12014-01-06 13:45:09 +0000462 return (jint) state;
Eric Laurenta553c252009-07-17 12:17:14 -0700463}
464
Ashok Bhat075e9a12014-01-06 13:45:09 +0000465static jint
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -0800466android_media_AudioSystem_handleDeviceConfigChange(JNIEnv *env, jobject thiz, jint device, jstring device_address, jstring device_name)
467{
468 const char *c_address = env->GetStringUTFChars(device_address, NULL);
469 const char *c_name = env->GetStringUTFChars(device_name, NULL);
470 int status = check_AudioSystem_Command(AudioSystem::handleDeviceConfigChange(static_cast <audio_devices_t>(device),
471 c_address, c_name));
472 env->ReleaseStringUTFChars(device_address, c_address);
473 env->ReleaseStringUTFChars(device_name, c_name);
474 return (jint) status;
475}
476
477static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700478android_media_AudioSystem_setPhoneState(JNIEnv *env, jobject thiz, jint state)
479{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000480 return (jint) check_AudioSystem_Command(AudioSystem::setPhoneState((audio_mode_t) state));
Eric Laurenta553c252009-07-17 12:17:14 -0700481}
482
Ashok Bhat075e9a12014-01-06 13:45:09 +0000483static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700484android_media_AudioSystem_setForceUse(JNIEnv *env, jobject thiz, jint usage, jint config)
485{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000486 return (jint) check_AudioSystem_Command(AudioSystem::setForceUse(static_cast <audio_policy_force_use_t>(usage),
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700487 static_cast <audio_policy_forced_cfg_t>(config)));
Eric Laurenta553c252009-07-17 12:17:14 -0700488}
489
Ashok Bhat075e9a12014-01-06 13:45:09 +0000490static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700491android_media_AudioSystem_getForceUse(JNIEnv *env, jobject thiz, jint usage)
492{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000493 return static_cast <jint>(AudioSystem::getForceUse(static_cast <audio_policy_force_use_t>(usage)));
Eric Laurenta553c252009-07-17 12:17:14 -0700494}
495
Ashok Bhat075e9a12014-01-06 13:45:09 +0000496static jint
Eric Laurenta553c252009-07-17 12:17:14 -0700497android_media_AudioSystem_initStreamVolume(JNIEnv *env, jobject thiz, jint stream, jint indexMin, jint indexMax)
498{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000499 return (jint) check_AudioSystem_Command(AudioSystem::initStreamVolume(static_cast <audio_stream_type_t>(stream),
Eric Laurenta553c252009-07-17 12:17:14 -0700500 indexMin,
501 indexMax));
502}
503
Ashok Bhat075e9a12014-01-06 13:45:09 +0000504static jint
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800505android_media_AudioSystem_setStreamVolumeIndex(JNIEnv *env,
506 jobject thiz,
507 jint stream,
508 jint index,
509 jint device)
Eric Laurenta553c252009-07-17 12:17:14 -0700510{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000511 return (jint) check_AudioSystem_Command(
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800512 AudioSystem::setStreamVolumeIndex(static_cast <audio_stream_type_t>(stream),
513 index,
514 (audio_devices_t)device));
Eric Laurenta553c252009-07-17 12:17:14 -0700515}
516
Ashok Bhat075e9a12014-01-06 13:45:09 +0000517static jint
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800518android_media_AudioSystem_getStreamVolumeIndex(JNIEnv *env,
519 jobject thiz,
520 jint stream,
521 jint device)
Eric Laurenta553c252009-07-17 12:17:14 -0700522{
523 int index;
Eric Laurent9bc8358d2011-11-18 16:43:31 -0800524 if (AudioSystem::getStreamVolumeIndex(static_cast <audio_stream_type_t>(stream),
525 &index,
526 (audio_devices_t)device)
527 != NO_ERROR) {
Eric Laurenta553c252009-07-17 12:17:14 -0700528 index = -1;
529 }
Ashok Bhat075e9a12014-01-06 13:45:09 +0000530 return (jint) index;
Eric Laurenta553c252009-07-17 12:17:14 -0700531}
532
Ashok Bhat075e9a12014-01-06 13:45:09 +0000533static jint
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400534android_media_AudioSystem_setMasterVolume(JNIEnv *env, jobject thiz, jfloat value)
535{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000536 return (jint) check_AudioSystem_Command(AudioSystem::setMasterVolume(value));
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400537}
538
539static jfloat
540android_media_AudioSystem_getMasterVolume(JNIEnv *env, jobject thiz)
541{
542 float value;
543 if (AudioSystem::getMasterVolume(&value) != NO_ERROR) {
544 value = -1.0;
545 }
546 return value;
547}
548
Ashok Bhat075e9a12014-01-06 13:45:09 +0000549static jint
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400550android_media_AudioSystem_setMasterMute(JNIEnv *env, jobject thiz, jboolean mute)
551{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000552 return (jint) check_AudioSystem_Command(AudioSystem::setMasterMute(mute));
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400553}
554
Vladimir Markoc1bcdbb2014-10-29 20:34:15 +0000555static jboolean
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -0400556android_media_AudioSystem_getMasterMute(JNIEnv *env, jobject thiz)
557{
558 bool mute;
559 if (AudioSystem::getMasterMute(&mute) != NO_ERROR) {
560 mute = false;
561 }
562 return mute;
563}
564
Glenn Kasten8b4b97a2011-02-04 13:54:26 -0800565static jint
Andy Hungf04b84d2015-12-18 17:33:27 -0800566android_media_AudioSystem_setMasterMono(JNIEnv *env, jobject thiz, jboolean mono)
567{
568 return (jint) check_AudioSystem_Command(AudioSystem::setMasterMono(mono));
569}
570
571static jboolean
572android_media_AudioSystem_getMasterMono(JNIEnv *env, jobject thiz)
573{
574 bool mono;
575 if (AudioSystem::getMasterMono(&mono) != NO_ERROR) {
576 mono = false;
577 }
578 return mono;
579}
580
581static jint
Glenn Kasten8b4b97a2011-02-04 13:54:26 -0800582android_media_AudioSystem_getDevicesForStream(JNIEnv *env, jobject thiz, jint stream)
583{
Dima Zavin24fc2fb2011-04-19 22:30:36 -0700584 return (jint) AudioSystem::getDevicesForStream(static_cast <audio_stream_type_t>(stream));
Glenn Kasten8b4b97a2011-02-04 13:54:26 -0800585}
586
Glenn Kastenc6c43652012-09-24 17:32:30 -0700587static jint
588android_media_AudioSystem_getPrimaryOutputSamplingRate(JNIEnv *env, jobject clazz)
589{
590 return (jint) AudioSystem::getPrimaryOutputSamplingRate();
591}
592
593static jint
594android_media_AudioSystem_getPrimaryOutputFrameCount(JNIEnv *env, jobject clazz)
595{
596 return (jint) AudioSystem::getPrimaryOutputFrameCount();
597}
598
Oliver Woodman61dcdf32013-06-26 12:43:36 +0100599static jint
600android_media_AudioSystem_getOutputLatency(JNIEnv *env, jobject clazz, jint stream)
601{
602 uint32_t afLatency;
603 if (AudioSystem::getOutputLatency(&afLatency, static_cast <audio_stream_type_t>(stream))
604 != NO_ERROR) {
605 afLatency = -1;
606 }
607 return (jint) afLatency;
608}
609
Glenn Kastenfd116ad2013-07-12 17:10:39 -0700610static jint
Andy Hung79583582018-01-23 13:58:02 -0800611android_media_AudioSystem_setLowRamDevice(
612 JNIEnv *env, jobject clazz, jboolean isLowRamDevice, jlong totalMemory)
Glenn Kastenfd116ad2013-07-12 17:10:39 -0700613{
Andy Hung79583582018-01-23 13:58:02 -0800614 return (jint) AudioSystem::setLowRamDevice((bool) isLowRamDevice, (int64_t) totalMemory);
Glenn Kastenfd116ad2013-07-12 17:10:39 -0700615}
616
Ashok Bhat075e9a12014-01-06 13:45:09 +0000617static jint
Eric Laurentdfb881f2013-07-18 14:41:39 -0700618android_media_AudioSystem_checkAudioFlinger(JNIEnv *env, jobject clazz)
619{
Ashok Bhat075e9a12014-01-06 13:45:09 +0000620 return (jint) check_AudioSystem_Command(AudioSystem::checkAudioFlinger());
Eric Laurentdfb881f2013-07-18 14:41:39 -0700621}
622
Eric Laurentb69681c2014-05-19 19:02:51 -0700623
624static bool useInChannelMask(audio_port_type_t type, audio_port_role_t role)
625{
626 return ((type == AUDIO_PORT_TYPE_DEVICE) && (role == AUDIO_PORT_ROLE_SOURCE)) ||
627 ((type == AUDIO_PORT_TYPE_MIX) && (role == AUDIO_PORT_ROLE_SINK));
628}
629
Eric Laurent3a241992014-05-19 19:33:26 -0700630static void convertAudioGainConfigToNative(JNIEnv *env,
631 struct audio_gain_config *nAudioGainConfig,
632 const jobject jAudioGainConfig,
633 bool useInMask)
634{
635 nAudioGainConfig->index = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mIndex);
636 nAudioGainConfig->mode = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mMode);
637 ALOGV("convertAudioGainConfigToNative got gain index %d", nAudioGainConfig->index);
638 jint jMask = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mChannelMask);
639 audio_channel_mask_t nMask;
640 if (useInMask) {
641 nMask = inChannelMaskToNative(jMask);
642 ALOGV("convertAudioGainConfigToNative IN mask java %x native %x", jMask, nMask);
643 } else {
644 nMask = outChannelMaskToNative(jMask);
645 ALOGV("convertAudioGainConfigToNative OUT mask java %x native %x", jMask, nMask);
646 }
647 nAudioGainConfig->channel_mask = nMask;
648 nAudioGainConfig->ramp_duration_ms = env->GetIntField(jAudioGainConfig,
649 gAudioGainConfigFields.mRampDurationMs);
650 jintArray jValues = (jintArray)env->GetObjectField(jAudioGainConfig,
651 gAudioGainConfigFields.mValues);
652 int *nValues = env->GetIntArrayElements(jValues, NULL);
653 size_t size = env->GetArrayLength(jValues);
654 memcpy(nAudioGainConfig->values, nValues, size * sizeof(int));
655 env->DeleteLocalRef(jValues);
656}
657
658
Eric Laurentb69681c2014-05-19 19:02:51 -0700659static jint convertAudioPortConfigToNative(JNIEnv *env,
660 struct audio_port_config *nAudioPortConfig,
Eric Laurent6368a7d2014-11-19 12:18:32 -0800661 const jobject jAudioPortConfig,
662 bool useConfigMask)
Eric Laurentb69681c2014-05-19 19:02:51 -0700663{
664 jobject jAudioPort = env->GetObjectField(jAudioPortConfig, gAudioPortConfigFields.mPort);
665 jobject jHandle = env->GetObjectField(jAudioPort, gAudioPortFields.mHandle);
666 nAudioPortConfig->id = env->GetIntField(jHandle, gAudioHandleFields.mId);
667 nAudioPortConfig->role = (audio_port_role_t)env->GetIntField(jAudioPort,
668 gAudioPortFields.mRole);
669 if (env->IsInstanceOf(jAudioPort, gAudioDevicePortClass)) {
670 nAudioPortConfig->type = AUDIO_PORT_TYPE_DEVICE;
671 } else if (env->IsInstanceOf(jAudioPort, gAudioMixPortClass)) {
672 nAudioPortConfig->type = AUDIO_PORT_TYPE_MIX;
673 } else {
674 env->DeleteLocalRef(jAudioPort);
675 env->DeleteLocalRef(jHandle);
676 return (jint)AUDIO_JAVA_ERROR;
677 }
678 ALOGV("convertAudioPortConfigToNative handle %d role %d type %d",
679 nAudioPortConfig->id, nAudioPortConfig->role, nAudioPortConfig->type);
680
Eric Laurent6368a7d2014-11-19 12:18:32 -0800681 unsigned int configMask = 0;
682
Eric Laurentb69681c2014-05-19 19:02:51 -0700683 nAudioPortConfig->sample_rate = env->GetIntField(jAudioPortConfig,
684 gAudioPortConfigFields.mSamplingRate);
Eric Laurent6368a7d2014-11-19 12:18:32 -0800685 if (nAudioPortConfig->sample_rate != 0) {
686 configMask |= AUDIO_PORT_CONFIG_SAMPLE_RATE;
687 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700688
689 bool useInMask = useInChannelMask(nAudioPortConfig->type, nAudioPortConfig->role);
690 audio_channel_mask_t nMask;
691 jint jMask = env->GetIntField(jAudioPortConfig,
692 gAudioPortConfigFields.mChannelMask);
693 if (useInMask) {
694 nMask = inChannelMaskToNative(jMask);
695 ALOGV("convertAudioPortConfigToNative IN mask java %x native %x", jMask, nMask);
696 } else {
697 nMask = outChannelMaskToNative(jMask);
698 ALOGV("convertAudioPortConfigToNative OUT mask java %x native %x", jMask, nMask);
699 }
700 nAudioPortConfig->channel_mask = nMask;
Eric Laurent6368a7d2014-11-19 12:18:32 -0800701 if (nAudioPortConfig->channel_mask != AUDIO_CHANNEL_NONE) {
702 configMask |= AUDIO_PORT_CONFIG_CHANNEL_MASK;
703 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700704
705 jint jFormat = env->GetIntField(jAudioPortConfig, gAudioPortConfigFields.mFormat);
706 audio_format_t nFormat = audioFormatToNative(jFormat);
707 ALOGV("convertAudioPortConfigToNative format %d native %d", jFormat, nFormat);
708 nAudioPortConfig->format = nFormat;
Eric Laurent6368a7d2014-11-19 12:18:32 -0800709 if (nAudioPortConfig->format != AUDIO_FORMAT_DEFAULT &&
710 nAudioPortConfig->format != AUDIO_FORMAT_INVALID) {
711 configMask |= AUDIO_PORT_CONFIG_FORMAT;
712 }
713
Eric Laurentb69681c2014-05-19 19:02:51 -0700714 jobject jGain = env->GetObjectField(jAudioPortConfig, gAudioPortConfigFields.mGain);
715 if (jGain != NULL) {
Eric Laurent3a241992014-05-19 19:33:26 -0700716 convertAudioGainConfigToNative(env, &nAudioPortConfig->gain, jGain, useInMask);
Eric Laurentb69681c2014-05-19 19:02:51 -0700717 env->DeleteLocalRef(jGain);
Eric Laurent6368a7d2014-11-19 12:18:32 -0800718 configMask |= AUDIO_PORT_CONFIG_GAIN;
Eric Laurentb69681c2014-05-19 19:02:51 -0700719 } else {
720 ALOGV("convertAudioPortConfigToNative no gain");
721 nAudioPortConfig->gain.index = -1;
722 }
Eric Laurent6368a7d2014-11-19 12:18:32 -0800723 if (useConfigMask) {
724 nAudioPortConfig->config_mask = env->GetIntField(jAudioPortConfig,
725 gAudioPortConfigFields.mConfigMask);
726 } else {
727 nAudioPortConfig->config_mask = configMask;
728 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700729 env->DeleteLocalRef(jAudioPort);
730 env->DeleteLocalRef(jHandle);
731 return (jint)AUDIO_JAVA_SUCCESS;
732}
733
734static jint convertAudioPortConfigFromNative(JNIEnv *env,
735 jobject jAudioPort,
736 jobject *jAudioPortConfig,
737 const struct audio_port_config *nAudioPortConfig)
738{
739 jint jStatus = AUDIO_JAVA_SUCCESS;
740 jobject jAudioGainConfig = NULL;
741 jobject jAudioGain = NULL;
742 jintArray jGainValues;
743 bool audioportCreated = false;
744
745 ALOGV("convertAudioPortConfigFromNative jAudioPort %p", jAudioPort);
746
747 if (jAudioPort == NULL) {
748 jobject jHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
749 nAudioPortConfig->id);
750
751 ALOGV("convertAudioPortConfigFromNative handle %d is a %s", nAudioPortConfig->id,
752 nAudioPortConfig->type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix");
753
754 if (jHandle == NULL) {
755 return (jint)AUDIO_JAVA_ERROR;
756 }
757 // create dummy port and port config objects with just the correct handle
758 // and configuration data. The actual AudioPortConfig objects will be
759 // constructed by java code with correct class type (device, mix etc...)
760 // and reference to AudioPort instance in this client
761 jAudioPort = env->NewObject(gAudioPortClass, gAudioPortCstor,
Paul McLeanf29e5f32015-06-15 10:19:22 -0700762 jHandle, // handle
763 0, // role
764 NULL, // name
765 NULL, // samplingRates
766 NULL, // channelMasks
767 NULL, // channelIndexMasks
768 NULL, // formats
769 NULL); // gains
Eric Laurentb69681c2014-05-19 19:02:51 -0700770 env->DeleteLocalRef(jHandle);
771 if (jAudioPort == NULL) {
772 return (jint)AUDIO_JAVA_ERROR;
773 }
774 ALOGV("convertAudioPortConfigFromNative jAudioPort created for handle %d",
775 nAudioPortConfig->id);
776
777 audioportCreated = true;
778 }
779
780 bool useInMask = useInChannelMask(nAudioPortConfig->type, nAudioPortConfig->role);
781
782 audio_channel_mask_t nMask;
783 jint jMask;
784
785 int gainIndex = nAudioPortConfig->gain.index;
786 if (gainIndex >= 0) {
787 ALOGV("convertAudioPortConfigFromNative gain found with index %d mode %x",
788 gainIndex, nAudioPortConfig->gain.mode);
789 if (audioportCreated) {
790 ALOGV("convertAudioPortConfigFromNative creating gain");
791 jAudioGain = env->NewObject(gAudioGainClass, gAudioGainCstor,
792 gainIndex,
793 0,
794 0,
795 0,
796 0,
797 0,
798 0,
799 0,
800 0);
801 if (jAudioGain == NULL) {
802 ALOGV("convertAudioPortConfigFromNative creating gain FAILED");
803 jStatus = (jint)AUDIO_JAVA_ERROR;
804 goto exit;
805 }
806 } else {
807 ALOGV("convertAudioPortConfigFromNative reading gain from port");
808 jobjectArray jGains = (jobjectArray)env->GetObjectField(jAudioPort,
809 gAudioPortFields.mGains);
810 if (jGains == NULL) {
811 ALOGV("convertAudioPortConfigFromNative could not get gains from port");
812 jStatus = (jint)AUDIO_JAVA_ERROR;
813 goto exit;
814 }
815 jAudioGain = env->GetObjectArrayElement(jGains, gainIndex);
816 env->DeleteLocalRef(jGains);
817 if (jAudioGain == NULL) {
818 ALOGV("convertAudioPortConfigFromNative could not get gain at index %d", gainIndex);
819 jStatus = (jint)AUDIO_JAVA_ERROR;
820 goto exit;
821 }
822 }
Eric Laurent0078c7c2014-06-04 09:49:52 -0700823 int numValues;
824 if (useInMask) {
825 numValues = audio_channel_count_from_in_mask(nAudioPortConfig->gain.channel_mask);
826 } else {
827 numValues = audio_channel_count_from_out_mask(nAudioPortConfig->gain.channel_mask);
828 }
Eric Laurentb69681c2014-05-19 19:02:51 -0700829 jGainValues = env->NewIntArray(numValues);
830 if (jGainValues == NULL) {
831 ALOGV("convertAudioPortConfigFromNative could not create gain values %d", numValues);
832 jStatus = (jint)AUDIO_JAVA_ERROR;
833 goto exit;
834 }
835 env->SetIntArrayRegion(jGainValues, 0, numValues,
836 nAudioPortConfig->gain.values);
837
838 nMask = nAudioPortConfig->gain.channel_mask;
839 if (useInMask) {
840 jMask = inChannelMaskFromNative(nMask);
841 ALOGV("convertAudioPortConfigFromNative IN mask java %x native %x", jMask, nMask);
842 } else {
843 jMask = outChannelMaskFromNative(nMask);
844 ALOGV("convertAudioPortConfigFromNative OUT mask java %x native %x", jMask, nMask);
845 }
846
847 jAudioGainConfig = env->NewObject(gAudioGainConfigClass,
848 gAudioGainConfigCstor,
849 gainIndex,
850 jAudioGain,
851 nAudioPortConfig->gain.mode,
852 jMask,
853 jGainValues,
854 nAudioPortConfig->gain.ramp_duration_ms);
855 env->DeleteLocalRef(jGainValues);
856 if (jAudioGainConfig == NULL) {
857 ALOGV("convertAudioPortConfigFromNative could not create gain config");
858 jStatus = (jint)AUDIO_JAVA_ERROR;
859 goto exit;
860 }
861 }
862 jclass clazz;
863 jmethodID methodID;
864 if (audioportCreated) {
865 clazz = gAudioPortConfigClass;
866 methodID = gAudioPortConfigCstor;
867 ALOGV("convertAudioPortConfigFromNative building a generic port config");
868 } else {
869 if (env->IsInstanceOf(jAudioPort, gAudioDevicePortClass)) {
870 clazz = gAudioDevicePortConfigClass;
871 methodID = gAudioDevicePortConfigCstor;
872 ALOGV("convertAudioPortConfigFromNative building a device config");
873 } else if (env->IsInstanceOf(jAudioPort, gAudioMixPortClass)) {
874 clazz = gAudioMixPortConfigClass;
875 methodID = gAudioMixPortConfigCstor;
876 ALOGV("convertAudioPortConfigFromNative building a mix config");
877 } else {
878 jStatus = (jint)AUDIO_JAVA_ERROR;
879 goto exit;
880 }
881 }
882 nMask = nAudioPortConfig->channel_mask;
883 if (useInMask) {
884 jMask = inChannelMaskFromNative(nMask);
885 ALOGV("convertAudioPortConfigFromNative IN mask java %x native %x", jMask, nMask);
886 } else {
887 jMask = outChannelMaskFromNative(nMask);
888 ALOGV("convertAudioPortConfigFromNative OUT mask java %x native %x", jMask, nMask);
889 }
890
891 *jAudioPortConfig = env->NewObject(clazz, methodID,
892 jAudioPort,
893 nAudioPortConfig->sample_rate,
894 jMask,
895 audioFormatFromNative(nAudioPortConfig->format),
896 jAudioGainConfig);
897 if (*jAudioPortConfig == NULL) {
898 ALOGV("convertAudioPortConfigFromNative could not create new port config");
899 jStatus = (jint)AUDIO_JAVA_ERROR;
900 } else {
901 ALOGV("convertAudioPortConfigFromNative OK");
902 }
903
904exit:
905 if (audioportCreated) {
906 env->DeleteLocalRef(jAudioPort);
907 if (jAudioGain != NULL) {
908 env->DeleteLocalRef(jAudioGain);
909 }
910 }
911 if (jAudioGainConfig != NULL) {
912 env->DeleteLocalRef(jAudioGainConfig);
913 }
914 return jStatus;
915}
916
Paul McLean4e5e9e92015-06-17 10:10:11 -0700917static bool hasFormat(int* formats, size_t size, int format) {
918 for (size_t index = 0; index < size; index++) {
919 if (formats[index] == format) {
920 return true; // found
921 }
922 }
923 return false; // not found
924}
925
Andy Hung737d9fb2016-08-16 18:38:49 -0700926// TODO: pull out to separate file
927template <typename T, size_t N>
928static constexpr size_t array_size(const T (&)[N]) {
929 return N;
930}
931
Eric Laurentb69681c2014-05-19 19:02:51 -0700932static jint convertAudioPortFromNative(JNIEnv *env,
933 jobject *jAudioPort, const struct audio_port *nAudioPort)
934{
935 jint jStatus = (jint)AUDIO_JAVA_SUCCESS;
936 jintArray jSamplingRates = NULL;
937 jintArray jChannelMasks = NULL;
Paul McLeanf29e5f32015-06-15 10:19:22 -0700938 jintArray jChannelIndexMasks = NULL;
Paul McLean4e5e9e92015-06-17 10:10:11 -0700939 int* cFormats = NULL;
Eric Laurentb69681c2014-05-19 19:02:51 -0700940 jintArray jFormats = NULL;
941 jobjectArray jGains = NULL;
942 jobject jHandle = NULL;
Paul McLean10804eb2015-01-28 11:16:35 -0800943 jstring jDeviceName = NULL;
Eric Laurentb69681c2014-05-19 19:02:51 -0700944 bool useInMask;
Paul McLeanf29e5f32015-06-15 10:19:22 -0700945 size_t numPositionMasks = 0;
946 size_t numIndexMasks = 0;
Paul McLean2db94372015-06-18 12:47:34 -0700947 size_t numUniqueFormats = 0;
948
Paul McLean10804eb2015-01-28 11:16:35 -0800949 ALOGV("convertAudioPortFromNative id %d role %d type %d name %s",
950 nAudioPort->id, nAudioPort->role, nAudioPort->type, nAudioPort->name);
Eric Laurentb69681c2014-05-19 19:02:51 -0700951
Andy Hung737d9fb2016-08-16 18:38:49 -0700952 // Verify audio port array count info.
953 if (nAudioPort->num_sample_rates > array_size(nAudioPort->sample_rates)
954 || nAudioPort->num_channel_masks > array_size(nAudioPort->channel_masks)
955 || nAudioPort->num_formats > array_size(nAudioPort->formats)
956 || nAudioPort->num_gains > array_size(nAudioPort->gains)) {
957
958 std::stringstream ss;
959 ss << "convertAudioPortFromNative array count out of bounds:"
960 << " num_sample_rates " << nAudioPort->num_sample_rates
961 << " num_channel_masks " << nAudioPort->num_channel_masks
962 << " num_formats " << nAudioPort->num_formats
963 << " num_gains " << nAudioPort->num_gains
964 ;
965 std::string s = ss.str();
966
967 // Prefer to log through Java wtf instead of native ALOGE.
968 ScopedLocalRef<jclass> jLogClass(env, env->FindClass("android/util/Log"));
969 jmethodID jWtfId = (jLogClass.get() == nullptr)
970 ? nullptr
971 : env->GetStaticMethodID(jLogClass.get(), "wtf",
972 "(Ljava/lang/String;Ljava/lang/String;)I");
973 if (jWtfId != nullptr) {
974 ScopedLocalRef<jstring> jMessage(env, env->NewStringUTF(s.c_str()));
975 ScopedLocalRef<jstring> jTag(env, env->NewStringUTF(LOG_TAG));
976 (void)env->CallStaticIntMethod(jLogClass.get(), jWtfId, jTag.get(), jMessage.get());
977 } else {
978 ALOGE("%s", s.c_str());
979 }
980 jStatus = (jint)AUDIO_JAVA_ERROR;
981 goto exit;
982 }
983
Eric Laurentb69681c2014-05-19 19:02:51 -0700984 jSamplingRates = env->NewIntArray(nAudioPort->num_sample_rates);
985 if (jSamplingRates == NULL) {
986 jStatus = (jint)AUDIO_JAVA_ERROR;
987 goto exit;
988 }
989 if (nAudioPort->num_sample_rates) {
990 env->SetIntArrayRegion(jSamplingRates, 0, nAudioPort->num_sample_rates,
991 (jint *)nAudioPort->sample_rates);
992 }
993
Paul McLeanf29e5f32015-06-15 10:19:22 -0700994 // count up how many masks are positional and indexed
995 for(size_t index = 0; index < nAudioPort->num_channel_masks; index++) {
996 const audio_channel_mask_t mask = nAudioPort->channel_masks[index];
997 if (audio_channel_mask_get_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
998 numIndexMasks++;
999 } else {
1000 numPositionMasks++;
1001 }
1002 }
1003
1004 jChannelMasks = env->NewIntArray(numPositionMasks);
Eric Laurentb69681c2014-05-19 19:02:51 -07001005 if (jChannelMasks == NULL) {
1006 jStatus = (jint)AUDIO_JAVA_ERROR;
1007 goto exit;
1008 }
Paul McLeanf29e5f32015-06-15 10:19:22 -07001009 jChannelIndexMasks = env->NewIntArray(numIndexMasks);
1010 if (jChannelIndexMasks == NULL) {
1011 jStatus = (jint)AUDIO_JAVA_ERROR;
1012 goto exit;
1013 }
Eric Laurentb69681c2014-05-19 19:02:51 -07001014 useInMask = useInChannelMask(nAudioPort->type, nAudioPort->role);
1015
Paul McLeanf29e5f32015-06-15 10:19:22 -07001016 // put the masks in the output arrays
1017 for (size_t maskIndex = 0, posMaskIndex = 0, indexedMaskIndex = 0;
1018 maskIndex < nAudioPort->num_channel_masks; maskIndex++) {
1019 const audio_channel_mask_t mask = nAudioPort->channel_masks[maskIndex];
1020 if (audio_channel_mask_get_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
1021 jint jMask = audio_channel_mask_get_bits(mask);
1022 env->SetIntArrayRegion(jChannelIndexMasks, indexedMaskIndex++, 1, &jMask);
Eric Laurentb69681c2014-05-19 19:02:51 -07001023 } else {
Paul McLeanf29e5f32015-06-15 10:19:22 -07001024 jint jMask = useInMask ? inChannelMaskFromNative(mask)
1025 : outChannelMaskFromNative(mask);
1026 env->SetIntArrayRegion(jChannelMasks, posMaskIndex++, 1, &jMask);
Eric Laurentb69681c2014-05-19 19:02:51 -07001027 }
Eric Laurentb69681c2014-05-19 19:02:51 -07001028 }
1029
Paul McLeanf29e5f32015-06-15 10:19:22 -07001030 // formats
Paul McLean2db94372015-06-18 12:47:34 -07001031 if (nAudioPort->num_formats != 0) {
1032 cFormats = new int[nAudioPort->num_formats];
1033 for (size_t index = 0; index < nAudioPort->num_formats; index++) {
1034 int format = audioFormatFromNative(nAudioPort->formats[index]);
1035 if (!hasFormat(cFormats, numUniqueFormats, format)) {
1036 cFormats[numUniqueFormats++] = format;
1037 }
Paul McLean4e5e9e92015-06-17 10:10:11 -07001038 }
1039 }
1040 jFormats = env->NewIntArray(numUniqueFormats);
Eric Laurentb69681c2014-05-19 19:02:51 -07001041 if (jFormats == NULL) {
1042 jStatus = (jint)AUDIO_JAVA_ERROR;
1043 goto exit;
1044 }
Paul McLean2db94372015-06-18 12:47:34 -07001045 if (numUniqueFormats != 0) {
1046 env->SetIntArrayRegion(jFormats, 0, numUniqueFormats, cFormats);
1047 }
Eric Laurentb69681c2014-05-19 19:02:51 -07001048
Paul McLeanf29e5f32015-06-15 10:19:22 -07001049 // gains
Eric Laurentb69681c2014-05-19 19:02:51 -07001050 jGains = env->NewObjectArray(nAudioPort->num_gains,
1051 gAudioGainClass, NULL);
1052 if (jGains == NULL) {
1053 jStatus = (jint)AUDIO_JAVA_ERROR;
1054 goto exit;
1055 }
Paul McLeanf29e5f32015-06-15 10:19:22 -07001056
Eric Laurentb69681c2014-05-19 19:02:51 -07001057 for (size_t j = 0; j < nAudioPort->num_gains; j++) {
1058 audio_channel_mask_t nMask = nAudioPort->gains[j].channel_mask;
Paul McLeanf29e5f32015-06-15 10:19:22 -07001059 jint jMask;
Eric Laurentb69681c2014-05-19 19:02:51 -07001060 if (useInMask) {
1061 jMask = inChannelMaskFromNative(nMask);
1062 ALOGV("convertAudioPortConfigFromNative IN mask java %x native %x", jMask, nMask);
1063 } else {
1064 jMask = outChannelMaskFromNative(nMask);
1065 ALOGV("convertAudioPortConfigFromNative OUT mask java %x native %x", jMask, nMask);
1066 }
1067
1068 jobject jGain = env->NewObject(gAudioGainClass, gAudioGainCstor,
1069 j,
1070 nAudioPort->gains[j].mode,
1071 jMask,
1072 nAudioPort->gains[j].min_value,
1073 nAudioPort->gains[j].max_value,
1074 nAudioPort->gains[j].default_value,
1075 nAudioPort->gains[j].step_value,
1076 nAudioPort->gains[j].min_ramp_ms,
1077 nAudioPort->gains[j].max_ramp_ms);
1078 if (jGain == NULL) {
1079 jStatus = (jint)AUDIO_JAVA_ERROR;
1080 goto exit;
1081 }
1082 env->SetObjectArrayElement(jGains, j, jGain);
1083 env->DeleteLocalRef(jGain);
1084 }
1085
1086 jHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
1087 nAudioPort->id);
1088 if (jHandle == NULL) {
1089 jStatus = (jint)AUDIO_JAVA_ERROR;
1090 goto exit;
1091 }
1092
Paul McLean10804eb2015-01-28 11:16:35 -08001093 jDeviceName = env->NewStringUTF(nAudioPort->name);
1094
Eric Laurentb69681c2014-05-19 19:02:51 -07001095 if (nAudioPort->type == AUDIO_PORT_TYPE_DEVICE) {
1096 ALOGV("convertAudioPortFromNative is a device %08x", nAudioPort->ext.device.type);
1097 jstring jAddress = env->NewStringUTF(nAudioPort->ext.device.address);
1098 *jAudioPort = env->NewObject(gAudioDevicePortClass, gAudioDevicePortCstor,
Paul McLean10804eb2015-01-28 11:16:35 -08001099 jHandle, jDeviceName,
Paul McLeanf29e5f32015-06-15 10:19:22 -07001100 jSamplingRates, jChannelMasks, jChannelIndexMasks,
1101 jFormats, jGains,
Eric Laurentb69681c2014-05-19 19:02:51 -07001102 nAudioPort->ext.device.type, jAddress);
1103 env->DeleteLocalRef(jAddress);
1104 } else if (nAudioPort->type == AUDIO_PORT_TYPE_MIX) {
1105 ALOGV("convertAudioPortFromNative is a mix");
1106 *jAudioPort = env->NewObject(gAudioMixPortClass, gAudioMixPortCstor,
Eric Laurent4bcdba82015-05-01 11:37:49 -07001107 jHandle, nAudioPort->ext.mix.handle,
1108 nAudioPort->role, jDeviceName,
Paul McLeanf29e5f32015-06-15 10:19:22 -07001109 jSamplingRates, jChannelMasks, jChannelIndexMasks,
Eric Laurentb69681c2014-05-19 19:02:51 -07001110 jFormats, jGains);
1111 } else {
1112 ALOGE("convertAudioPortFromNative unknown nAudioPort type %d", nAudioPort->type);
1113 jStatus = (jint)AUDIO_JAVA_ERROR;
1114 goto exit;
1115 }
1116 if (*jAudioPort == NULL) {
1117 jStatus = (jint)AUDIO_JAVA_ERROR;
1118 goto exit;
1119 }
1120
1121 jobject jAudioPortConfig;
1122 jStatus = convertAudioPortConfigFromNative(env,
1123 *jAudioPort,
1124 &jAudioPortConfig,
1125 &nAudioPort->active_config);
1126 if (jStatus != AUDIO_JAVA_SUCCESS) {
Andy Hung737d9fb2016-08-16 18:38:49 -07001127 goto exit;
Eric Laurentb69681c2014-05-19 19:02:51 -07001128 }
1129
1130 env->SetObjectField(*jAudioPort, gAudioPortFields.mActiveConfig, jAudioPortConfig);
1131
1132exit:
Paul McLean10804eb2015-01-28 11:16:35 -08001133 if (jDeviceName != NULL) {
1134 env->DeleteLocalRef(jDeviceName);
1135 }
Eric Laurentb69681c2014-05-19 19:02:51 -07001136 if (jSamplingRates != NULL) {
1137 env->DeleteLocalRef(jSamplingRates);
1138 }
1139 if (jChannelMasks != NULL) {
1140 env->DeleteLocalRef(jChannelMasks);
1141 }
Paul McLean4e5e9e92015-06-17 10:10:11 -07001142 if (jChannelIndexMasks != NULL) {
1143 env->DeleteLocalRef(jChannelIndexMasks);
1144 }
1145 if (cFormats != NULL) {
1146 delete[] cFormats;
1147 }
Eric Laurentb69681c2014-05-19 19:02:51 -07001148 if (jFormats != NULL) {
1149 env->DeleteLocalRef(jFormats);
1150 }
1151 if (jGains != NULL) {
1152 env->DeleteLocalRef(jGains);
1153 }
1154 if (jHandle != NULL) {
1155 env->DeleteLocalRef(jHandle);
1156 }
1157
1158 return jStatus;
1159}
1160
1161
1162static jint
1163android_media_AudioSystem_listAudioPorts(JNIEnv *env, jobject clazz,
1164 jobject jPorts, jintArray jGeneration)
1165{
1166 ALOGV("listAudioPorts");
1167
1168 if (jPorts == NULL) {
1169 ALOGE("listAudioPorts NULL AudioPort ArrayList");
1170 return (jint)AUDIO_JAVA_BAD_VALUE;
1171 }
1172 if (!env->IsInstanceOf(jPorts, gArrayListClass)) {
1173 ALOGE("listAudioPorts not an arraylist");
1174 return (jint)AUDIO_JAVA_BAD_VALUE;
1175 }
1176
1177 if (jGeneration == NULL || env->GetArrayLength(jGeneration) != 1) {
1178 return (jint)AUDIO_JAVA_BAD_VALUE;
1179 }
1180
1181 status_t status;
1182 unsigned int generation1;
1183 unsigned int generation;
1184 unsigned int numPorts;
1185 jint *nGeneration;
1186 struct audio_port *nPorts = NULL;
1187 int attempts = MAX_PORT_GENERATION_SYNC_ATTEMPTS;
Eric Laurentb36d1042016-04-14 18:00:38 -07001188 jint jStatus;
Eric Laurentb69681c2014-05-19 19:02:51 -07001189
1190 // get the port count and all the ports until they both return the same generation
1191 do {
1192 if (attempts-- < 0) {
1193 status = TIMED_OUT;
1194 break;
1195 }
1196
1197 numPorts = 0;
1198 status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE,
1199 AUDIO_PORT_TYPE_NONE,
1200 &numPorts,
1201 NULL,
1202 &generation1);
Eric Laurentb36d1042016-04-14 18:00:38 -07001203 if (status != NO_ERROR) {
Eric Laurentb69681c2014-05-19 19:02:51 -07001204 ALOGE_IF(status != NO_ERROR, "AudioSystem::listAudioPorts error %d", status);
1205 break;
1206 }
Eric Laurentb36d1042016-04-14 18:00:38 -07001207 if (numPorts == 0) {
1208 jStatus = (jint)AUDIO_JAVA_SUCCESS;
1209 goto exit;
1210 }
Eric Laurentb69681c2014-05-19 19:02:51 -07001211 nPorts = (struct audio_port *)realloc(nPorts, numPorts * sizeof(struct audio_port));
1212
1213 status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE,
1214 AUDIO_PORT_TYPE_NONE,
1215 &numPorts,
1216 nPorts,
1217 &generation);
1218 ALOGV("listAudioPorts AudioSystem::listAudioPorts numPorts %d generation %d generation1 %d",
1219 numPorts, generation, generation1);
1220 } while (generation1 != generation && status == NO_ERROR);
1221
Eric Laurentb36d1042016-04-14 18:00:38 -07001222 jStatus = nativeToJavaStatus(status);
Eric Laurentb69681c2014-05-19 19:02:51 -07001223 if (jStatus != AUDIO_JAVA_SUCCESS) {
1224 goto exit;
1225 }
1226
Eric Laurentb69681c2014-05-19 19:02:51 -07001227 for (size_t i = 0; i < numPorts; i++) {
1228 jobject jAudioPort;
1229 jStatus = convertAudioPortFromNative(env, &jAudioPort, &nPorts[i]);
1230 if (jStatus != AUDIO_JAVA_SUCCESS) {
1231 goto exit;
1232 }
1233 env->CallBooleanMethod(jPorts, gArrayListMethods.add, jAudioPort);
1234 }
1235
1236exit:
Eric Laurentb36d1042016-04-14 18:00:38 -07001237 nGeneration = env->GetIntArrayElements(jGeneration, NULL);
1238 if (nGeneration == NULL) {
1239 jStatus = (jint)AUDIO_JAVA_ERROR;
1240 } else {
1241 nGeneration[0] = generation1;
1242 env->ReleaseIntArrayElements(jGeneration, nGeneration, 0);
1243 }
Eric Laurentb69681c2014-05-19 19:02:51 -07001244 free(nPorts);
1245 return jStatus;
1246}
1247
1248static int
1249android_media_AudioSystem_createAudioPatch(JNIEnv *env, jobject clazz,
1250 jobjectArray jPatches, jobjectArray jSources, jobjectArray jSinks)
1251{
1252 status_t status;
1253 jint jStatus;
1254
1255 ALOGV("createAudioPatch");
1256 if (jPatches == NULL || jSources == NULL || jSinks == NULL) {
1257 return (jint)AUDIO_JAVA_BAD_VALUE;
1258 }
1259
1260 if (env->GetArrayLength(jPatches) != 1) {
1261 return (jint)AUDIO_JAVA_BAD_VALUE;
1262 }
1263 jint numSources = env->GetArrayLength(jSources);
1264 if (numSources == 0 || numSources > AUDIO_PATCH_PORTS_MAX) {
1265 return (jint)AUDIO_JAVA_BAD_VALUE;
1266 }
1267
1268 jint numSinks = env->GetArrayLength(jSinks);
1269 if (numSinks == 0 || numSinks > AUDIO_PATCH_PORTS_MAX) {
1270 return (jint)AUDIO_JAVA_BAD_VALUE;
1271 }
1272
1273 audio_patch_handle_t handle = (audio_patch_handle_t)0;
1274 jobject jPatch = env->GetObjectArrayElement(jPatches, 0);
1275 jobject jPatchHandle = NULL;
1276 if (jPatch != NULL) {
1277 if (!env->IsInstanceOf(jPatch, gAudioPatchClass)) {
1278 return (jint)AUDIO_JAVA_BAD_VALUE;
1279 }
1280 jPatchHandle = env->GetObjectField(jPatch, gAudioPatchFields.mHandle);
1281 handle = (audio_patch_handle_t)env->GetIntField(jPatchHandle, gAudioHandleFields.mId);
1282 }
1283
1284 struct audio_patch nPatch;
1285
1286 nPatch.id = handle;
1287 nPatch.num_sources = 0;
1288 nPatch.num_sinks = 0;
1289 jobject jSource = NULL;
1290 jobject jSink = NULL;
1291
1292 for (jint i = 0; i < numSources; i++) {
1293 jSource = env->GetObjectArrayElement(jSources, i);
1294 if (!env->IsInstanceOf(jSource, gAudioPortConfigClass)) {
1295 jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
1296 goto exit;
1297 }
Eric Laurent6368a7d2014-11-19 12:18:32 -08001298 jStatus = convertAudioPortConfigToNative(env, &nPatch.sources[i], jSource, false);
Eric Laurentb69681c2014-05-19 19:02:51 -07001299 env->DeleteLocalRef(jSource);
1300 jSource = NULL;
1301 if (jStatus != AUDIO_JAVA_SUCCESS) {
1302 goto exit;
1303 }
1304 nPatch.num_sources++;
1305 }
1306
1307 for (jint i = 0; i < numSinks; i++) {
1308 jSink = env->GetObjectArrayElement(jSinks, i);
1309 if (!env->IsInstanceOf(jSink, gAudioPortConfigClass)) {
1310 jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
1311 goto exit;
1312 }
Eric Laurent6368a7d2014-11-19 12:18:32 -08001313 jStatus = convertAudioPortConfigToNative(env, &nPatch.sinks[i], jSink, false);
Eric Laurentb69681c2014-05-19 19:02:51 -07001314 env->DeleteLocalRef(jSink);
1315 jSink = NULL;
1316 if (jStatus != AUDIO_JAVA_SUCCESS) {
1317 goto exit;
1318 }
1319 nPatch.num_sinks++;
1320 }
1321
1322 ALOGV("AudioSystem::createAudioPatch");
1323 status = AudioSystem::createAudioPatch(&nPatch, &handle);
1324 ALOGV("AudioSystem::createAudioPatch() returned %d hande %d", status, handle);
1325
1326 jStatus = nativeToJavaStatus(status);
1327 if (jStatus != AUDIO_JAVA_SUCCESS) {
1328 goto exit;
1329 }
1330
1331 if (jPatchHandle == NULL) {
1332 jPatchHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
1333 handle);
1334 if (jPatchHandle == NULL) {
1335 jStatus = (jint)AUDIO_JAVA_ERROR;
1336 goto exit;
1337 }
1338 jPatch = env->NewObject(gAudioPatchClass, gAudioPatchCstor, jPatchHandle, jSources, jSinks);
1339 if (jPatch == NULL) {
1340 jStatus = (jint)AUDIO_JAVA_ERROR;
1341 goto exit;
1342 }
1343 env->SetObjectArrayElement(jPatches, 0, jPatch);
1344 } else {
1345 env->SetIntField(jPatchHandle, gAudioHandleFields.mId, handle);
1346 }
1347
1348exit:
1349 if (jPatchHandle != NULL) {
1350 env->DeleteLocalRef(jPatchHandle);
1351 }
1352 if (jPatch != NULL) {
1353 env->DeleteLocalRef(jPatch);
1354 }
1355 if (jSource != NULL) {
1356 env->DeleteLocalRef(jSource);
1357 }
1358 if (jSink != NULL) {
1359 env->DeleteLocalRef(jSink);
1360 }
1361 return jStatus;
1362}
1363
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001364static jint
Eric Laurentb69681c2014-05-19 19:02:51 -07001365android_media_AudioSystem_releaseAudioPatch(JNIEnv *env, jobject clazz,
1366 jobject jPatch)
1367{
1368 ALOGV("releaseAudioPatch");
1369 if (jPatch == NULL) {
1370 return (jint)AUDIO_JAVA_BAD_VALUE;
1371 }
1372
1373 audio_patch_handle_t handle = (audio_patch_handle_t)0;
1374 jobject jPatchHandle = NULL;
1375 if (!env->IsInstanceOf(jPatch, gAudioPatchClass)) {
1376 return (jint)AUDIO_JAVA_BAD_VALUE;
1377 }
1378 jPatchHandle = env->GetObjectField(jPatch, gAudioPatchFields.mHandle);
1379 handle = (audio_patch_handle_t)env->GetIntField(jPatchHandle, gAudioHandleFields.mId);
1380 env->DeleteLocalRef(jPatchHandle);
1381
1382 ALOGV("AudioSystem::releaseAudioPatch");
1383 status_t status = AudioSystem::releaseAudioPatch(handle);
1384 ALOGV("AudioSystem::releaseAudioPatch() returned %d", status);
1385 jint jStatus = nativeToJavaStatus(status);
Andreas Gampe0f0b4912014-11-12 08:03:48 -08001386 return jStatus;
Eric Laurentb69681c2014-05-19 19:02:51 -07001387}
1388
1389static jint
1390android_media_AudioSystem_listAudioPatches(JNIEnv *env, jobject clazz,
1391 jobject jPatches, jintArray jGeneration)
1392{
1393 ALOGV("listAudioPatches");
1394 if (jPatches == NULL) {
1395 ALOGE("listAudioPatches NULL AudioPatch ArrayList");
1396 return (jint)AUDIO_JAVA_BAD_VALUE;
1397 }
1398 if (!env->IsInstanceOf(jPatches, gArrayListClass)) {
1399 ALOGE("listAudioPatches not an arraylist");
1400 return (jint)AUDIO_JAVA_BAD_VALUE;
1401 }
1402
1403 if (jGeneration == NULL || env->GetArrayLength(jGeneration) != 1) {
1404 return (jint)AUDIO_JAVA_BAD_VALUE;
1405 }
1406
1407 status_t status;
1408 unsigned int generation1;
1409 unsigned int generation;
1410 unsigned int numPatches;
1411 jint *nGeneration;
1412 struct audio_patch *nPatches = NULL;
1413 jobjectArray jSources = NULL;
1414 jobject jSource = NULL;
1415 jobjectArray jSinks = NULL;
1416 jobject jSink = NULL;
1417 jobject jPatch = NULL;
1418 int attempts = MAX_PORT_GENERATION_SYNC_ATTEMPTS;
Eric Laurentb36d1042016-04-14 18:00:38 -07001419 jint jStatus;
Eric Laurentb69681c2014-05-19 19:02:51 -07001420
1421 // get the patch count and all the patches until they both return the same generation
1422 do {
1423 if (attempts-- < 0) {
1424 status = TIMED_OUT;
1425 break;
1426 }
1427
1428 numPatches = 0;
1429 status = AudioSystem::listAudioPatches(&numPatches,
1430 NULL,
1431 &generation1);
Eric Laurentb36d1042016-04-14 18:00:38 -07001432 if (status != NO_ERROR) {
Eric Laurentb69681c2014-05-19 19:02:51 -07001433 ALOGE_IF(status != NO_ERROR, "listAudioPatches AudioSystem::listAudioPatches error %d",
1434 status);
1435 break;
1436 }
Eric Laurentb36d1042016-04-14 18:00:38 -07001437 if (numPatches == 0) {
1438 jStatus = (jint)AUDIO_JAVA_SUCCESS;
1439 goto exit;
1440 }
1441
Eric Laurentb69681c2014-05-19 19:02:51 -07001442 nPatches = (struct audio_patch *)realloc(nPatches, numPatches * sizeof(struct audio_patch));
1443
1444 status = AudioSystem::listAudioPatches(&numPatches,
1445 nPatches,
1446 &generation);
1447 ALOGV("listAudioPatches AudioSystem::listAudioPatches numPatches %d generation %d generation1 %d",
1448 numPatches, generation, generation1);
1449
1450 } while (generation1 != generation && status == NO_ERROR);
1451
Eric Laurentb36d1042016-04-14 18:00:38 -07001452 jStatus = nativeToJavaStatus(status);
Eric Laurentb69681c2014-05-19 19:02:51 -07001453 if (jStatus != AUDIO_JAVA_SUCCESS) {
1454 goto exit;
1455 }
1456
Eric Laurentb69681c2014-05-19 19:02:51 -07001457 for (size_t i = 0; i < numPatches; i++) {
1458 jobject patchHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
1459 nPatches[i].id);
1460 if (patchHandle == NULL) {
1461 jStatus = AUDIO_JAVA_ERROR;
1462 goto exit;
1463 }
Dan Albert46d84442014-11-18 16:07:51 -08001464 ALOGV("listAudioPatches patch %zu num_sources %d num_sinks %d",
Eric Laurentb69681c2014-05-19 19:02:51 -07001465 i, nPatches[i].num_sources, nPatches[i].num_sinks);
1466
1467 env->SetIntField(patchHandle, gAudioHandleFields.mId, nPatches[i].id);
1468
1469 // load sources
1470 jSources = env->NewObjectArray(nPatches[i].num_sources,
1471 gAudioPortConfigClass, NULL);
1472 if (jSources == NULL) {
1473 jStatus = AUDIO_JAVA_ERROR;
1474 goto exit;
1475 }
1476
1477 for (size_t j = 0; j < nPatches[i].num_sources; j++) {
1478 jStatus = convertAudioPortConfigFromNative(env,
1479 NULL,
1480 &jSource,
1481 &nPatches[i].sources[j]);
1482 if (jStatus != AUDIO_JAVA_SUCCESS) {
1483 goto exit;
1484 }
1485 env->SetObjectArrayElement(jSources, j, jSource);
1486 env->DeleteLocalRef(jSource);
1487 jSource = NULL;
Dan Albert46d84442014-11-18 16:07:51 -08001488 ALOGV("listAudioPatches patch %zu source %zu is a %s handle %d",
Eric Laurentb69681c2014-05-19 19:02:51 -07001489 i, j,
1490 nPatches[i].sources[j].type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix",
1491 nPatches[i].sources[j].id);
1492 }
1493 // load sinks
1494 jSinks = env->NewObjectArray(nPatches[i].num_sinks,
1495 gAudioPortConfigClass, NULL);
1496 if (jSinks == NULL) {
1497 jStatus = AUDIO_JAVA_ERROR;
1498 goto exit;
1499 }
1500
1501 for (size_t j = 0; j < nPatches[i].num_sinks; j++) {
1502 jStatus = convertAudioPortConfigFromNative(env,
1503 NULL,
1504 &jSink,
1505 &nPatches[i].sinks[j]);
1506
1507 if (jStatus != AUDIO_JAVA_SUCCESS) {
1508 goto exit;
1509 }
1510 env->SetObjectArrayElement(jSinks, j, jSink);
1511 env->DeleteLocalRef(jSink);
1512 jSink = NULL;
Dan Albert46d84442014-11-18 16:07:51 -08001513 ALOGV("listAudioPatches patch %zu sink %zu is a %s handle %d",
Eric Laurentb69681c2014-05-19 19:02:51 -07001514 i, j,
1515 nPatches[i].sinks[j].type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix",
1516 nPatches[i].sinks[j].id);
1517 }
1518
1519 jPatch = env->NewObject(gAudioPatchClass, gAudioPatchCstor,
1520 patchHandle, jSources, jSinks);
1521 env->DeleteLocalRef(jSources);
1522 jSources = NULL;
1523 env->DeleteLocalRef(jSinks);
1524 jSinks = NULL;
1525 if (jPatch == NULL) {
1526 jStatus = AUDIO_JAVA_ERROR;
1527 goto exit;
1528 }
1529 env->CallBooleanMethod(jPatches, gArrayListMethods.add, jPatch);
1530 env->DeleteLocalRef(jPatch);
1531 jPatch = NULL;
1532 }
1533
1534exit:
Eric Laurentb36d1042016-04-14 18:00:38 -07001535
1536 nGeneration = env->GetIntArrayElements(jGeneration, NULL);
1537 if (nGeneration == NULL) {
1538 jStatus = AUDIO_JAVA_ERROR;
1539 } else {
1540 nGeneration[0] = generation1;
1541 env->ReleaseIntArrayElements(jGeneration, nGeneration, 0);
1542 }
1543
Eric Laurentb69681c2014-05-19 19:02:51 -07001544 if (jSources != NULL) {
1545 env->DeleteLocalRef(jSources);
1546 }
1547 if (jSource != NULL) {
1548 env->DeleteLocalRef(jSource);
1549 }
1550 if (jSinks != NULL) {
1551 env->DeleteLocalRef(jSinks);
1552 }
1553 if (jSink != NULL) {
1554 env->DeleteLocalRef(jSink);
1555 }
1556 if (jPatch != NULL) {
1557 env->DeleteLocalRef(jPatch);
1558 }
1559 free(nPatches);
1560 return jStatus;
1561}
1562
Eric Laurent3a241992014-05-19 19:33:26 -07001563static jint
1564android_media_AudioSystem_setAudioPortConfig(JNIEnv *env, jobject clazz,
1565 jobject jAudioPortConfig)
1566{
1567 ALOGV("setAudioPortConfig");
1568 if (jAudioPortConfig == NULL) {
1569 return AUDIO_JAVA_BAD_VALUE;
1570 }
1571 if (!env->IsInstanceOf(jAudioPortConfig, gAudioPortConfigClass)) {
1572 return AUDIO_JAVA_BAD_VALUE;
1573 }
1574 struct audio_port_config nAudioPortConfig;
Eric Laurent6368a7d2014-11-19 12:18:32 -08001575 jint jStatus = convertAudioPortConfigToNative(env, &nAudioPortConfig, jAudioPortConfig, true);
Eric Laurent3a241992014-05-19 19:33:26 -07001576 if (jStatus != AUDIO_JAVA_SUCCESS) {
1577 return jStatus;
1578 }
1579 status_t status = AudioSystem::setAudioPortConfig(&nAudioPortConfig);
1580 ALOGV("AudioSystem::setAudioPortConfig() returned %d", status);
1581 jStatus = nativeToJavaStatus(status);
1582 return jStatus;
1583}
1584
Eric Laurent700e7342014-05-02 18:33:15 -07001585static void
1586android_media_AudioSystem_eventHandlerSetup(JNIEnv *env, jobject thiz, jobject weak_this)
1587{
1588 ALOGV("eventHandlerSetup");
1589
1590 sp<JNIAudioPortCallback> callback = new JNIAudioPortCallback(env, thiz, weak_this);
1591
Eric Laurent2615afb2015-03-25 14:51:08 -07001592 if (AudioSystem::addAudioPortCallback(callback) == NO_ERROR) {
1593 setJniCallback(env, thiz, callback);
1594 }
Eric Laurent700e7342014-05-02 18:33:15 -07001595}
1596
1597static void
1598android_media_AudioSystem_eventHandlerFinalize(JNIEnv *env, jobject thiz)
1599{
1600 ALOGV("eventHandlerFinalize");
1601
Eric Laurent2615afb2015-03-25 14:51:08 -07001602 sp<JNIAudioPortCallback> callback = setJniCallback(env, thiz, 0);
Eric Laurent700e7342014-05-02 18:33:15 -07001603
Eric Laurent2615afb2015-03-25 14:51:08 -07001604 if (callback != 0) {
1605 AudioSystem::removeAudioPortCallback(callback);
1606 }
Eric Laurent700e7342014-05-02 18:33:15 -07001607}
1608
Eric Laurentb634e1b2014-08-01 14:44:46 -07001609static jint
1610android_media_AudioSystem_getAudioHwSyncForSession(JNIEnv *env, jobject thiz, jint sessionId)
1611{
Glenn Kasten33b84042016-03-08 12:02:55 -08001612 return (jint) AudioSystem::getAudioHwSyncForSession((audio_session_t) sessionId);
Eric Laurentb634e1b2014-08-01 14:44:46 -07001613}
1614
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001615static void
1616android_media_AudioSystem_registerDynPolicyCallback(JNIEnv *env, jobject thiz)
1617{
1618 AudioSystem::setDynPolicyCallback(android_media_AudioSystem_dyn_policy_callback);
1619}
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001620
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08001621static void
1622android_media_AudioSystem_registerRecordingCallback(JNIEnv *env, jobject thiz)
1623{
1624 AudioSystem::setRecordConfigCallback(android_media_AudioSystem_recording_callback);
1625}
1626
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001627
1628static jint convertAudioMixToNative(JNIEnv *env,
1629 AudioMix *nAudioMix,
1630 const jobject jAudioMix)
1631{
1632 nAudioMix->mMixType = env->GetIntField(jAudioMix, gAudioMixFields.mMixType);
1633 nAudioMix->mRouteFlags = env->GetIntField(jAudioMix, gAudioMixFields.mRouteFlags);
Jean-Michel Trivi4ad39882016-03-14 18:46:41 -07001634 nAudioMix->mDeviceType = (audio_devices_t)
1635 env->GetIntField(jAudioMix, gAudioMixFields.mDeviceType);
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001636
Jean-Michel Trivi4ad39882016-03-14 18:46:41 -07001637 jstring jDeviceAddress = (jstring)env->GetObjectField(jAudioMix,
1638 gAudioMixFields.mDeviceAddress);
1639 const char *nDeviceAddress = env->GetStringUTFChars(jDeviceAddress, NULL);
1640 nAudioMix->mDeviceAddress = String8(nDeviceAddress);
1641 env->ReleaseStringUTFChars(jDeviceAddress, nDeviceAddress);
1642 env->DeleteLocalRef(jDeviceAddress);
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001643
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001644 nAudioMix->mCbFlags = env->GetIntField(jAudioMix, gAudioMixFields.mCallbackFlags);
1645
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001646 jobject jFormat = env->GetObjectField(jAudioMix, gAudioMixFields.mFormat);
1647 nAudioMix->mFormat.sample_rate = env->GetIntField(jFormat,
1648 gAudioFormatFields.mSampleRate);
1649 nAudioMix->mFormat.channel_mask = outChannelMaskToNative(env->GetIntField(jFormat,
1650 gAudioFormatFields.mChannelMask));
1651 nAudioMix->mFormat.format = audioFormatToNative(env->GetIntField(jFormat,
1652 gAudioFormatFields.mEncoding));
1653 env->DeleteLocalRef(jFormat);
1654
1655 jobject jRule = env->GetObjectField(jAudioMix, gAudioMixFields.mRule);
1656 jobject jRuleCriteria = env->GetObjectField(jRule, gAudioMixingRuleFields.mCriteria);
1657 env->DeleteLocalRef(jRule);
1658 jobjectArray jCriteria = (jobjectArray)env->CallObjectMethod(jRuleCriteria,
1659 gArrayListMethods.toArray);
1660 env->DeleteLocalRef(jRuleCriteria);
1661
1662 jint numCriteria = env->GetArrayLength(jCriteria);
1663 if (numCriteria > MAX_CRITERIA_PER_MIX) {
1664 numCriteria = MAX_CRITERIA_PER_MIX;
1665 }
1666
1667 for (jint i = 0; i < numCriteria; i++) {
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -08001668 AudioMixMatchCriterion nCriterion;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001669
1670 jobject jCriterion = env->GetObjectArrayElement(jCriteria, i);
1671
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -08001672 nCriterion.mRule = env->GetIntField(jCriterion, gAudioMixMatchCriterionFields.mRule);
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001673
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -08001674 const uint32_t match_rule = nCriterion.mRule & ~RULE_EXCLUSION_MASK;
1675 switch (match_rule) {
1676 case RULE_MATCH_UID:
1677 nCriterion.mValue.mUid = env->GetIntField(jCriterion,
1678 gAudioMixMatchCriterionFields.mIntProp);
1679 break;
1680 case RULE_MATCH_ATTRIBUTE_USAGE:
1681 case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET: {
1682 jobject jAttributes = env->GetObjectField(jCriterion, gAudioMixMatchCriterionFields.mAttr);
1683 if (match_rule == RULE_MATCH_ATTRIBUTE_USAGE) {
1684 nCriterion.mValue.mUsage = (audio_usage_t)env->GetIntField(jAttributes,
1685 gAudioAttributesFields.mUsage);
1686 } else {
1687 nCriterion.mValue.mSource = (audio_source_t)env->GetIntField(jAttributes,
1688 gAudioAttributesFields.mSource);
1689 }
1690 env->DeleteLocalRef(jAttributes);
1691 }
1692 break;
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001693 }
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001694
1695 nAudioMix->mCriteria.add(nCriterion);
1696 env->DeleteLocalRef(jCriterion);
1697 }
1698
1699 env->DeleteLocalRef(jCriteria);
1700
1701 return (jint)AUDIO_JAVA_SUCCESS;
1702}
1703
1704static jint
1705android_media_AudioSystem_registerPolicyMixes(JNIEnv *env, jobject clazz,
1706 jobject jMixesList, jboolean registration)
1707{
1708 ALOGV("registerPolicyMixes");
1709
1710 if (jMixesList == NULL) {
1711 return (jint)AUDIO_JAVA_BAD_VALUE;
1712 }
1713 if (!env->IsInstanceOf(jMixesList, gArrayListClass)) {
1714 return (jint)AUDIO_JAVA_BAD_VALUE;
1715 }
1716 jobjectArray jMixes = (jobjectArray)env->CallObjectMethod(jMixesList,
1717 gArrayListMethods.toArray);
1718 jint numMixes = env->GetArrayLength(jMixes);
1719 if (numMixes > MAX_MIXES_PER_POLICY) {
1720 numMixes = MAX_MIXES_PER_POLICY;
1721 }
1722
1723 status_t status;
1724 jint jStatus;
1725 jobject jAudioMix = NULL;
1726 Vector <AudioMix> mixes;
1727 for (jint i = 0; i < numMixes; i++) {
1728 jAudioMix = env->GetObjectArrayElement(jMixes, i);
1729 if (!env->IsInstanceOf(jAudioMix, gAudioMixClass)) {
1730 jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
1731 goto exit;
1732 }
1733 AudioMix mix;
1734 jStatus = convertAudioMixToNative(env, &mix, jAudioMix);
1735 env->DeleteLocalRef(jAudioMix);
1736 jAudioMix = NULL;
1737 if (jStatus != AUDIO_JAVA_SUCCESS) {
1738 goto exit;
1739 }
1740 mixes.add(mix);
1741 }
1742
1743 ALOGV("AudioSystem::registerPolicyMixes numMixes %d registration %d", numMixes, registration);
1744 status = AudioSystem::registerPolicyMixes(mixes, registration);
1745 ALOGV("AudioSystem::registerPolicyMixes() returned %d", status);
1746
1747 jStatus = nativeToJavaStatus(status);
1748 if (jStatus != AUDIO_JAVA_SUCCESS) {
1749 goto exit;
1750 }
1751
1752exit:
1753 if (jAudioMix != NULL) {
1754 env->DeleteLocalRef(jAudioMix);
1755 }
1756 return jStatus;
1757}
1758
Eric Laurent0867bed2015-05-20 14:49:08 -07001759static jint
1760android_media_AudioSystem_systemReady(JNIEnv *env, jobject thiz)
1761{
1762 return nativeToJavaStatus(AudioSystem::systemReady());
1763}
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001764
Eric Laurenteab40d12017-06-09 12:45:21 -07001765static jfloat
1766android_media_AudioSystem_getStreamVolumeDB(JNIEnv *env, jobject thiz,
1767 jint stream, jint index, jint device)
1768{
1769 return (jfloat)AudioSystem::getStreamVolumeDB((audio_stream_type_t)stream,
1770 (int)index,
1771 (audio_devices_t)device);
1772}
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001773
Jean-Michel Trivi980d38f2018-01-08 15:43:35 -08001774static jboolean
1775android_media_AudioSystem_isOffloadSupported(JNIEnv *env, jobject thiz,
1776 jint encoding, jint sampleRate, jint channelMask, jint channelIndexMask)
1777{
1778 audio_offload_info_t format = AUDIO_INFO_INITIALIZER;
1779 format.format = (audio_format_t) audioFormatToNative(encoding);
1780 format.sample_rate = (uint32_t) sampleRate;
1781 format.channel_mask = nativeChannelMaskFromJavaChannelMasks(channelMask, channelIndexMask);
1782 format.stream_type = AUDIO_STREAM_MUSIC;
1783 format.has_video = false;
1784 format.is_streaming = false;
1785 // offload duration unknown at this point:
1786 // client side code cannot access "audio.offload.min.duration.secs" property to make a query
1787 // agnostic of duration, so using acceptable estimate of 2mn
1788 format.duration_us = 120 * 1000000;
1789 return AudioSystem::isOffloadSupported(format);
1790}
1791
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001792// ----------------------------------------------------------------------------
1793
Daniel Micay76f6a862015-09-19 17:31:01 -04001794static const JNINativeMethod gMethods[] = {
Eric Laurenta553c252009-07-17 12:17:14 -07001795 {"setParameters", "(Ljava/lang/String;)I", (void *)android_media_AudioSystem_setParameters},
1796 {"getParameters", "(Ljava/lang/String;)Ljava/lang/String;", (void *)android_media_AudioSystem_getParameters},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001797 {"muteMicrophone", "(Z)I", (void *)android_media_AudioSystem_muteMicrophone},
1798 {"isMicrophoneMuted", "()Z", (void *)android_media_AudioSystem_isMicrophoneMuted},
Jean-Michel Trivid6770542012-10-10 12:03:41 -07001799 {"isStreamActive", "(II)Z", (void *)android_media_AudioSystem_isStreamActive},
Jean-Michel Trivi679d5042013-02-04 16:24:09 -08001800 {"isStreamActiveRemotely","(II)Z", (void *)android_media_AudioSystem_isStreamActiveRemotely},
Jean-Michel Trivid6770542012-10-10 12:03:41 -07001801 {"isSourceActive", "(I)Z", (void *)android_media_AudioSystem_isSourceActive},
Jean-Michel Trivi8a21f5d2014-06-05 15:03:52 -07001802 {"newAudioSessionId", "()I", (void *)android_media_AudioSystem_newAudioSessionId},
Jean-Michel Trivi292a6a42016-12-01 08:32:15 -08001803 {"newAudioPlayerId", "()I", (void *)android_media_AudioSystem_newAudioPlayerId},
Paul McLean10804eb2015-01-28 11:16:35 -08001804 {"setDeviceConnectionState", "(IILjava/lang/String;Ljava/lang/String;)I", (void *)android_media_AudioSystem_setDeviceConnectionState},
Eric Laurenta553c252009-07-17 12:17:14 -07001805 {"getDeviceConnectionState", "(ILjava/lang/String;)I", (void *)android_media_AudioSystem_getDeviceConnectionState},
Pavlin Radoslavov44a4ef02016-12-21 12:05:51 -08001806 {"handleDeviceConfigChange", "(ILjava/lang/String;Ljava/lang/String;)I", (void *)android_media_AudioSystem_handleDeviceConfigChange},
Eric Laurenta553c252009-07-17 12:17:14 -07001807 {"setPhoneState", "(I)I", (void *)android_media_AudioSystem_setPhoneState},
Eric Laurenta553c252009-07-17 12:17:14 -07001808 {"setForceUse", "(II)I", (void *)android_media_AudioSystem_setForceUse},
1809 {"getForceUse", "(I)I", (void *)android_media_AudioSystem_getForceUse},
1810 {"initStreamVolume", "(III)I", (void *)android_media_AudioSystem_initStreamVolume},
Eric Laurent9bc8358d2011-11-18 16:43:31 -08001811 {"setStreamVolumeIndex","(III)I", (void *)android_media_AudioSystem_setStreamVolumeIndex},
1812 {"getStreamVolumeIndex","(II)I", (void *)android_media_AudioSystem_getStreamVolumeIndex},
Mike Lockwoodcbdb49d2011-10-20 12:54:05 -04001813 {"setMasterVolume", "(F)I", (void *)android_media_AudioSystem_setMasterVolume},
1814 {"getMasterVolume", "()F", (void *)android_media_AudioSystem_getMasterVolume},
1815 {"setMasterMute", "(Z)I", (void *)android_media_AudioSystem_setMasterMute},
1816 {"getMasterMute", "()Z", (void *)android_media_AudioSystem_getMasterMute},
Andy Hungf04b84d2015-12-18 17:33:27 -08001817 {"setMasterMono", "(Z)I", (void *)android_media_AudioSystem_setMasterMono},
1818 {"getMasterMono", "()Z", (void *)android_media_AudioSystem_getMasterMono},
Glenn Kasten8b4b97a2011-02-04 13:54:26 -08001819 {"getDevicesForStream", "(I)I", (void *)android_media_AudioSystem_getDevicesForStream},
Glenn Kastenc6c43652012-09-24 17:32:30 -07001820 {"getPrimaryOutputSamplingRate", "()I", (void *)android_media_AudioSystem_getPrimaryOutputSamplingRate},
1821 {"getPrimaryOutputFrameCount", "()I", (void *)android_media_AudioSystem_getPrimaryOutputFrameCount},
Oliver Woodman61dcdf32013-06-26 12:43:36 +01001822 {"getOutputLatency", "(I)I", (void *)android_media_AudioSystem_getOutputLatency},
Andy Hung79583582018-01-23 13:58:02 -08001823 {"setLowRamDevice", "(ZJ)I", (void *)android_media_AudioSystem_setLowRamDevice},
Eric Laurentdfb881f2013-07-18 14:41:39 -07001824 {"checkAudioFlinger", "()I", (void *)android_media_AudioSystem_checkAudioFlinger},
Eric Laurentb69681c2014-05-19 19:02:51 -07001825 {"listAudioPorts", "(Ljava/util/ArrayList;[I)I",
1826 (void *)android_media_AudioSystem_listAudioPorts},
1827 {"createAudioPatch", "([Landroid/media/AudioPatch;[Landroid/media/AudioPortConfig;[Landroid/media/AudioPortConfig;)I",
1828 (void *)android_media_AudioSystem_createAudioPatch},
1829 {"releaseAudioPatch", "(Landroid/media/AudioPatch;)I",
1830 (void *)android_media_AudioSystem_releaseAudioPatch},
1831 {"listAudioPatches", "(Ljava/util/ArrayList;[I)I",
1832 (void *)android_media_AudioSystem_listAudioPatches},
Eric Laurent3a241992014-05-19 19:33:26 -07001833 {"setAudioPortConfig", "(Landroid/media/AudioPortConfig;)I",
1834 (void *)android_media_AudioSystem_setAudioPortConfig},
Eric Laurentb634e1b2014-08-01 14:44:46 -07001835 {"getAudioHwSyncForSession", "(I)I",
1836 (void *)android_media_AudioSystem_getAudioHwSyncForSession},
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001837 {"registerPolicyMixes", "(Ljava/util/ArrayList;Z)I",
1838 (void *)android_media_AudioSystem_registerPolicyMixes},
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001839 {"native_register_dynamic_policy_callback", "()V",
1840 (void *)android_media_AudioSystem_registerDynPolicyCallback},
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08001841 {"native_register_recording_callback", "()V",
1842 (void *)android_media_AudioSystem_registerRecordingCallback},
Eric Laurent0867bed2015-05-20 14:49:08 -07001843 {"systemReady", "()I", (void *)android_media_AudioSystem_systemReady},
Eric Laurenteab40d12017-06-09 12:45:21 -07001844 {"getStreamVolumeDB", "(III)F", (void *)android_media_AudioSystem_getStreamVolumeDB},
Jean-Michel Trivi980d38f2018-01-08 15:43:35 -08001845 {"native_is_offload_supported", "(IIII)Z", (void *)android_media_AudioSystem_isOffloadSupported},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001846};
1847
Eric Laurentb69681c2014-05-19 19:02:51 -07001848
Daniel Micay76f6a862015-09-19 17:31:01 -04001849static const JNINativeMethod gEventHandlerMethods[] = {
Eric Laurent700e7342014-05-02 18:33:15 -07001850 {"native_setup",
1851 "(Ljava/lang/Object;)V",
1852 (void *)android_media_AudioSystem_eventHandlerSetup},
1853 {"native_finalize",
1854 "()V",
1855 (void *)android_media_AudioSystem_eventHandlerFinalize},
1856};
1857
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001858int register_android_media_AudioSystem(JNIEnv *env)
1859{
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001860 jclass arrayListClass = FindClassOrDie(env, "java/util/ArrayList");
1861 gArrayListClass = MakeGlobalRefOrDie(env, arrayListClass);
1862 gArrayListMethods.add = GetMethodIDOrDie(env, arrayListClass, "add", "(Ljava/lang/Object;)Z");
Eric Laurent09378972014-12-10 10:42:08 -08001863 gArrayListMethods.toArray = GetMethodIDOrDie(env, arrayListClass, "toArray", "()[Ljava/lang/Object;");
Eric Laurentb69681c2014-05-19 19:02:51 -07001864
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001865 jclass audioHandleClass = FindClassOrDie(env, "android/media/AudioHandle");
1866 gAudioHandleClass = MakeGlobalRefOrDie(env, audioHandleClass);
1867 gAudioHandleCstor = GetMethodIDOrDie(env, audioHandleClass, "<init>", "(I)V");
1868 gAudioHandleFields.mId = GetFieldIDOrDie(env, audioHandleClass, "mId", "I");
Eric Laurentb69681c2014-05-19 19:02:51 -07001869
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001870 jclass audioPortClass = FindClassOrDie(env, "android/media/AudioPort");
1871 gAudioPortClass = MakeGlobalRefOrDie(env, audioPortClass);
1872 gAudioPortCstor = GetMethodIDOrDie(env, audioPortClass, "<init>",
Paul McLeanf29e5f32015-06-15 10:19:22 -07001873 "(Landroid/media/AudioHandle;ILjava/lang/String;[I[I[I[I[Landroid/media/AudioGain;)V");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001874 gAudioPortFields.mHandle = GetFieldIDOrDie(env, audioPortClass, "mHandle",
Eric Laurentb69681c2014-05-19 19:02:51 -07001875 "Landroid/media/AudioHandle;");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001876 gAudioPortFields.mRole = GetFieldIDOrDie(env, audioPortClass, "mRole", "I");
1877 gAudioPortFields.mGains = GetFieldIDOrDie(env, audioPortClass, "mGains",
Eric Laurentb69681c2014-05-19 19:02:51 -07001878 "[Landroid/media/AudioGain;");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001879 gAudioPortFields.mActiveConfig = GetFieldIDOrDie(env, audioPortClass, "mActiveConfig",
1880 "Landroid/media/AudioPortConfig;");
Eric Laurentb69681c2014-05-19 19:02:51 -07001881
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001882 jclass audioPortConfigClass = FindClassOrDie(env, "android/media/AudioPortConfig");
1883 gAudioPortConfigClass = MakeGlobalRefOrDie(env, audioPortConfigClass);
1884 gAudioPortConfigCstor = GetMethodIDOrDie(env, audioPortConfigClass, "<init>",
1885 "(Landroid/media/AudioPort;IIILandroid/media/AudioGainConfig;)V");
1886 gAudioPortConfigFields.mPort = GetFieldIDOrDie(env, audioPortConfigClass, "mPort",
Eric Laurentb69681c2014-05-19 19:02:51 -07001887 "Landroid/media/AudioPort;");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001888 gAudioPortConfigFields.mSamplingRate = GetFieldIDOrDie(env, audioPortConfigClass,
Eric Laurentb69681c2014-05-19 19:02:51 -07001889 "mSamplingRate", "I");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001890 gAudioPortConfigFields.mChannelMask = GetFieldIDOrDie(env, audioPortConfigClass,
Eric Laurentb69681c2014-05-19 19:02:51 -07001891 "mChannelMask", "I");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001892 gAudioPortConfigFields.mFormat = GetFieldIDOrDie(env, audioPortConfigClass, "mFormat", "I");
1893 gAudioPortConfigFields.mGain = GetFieldIDOrDie(env, audioPortConfigClass, "mGain",
Eric Laurentb69681c2014-05-19 19:02:51 -07001894 "Landroid/media/AudioGainConfig;");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001895 gAudioPortConfigFields.mConfigMask = GetFieldIDOrDie(env, audioPortConfigClass, "mConfigMask",
1896 "I");
Eric Laurentb69681c2014-05-19 19:02:51 -07001897
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001898 jclass audioDevicePortConfigClass = FindClassOrDie(env, "android/media/AudioDevicePortConfig");
1899 gAudioDevicePortConfigClass = MakeGlobalRefOrDie(env, audioDevicePortConfigClass);
1900 gAudioDevicePortConfigCstor = GetMethodIDOrDie(env, audioDevicePortConfigClass, "<init>",
1901 "(Landroid/media/AudioDevicePort;IIILandroid/media/AudioGainConfig;)V");
Eric Laurentb69681c2014-05-19 19:02:51 -07001902
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001903 jclass audioMixPortConfigClass = FindClassOrDie(env, "android/media/AudioMixPortConfig");
1904 gAudioMixPortConfigClass = MakeGlobalRefOrDie(env, audioMixPortConfigClass);
1905 gAudioMixPortConfigCstor = GetMethodIDOrDie(env, audioMixPortConfigClass, "<init>",
1906 "(Landroid/media/AudioMixPort;IIILandroid/media/AudioGainConfig;)V");
Eric Laurentb69681c2014-05-19 19:02:51 -07001907
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001908 jclass audioDevicePortClass = FindClassOrDie(env, "android/media/AudioDevicePort");
1909 gAudioDevicePortClass = MakeGlobalRefOrDie(env, audioDevicePortClass);
1910 gAudioDevicePortCstor = GetMethodIDOrDie(env, audioDevicePortClass, "<init>",
Paul McLeanf29e5f32015-06-15 10:19:22 -07001911 "(Landroid/media/AudioHandle;Ljava/lang/String;[I[I[I[I[Landroid/media/AudioGain;ILjava/lang/String;)V");
Eric Laurentb69681c2014-05-19 19:02:51 -07001912
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001913 jclass audioMixPortClass = FindClassOrDie(env, "android/media/AudioMixPort");
1914 gAudioMixPortClass = MakeGlobalRefOrDie(env, audioMixPortClass);
1915 gAudioMixPortCstor = GetMethodIDOrDie(env, audioMixPortClass, "<init>",
Paul McLeanf29e5f32015-06-15 10:19:22 -07001916 "(Landroid/media/AudioHandle;IILjava/lang/String;[I[I[I[I[Landroid/media/AudioGain;)V");
Eric Laurentb69681c2014-05-19 19:02:51 -07001917
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001918 jclass audioGainClass = FindClassOrDie(env, "android/media/AudioGain");
1919 gAudioGainClass = MakeGlobalRefOrDie(env, audioGainClass);
1920 gAudioGainCstor = GetMethodIDOrDie(env, audioGainClass, "<init>", "(IIIIIIIII)V");
Eric Laurentb69681c2014-05-19 19:02:51 -07001921
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001922 jclass audioGainConfigClass = FindClassOrDie(env, "android/media/AudioGainConfig");
1923 gAudioGainConfigClass = MakeGlobalRefOrDie(env, audioGainConfigClass);
1924 gAudioGainConfigCstor = GetMethodIDOrDie(env, audioGainConfigClass, "<init>",
Eric Laurentb69681c2014-05-19 19:02:51 -07001925 "(ILandroid/media/AudioGain;II[II)V");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001926 gAudioGainConfigFields.mIndex = GetFieldIDOrDie(env, gAudioGainConfigClass, "mIndex", "I");
1927 gAudioGainConfigFields.mMode = GetFieldIDOrDie(env, audioGainConfigClass, "mMode", "I");
1928 gAudioGainConfigFields.mChannelMask = GetFieldIDOrDie(env, audioGainConfigClass, "mChannelMask",
Eric Laurentb69681c2014-05-19 19:02:51 -07001929 "I");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001930 gAudioGainConfigFields.mValues = GetFieldIDOrDie(env, audioGainConfigClass, "mValues", "[I");
1931 gAudioGainConfigFields.mRampDurationMs = GetFieldIDOrDie(env, audioGainConfigClass,
Eric Laurentb69681c2014-05-19 19:02:51 -07001932 "mRampDurationMs", "I");
1933
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001934 jclass audioPatchClass = FindClassOrDie(env, "android/media/AudioPatch");
1935 gAudioPatchClass = MakeGlobalRefOrDie(env, audioPatchClass);
1936 gAudioPatchCstor = GetMethodIDOrDie(env, audioPatchClass, "<init>",
Eric Laurentb69681c2014-05-19 19:02:51 -07001937"(Landroid/media/AudioHandle;[Landroid/media/AudioPortConfig;[Landroid/media/AudioPortConfig;)V");
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001938 gAudioPatchFields.mHandle = GetFieldIDOrDie(env, audioPatchClass, "mHandle",
Eric Laurentb69681c2014-05-19 19:02:51 -07001939 "Landroid/media/AudioHandle;");
1940
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001941 jclass eventHandlerClass = FindClassOrDie(env, kEventHandlerClassPathName);
Eric Laurent2615afb2015-03-25 14:51:08 -07001942 gAudioPortEventHandlerMethods.postEventFromNative = GetStaticMethodIDOrDie(
1943 env, eventHandlerClass, "postEventFromNative",
1944 "(Ljava/lang/Object;IIILjava/lang/Object;)V");
1945 gEventHandlerFields.mJniCallback = GetFieldIDOrDie(env,
1946 eventHandlerClass, "mJniCallback", "J");
Eric Laurent700e7342014-05-02 18:33:15 -07001947
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08001948 gAudioPolicyEventHandlerMethods.postDynPolicyEventFromNative =
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001949 GetStaticMethodIDOrDie(env, env->FindClass(kClassPathName),
1950 "dynamicPolicyCallbackFromNative", "(ILjava/lang/String;I)V");
Jean-Michel Trivid3c71f02015-12-07 11:59:31 -08001951 gAudioPolicyEventHandlerMethods.postRecordConfigEventFromNative =
1952 GetStaticMethodIDOrDie(env, env->FindClass(kClassPathName),
Jean-Michel Trivi66ffacf2017-02-04 17:25:31 -08001953 "recordingCallbackFromNative", "(IIII[I)V");
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001954
Eric Laurent09378972014-12-10 10:42:08 -08001955 jclass audioMixClass = FindClassOrDie(env, "android/media/audiopolicy/AudioMix");
1956 gAudioMixClass = MakeGlobalRefOrDie(env, audioMixClass);
1957 gAudioMixFields.mRule = GetFieldIDOrDie(env, audioMixClass, "mRule",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001958 "Landroid/media/audiopolicy/AudioMixingRule;");
Eric Laurent09378972014-12-10 10:42:08 -08001959 gAudioMixFields.mFormat = GetFieldIDOrDie(env, audioMixClass, "mFormat",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001960 "Landroid/media/AudioFormat;");
Eric Laurent09378972014-12-10 10:42:08 -08001961 gAudioMixFields.mRouteFlags = GetFieldIDOrDie(env, audioMixClass, "mRouteFlags", "I");
Jean-Michel Trivi4ad39882016-03-14 18:46:41 -07001962 gAudioMixFields.mDeviceType = GetFieldIDOrDie(env, audioMixClass, "mDeviceSystemType", "I");
1963 gAudioMixFields.mDeviceAddress = GetFieldIDOrDie(env, audioMixClass, "mDeviceAddress",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001964 "Ljava/lang/String;");
Eric Laurent09378972014-12-10 10:42:08 -08001965 gAudioMixFields.mMixType = GetFieldIDOrDie(env, audioMixClass, "mMixType", "I");
Jean-Michel Trivi5a561092015-04-23 18:48:08 -07001966 gAudioMixFields.mCallbackFlags = GetFieldIDOrDie(env, audioMixClass, "mCallbackFlags", "I");
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001967
Eric Laurent09378972014-12-10 10:42:08 -08001968 jclass audioFormatClass = FindClassOrDie(env, "android/media/AudioFormat");
1969 gAudioFormatClass = MakeGlobalRefOrDie(env, audioFormatClass);
1970 gAudioFormatFields.mEncoding = GetFieldIDOrDie(env, audioFormatClass, "mEncoding", "I");
1971 gAudioFormatFields.mSampleRate = GetFieldIDOrDie(env, audioFormatClass, "mSampleRate", "I");
1972 gAudioFormatFields.mChannelMask = GetFieldIDOrDie(env, audioFormatClass, "mChannelMask", "I");
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001973
Eric Laurent09378972014-12-10 10:42:08 -08001974 jclass audioMixingRuleClass = FindClassOrDie(env, "android/media/audiopolicy/AudioMixingRule");
1975 gAudioMixingRuleClass = MakeGlobalRefOrDie(env, audioMixingRuleClass);
1976 gAudioMixingRuleFields.mCriteria = GetFieldIDOrDie(env, audioMixingRuleClass, "mCriteria",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001977 "Ljava/util/ArrayList;");
1978
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -08001979 jclass audioMixMatchCriterionClass =
1980 FindClassOrDie(env, "android/media/audiopolicy/AudioMixingRule$AudioMixMatchCriterion");
1981 gAudioMixMatchCriterionClass = MakeGlobalRefOrDie(env,audioMixMatchCriterionClass);
1982 gAudioMixMatchCriterionFields.mAttr = GetFieldIDOrDie(env, audioMixMatchCriterionClass, "mAttr",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001983 "Landroid/media/AudioAttributes;");
Jean-Michel Triviba6b4b42016-02-10 14:26:35 -08001984 gAudioMixMatchCriterionFields.mIntProp = GetFieldIDOrDie(env, audioMixMatchCriterionClass, "mIntProp",
1985 "I");
1986 gAudioMixMatchCriterionFields.mRule = GetFieldIDOrDie(env, audioMixMatchCriterionClass, "mRule",
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001987 "I");
1988
Eric Laurent09378972014-12-10 10:42:08 -08001989 jclass audioAttributesClass = FindClassOrDie(env, "android/media/AudioAttributes");
1990 gAudioAttributesClass = MakeGlobalRefOrDie(env, audioAttributesClass);
1991 gAudioAttributesFields.mUsage = GetFieldIDOrDie(env, audioAttributesClass, "mUsage", "I");
1992 gAudioAttributesFields.mSource = GetFieldIDOrDie(env, audioAttributesClass, "mSource", "I");
Eric Laurent7f5eb9f2014-12-01 19:36:30 -08001993
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001994 AudioSystem::setErrorCallback(android_media_AudioSystem_error_callback);
Glenn Kasten18db49a2012-03-12 16:29:55 -07001995
Andreas Gampeed6b9df2014-11-20 22:02:20 -08001996 RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
1997 return RegisterMethodsOrDie(env, kEventHandlerClassPathName, gEventHandlerMethods,
1998 NELEM(gEventHandlerMethods));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001999}