• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 **
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 
18 //#define LOG_NDEBUG 0
19 
20 #define LOG_TAG "AudioSystem-JNI"
21 #include <utils/Log.h>
22 
23 #include <jni.h>
24 #include <JNIHelp.h>
25 #include <android_runtime/AndroidRuntime.h>
26 
27 #include <media/AudioSystem.h>
28 #include <media/AudioPolicy.h>
29 
30 #include <system/audio.h>
31 #include <system/audio_policy.h>
32 #include "android_media_AudioFormat.h"
33 #include "android_media_AudioErrors.h"
34 
35 // ----------------------------------------------------------------------------
36 
37 using namespace android;
38 
39 static const char* const kClassPathName = "android/media/AudioSystem";
40 
41 static jclass gArrayListClass;
42 static struct {
43     jmethodID    add;
44     jmethodID    toArray;
45 } gArrayListMethods;
46 
47 static jclass gAudioHandleClass;
48 static jmethodID gAudioHandleCstor;
49 static struct {
50     jfieldID    mId;
51 } gAudioHandleFields;
52 
53 static jclass gAudioPortClass;
54 static jmethodID gAudioPortCstor;
55 static struct {
56     jfieldID    mHandle;
57     jfieldID    mRole;
58     jfieldID    mGains;
59     jfieldID    mActiveConfig;
60     // other fields unused by JNI
61 } gAudioPortFields;
62 
63 static jclass gAudioPortConfigClass;
64 static jmethodID gAudioPortConfigCstor;
65 static struct {
66     jfieldID    mPort;
67     jfieldID    mSamplingRate;
68     jfieldID    mChannelMask;
69     jfieldID    mFormat;
70     jfieldID    mGain;
71     jfieldID    mConfigMask;
72 } gAudioPortConfigFields;
73 
74 static jclass gAudioDevicePortClass;
75 static jmethodID gAudioDevicePortCstor;
76 
77 static jclass gAudioDevicePortConfigClass;
78 static jmethodID gAudioDevicePortConfigCstor;
79 
80 static jclass gAudioMixPortClass;
81 static jmethodID gAudioMixPortCstor;
82 
83 static jclass gAudioMixPortConfigClass;
84 static jmethodID gAudioMixPortConfigCstor;
85 
86 static jclass gAudioGainClass;
87 static jmethodID gAudioGainCstor;
88 
89 static jclass gAudioGainConfigClass;
90 static jmethodID gAudioGainConfigCstor;
91 static struct {
92     jfieldID mIndex;
93     jfieldID mMode;
94     jfieldID mChannelMask;
95     jfieldID mValues;
96     jfieldID mRampDurationMs;
97     // other fields unused by JNI
98 } gAudioGainConfigFields;
99 
100 static jclass gAudioPatchClass;
101 static jmethodID gAudioPatchCstor;
102 static struct {
103     jfieldID    mHandle;
104     // other fields unused by JNI
105 } gAudioPatchFields;
106 
107 static jclass gAudioMixClass;
108 static struct {
109     jfieldID    mRule;
110     jfieldID    mFormat;
111     jfieldID    mRouteFlags;
112     jfieldID    mRegistrationId;
113     jfieldID    mMixType;
114 } gAudioMixFields;
115 
116 static jclass gAudioFormatClass;
117 static struct {
118     jfieldID    mEncoding;
119     jfieldID    mSampleRate;
120     jfieldID    mChannelMask;
121     // other fields unused by JNI
122 } gAudioFormatFields;
123 
124 static jclass gAudioMixingRuleClass;
125 static struct {
126     jfieldID    mCriteria;
127     // other fields unused by JNI
128 } gAudioMixingRuleFields;
129 
130 static jclass gAttributeMatchCriterionClass;
131 static struct {
132     jfieldID    mAttr;
133     jfieldID    mRule;
134 } gAttributeMatchCriterionFields;
135 
136 static jclass gAudioAttributesClass;
137 static struct {
138     jfieldID    mUsage;
139     jfieldID    mSource;
140 } gAudioAttributesFields;
141 
142 
143 static const char* const kEventHandlerClassPathName =
144         "android/media/AudioPortEventHandler";
145 static jmethodID gPostEventFromNative;
146 
147 enum AudioError {
148     kAudioStatusOk = 0,
149     kAudioStatusError = 1,
150     kAudioStatusMediaServerDied = 100
151 };
152 
153 enum  {
154     AUDIOPORT_EVENT_PORT_LIST_UPDATED = 1,
155     AUDIOPORT_EVENT_PATCH_LIST_UPDATED = 2,
156     AUDIOPORT_EVENT_SERVICE_DIED = 3,
157 };
158 
159 #define MAX_PORT_GENERATION_SYNC_ATTEMPTS 5
160 
161 // ----------------------------------------------------------------------------
162 // ref-counted object for callbacks
163 class JNIAudioPortCallback: public AudioSystem::AudioPortCallback
164 {
165 public:
166     JNIAudioPortCallback(JNIEnv* env, jobject thiz, jobject weak_thiz);
167     ~JNIAudioPortCallback();
168 
169     virtual void onAudioPortListUpdate();
170     virtual void onAudioPatchListUpdate();
171     virtual void onServiceDied();
172 
173 private:
174     void sendEvent(int event);
175 
176     jclass      mClass;     // Reference to AudioPortEventHandlerDelegate class
177     jobject     mObject;    // Weak ref to AudioPortEventHandlerDelegate Java object to call on
178 };
179 
JNIAudioPortCallback(JNIEnv * env,jobject thiz,jobject weak_thiz)180 JNIAudioPortCallback::JNIAudioPortCallback(JNIEnv* env, jobject thiz, jobject weak_thiz)
181 {
182 
183     // Hold onto the SoundTriggerModule class for use in calling the static method
184     // that posts events to the application thread.
185     jclass clazz = env->GetObjectClass(thiz);
186     if (clazz == NULL) {
187         ALOGE("Can't find class %s", kEventHandlerClassPathName);
188         return;
189     }
190     mClass = (jclass)env->NewGlobalRef(clazz);
191 
192     // We use a weak reference so the SoundTriggerModule object can be garbage collected.
193     // The reference is only used as a proxy for callbacks.
194     mObject  = env->NewGlobalRef(weak_thiz);
195 }
196 
~JNIAudioPortCallback()197 JNIAudioPortCallback::~JNIAudioPortCallback()
198 {
199     // remove global references
200     JNIEnv *env = AndroidRuntime::getJNIEnv();
201     if (env == NULL) {
202         return;
203     }
204     env->DeleteGlobalRef(mObject);
205     env->DeleteGlobalRef(mClass);
206 }
207 
sendEvent(int event)208 void JNIAudioPortCallback::sendEvent(int event)
209 {
210     JNIEnv *env = AndroidRuntime::getJNIEnv();
211     if (env == NULL) {
212         return;
213     }
214     env->CallStaticVoidMethod(mClass, gPostEventFromNative, mObject,
215                               event, 0, 0, NULL);
216     if (env->ExceptionCheck()) {
217         ALOGW("An exception occurred while notifying an event.");
218         env->ExceptionClear();
219     }
220 }
221 
onAudioPortListUpdate()222 void JNIAudioPortCallback::onAudioPortListUpdate()
223 {
224     sendEvent(AUDIOPORT_EVENT_PORT_LIST_UPDATED);
225 }
226 
onAudioPatchListUpdate()227 void JNIAudioPortCallback::onAudioPatchListUpdate()
228 {
229     sendEvent(AUDIOPORT_EVENT_PATCH_LIST_UPDATED);
230 }
231 
onServiceDied()232 void JNIAudioPortCallback::onServiceDied()
233 {
234     sendEvent(AUDIOPORT_EVENT_SERVICE_DIED);
235 }
236 
check_AudioSystem_Command(status_t status)237 static int check_AudioSystem_Command(status_t status)
238 {
239     switch (status) {
240     case DEAD_OBJECT:
241         return kAudioStatusMediaServerDied;
242     case NO_ERROR:
243         return kAudioStatusOk;
244     default:
245         break;
246     }
247     return kAudioStatusError;
248 }
249 
250 static jint
android_media_AudioSystem_muteMicrophone(JNIEnv * env,jobject thiz,jboolean on)251 android_media_AudioSystem_muteMicrophone(JNIEnv *env, jobject thiz, jboolean on)
252 {
253     return (jint) check_AudioSystem_Command(AudioSystem::muteMicrophone(on));
254 }
255 
256 static jboolean
android_media_AudioSystem_isMicrophoneMuted(JNIEnv * env,jobject thiz)257 android_media_AudioSystem_isMicrophoneMuted(JNIEnv *env, jobject thiz)
258 {
259     bool state = false;
260     AudioSystem::isMicrophoneMuted(&state);
261     return state;
262 }
263 
264 static jboolean
android_media_AudioSystem_isStreamActive(JNIEnv * env,jobject thiz,jint stream,jint inPastMs)265 android_media_AudioSystem_isStreamActive(JNIEnv *env, jobject thiz, jint stream, jint inPastMs)
266 {
267     bool state = false;
268     AudioSystem::isStreamActive((audio_stream_type_t) stream, &state, inPastMs);
269     return state;
270 }
271 
272 static jboolean
android_media_AudioSystem_isStreamActiveRemotely(JNIEnv * env,jobject thiz,jint stream,jint inPastMs)273 android_media_AudioSystem_isStreamActiveRemotely(JNIEnv *env, jobject thiz, jint stream,
274         jint inPastMs)
275 {
276     bool state = false;
277     AudioSystem::isStreamActiveRemotely((audio_stream_type_t) stream, &state, inPastMs);
278     return state;
279 }
280 
281 static jboolean
android_media_AudioSystem_isSourceActive(JNIEnv * env,jobject thiz,jint source)282 android_media_AudioSystem_isSourceActive(JNIEnv *env, jobject thiz, jint source)
283 {
284     bool state = false;
285     AudioSystem::isSourceActive((audio_source_t) source, &state);
286     return state;
287 }
288 
289 static jint
android_media_AudioSystem_newAudioSessionId(JNIEnv * env,jobject thiz)290 android_media_AudioSystem_newAudioSessionId(JNIEnv *env, jobject thiz)
291 {
292     return AudioSystem::newAudioUniqueId();
293 }
294 
295 static jint
android_media_AudioSystem_setParameters(JNIEnv * env,jobject thiz,jstring keyValuePairs)296 android_media_AudioSystem_setParameters(JNIEnv *env, jobject thiz, jstring keyValuePairs)
297 {
298     const jchar* c_keyValuePairs = env->GetStringCritical(keyValuePairs, 0);
299     String8 c_keyValuePairs8;
300     if (keyValuePairs) {
301         c_keyValuePairs8 = String8(c_keyValuePairs, env->GetStringLength(keyValuePairs));
302         env->ReleaseStringCritical(keyValuePairs, c_keyValuePairs);
303     }
304     int status = check_AudioSystem_Command(AudioSystem::setParameters(c_keyValuePairs8));
305     return (jint) status;
306 }
307 
308 static jstring
android_media_AudioSystem_getParameters(JNIEnv * env,jobject thiz,jstring keys)309 android_media_AudioSystem_getParameters(JNIEnv *env, jobject thiz, jstring keys)
310 {
311     const jchar* c_keys = env->GetStringCritical(keys, 0);
312     String8 c_keys8;
313     if (keys) {
314         c_keys8 = String8(c_keys, env->GetStringLength(keys));
315         env->ReleaseStringCritical(keys, c_keys);
316     }
317     return env->NewStringUTF(AudioSystem::getParameters(c_keys8).string());
318 }
319 
320 static void
android_media_AudioSystem_error_callback(status_t err)321 android_media_AudioSystem_error_callback(status_t err)
322 {
323     JNIEnv *env = AndroidRuntime::getJNIEnv();
324     if (env == NULL) {
325         return;
326     }
327 
328     jclass clazz = env->FindClass(kClassPathName);
329 
330     env->CallStaticVoidMethod(clazz, env->GetStaticMethodID(clazz,
331                               "errorCallbackFromNative","(I)V"),
332                               check_AudioSystem_Command(err));
333 
334     env->DeleteLocalRef(clazz);
335 }
336 
337 static jint
android_media_AudioSystem_setDeviceConnectionState(JNIEnv * env,jobject thiz,jint device,jint state,jstring device_address)338 android_media_AudioSystem_setDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jint state, jstring device_address)
339 {
340     const char *c_address = env->GetStringUTFChars(device_address, NULL);
341     int status = check_AudioSystem_Command(AudioSystem::setDeviceConnectionState(static_cast <audio_devices_t>(device),
342                                           static_cast <audio_policy_dev_state_t>(state),
343                                           c_address));
344     env->ReleaseStringUTFChars(device_address, c_address);
345     return (jint) status;
346 }
347 
348 static jint
android_media_AudioSystem_getDeviceConnectionState(JNIEnv * env,jobject thiz,jint device,jstring device_address)349 android_media_AudioSystem_getDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jstring device_address)
350 {
351     const char *c_address = env->GetStringUTFChars(device_address, NULL);
352     int state = static_cast <int>(AudioSystem::getDeviceConnectionState(static_cast <audio_devices_t>(device),
353                                           c_address));
354     env->ReleaseStringUTFChars(device_address, c_address);
355     return (jint) state;
356 }
357 
358 static jint
android_media_AudioSystem_setPhoneState(JNIEnv * env,jobject thiz,jint state)359 android_media_AudioSystem_setPhoneState(JNIEnv *env, jobject thiz, jint state)
360 {
361     return (jint) check_AudioSystem_Command(AudioSystem::setPhoneState((audio_mode_t) state));
362 }
363 
364 static jint
android_media_AudioSystem_setForceUse(JNIEnv * env,jobject thiz,jint usage,jint config)365 android_media_AudioSystem_setForceUse(JNIEnv *env, jobject thiz, jint usage, jint config)
366 {
367     return (jint) check_AudioSystem_Command(AudioSystem::setForceUse(static_cast <audio_policy_force_use_t>(usage),
368                                                            static_cast <audio_policy_forced_cfg_t>(config)));
369 }
370 
371 static jint
android_media_AudioSystem_getForceUse(JNIEnv * env,jobject thiz,jint usage)372 android_media_AudioSystem_getForceUse(JNIEnv *env, jobject thiz, jint usage)
373 {
374     return static_cast <jint>(AudioSystem::getForceUse(static_cast <audio_policy_force_use_t>(usage)));
375 }
376 
377 static jint
android_media_AudioSystem_initStreamVolume(JNIEnv * env,jobject thiz,jint stream,jint indexMin,jint indexMax)378 android_media_AudioSystem_initStreamVolume(JNIEnv *env, jobject thiz, jint stream, jint indexMin, jint indexMax)
379 {
380     return (jint) check_AudioSystem_Command(AudioSystem::initStreamVolume(static_cast <audio_stream_type_t>(stream),
381                                                                    indexMin,
382                                                                    indexMax));
383 }
384 
385 static jint
android_media_AudioSystem_setStreamVolumeIndex(JNIEnv * env,jobject thiz,jint stream,jint index,jint device)386 android_media_AudioSystem_setStreamVolumeIndex(JNIEnv *env,
387                                                jobject thiz,
388                                                jint stream,
389                                                jint index,
390                                                jint device)
391 {
392     return (jint) check_AudioSystem_Command(
393             AudioSystem::setStreamVolumeIndex(static_cast <audio_stream_type_t>(stream),
394                                               index,
395                                               (audio_devices_t)device));
396 }
397 
398 static jint
android_media_AudioSystem_getStreamVolumeIndex(JNIEnv * env,jobject thiz,jint stream,jint device)399 android_media_AudioSystem_getStreamVolumeIndex(JNIEnv *env,
400                                                jobject thiz,
401                                                jint stream,
402                                                jint device)
403 {
404     int index;
405     if (AudioSystem::getStreamVolumeIndex(static_cast <audio_stream_type_t>(stream),
406                                           &index,
407                                           (audio_devices_t)device)
408             != NO_ERROR) {
409         index = -1;
410     }
411     return (jint) index;
412 }
413 
414 static jint
android_media_AudioSystem_setMasterVolume(JNIEnv * env,jobject thiz,jfloat value)415 android_media_AudioSystem_setMasterVolume(JNIEnv *env, jobject thiz, jfloat value)
416 {
417     return (jint) check_AudioSystem_Command(AudioSystem::setMasterVolume(value));
418 }
419 
420 static jfloat
android_media_AudioSystem_getMasterVolume(JNIEnv * env,jobject thiz)421 android_media_AudioSystem_getMasterVolume(JNIEnv *env, jobject thiz)
422 {
423     float value;
424     if (AudioSystem::getMasterVolume(&value) != NO_ERROR) {
425         value = -1.0;
426     }
427     return value;
428 }
429 
430 static jint
android_media_AudioSystem_setMasterMute(JNIEnv * env,jobject thiz,jboolean mute)431 android_media_AudioSystem_setMasterMute(JNIEnv *env, jobject thiz, jboolean mute)
432 {
433     return (jint) check_AudioSystem_Command(AudioSystem::setMasterMute(mute));
434 }
435 
436 static jboolean
android_media_AudioSystem_getMasterMute(JNIEnv * env,jobject thiz)437 android_media_AudioSystem_getMasterMute(JNIEnv *env, jobject thiz)
438 {
439     bool mute;
440     if (AudioSystem::getMasterMute(&mute) != NO_ERROR) {
441         mute = false;
442     }
443     return mute;
444 }
445 
446 static jint
android_media_AudioSystem_getDevicesForStream(JNIEnv * env,jobject thiz,jint stream)447 android_media_AudioSystem_getDevicesForStream(JNIEnv *env, jobject thiz, jint stream)
448 {
449     return (jint) AudioSystem::getDevicesForStream(static_cast <audio_stream_type_t>(stream));
450 }
451 
452 static jint
android_media_AudioSystem_getPrimaryOutputSamplingRate(JNIEnv * env,jobject clazz)453 android_media_AudioSystem_getPrimaryOutputSamplingRate(JNIEnv *env, jobject clazz)
454 {
455     return (jint) AudioSystem::getPrimaryOutputSamplingRate();
456 }
457 
458 static jint
android_media_AudioSystem_getPrimaryOutputFrameCount(JNIEnv * env,jobject clazz)459 android_media_AudioSystem_getPrimaryOutputFrameCount(JNIEnv *env, jobject clazz)
460 {
461     return (jint) AudioSystem::getPrimaryOutputFrameCount();
462 }
463 
464 static jint
android_media_AudioSystem_getOutputLatency(JNIEnv * env,jobject clazz,jint stream)465 android_media_AudioSystem_getOutputLatency(JNIEnv *env, jobject clazz, jint stream)
466 {
467     uint32_t afLatency;
468     if (AudioSystem::getOutputLatency(&afLatency, static_cast <audio_stream_type_t>(stream))
469             != NO_ERROR) {
470         afLatency = -1;
471     }
472     return (jint) afLatency;
473 }
474 
475 static jint
android_media_AudioSystem_setLowRamDevice(JNIEnv * env,jobject clazz,jboolean isLowRamDevice)476 android_media_AudioSystem_setLowRamDevice(JNIEnv *env, jobject clazz, jboolean isLowRamDevice)
477 {
478     return (jint) AudioSystem::setLowRamDevice((bool) isLowRamDevice);
479 }
480 
481 static jint
android_media_AudioSystem_checkAudioFlinger(JNIEnv * env,jobject clazz)482 android_media_AudioSystem_checkAudioFlinger(JNIEnv *env, jobject clazz)
483 {
484     return (jint) check_AudioSystem_Command(AudioSystem::checkAudioFlinger());
485 }
486 
487 
useInChannelMask(audio_port_type_t type,audio_port_role_t role)488 static bool useInChannelMask(audio_port_type_t type, audio_port_role_t role)
489 {
490     return ((type == AUDIO_PORT_TYPE_DEVICE) && (role == AUDIO_PORT_ROLE_SOURCE)) ||
491                 ((type == AUDIO_PORT_TYPE_MIX) && (role == AUDIO_PORT_ROLE_SINK));
492 }
493 
convertAudioGainConfigToNative(JNIEnv * env,struct audio_gain_config * nAudioGainConfig,const jobject jAudioGainConfig,bool useInMask)494 static void convertAudioGainConfigToNative(JNIEnv *env,
495                                                struct audio_gain_config *nAudioGainConfig,
496                                                const jobject jAudioGainConfig,
497                                                bool useInMask)
498 {
499     nAudioGainConfig->index = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mIndex);
500     nAudioGainConfig->mode = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mMode);
501     ALOGV("convertAudioGainConfigToNative got gain index %d", nAudioGainConfig->index);
502     jint jMask = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mChannelMask);
503     audio_channel_mask_t nMask;
504     if (useInMask) {
505         nMask = inChannelMaskToNative(jMask);
506         ALOGV("convertAudioGainConfigToNative IN mask java %x native %x", jMask, nMask);
507     } else {
508         nMask = outChannelMaskToNative(jMask);
509         ALOGV("convertAudioGainConfigToNative OUT mask java %x native %x", jMask, nMask);
510     }
511     nAudioGainConfig->channel_mask = nMask;
512     nAudioGainConfig->ramp_duration_ms = env->GetIntField(jAudioGainConfig,
513                                                        gAudioGainConfigFields.mRampDurationMs);
514     jintArray jValues = (jintArray)env->GetObjectField(jAudioGainConfig,
515                                                        gAudioGainConfigFields.mValues);
516     int *nValues = env->GetIntArrayElements(jValues, NULL);
517     size_t size = env->GetArrayLength(jValues);
518     memcpy(nAudioGainConfig->values, nValues, size * sizeof(int));
519     env->DeleteLocalRef(jValues);
520 }
521 
522 
convertAudioPortConfigToNative(JNIEnv * env,struct audio_port_config * nAudioPortConfig,const jobject jAudioPortConfig,bool useConfigMask)523 static jint convertAudioPortConfigToNative(JNIEnv *env,
524                                                struct audio_port_config *nAudioPortConfig,
525                                                const jobject jAudioPortConfig,
526                                                bool useConfigMask)
527 {
528     jobject jAudioPort = env->GetObjectField(jAudioPortConfig, gAudioPortConfigFields.mPort);
529     jobject jHandle = env->GetObjectField(jAudioPort, gAudioPortFields.mHandle);
530     nAudioPortConfig->id = env->GetIntField(jHandle, gAudioHandleFields.mId);
531     nAudioPortConfig->role = (audio_port_role_t)env->GetIntField(jAudioPort,
532                                                                  gAudioPortFields.mRole);
533     if (env->IsInstanceOf(jAudioPort, gAudioDevicePortClass)) {
534         nAudioPortConfig->type = AUDIO_PORT_TYPE_DEVICE;
535     } else if (env->IsInstanceOf(jAudioPort, gAudioMixPortClass)) {
536         nAudioPortConfig->type = AUDIO_PORT_TYPE_MIX;
537     } else {
538         env->DeleteLocalRef(jAudioPort);
539         env->DeleteLocalRef(jHandle);
540         return (jint)AUDIO_JAVA_ERROR;
541     }
542     ALOGV("convertAudioPortConfigToNative handle %d role %d type %d",
543           nAudioPortConfig->id, nAudioPortConfig->role, nAudioPortConfig->type);
544 
545     unsigned int configMask = 0;
546 
547     nAudioPortConfig->sample_rate = env->GetIntField(jAudioPortConfig,
548                                                      gAudioPortConfigFields.mSamplingRate);
549     if (nAudioPortConfig->sample_rate != 0) {
550         configMask |= AUDIO_PORT_CONFIG_SAMPLE_RATE;
551     }
552 
553     bool useInMask = useInChannelMask(nAudioPortConfig->type, nAudioPortConfig->role);
554     audio_channel_mask_t nMask;
555     jint jMask = env->GetIntField(jAudioPortConfig,
556                                    gAudioPortConfigFields.mChannelMask);
557     if (useInMask) {
558         nMask = inChannelMaskToNative(jMask);
559         ALOGV("convertAudioPortConfigToNative IN mask java %x native %x", jMask, nMask);
560     } else {
561         nMask = outChannelMaskToNative(jMask);
562         ALOGV("convertAudioPortConfigToNative OUT mask java %x native %x", jMask, nMask);
563     }
564     nAudioPortConfig->channel_mask = nMask;
565     if (nAudioPortConfig->channel_mask != AUDIO_CHANNEL_NONE) {
566         configMask |= AUDIO_PORT_CONFIG_CHANNEL_MASK;
567     }
568 
569     jint jFormat = env->GetIntField(jAudioPortConfig, gAudioPortConfigFields.mFormat);
570     audio_format_t nFormat = audioFormatToNative(jFormat);
571     ALOGV("convertAudioPortConfigToNative format %d native %d", jFormat, nFormat);
572     nAudioPortConfig->format = nFormat;
573     if (nAudioPortConfig->format != AUDIO_FORMAT_DEFAULT &&
574             nAudioPortConfig->format != AUDIO_FORMAT_INVALID) {
575         configMask |= AUDIO_PORT_CONFIG_FORMAT;
576     }
577 
578     jobject jGain = env->GetObjectField(jAudioPortConfig, gAudioPortConfigFields.mGain);
579     if (jGain != NULL) {
580         convertAudioGainConfigToNative(env, &nAudioPortConfig->gain, jGain, useInMask);
581         env->DeleteLocalRef(jGain);
582         configMask |= AUDIO_PORT_CONFIG_GAIN;
583     } else {
584         ALOGV("convertAudioPortConfigToNative no gain");
585         nAudioPortConfig->gain.index = -1;
586     }
587     if (useConfigMask) {
588         nAudioPortConfig->config_mask = env->GetIntField(jAudioPortConfig,
589                                                          gAudioPortConfigFields.mConfigMask);
590     } else {
591         nAudioPortConfig->config_mask = configMask;
592     }
593     env->DeleteLocalRef(jAudioPort);
594     env->DeleteLocalRef(jHandle);
595     return (jint)AUDIO_JAVA_SUCCESS;
596 }
597 
convertAudioPortConfigFromNative(JNIEnv * env,jobject jAudioPort,jobject * jAudioPortConfig,const struct audio_port_config * nAudioPortConfig)598 static jint convertAudioPortConfigFromNative(JNIEnv *env,
599                                                  jobject jAudioPort,
600                                                  jobject *jAudioPortConfig,
601                                                  const struct audio_port_config *nAudioPortConfig)
602 {
603     jint jStatus = AUDIO_JAVA_SUCCESS;
604     jobject jAudioGainConfig = NULL;
605     jobject jAudioGain = NULL;
606     jintArray jGainValues;
607     bool audioportCreated = false;
608 
609     ALOGV("convertAudioPortConfigFromNative jAudioPort %p", jAudioPort);
610 
611     if (jAudioPort == NULL) {
612         jobject jHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
613                                                  nAudioPortConfig->id);
614 
615         ALOGV("convertAudioPortConfigFromNative handle %d is a %s", nAudioPortConfig->id,
616               nAudioPortConfig->type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix");
617 
618         if (jHandle == NULL) {
619             return (jint)AUDIO_JAVA_ERROR;
620         }
621         // create dummy port and port config objects with just the correct handle
622         // and configuration data. The actual AudioPortConfig objects will be
623         // constructed by java code with correct class type (device, mix etc...)
624         // and reference to AudioPort instance in this client
625         jAudioPort = env->NewObject(gAudioPortClass, gAudioPortCstor,
626                                            jHandle,
627                                            0,
628                                            NULL,
629                                            NULL,
630                                            NULL,
631                                            NULL);
632         env->DeleteLocalRef(jHandle);
633         if (jAudioPort == NULL) {
634             return (jint)AUDIO_JAVA_ERROR;
635         }
636         ALOGV("convertAudioPortConfigFromNative jAudioPort created for handle %d",
637               nAudioPortConfig->id);
638 
639         audioportCreated = true;
640     }
641 
642     bool useInMask = useInChannelMask(nAudioPortConfig->type, nAudioPortConfig->role);
643 
644     audio_channel_mask_t nMask;
645     jint jMask;
646 
647     int gainIndex = nAudioPortConfig->gain.index;
648     if (gainIndex >= 0) {
649         ALOGV("convertAudioPortConfigFromNative gain found with index %d mode %x",
650               gainIndex, nAudioPortConfig->gain.mode);
651         if (audioportCreated) {
652             ALOGV("convertAudioPortConfigFromNative creating gain");
653             jAudioGain = env->NewObject(gAudioGainClass, gAudioGainCstor,
654                                                gainIndex,
655                                                0,
656                                                0,
657                                                0,
658                                                0,
659                                                0,
660                                                0,
661                                                0,
662                                                0);
663             if (jAudioGain == NULL) {
664                 ALOGV("convertAudioPortConfigFromNative creating gain FAILED");
665                 jStatus = (jint)AUDIO_JAVA_ERROR;
666                 goto exit;
667             }
668         } else {
669             ALOGV("convertAudioPortConfigFromNative reading gain from port");
670             jobjectArray jGains = (jobjectArray)env->GetObjectField(jAudioPort,
671                                                                       gAudioPortFields.mGains);
672             if (jGains == NULL) {
673                 ALOGV("convertAudioPortConfigFromNative could not get gains from port");
674                 jStatus = (jint)AUDIO_JAVA_ERROR;
675                 goto exit;
676             }
677             jAudioGain = env->GetObjectArrayElement(jGains, gainIndex);
678             env->DeleteLocalRef(jGains);
679             if (jAudioGain == NULL) {
680                 ALOGV("convertAudioPortConfigFromNative could not get gain at index %d", gainIndex);
681                 jStatus = (jint)AUDIO_JAVA_ERROR;
682                 goto exit;
683             }
684         }
685         int numValues;
686         if (useInMask) {
687             numValues = audio_channel_count_from_in_mask(nAudioPortConfig->gain.channel_mask);
688         } else {
689             numValues = audio_channel_count_from_out_mask(nAudioPortConfig->gain.channel_mask);
690         }
691         jGainValues = env->NewIntArray(numValues);
692         if (jGainValues == NULL) {
693             ALOGV("convertAudioPortConfigFromNative could not create gain values %d", numValues);
694             jStatus = (jint)AUDIO_JAVA_ERROR;
695             goto exit;
696         }
697         env->SetIntArrayRegion(jGainValues, 0, numValues,
698                                nAudioPortConfig->gain.values);
699 
700         nMask = nAudioPortConfig->gain.channel_mask;
701         if (useInMask) {
702             jMask = inChannelMaskFromNative(nMask);
703             ALOGV("convertAudioPortConfigFromNative IN mask java %x native %x", jMask, nMask);
704         } else {
705             jMask = outChannelMaskFromNative(nMask);
706             ALOGV("convertAudioPortConfigFromNative OUT mask java %x native %x", jMask, nMask);
707         }
708 
709         jAudioGainConfig = env->NewObject(gAudioGainConfigClass,
710                                         gAudioGainConfigCstor,
711                                         gainIndex,
712                                         jAudioGain,
713                                         nAudioPortConfig->gain.mode,
714                                         jMask,
715                                         jGainValues,
716                                         nAudioPortConfig->gain.ramp_duration_ms);
717         env->DeleteLocalRef(jGainValues);
718         if (jAudioGainConfig == NULL) {
719             ALOGV("convertAudioPortConfigFromNative could not create gain config");
720             jStatus = (jint)AUDIO_JAVA_ERROR;
721             goto exit;
722         }
723     }
724     jclass clazz;
725     jmethodID methodID;
726     if (audioportCreated) {
727         clazz = gAudioPortConfigClass;
728         methodID = gAudioPortConfigCstor;
729         ALOGV("convertAudioPortConfigFromNative building a generic port config");
730     } else {
731         if (env->IsInstanceOf(jAudioPort, gAudioDevicePortClass)) {
732             clazz = gAudioDevicePortConfigClass;
733             methodID = gAudioDevicePortConfigCstor;
734             ALOGV("convertAudioPortConfigFromNative building a device config");
735         } else if (env->IsInstanceOf(jAudioPort, gAudioMixPortClass)) {
736             clazz = gAudioMixPortConfigClass;
737             methodID = gAudioMixPortConfigCstor;
738             ALOGV("convertAudioPortConfigFromNative building a mix config");
739         } else {
740             jStatus = (jint)AUDIO_JAVA_ERROR;
741             goto exit;
742         }
743     }
744     nMask = nAudioPortConfig->channel_mask;
745     if (useInMask) {
746         jMask = inChannelMaskFromNative(nMask);
747         ALOGV("convertAudioPortConfigFromNative IN mask java %x native %x", jMask, nMask);
748     } else {
749         jMask = outChannelMaskFromNative(nMask);
750         ALOGV("convertAudioPortConfigFromNative OUT mask java %x native %x", jMask, nMask);
751     }
752 
753     *jAudioPortConfig = env->NewObject(clazz, methodID,
754                                        jAudioPort,
755                                        nAudioPortConfig->sample_rate,
756                                        jMask,
757                                        audioFormatFromNative(nAudioPortConfig->format),
758                                        jAudioGainConfig);
759     if (*jAudioPortConfig == NULL) {
760         ALOGV("convertAudioPortConfigFromNative could not create new port config");
761         jStatus = (jint)AUDIO_JAVA_ERROR;
762     } else {
763         ALOGV("convertAudioPortConfigFromNative OK");
764     }
765 
766 exit:
767     if (audioportCreated) {
768         env->DeleteLocalRef(jAudioPort);
769         if (jAudioGain != NULL) {
770             env->DeleteLocalRef(jAudioGain);
771         }
772     }
773     if (jAudioGainConfig != NULL) {
774         env->DeleteLocalRef(jAudioGainConfig);
775     }
776     return jStatus;
777 }
778 
convertAudioPortFromNative(JNIEnv * env,jobject * jAudioPort,const struct audio_port * nAudioPort)779 static jint convertAudioPortFromNative(JNIEnv *env,
780                                            jobject *jAudioPort, const struct audio_port *nAudioPort)
781 {
782     jint jStatus = (jint)AUDIO_JAVA_SUCCESS;
783     jintArray jSamplingRates = NULL;
784     jintArray jChannelMasks = NULL;
785     jintArray jFormats = NULL;
786     jobjectArray jGains = NULL;
787     jobject jHandle = NULL;
788     bool useInMask;
789 
790     ALOGV("convertAudioPortFromNative id %d role %d type %d",
791                                   nAudioPort->id, nAudioPort->role, nAudioPort->type);
792 
793     jSamplingRates = env->NewIntArray(nAudioPort->num_sample_rates);
794     if (jSamplingRates == NULL) {
795         jStatus = (jint)AUDIO_JAVA_ERROR;
796         goto exit;
797     }
798     if (nAudioPort->num_sample_rates) {
799         env->SetIntArrayRegion(jSamplingRates, 0, nAudioPort->num_sample_rates,
800                                (jint *)nAudioPort->sample_rates);
801     }
802 
803     jChannelMasks = env->NewIntArray(nAudioPort->num_channel_masks);
804     if (jChannelMasks == NULL) {
805         jStatus = (jint)AUDIO_JAVA_ERROR;
806         goto exit;
807     }
808     useInMask = useInChannelMask(nAudioPort->type, nAudioPort->role);
809 
810     jint jMask;
811     for (size_t j = 0; j < nAudioPort->num_channel_masks; j++) {
812         if (useInMask) {
813             jMask = inChannelMaskFromNative(nAudioPort->channel_masks[j]);
814         } else {
815             jMask = outChannelMaskFromNative(nAudioPort->channel_masks[j]);
816         }
817         env->SetIntArrayRegion(jChannelMasks, j, 1, &jMask);
818     }
819 
820     jFormats = env->NewIntArray(nAudioPort->num_formats);
821     if (jFormats == NULL) {
822         jStatus = (jint)AUDIO_JAVA_ERROR;
823         goto exit;
824     }
825     for (size_t j = 0; j < nAudioPort->num_formats; j++) {
826         jint jFormat = audioFormatFromNative(nAudioPort->formats[j]);
827         env->SetIntArrayRegion(jFormats, j, 1, &jFormat);
828     }
829 
830     jGains = env->NewObjectArray(nAudioPort->num_gains,
831                                           gAudioGainClass, NULL);
832     if (jGains == NULL) {
833         jStatus = (jint)AUDIO_JAVA_ERROR;
834         goto exit;
835     }
836     for (size_t j = 0; j < nAudioPort->num_gains; j++) {
837         audio_channel_mask_t nMask = nAudioPort->gains[j].channel_mask;
838         if (useInMask) {
839             jMask = inChannelMaskFromNative(nMask);
840             ALOGV("convertAudioPortConfigFromNative IN mask java %x native %x", jMask, nMask);
841         } else {
842             jMask = outChannelMaskFromNative(nMask);
843             ALOGV("convertAudioPortConfigFromNative OUT mask java %x native %x", jMask, nMask);
844         }
845 
846         jobject jGain = env->NewObject(gAudioGainClass, gAudioGainCstor,
847                                                  j,
848                                                  nAudioPort->gains[j].mode,
849                                                  jMask,
850                                                  nAudioPort->gains[j].min_value,
851                                                  nAudioPort->gains[j].max_value,
852                                                  nAudioPort->gains[j].default_value,
853                                                  nAudioPort->gains[j].step_value,
854                                                  nAudioPort->gains[j].min_ramp_ms,
855                                                  nAudioPort->gains[j].max_ramp_ms);
856         if (jGain == NULL) {
857             jStatus = (jint)AUDIO_JAVA_ERROR;
858             goto exit;
859         }
860         env->SetObjectArrayElement(jGains, j, jGain);
861         env->DeleteLocalRef(jGain);
862     }
863 
864     jHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
865                                              nAudioPort->id);
866     if (jHandle == NULL) {
867         jStatus = (jint)AUDIO_JAVA_ERROR;
868         goto exit;
869     }
870 
871     if (nAudioPort->type == AUDIO_PORT_TYPE_DEVICE) {
872         ALOGV("convertAudioPortFromNative is a device %08x", nAudioPort->ext.device.type);
873         jstring jAddress = env->NewStringUTF(nAudioPort->ext.device.address);
874         *jAudioPort = env->NewObject(gAudioDevicePortClass, gAudioDevicePortCstor,
875                                      jHandle, jSamplingRates, jChannelMasks, jFormats, jGains,
876                                      nAudioPort->ext.device.type, jAddress);
877         env->DeleteLocalRef(jAddress);
878     } else if (nAudioPort->type == AUDIO_PORT_TYPE_MIX) {
879         ALOGV("convertAudioPortFromNative is a mix");
880         *jAudioPort = env->NewObject(gAudioMixPortClass, gAudioMixPortCstor,
881                                      jHandle, nAudioPort->role, jSamplingRates, jChannelMasks,
882                                      jFormats, jGains);
883     } else {
884         ALOGE("convertAudioPortFromNative unknown nAudioPort type %d", nAudioPort->type);
885         jStatus = (jint)AUDIO_JAVA_ERROR;
886         goto exit;
887     }
888     if (*jAudioPort == NULL) {
889         jStatus = (jint)AUDIO_JAVA_ERROR;
890         goto exit;
891     }
892 
893     jobject jAudioPortConfig;
894     jStatus = convertAudioPortConfigFromNative(env,
895                                                        *jAudioPort,
896                                                        &jAudioPortConfig,
897                                                        &nAudioPort->active_config);
898     if (jStatus != AUDIO_JAVA_SUCCESS) {
899         return jStatus;
900     }
901 
902     env->SetObjectField(*jAudioPort, gAudioPortFields.mActiveConfig, jAudioPortConfig);
903 
904 exit:
905     if (jSamplingRates != NULL) {
906         env->DeleteLocalRef(jSamplingRates);
907     }
908     if (jChannelMasks != NULL) {
909         env->DeleteLocalRef(jChannelMasks);
910     }
911     if (jFormats != NULL) {
912         env->DeleteLocalRef(jFormats);
913     }
914     if (jGains != NULL) {
915         env->DeleteLocalRef(jGains);
916     }
917     if (jHandle != NULL) {
918         env->DeleteLocalRef(jHandle);
919     }
920 
921     return jStatus;
922 }
923 
924 
925 static jint
android_media_AudioSystem_listAudioPorts(JNIEnv * env,jobject clazz,jobject jPorts,jintArray jGeneration)926 android_media_AudioSystem_listAudioPorts(JNIEnv *env, jobject clazz,
927                                          jobject jPorts, jintArray jGeneration)
928 {
929     ALOGV("listAudioPorts");
930 
931     if (jPorts == NULL) {
932         ALOGE("listAudioPorts NULL AudioPort ArrayList");
933         return (jint)AUDIO_JAVA_BAD_VALUE;
934     }
935     if (!env->IsInstanceOf(jPorts, gArrayListClass)) {
936         ALOGE("listAudioPorts not an arraylist");
937         return (jint)AUDIO_JAVA_BAD_VALUE;
938     }
939 
940     if (jGeneration == NULL || env->GetArrayLength(jGeneration) != 1) {
941         return (jint)AUDIO_JAVA_BAD_VALUE;
942     }
943 
944     status_t status;
945     unsigned int generation1;
946     unsigned int generation;
947     unsigned int numPorts;
948     jint *nGeneration;
949     struct audio_port *nPorts = NULL;
950     int attempts = MAX_PORT_GENERATION_SYNC_ATTEMPTS;
951 
952     // get the port count and all the ports until they both return the same generation
953     do {
954         if (attempts-- < 0) {
955             status = TIMED_OUT;
956             break;
957         }
958 
959         numPorts = 0;
960         status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE,
961                                              AUDIO_PORT_TYPE_NONE,
962                                                       &numPorts,
963                                                       NULL,
964                                                       &generation1);
965         if (status != NO_ERROR || numPorts == 0) {
966             ALOGE_IF(status != NO_ERROR, "AudioSystem::listAudioPorts error %d", status);
967             break;
968         }
969         nPorts = (struct audio_port *)realloc(nPorts, numPorts * sizeof(struct audio_port));
970 
971         status = AudioSystem::listAudioPorts(AUDIO_PORT_ROLE_NONE,
972                                              AUDIO_PORT_TYPE_NONE,
973                                                       &numPorts,
974                                                       nPorts,
975                                                       &generation);
976         ALOGV("listAudioPorts AudioSystem::listAudioPorts numPorts %d generation %d generation1 %d",
977               numPorts, generation, generation1);
978     } while (generation1 != generation && status == NO_ERROR);
979 
980     jint jStatus = nativeToJavaStatus(status);
981     if (jStatus != AUDIO_JAVA_SUCCESS) {
982         goto exit;
983     }
984 
985     nGeneration = env->GetIntArrayElements(jGeneration, NULL);
986     if (nGeneration == NULL) {
987         jStatus = (jint)AUDIO_JAVA_ERROR;
988         goto exit;
989     }
990     nGeneration[0] = generation1;
991     env->ReleaseIntArrayElements(jGeneration, nGeneration, 0);
992 
993     for (size_t i = 0; i < numPorts; i++) {
994         jobject jAudioPort;
995         jStatus = convertAudioPortFromNative(env, &jAudioPort, &nPorts[i]);
996         if (jStatus != AUDIO_JAVA_SUCCESS) {
997             goto exit;
998         }
999         env->CallBooleanMethod(jPorts, gArrayListMethods.add, jAudioPort);
1000     }
1001 
1002 exit:
1003     free(nPorts);
1004     return jStatus;
1005 }
1006 
1007 static int
android_media_AudioSystem_createAudioPatch(JNIEnv * env,jobject clazz,jobjectArray jPatches,jobjectArray jSources,jobjectArray jSinks)1008 android_media_AudioSystem_createAudioPatch(JNIEnv *env, jobject clazz,
1009                                  jobjectArray jPatches, jobjectArray jSources, jobjectArray jSinks)
1010 {
1011     status_t status;
1012     jint jStatus;
1013 
1014     ALOGV("createAudioPatch");
1015     if (jPatches == NULL || jSources == NULL || jSinks == NULL) {
1016         return (jint)AUDIO_JAVA_BAD_VALUE;
1017     }
1018 
1019     if (env->GetArrayLength(jPatches) != 1) {
1020         return (jint)AUDIO_JAVA_BAD_VALUE;
1021     }
1022     jint numSources = env->GetArrayLength(jSources);
1023     if (numSources == 0 || numSources > AUDIO_PATCH_PORTS_MAX) {
1024         return (jint)AUDIO_JAVA_BAD_VALUE;
1025     }
1026 
1027     jint numSinks = env->GetArrayLength(jSinks);
1028     if (numSinks == 0 || numSinks > AUDIO_PATCH_PORTS_MAX) {
1029         return (jint)AUDIO_JAVA_BAD_VALUE;
1030     }
1031 
1032     audio_patch_handle_t handle = (audio_patch_handle_t)0;
1033     jobject jPatch = env->GetObjectArrayElement(jPatches, 0);
1034     jobject jPatchHandle = NULL;
1035     if (jPatch != NULL) {
1036         if (!env->IsInstanceOf(jPatch, gAudioPatchClass)) {
1037             return (jint)AUDIO_JAVA_BAD_VALUE;
1038         }
1039         jPatchHandle = env->GetObjectField(jPatch, gAudioPatchFields.mHandle);
1040         handle = (audio_patch_handle_t)env->GetIntField(jPatchHandle, gAudioHandleFields.mId);
1041     }
1042 
1043     struct audio_patch nPatch;
1044 
1045     nPatch.id = handle;
1046     nPatch.num_sources = 0;
1047     nPatch.num_sinks = 0;
1048     jobject jSource = NULL;
1049     jobject jSink = NULL;
1050 
1051     for (jint i = 0; i < numSources; i++) {
1052         jSource = env->GetObjectArrayElement(jSources, i);
1053         if (!env->IsInstanceOf(jSource, gAudioPortConfigClass)) {
1054             jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
1055             goto exit;
1056         }
1057         jStatus = convertAudioPortConfigToNative(env, &nPatch.sources[i], jSource, false);
1058         env->DeleteLocalRef(jSource);
1059         jSource = NULL;
1060         if (jStatus != AUDIO_JAVA_SUCCESS) {
1061             goto exit;
1062         }
1063         nPatch.num_sources++;
1064     }
1065 
1066     for (jint i = 0; i < numSinks; i++) {
1067         jSink = env->GetObjectArrayElement(jSinks, i);
1068         if (!env->IsInstanceOf(jSink, gAudioPortConfigClass)) {
1069             jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
1070             goto exit;
1071         }
1072         jStatus = convertAudioPortConfigToNative(env, &nPatch.sinks[i], jSink, false);
1073         env->DeleteLocalRef(jSink);
1074         jSink = NULL;
1075         if (jStatus != AUDIO_JAVA_SUCCESS) {
1076             goto exit;
1077         }
1078         nPatch.num_sinks++;
1079     }
1080 
1081     ALOGV("AudioSystem::createAudioPatch");
1082     status = AudioSystem::createAudioPatch(&nPatch, &handle);
1083     ALOGV("AudioSystem::createAudioPatch() returned %d hande %d", status, handle);
1084 
1085     jStatus = nativeToJavaStatus(status);
1086     if (jStatus != AUDIO_JAVA_SUCCESS) {
1087         goto exit;
1088     }
1089 
1090     if (jPatchHandle == NULL) {
1091         jPatchHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
1092                                            handle);
1093         if (jPatchHandle == NULL) {
1094             jStatus = (jint)AUDIO_JAVA_ERROR;
1095             goto exit;
1096         }
1097         jPatch = env->NewObject(gAudioPatchClass, gAudioPatchCstor, jPatchHandle, jSources, jSinks);
1098         if (jPatch == NULL) {
1099             jStatus = (jint)AUDIO_JAVA_ERROR;
1100             goto exit;
1101         }
1102         env->SetObjectArrayElement(jPatches, 0, jPatch);
1103     } else {
1104         env->SetIntField(jPatchHandle, gAudioHandleFields.mId, handle);
1105     }
1106 
1107 exit:
1108     if (jPatchHandle != NULL) {
1109         env->DeleteLocalRef(jPatchHandle);
1110     }
1111     if (jPatch != NULL) {
1112         env->DeleteLocalRef(jPatch);
1113     }
1114     if (jSource != NULL) {
1115         env->DeleteLocalRef(jSource);
1116     }
1117     if (jSink != NULL) {
1118         env->DeleteLocalRef(jSink);
1119     }
1120     return jStatus;
1121 }
1122 
1123 static int
android_media_AudioSystem_releaseAudioPatch(JNIEnv * env,jobject clazz,jobject jPatch)1124 android_media_AudioSystem_releaseAudioPatch(JNIEnv *env, jobject clazz,
1125                                                jobject jPatch)
1126 {
1127     ALOGV("releaseAudioPatch");
1128     if (jPatch == NULL) {
1129         return (jint)AUDIO_JAVA_BAD_VALUE;
1130     }
1131 
1132     audio_patch_handle_t handle = (audio_patch_handle_t)0;
1133     jobject jPatchHandle = NULL;
1134     if (!env->IsInstanceOf(jPatch, gAudioPatchClass)) {
1135         return (jint)AUDIO_JAVA_BAD_VALUE;
1136     }
1137     jPatchHandle = env->GetObjectField(jPatch, gAudioPatchFields.mHandle);
1138     handle = (audio_patch_handle_t)env->GetIntField(jPatchHandle, gAudioHandleFields.mId);
1139     env->DeleteLocalRef(jPatchHandle);
1140 
1141     ALOGV("AudioSystem::releaseAudioPatch");
1142     status_t status = AudioSystem::releaseAudioPatch(handle);
1143     ALOGV("AudioSystem::releaseAudioPatch() returned %d", status);
1144     jint jStatus = nativeToJavaStatus(status);
1145     return status;
1146 }
1147 
1148 static jint
android_media_AudioSystem_listAudioPatches(JNIEnv * env,jobject clazz,jobject jPatches,jintArray jGeneration)1149 android_media_AudioSystem_listAudioPatches(JNIEnv *env, jobject clazz,
1150                                            jobject jPatches, jintArray jGeneration)
1151 {
1152     ALOGV("listAudioPatches");
1153     if (jPatches == NULL) {
1154         ALOGE("listAudioPatches NULL AudioPatch ArrayList");
1155         return (jint)AUDIO_JAVA_BAD_VALUE;
1156     }
1157     if (!env->IsInstanceOf(jPatches, gArrayListClass)) {
1158         ALOGE("listAudioPatches not an arraylist");
1159         return (jint)AUDIO_JAVA_BAD_VALUE;
1160     }
1161 
1162     if (jGeneration == NULL || env->GetArrayLength(jGeneration) != 1) {
1163         return (jint)AUDIO_JAVA_BAD_VALUE;
1164     }
1165 
1166     status_t status;
1167     unsigned int generation1;
1168     unsigned int generation;
1169     unsigned int numPatches;
1170     jint *nGeneration;
1171     struct audio_patch *nPatches = NULL;
1172     jobjectArray jSources = NULL;
1173     jobject jSource = NULL;
1174     jobjectArray jSinks = NULL;
1175     jobject jSink = NULL;
1176     jobject jPatch = NULL;
1177     int attempts = MAX_PORT_GENERATION_SYNC_ATTEMPTS;
1178 
1179     // get the patch count and all the patches until they both return the same generation
1180     do {
1181         if (attempts-- < 0) {
1182             status = TIMED_OUT;
1183             break;
1184         }
1185 
1186         numPatches = 0;
1187         status = AudioSystem::listAudioPatches(&numPatches,
1188                                                NULL,
1189                                                &generation1);
1190         if (status != NO_ERROR || numPatches == 0) {
1191             ALOGE_IF(status != NO_ERROR, "listAudioPatches AudioSystem::listAudioPatches error %d",
1192                                       status);
1193             break;
1194         }
1195         nPatches = (struct audio_patch *)realloc(nPatches, numPatches * sizeof(struct audio_patch));
1196 
1197         status = AudioSystem::listAudioPatches(&numPatches,
1198                                                nPatches,
1199                                                &generation);
1200         ALOGV("listAudioPatches AudioSystem::listAudioPatches numPatches %d generation %d generation1 %d",
1201               numPatches, generation, generation1);
1202 
1203     } while (generation1 != generation && status == NO_ERROR);
1204 
1205     jint jStatus = nativeToJavaStatus(status);
1206     if (jStatus != AUDIO_JAVA_SUCCESS) {
1207         goto exit;
1208     }
1209 
1210     nGeneration = env->GetIntArrayElements(jGeneration, NULL);
1211     if (nGeneration == NULL) {
1212         jStatus = AUDIO_JAVA_ERROR;
1213         goto exit;
1214     }
1215     nGeneration[0] = generation1;
1216     env->ReleaseIntArrayElements(jGeneration, nGeneration, 0);
1217 
1218     for (size_t i = 0; i < numPatches; i++) {
1219         jobject patchHandle = env->NewObject(gAudioHandleClass, gAudioHandleCstor,
1220                                                  nPatches[i].id);
1221         if (patchHandle == NULL) {
1222             jStatus = AUDIO_JAVA_ERROR;
1223             goto exit;
1224         }
1225         ALOGV("listAudioPatches patch %d num_sources %d num_sinks %d",
1226               i, nPatches[i].num_sources, nPatches[i].num_sinks);
1227 
1228         env->SetIntField(patchHandle, gAudioHandleFields.mId, nPatches[i].id);
1229 
1230         // load sources
1231         jSources = env->NewObjectArray(nPatches[i].num_sources,
1232                                        gAudioPortConfigClass, NULL);
1233         if (jSources == NULL) {
1234             jStatus = AUDIO_JAVA_ERROR;
1235             goto exit;
1236         }
1237 
1238         for (size_t j = 0; j < nPatches[i].num_sources; j++) {
1239             jStatus = convertAudioPortConfigFromNative(env,
1240                                                       NULL,
1241                                                       &jSource,
1242                                                       &nPatches[i].sources[j]);
1243             if (jStatus != AUDIO_JAVA_SUCCESS) {
1244                 goto exit;
1245             }
1246             env->SetObjectArrayElement(jSources, j, jSource);
1247             env->DeleteLocalRef(jSource);
1248             jSource = NULL;
1249             ALOGV("listAudioPatches patch %d source %d is a %s handle %d",
1250                   i, j,
1251                   nPatches[i].sources[j].type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix",
1252                   nPatches[i].sources[j].id);
1253         }
1254         // load sinks
1255         jSinks = env->NewObjectArray(nPatches[i].num_sinks,
1256                                      gAudioPortConfigClass, NULL);
1257         if (jSinks == NULL) {
1258             jStatus = AUDIO_JAVA_ERROR;
1259             goto exit;
1260         }
1261 
1262         for (size_t j = 0; j < nPatches[i].num_sinks; j++) {
1263             jStatus = convertAudioPortConfigFromNative(env,
1264                                                       NULL,
1265                                                       &jSink,
1266                                                       &nPatches[i].sinks[j]);
1267 
1268             if (jStatus != AUDIO_JAVA_SUCCESS) {
1269                 goto exit;
1270             }
1271             env->SetObjectArrayElement(jSinks, j, jSink);
1272             env->DeleteLocalRef(jSink);
1273             jSink = NULL;
1274             ALOGV("listAudioPatches patch %d sink %d is a %s handle %d",
1275                   i, j,
1276                   nPatches[i].sinks[j].type == AUDIO_PORT_TYPE_DEVICE ? "device" : "mix",
1277                   nPatches[i].sinks[j].id);
1278         }
1279 
1280         jPatch = env->NewObject(gAudioPatchClass, gAudioPatchCstor,
1281                                        patchHandle, jSources, jSinks);
1282         env->DeleteLocalRef(jSources);
1283         jSources = NULL;
1284         env->DeleteLocalRef(jSinks);
1285         jSinks = NULL;
1286         if (jPatch == NULL) {
1287             jStatus = AUDIO_JAVA_ERROR;
1288             goto exit;
1289         }
1290         env->CallBooleanMethod(jPatches, gArrayListMethods.add, jPatch);
1291         env->DeleteLocalRef(jPatch);
1292         jPatch = NULL;
1293     }
1294 
1295 exit:
1296     if (jSources != NULL) {
1297         env->DeleteLocalRef(jSources);
1298     }
1299     if (jSource != NULL) {
1300         env->DeleteLocalRef(jSource);
1301     }
1302     if (jSinks != NULL) {
1303         env->DeleteLocalRef(jSinks);
1304     }
1305     if (jSink != NULL) {
1306         env->DeleteLocalRef(jSink);
1307     }
1308     if (jPatch != NULL) {
1309         env->DeleteLocalRef(jPatch);
1310     }
1311     free(nPatches);
1312     return jStatus;
1313 }
1314 
1315 static jint
android_media_AudioSystem_setAudioPortConfig(JNIEnv * env,jobject clazz,jobject jAudioPortConfig)1316 android_media_AudioSystem_setAudioPortConfig(JNIEnv *env, jobject clazz,
1317                                  jobject jAudioPortConfig)
1318 {
1319     ALOGV("setAudioPortConfig");
1320     if (jAudioPortConfig == NULL) {
1321         return AUDIO_JAVA_BAD_VALUE;
1322     }
1323     if (!env->IsInstanceOf(jAudioPortConfig, gAudioPortConfigClass)) {
1324         return AUDIO_JAVA_BAD_VALUE;
1325     }
1326     struct audio_port_config nAudioPortConfig;
1327     jint jStatus = convertAudioPortConfigToNative(env, &nAudioPortConfig, jAudioPortConfig, true);
1328     if (jStatus != AUDIO_JAVA_SUCCESS) {
1329         return jStatus;
1330     }
1331     status_t status = AudioSystem::setAudioPortConfig(&nAudioPortConfig);
1332     ALOGV("AudioSystem::setAudioPortConfig() returned %d", status);
1333     jStatus = nativeToJavaStatus(status);
1334     return jStatus;
1335 }
1336 
1337 static void
android_media_AudioSystem_eventHandlerSetup(JNIEnv * env,jobject thiz,jobject weak_this)1338 android_media_AudioSystem_eventHandlerSetup(JNIEnv *env, jobject thiz, jobject weak_this)
1339 {
1340     ALOGV("eventHandlerSetup");
1341 
1342     sp<JNIAudioPortCallback> callback = new JNIAudioPortCallback(env, thiz, weak_this);
1343 
1344     AudioSystem::setAudioPortCallback(callback);
1345 }
1346 
1347 static void
android_media_AudioSystem_eventHandlerFinalize(JNIEnv * env,jobject thiz)1348 android_media_AudioSystem_eventHandlerFinalize(JNIEnv *env, jobject thiz)
1349 {
1350     ALOGV("eventHandlerFinalize");
1351 
1352     sp<JNIAudioPortCallback> callback;
1353 
1354     AudioSystem::setAudioPortCallback(callback);
1355 }
1356 
1357 static jint
android_media_AudioSystem_getAudioHwSyncForSession(JNIEnv * env,jobject thiz,jint sessionId)1358 android_media_AudioSystem_getAudioHwSyncForSession(JNIEnv *env, jobject thiz, jint sessionId)
1359 {
1360     return (jint)AudioSystem::getAudioHwSyncForSession((audio_session_t)sessionId);
1361 }
1362 
1363 
1364 
1365 
convertAudioMixToNative(JNIEnv * env,AudioMix * nAudioMix,const jobject jAudioMix)1366 static jint convertAudioMixToNative(JNIEnv *env,
1367                                     AudioMix *nAudioMix,
1368                                     const jobject jAudioMix)
1369 {
1370     nAudioMix->mMixType = env->GetIntField(jAudioMix, gAudioMixFields.mMixType);
1371     nAudioMix->mRouteFlags = env->GetIntField(jAudioMix, gAudioMixFields.mRouteFlags);
1372 
1373     jstring jRegistrationId = (jstring)env->GetObjectField(jAudioMix,
1374                                                            gAudioMixFields.mRegistrationId);
1375     const char *nRegistrationId = env->GetStringUTFChars(jRegistrationId, NULL);
1376     nAudioMix->mRegistrationId = String8(nRegistrationId);
1377     env->ReleaseStringUTFChars(jRegistrationId, nRegistrationId);
1378     env->DeleteLocalRef(jRegistrationId);
1379 
1380     jobject jFormat = env->GetObjectField(jAudioMix, gAudioMixFields.mFormat);
1381     nAudioMix->mFormat.sample_rate = env->GetIntField(jFormat,
1382                                                      gAudioFormatFields.mSampleRate);
1383     nAudioMix->mFormat.channel_mask = outChannelMaskToNative(env->GetIntField(jFormat,
1384                                                      gAudioFormatFields.mChannelMask));
1385     nAudioMix->mFormat.format = audioFormatToNative(env->GetIntField(jFormat,
1386                                                      gAudioFormatFields.mEncoding));
1387     env->DeleteLocalRef(jFormat);
1388 
1389     jobject jRule = env->GetObjectField(jAudioMix, gAudioMixFields.mRule);
1390     jobject jRuleCriteria = env->GetObjectField(jRule, gAudioMixingRuleFields.mCriteria);
1391     env->DeleteLocalRef(jRule);
1392     jobjectArray jCriteria = (jobjectArray)env->CallObjectMethod(jRuleCriteria,
1393                                                                  gArrayListMethods.toArray);
1394     env->DeleteLocalRef(jRuleCriteria);
1395 
1396     jint numCriteria = env->GetArrayLength(jCriteria);
1397     if (numCriteria > MAX_CRITERIA_PER_MIX) {
1398         numCriteria = MAX_CRITERIA_PER_MIX;
1399     }
1400 
1401     for (jint i = 0; i < numCriteria; i++) {
1402         AttributeMatchCriterion nCriterion;
1403 
1404         jobject jCriterion = env->GetObjectArrayElement(jCriteria, i);
1405 
1406         nCriterion.mRule = env->GetIntField(jCriterion, gAttributeMatchCriterionFields.mRule);
1407 
1408         jobject jAttributes = env->GetObjectField(jCriterion, gAttributeMatchCriterionFields.mAttr);
1409         if (nCriterion.mRule == RULE_MATCH_ATTRIBUTE_USAGE ||
1410                 nCriterion.mRule == RULE_EXCLUDE_ATTRIBUTE_USAGE) {
1411             nCriterion.mAttr.mUsage = (audio_usage_t)env->GetIntField(jAttributes,
1412                                                        gAudioAttributesFields.mUsage);
1413         } else {
1414             nCriterion.mAttr.mSource = (audio_source_t)env->GetIntField(jAttributes,
1415                                                         gAudioAttributesFields.mSource);
1416         }
1417         env->DeleteLocalRef(jAttributes);
1418 
1419         nAudioMix->mCriteria.add(nCriterion);
1420         env->DeleteLocalRef(jCriterion);
1421     }
1422 
1423     env->DeleteLocalRef(jCriteria);
1424 
1425     return (jint)AUDIO_JAVA_SUCCESS;
1426 }
1427 
1428 static jint
android_media_AudioSystem_registerPolicyMixes(JNIEnv * env,jobject clazz,jobject jMixesList,jboolean registration)1429 android_media_AudioSystem_registerPolicyMixes(JNIEnv *env, jobject clazz,
1430                                               jobject jMixesList, jboolean registration)
1431 {
1432     ALOGV("registerPolicyMixes");
1433 
1434     if (jMixesList == NULL) {
1435         return (jint)AUDIO_JAVA_BAD_VALUE;
1436     }
1437     if (!env->IsInstanceOf(jMixesList, gArrayListClass)) {
1438         return (jint)AUDIO_JAVA_BAD_VALUE;
1439     }
1440     jobjectArray jMixes = (jobjectArray)env->CallObjectMethod(jMixesList,
1441                                                               gArrayListMethods.toArray);
1442     jint numMixes = env->GetArrayLength(jMixes);
1443     if (numMixes > MAX_MIXES_PER_POLICY) {
1444         numMixes = MAX_MIXES_PER_POLICY;
1445     }
1446 
1447     status_t status;
1448     jint jStatus;
1449     jobject jAudioMix = NULL;
1450     Vector <AudioMix> mixes;
1451     for (jint i = 0; i < numMixes; i++) {
1452         jAudioMix = env->GetObjectArrayElement(jMixes, i);
1453         if (!env->IsInstanceOf(jAudioMix, gAudioMixClass)) {
1454             jStatus = (jint)AUDIO_JAVA_BAD_VALUE;
1455             goto exit;
1456         }
1457         AudioMix mix;
1458         jStatus = convertAudioMixToNative(env, &mix, jAudioMix);
1459         env->DeleteLocalRef(jAudioMix);
1460         jAudioMix = NULL;
1461         if (jStatus != AUDIO_JAVA_SUCCESS) {
1462             goto exit;
1463         }
1464         mixes.add(mix);
1465     }
1466 
1467     ALOGV("AudioSystem::registerPolicyMixes numMixes %d registration %d", numMixes, registration);
1468     status = AudioSystem::registerPolicyMixes(mixes, registration);
1469     ALOGV("AudioSystem::registerPolicyMixes() returned %d", status);
1470 
1471     jStatus = nativeToJavaStatus(status);
1472     if (jStatus != AUDIO_JAVA_SUCCESS) {
1473         goto exit;
1474     }
1475 
1476 exit:
1477     if (jAudioMix != NULL) {
1478         env->DeleteLocalRef(jAudioMix);
1479     }
1480     return jStatus;
1481 }
1482 
1483 
1484 
1485 // ----------------------------------------------------------------------------
1486 
1487 static JNINativeMethod gMethods[] = {
1488     {"setParameters",        "(Ljava/lang/String;)I", (void *)android_media_AudioSystem_setParameters},
1489     {"getParameters",        "(Ljava/lang/String;)Ljava/lang/String;", (void *)android_media_AudioSystem_getParameters},
1490     {"muteMicrophone",      "(Z)I",     (void *)android_media_AudioSystem_muteMicrophone},
1491     {"isMicrophoneMuted",   "()Z",      (void *)android_media_AudioSystem_isMicrophoneMuted},
1492     {"isStreamActive",      "(II)Z",    (void *)android_media_AudioSystem_isStreamActive},
1493     {"isStreamActiveRemotely","(II)Z",  (void *)android_media_AudioSystem_isStreamActiveRemotely},
1494     {"isSourceActive",      "(I)Z",     (void *)android_media_AudioSystem_isSourceActive},
1495     {"newAudioSessionId",   "()I",      (void *)android_media_AudioSystem_newAudioSessionId},
1496     {"setDeviceConnectionState", "(IILjava/lang/String;)I", (void *)android_media_AudioSystem_setDeviceConnectionState},
1497     {"getDeviceConnectionState", "(ILjava/lang/String;)I",  (void *)android_media_AudioSystem_getDeviceConnectionState},
1498     {"setPhoneState",       "(I)I",     (void *)android_media_AudioSystem_setPhoneState},
1499     {"setForceUse",         "(II)I",    (void *)android_media_AudioSystem_setForceUse},
1500     {"getForceUse",         "(I)I",     (void *)android_media_AudioSystem_getForceUse},
1501     {"initStreamVolume",    "(III)I",   (void *)android_media_AudioSystem_initStreamVolume},
1502     {"setStreamVolumeIndex","(III)I",   (void *)android_media_AudioSystem_setStreamVolumeIndex},
1503     {"getStreamVolumeIndex","(II)I",    (void *)android_media_AudioSystem_getStreamVolumeIndex},
1504     {"setMasterVolume",     "(F)I",     (void *)android_media_AudioSystem_setMasterVolume},
1505     {"getMasterVolume",     "()F",      (void *)android_media_AudioSystem_getMasterVolume},
1506     {"setMasterMute",       "(Z)I",     (void *)android_media_AudioSystem_setMasterMute},
1507     {"getMasterMute",       "()Z",      (void *)android_media_AudioSystem_getMasterMute},
1508     {"getDevicesForStream", "(I)I",     (void *)android_media_AudioSystem_getDevicesForStream},
1509     {"getPrimaryOutputSamplingRate", "()I", (void *)android_media_AudioSystem_getPrimaryOutputSamplingRate},
1510     {"getPrimaryOutputFrameCount",   "()I", (void *)android_media_AudioSystem_getPrimaryOutputFrameCount},
1511     {"getOutputLatency",    "(I)I",     (void *)android_media_AudioSystem_getOutputLatency},
1512     {"setLowRamDevice",     "(Z)I",     (void *)android_media_AudioSystem_setLowRamDevice},
1513     {"checkAudioFlinger",    "()I",     (void *)android_media_AudioSystem_checkAudioFlinger},
1514     {"listAudioPorts",      "(Ljava/util/ArrayList;[I)I",
1515                                                 (void *)android_media_AudioSystem_listAudioPorts},
1516     {"createAudioPatch",    "([Landroid/media/AudioPatch;[Landroid/media/AudioPortConfig;[Landroid/media/AudioPortConfig;)I",
1517                                             (void *)android_media_AudioSystem_createAudioPatch},
1518     {"releaseAudioPatch",   "(Landroid/media/AudioPatch;)I",
1519                                             (void *)android_media_AudioSystem_releaseAudioPatch},
1520     {"listAudioPatches",    "(Ljava/util/ArrayList;[I)I",
1521                                                 (void *)android_media_AudioSystem_listAudioPatches},
1522     {"setAudioPortConfig",   "(Landroid/media/AudioPortConfig;)I",
1523                                             (void *)android_media_AudioSystem_setAudioPortConfig},
1524     {"getAudioHwSyncForSession", "(I)I",
1525                                     (void *)android_media_AudioSystem_getAudioHwSyncForSession},
1526     {"registerPolicyMixes",    "(Ljava/util/ArrayList;Z)I",
1527                                             (void *)android_media_AudioSystem_registerPolicyMixes},
1528 
1529 };
1530 
1531 
1532 static JNINativeMethod gEventHandlerMethods[] = {
1533     {"native_setup",
1534         "(Ljava/lang/Object;)V",
1535         (void *)android_media_AudioSystem_eventHandlerSetup},
1536     {"native_finalize",
1537         "()V",
1538         (void *)android_media_AudioSystem_eventHandlerFinalize},
1539 };
1540 
register_android_media_AudioSystem(JNIEnv * env)1541 int register_android_media_AudioSystem(JNIEnv *env)
1542 {
1543 
1544     jclass arrayListClass = env->FindClass("java/util/ArrayList");
1545     gArrayListClass = (jclass) env->NewGlobalRef(arrayListClass);
1546     gArrayListMethods.add = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
1547     gArrayListMethods.toArray = env->GetMethodID(arrayListClass, "toArray", "()[Ljava/lang/Object;");
1548 
1549     jclass audioHandleClass = env->FindClass("android/media/AudioHandle");
1550     gAudioHandleClass = (jclass) env->NewGlobalRef(audioHandleClass);
1551     gAudioHandleCstor = env->GetMethodID(audioHandleClass, "<init>", "(I)V");
1552     gAudioHandleFields.mId = env->GetFieldID(audioHandleClass, "mId", "I");
1553 
1554     jclass audioPortClass = env->FindClass("android/media/AudioPort");
1555     gAudioPortClass = (jclass) env->NewGlobalRef(audioPortClass);
1556     gAudioPortCstor = env->GetMethodID(audioPortClass, "<init>",
1557                                "(Landroid/media/AudioHandle;I[I[I[I[Landroid/media/AudioGain;)V");
1558     gAudioPortFields.mHandle = env->GetFieldID(audioPortClass, "mHandle",
1559                                                "Landroid/media/AudioHandle;");
1560     gAudioPortFields.mRole = env->GetFieldID(audioPortClass, "mRole", "I");
1561     gAudioPortFields.mGains = env->GetFieldID(audioPortClass, "mGains",
1562                                               "[Landroid/media/AudioGain;");
1563     gAudioPortFields.mActiveConfig = env->GetFieldID(audioPortClass, "mActiveConfig",
1564                                               "Landroid/media/AudioPortConfig;");
1565 
1566     jclass audioPortConfigClass = env->FindClass("android/media/AudioPortConfig");
1567     gAudioPortConfigClass = (jclass) env->NewGlobalRef(audioPortConfigClass);
1568     gAudioPortConfigCstor = env->GetMethodID(audioPortConfigClass, "<init>",
1569                                  "(Landroid/media/AudioPort;IIILandroid/media/AudioGainConfig;)V");
1570     gAudioPortConfigFields.mPort = env->GetFieldID(audioPortConfigClass, "mPort",
1571                                                    "Landroid/media/AudioPort;");
1572     gAudioPortConfigFields.mSamplingRate = env->GetFieldID(audioPortConfigClass,
1573                                                            "mSamplingRate", "I");
1574     gAudioPortConfigFields.mChannelMask = env->GetFieldID(audioPortConfigClass,
1575                                                           "mChannelMask", "I");
1576     gAudioPortConfigFields.mFormat = env->GetFieldID(audioPortConfigClass, "mFormat", "I");
1577     gAudioPortConfigFields.mGain = env->GetFieldID(audioPortConfigClass, "mGain",
1578                                                    "Landroid/media/AudioGainConfig;");
1579     gAudioPortConfigFields.mConfigMask = env->GetFieldID(audioPortConfigClass, "mConfigMask", "I");
1580 
1581     jclass audioDevicePortConfigClass = env->FindClass("android/media/AudioDevicePortConfig");
1582     gAudioDevicePortConfigClass = (jclass) env->NewGlobalRef(audioDevicePortConfigClass);
1583     gAudioDevicePortConfigCstor = env->GetMethodID(audioDevicePortConfigClass, "<init>",
1584                          "(Landroid/media/AudioDevicePort;IIILandroid/media/AudioGainConfig;)V");
1585 
1586     jclass audioMixPortConfigClass = env->FindClass("android/media/AudioMixPortConfig");
1587     gAudioMixPortConfigClass = (jclass) env->NewGlobalRef(audioMixPortConfigClass);
1588     gAudioMixPortConfigCstor = env->GetMethodID(audioMixPortConfigClass, "<init>",
1589                          "(Landroid/media/AudioMixPort;IIILandroid/media/AudioGainConfig;)V");
1590 
1591     jclass audioDevicePortClass = env->FindClass("android/media/AudioDevicePort");
1592     gAudioDevicePortClass = (jclass) env->NewGlobalRef(audioDevicePortClass);
1593     gAudioDevicePortCstor = env->GetMethodID(audioDevicePortClass, "<init>",
1594              "(Landroid/media/AudioHandle;[I[I[I[Landroid/media/AudioGain;ILjava/lang/String;)V");
1595 
1596     jclass audioMixPortClass = env->FindClass("android/media/AudioMixPort");
1597     gAudioMixPortClass = (jclass) env->NewGlobalRef(audioMixPortClass);
1598     gAudioMixPortCstor = env->GetMethodID(audioMixPortClass, "<init>",
1599                               "(Landroid/media/AudioHandle;I[I[I[I[Landroid/media/AudioGain;)V");
1600 
1601     jclass audioGainClass = env->FindClass("android/media/AudioGain");
1602     gAudioGainClass = (jclass) env->NewGlobalRef(audioGainClass);
1603     gAudioGainCstor = env->GetMethodID(audioGainClass, "<init>", "(IIIIIIIII)V");
1604 
1605     jclass audioGainConfigClass = env->FindClass("android/media/AudioGainConfig");
1606     gAudioGainConfigClass = (jclass) env->NewGlobalRef(audioGainConfigClass);
1607     gAudioGainConfigCstor = env->GetMethodID(audioGainConfigClass, "<init>",
1608                                              "(ILandroid/media/AudioGain;II[II)V");
1609     gAudioGainConfigFields.mIndex = env->GetFieldID(gAudioGainConfigClass, "mIndex", "I");
1610     gAudioGainConfigFields.mMode = env->GetFieldID(audioGainConfigClass, "mMode", "I");
1611     gAudioGainConfigFields.mChannelMask = env->GetFieldID(audioGainConfigClass, "mChannelMask",
1612                                                           "I");
1613     gAudioGainConfigFields.mValues = env->GetFieldID(audioGainConfigClass, "mValues", "[I");
1614     gAudioGainConfigFields.mRampDurationMs = env->GetFieldID(audioGainConfigClass,
1615                                                              "mRampDurationMs", "I");
1616 
1617     jclass audioPatchClass = env->FindClass("android/media/AudioPatch");
1618     gAudioPatchClass = (jclass) env->NewGlobalRef(audioPatchClass);
1619     gAudioPatchCstor = env->GetMethodID(audioPatchClass, "<init>",
1620 "(Landroid/media/AudioHandle;[Landroid/media/AudioPortConfig;[Landroid/media/AudioPortConfig;)V");
1621     gAudioPatchFields.mHandle = env->GetFieldID(audioPatchClass, "mHandle",
1622                                                 "Landroid/media/AudioHandle;");
1623 
1624     jclass eventHandlerClass = env->FindClass(kEventHandlerClassPathName);
1625     gPostEventFromNative = env->GetStaticMethodID(eventHandlerClass, "postEventFromNative",
1626                                             "(Ljava/lang/Object;IIILjava/lang/Object;)V");
1627 
1628 
1629     jclass audioMixClass = env->FindClass("android/media/audiopolicy/AudioMix");
1630     gAudioMixClass = (jclass) env->NewGlobalRef(audioMixClass);
1631     gAudioMixFields.mRule = env->GetFieldID(audioMixClass, "mRule",
1632                                                 "Landroid/media/audiopolicy/AudioMixingRule;");
1633     gAudioMixFields.mFormat = env->GetFieldID(audioMixClass, "mFormat",
1634                                                 "Landroid/media/AudioFormat;");
1635     gAudioMixFields.mRouteFlags = env->GetFieldID(audioMixClass, "mRouteFlags", "I");
1636     gAudioMixFields.mRegistrationId = env->GetFieldID(audioMixClass, "mRegistrationId",
1637                                                       "Ljava/lang/String;");
1638     gAudioMixFields.mMixType = env->GetFieldID(audioMixClass, "mMixType", "I");
1639 
1640     jclass audioFormatClass = env->FindClass("android/media/AudioFormat");
1641     gAudioFormatClass = (jclass) env->NewGlobalRef(audioFormatClass);
1642     gAudioFormatFields.mEncoding = env->GetFieldID(audioFormatClass, "mEncoding", "I");
1643     gAudioFormatFields.mSampleRate = env->GetFieldID(audioFormatClass, "mSampleRate", "I");
1644     gAudioFormatFields.mChannelMask = env->GetFieldID(audioFormatClass, "mChannelMask", "I");
1645 
1646     jclass audioMixingRuleClass = env->FindClass("android/media/audiopolicy/AudioMixingRule");
1647     gAudioMixingRuleClass = (jclass) env->NewGlobalRef(audioMixingRuleClass);
1648     gAudioMixingRuleFields.mCriteria = env->GetFieldID(audioMixingRuleClass, "mCriteria",
1649                                                        "Ljava/util/ArrayList;");
1650 
1651     jclass attributeMatchCriterionClass =
1652                 env->FindClass("android/media/audiopolicy/AudioMixingRule$AttributeMatchCriterion");
1653     gAttributeMatchCriterionClass = (jclass) env->NewGlobalRef(attributeMatchCriterionClass);
1654     gAttributeMatchCriterionFields.mAttr = env->GetFieldID(attributeMatchCriterionClass, "mAttr",
1655                                                        "Landroid/media/AudioAttributes;");
1656     gAttributeMatchCriterionFields.mRule = env->GetFieldID(attributeMatchCriterionClass, "mRule",
1657                                                        "I");
1658 
1659     jclass audioAttributesClass = env->FindClass("android/media/AudioAttributes");
1660     gAudioAttributesClass = (jclass) env->NewGlobalRef(audioAttributesClass);
1661     gAudioAttributesFields.mUsage = env->GetFieldID(audioAttributesClass, "mUsage", "I");
1662     gAudioAttributesFields.mSource = env->GetFieldID(audioAttributesClass, "mSource", "I");
1663 
1664     AudioSystem::setErrorCallback(android_media_AudioSystem_error_callback);
1665 
1666     int status = AndroidRuntime::registerNativeMethods(env,
1667                 kClassPathName, gMethods, NELEM(gMethods));
1668 
1669     if (status == 0) {
1670         status = AndroidRuntime::registerNativeMethods(env,
1671                 kEventHandlerClassPathName, gEventHandlerMethods, NELEM(gEventHandlerMethods));
1672     }
1673     return status;
1674 }
1675