142309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi/*
242309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi * Copyright (C) 2010 The Android Open Source Project
342309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi *
442309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License");
542309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi * you may not use this file except in compliance with the License.
642309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi * You may obtain a copy of the License at
742309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi *
842309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi *      http://www.apache.org/licenses/LICENSE-2.0
942309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi *
1042309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi * Unless required by applicable law or agreed to in writing, software
1142309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS,
1242309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1342309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi * See the License for the specific language governing permissions and
1442309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi * limitations under the License.
1542309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi */
1642309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi
1742309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi/* AndroidConfiguration implementation */
1842309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi
19053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean#include <android/log.h>
20053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean
2142309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi#include "sles_allinclusive.h"
22e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean#include <SLES/OpenSLES_Android.h>
2342309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi
24053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean#include <android_runtime/AndroidRuntime.h>
25053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean
2642309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivistatic SLresult IAndroidConfiguration_SetConfiguration(SLAndroidConfigurationItf self,
2742309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi        const SLchar *configKey,
2842309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi        const void *pConfigValue,
2942309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi        SLuint32 valueSize)
3042309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi{
3142309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi    SL_ENTER_INTERFACE
3242309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi
33c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten    // object-specific code will check that valueSize is large enough for the key
34c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten    if (NULL == configKey || NULL == pConfigValue || valueSize == 0) {
35c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten        result = SL_RESULT_PARAMETER_INVALID;
36b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi
3775e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi    } else {
38c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten        IAndroidConfiguration *thiz = (IAndroidConfiguration *) self;
39c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten        interface_lock_exclusive(thiz);
4042309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi
41c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten        // route configuration to the appropriate object
42c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten        switch (IObjectToObjectID((thiz)->mThis)) {
43c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten        case SL_OBJECTID_AUDIORECORDER:
44c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten            SL_LOGV("SetConfiguration issued for AudioRecorder key=%s valueSize=%u",
45c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten                    configKey, valueSize);
46c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten            result = android_audioRecorder_setConfig((CAudioRecorder *) thiz->mThis, configKey,
47c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten                    pConfigValue, valueSize);
48c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten            break;
49c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten        case SL_OBJECTID_AUDIOPLAYER:
50c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten            SL_LOGV("SetConfiguration issued for AudioPlayer key=%s valueSize=%u",
51c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten                    configKey, valueSize);
52c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten            result = android_audioPlayer_setConfig((CAudioPlayer *) thiz->mThis, configKey,
53c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten                    pConfigValue, valueSize);
54c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten            break;
55c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten        default:
56c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten            result = SL_RESULT_FEATURE_UNSUPPORTED;
57c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten            break;
58c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten        }
59c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten
60c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten        interface_unlock_exclusive(thiz);
61c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten    }
6242309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi
6342309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi    SL_LEAVE_INTERFACE
6442309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi}
6542309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi
6642309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi
6742309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivistatic SLresult IAndroidConfiguration_GetConfiguration(SLAndroidConfigurationItf self,
6842309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi        const SLchar *configKey,
6942309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi        SLuint32 *pValueSize,
7042309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi        void *pConfigValue)
7142309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi{
7242309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi    SL_ENTER_INTERFACE
7342309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi
74c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten    // non-NULL pValueSize is required, but a NULL pConfigValue is allowed, so
75c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten    // that we can report the actual value size without returning the value itself
76c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten    if (NULL == configKey || NULL == pValueSize) {
7742309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi        result = SL_RESULT_PARAMETER_INVALID;
7842309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi    } else {
79bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        IAndroidConfiguration *thiz = (IAndroidConfiguration *) self;
80bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        interface_lock_exclusive(thiz);
81b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi
82b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        // route configuration request to the appropriate object
83c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten        switch (IObjectToObjectID((thiz)->mThis)) {
84c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten        case SL_OBJECTID_AUDIORECORDER:
85bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten            result = android_audioRecorder_getConfig((CAudioRecorder *) thiz->mThis, configKey,
86b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi                    pValueSize, pConfigValue);
87c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten            break;
88c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten        case SL_OBJECTID_AUDIOPLAYER:
89bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten            result = android_audioPlayer_getConfig((CAudioPlayer *) thiz->mThis, configKey,
9075e22870e41386cdc597bd29c76744d74d4c22adJean-Michel Trivi                    pValueSize, pConfigValue);
91c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten        default:
92c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten            result = SL_RESULT_FEATURE_UNSUPPORTED;
93c2a325746469c4c7625ec78a169b65a11dbe1e30Glenn Kasten            break;
94b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi        }
95b3e52a63baaea367cf411348b68ecd8fd429b029Jean-Michel Trivi
96bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten        interface_unlock_exclusive(thiz);
9742309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi    }
9842309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi
9942309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi    SL_LEAVE_INTERFACE
10042309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi}
10142309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi
102e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean/*
103e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean * Native Routing API
104e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean */
105053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLeanstatic SLresult ValidatePlayerConfig(IAndroidConfiguration* iConfig) {
106053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    SLresult result;
107053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean
108053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    if (iConfig->mRoutingProxy != NULL) {
109053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean        result = SL_RESULT_PRECONDITIONS_VIOLATED;
11003c708c0b6c04d738aabe45ea7e6615e60f43963Paul McLean        SL_LOGE("Error creating player routing object - Routing Proxy Already Acquired.");
111053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    }
112053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    else {
113053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean        IObject* configObj = iConfig->mThis;                // get corresponding object
114053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean        CAudioPlayer* player = (CAudioPlayer*)configObj;    // get the native player
115053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean
116053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean        switch (player->mAndroidObjType) {
117053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean            case AUDIOPLAYER_FROM_PCM_BUFFERQUEUE:
11803c708c0b6c04d738aabe45ea7e6615e60f43963Paul McLean                //TODO remove these commented out lines when our comfort level is good
11915f1e492e8fe7e2b6665009b5facd2b42913ab0fPaul McLean//                if (player->mObject.mState != SL_OBJECT_STATE_REALIZED) {
12015f1e492e8fe7e2b6665009b5facd2b42913ab0fPaul McLean//                    // Make sure the player has been realized.
12115f1e492e8fe7e2b6665009b5facd2b42913ab0fPaul McLean//                    result = SL_RESULT_PRECONDITIONS_VIOLATED;
12215f1e492e8fe7e2b6665009b5facd2b42913ab0fPaul McLean//                    SL_LOGE("Error creating routing object - Player not realized.");
12315f1e492e8fe7e2b6665009b5facd2b42913ab0fPaul McLean//                } else {
12415f1e492e8fe7e2b6665009b5facd2b42913ab0fPaul McLean//                    android::AudioTrack* pAudioTrack = player->mAudioTrack.get();
12515f1e492e8fe7e2b6665009b5facd2b42913ab0fPaul McLean//                    if (pAudioTrack == NULL) {
12615f1e492e8fe7e2b6665009b5facd2b42913ab0fPaul McLean//                        result = SL_RESULT_INTERNAL_ERROR;
12715f1e492e8fe7e2b6665009b5facd2b42913ab0fPaul McLean//                        SL_LOGE("Error creating routing object - Couldn't get AudioTrack.");
12815f1e492e8fe7e2b6665009b5facd2b42913ab0fPaul McLean//                    } else {
12915f1e492e8fe7e2b6665009b5facd2b42913ab0fPaul McLean                        result = SL_RESULT_SUCCESS;
13015f1e492e8fe7e2b6665009b5facd2b42913ab0fPaul McLean//                    }
13115f1e492e8fe7e2b6665009b5facd2b42913ab0fPaul McLean//                }
132053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                break;
133053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean
134053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean            default:
135053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                result =  SL_RESULT_PARAMETER_INVALID;
136053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                SL_LOGE("Error creating routing object - Player is not a buffer-queue player.");
137053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                break;
138053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean        }
139053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    }
140053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean
141053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    return result;
142053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean}
143053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean
144053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLeanstatic SLresult AllocPlayerRoutingProxy(IAndroidConfiguration* iConfig, jobject* proxyObj) {
145053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    SLresult result;
146053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean
147053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    IObject* configObj = iConfig->mThis;                // get corresponding object
148053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    android::AudioTrack* pAudioTrack = ((CAudioPlayer*)configObj)->mAudioTrack.get();
149053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean
150053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    JNIEnv* j_env = android::AndroidRuntime::getJNIEnv();
151053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean
152053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    // Get the constructor for (Java) AudioTrackRoutingProxy
153053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    jclass clsAudioTrackRoutingProxy =
154053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean            j_env->FindClass("android/media/AudioTrackRoutingProxy");
155053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    jmethodID midAudioTrackRoutingProxy_ctor =
156053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean        j_env->GetMethodID(clsAudioTrackRoutingProxy, "<init>", "(J)V");
157053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean
158053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    j_env->ExceptionClear();
159053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean
160053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    jobject localObjRef =
161053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean        j_env->NewObject(clsAudioTrackRoutingProxy,
162053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                         midAudioTrackRoutingProxy_ctor,
16303c708c0b6c04d738aabe45ea7e6615e60f43963Paul McLean                         (jlong)pAudioTrack /*audioTrackObjInLong*/);
16403c708c0b6c04d738aabe45ea7e6615e60f43963Paul McLean
165053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    *proxyObj = j_env->NewGlobalRef(localObjRef);
166053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean
167053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    if (j_env->ExceptionCheck()) {
168053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean        SL_LOGE("Java exception creating player routing object.");
169053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean        result = SL_RESULT_INTERNAL_ERROR;
170053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    } else {
171053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean        // stash it in the Interface object
172053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean        iConfig->mRoutingProxy = *proxyObj;
173053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean        result = SL_RESULT_SUCCESS;
174053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    }
175053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean
176053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    return result;
177053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean}
178053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean
179053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLeanstatic SLresult ValidateRecorderConfig(IAndroidConfiguration* iConfig) {
180053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    SLresult result;
181053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean
182053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    if (iConfig->mRoutingProxy != NULL) {
183053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean        result = SL_RESULT_PRECONDITIONS_VIOLATED;
18403c708c0b6c04d738aabe45ea7e6615e60f43963Paul McLean        SL_LOGE("Error creating record routing object - Routing Proxy Already Acquired.");
185053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    } else {
186053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean        IObject* configObj = iConfig->mThis;                  // get corresponding object
187053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean        CAudioRecorder* recorder = (CAudioRecorder*)configObj;  // get the native recorder
188053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean        switch (recorder->mAndroidObjType) {
189053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean            case AUDIORECORDER_FROM_MIC_TO_PCM_BUFFERQUEUE:
19003c708c0b6c04d738aabe45ea7e6615e60f43963Paul McLean                //TODO remove these commented out lines when our comfort level is good
19103c708c0b6c04d738aabe45ea7e6615e60f43963Paul McLean//                if (recorder->mObject.mState != SL_OBJECT_STATE_REALIZED) {
19203c708c0b6c04d738aabe45ea7e6615e60f43963Paul McLean//                    // Make sure the recorder has been realized.
19303c708c0b6c04d738aabe45ea7e6615e60f43963Paul McLean//                    result = SL_RESULT_PRECONDITIONS_VIOLATED;
19403c708c0b6c04d738aabe45ea7e6615e60f43963Paul McLean//                    SL_LOGE("Error creating routing object - Recorder not realized.");
19503c708c0b6c04d738aabe45ea7e6615e60f43963Paul McLean//                } else {
19603c708c0b6c04d738aabe45ea7e6615e60f43963Paul McLean//                    android::AudioRecord* pAudioRecord = recorder->mAudioRecord.get();
19703c708c0b6c04d738aabe45ea7e6615e60f43963Paul McLean//                    if (pAudioRecord == NULL) {
19803c708c0b6c04d738aabe45ea7e6615e60f43963Paul McLean//                        result = SL_RESULT_INTERNAL_ERROR;
19903c708c0b6c04d738aabe45ea7e6615e60f43963Paul McLean//                        SL_LOGE("Error creating routing object - Couldn't get AudioRecord.");
20003c708c0b6c04d738aabe45ea7e6615e60f43963Paul McLean//                    } else if (iConfig->mRoutingProxy != NULL) {
20103c708c0b6c04d738aabe45ea7e6615e60f43963Paul McLean//                        result = SL_RESULT_PRECONDITIONS_VIOLATED;
20203c708c0b6c04d738aabe45ea7e6615e60f43963Paul McLean//                        SL_LOGE("Error creating routing object - Routing Proxy Already Acquired.");
20303c708c0b6c04d738aabe45ea7e6615e60f43963Paul McLean//                    } else {
204053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                        result = SL_RESULT_SUCCESS;
20503c708c0b6c04d738aabe45ea7e6615e60f43963Paul McLean//                    }
20603c708c0b6c04d738aabe45ea7e6615e60f43963Paul McLean//                }
207053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                break;
208053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean
209053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean            default:
210053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                result =  SL_RESULT_PARAMETER_INVALID;
211053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                SL_LOGE("Error creating routing object - Recorder is not a buffer-queue recorder.");
212053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                break;
213053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean        }
214053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    }
215053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean
216053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    return result;
217053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean}
218053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean
219053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLeanstatic SLresult AllocRecorderRoutingProxy(IAndroidConfiguration* iConfig, jobject* proxyObj) {
220053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    SLresult result;
221053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean
222053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    IObject* configObj = iConfig->mThis;                  // get corresponding object
223053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    android::AudioRecord* pAudioRecord = ((CAudioRecorder*)configObj)->mAudioRecord.get();
224053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean
225053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    JNIEnv* j_env = android::AndroidRuntime::getJNIEnv();
226053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean
227053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    // Get the constructor for (Java) AudioRecordRoutingProxy
228053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    jclass clsAudioRecordRoutingProxy =
229053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean            j_env->FindClass("android/media/AudioRecordRoutingProxy");
230053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    jmethodID midAudioRecordRoutingProxy_ctor =
231053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean        j_env->GetMethodID(clsAudioRecordRoutingProxy, "<init>", "(J)V");
232053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean
233053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    j_env->ExceptionClear();
234053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    jobject localObjRef =
23503c708c0b6c04d738aabe45ea7e6615e60f43963Paul McLean        j_env->NewObject(clsAudioRecordRoutingProxy,
23603c708c0b6c04d738aabe45ea7e6615e60f43963Paul McLean                         midAudioRecordRoutingProxy_ctor,
23703c708c0b6c04d738aabe45ea7e6615e60f43963Paul McLean                         (jlong)pAudioRecord /*audioRecordObjInLong*/);
23803c708c0b6c04d738aabe45ea7e6615e60f43963Paul McLean
239053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    *proxyObj = j_env->NewGlobalRef(localObjRef);
240053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    if (j_env->ExceptionCheck()) {
241053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean        SL_LOGE("Java exception creating recorder routing object.");
242053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean        result = SL_RESULT_INTERNAL_ERROR;
243053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    } else {
244053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean        // stash it in the Interface object
245053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean        iConfig->mRoutingProxy = *proxyObj;
246053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean        result = SL_RESULT_SUCCESS;
247053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    }
248053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean
249053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    return result;
250053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean}
251e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean
252e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean/*
253053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean * Acquires a Java proxy object, such as AudioRouting object which can be used to control
254053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean * aspects of the associated native player or recorder.
255e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean * Parameters:
256e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean *   self   An SLAndroidConfigurationItf obtained from either an OpenSL ES AudioPlayer
257e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean *          or AudioRecorder.
258e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean *   j_env  The Java Environment pointer (passed in to the calling JNI function).
259053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean *   proxyType Specifies the type of proxy desired. Currently only SL_ANDROID_JAVA_PROXY_ROUTING
260053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean *          is supported.
261053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean *   proxyObj
262053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean *          Points to the jobject to receive the acquired Java proxy object (as a GlobalRef).
263053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean * Returns SL_RESULT_SUCCESS is the proxy object is acquired, SL_RESULT_PARAMETER_INVALID if
264e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean *   there is a problem with the arguments causing the function to fail,
265053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean *   <working on this>
266e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean *   SL_RESULT_PRECONDITIONS_VIOLATED it the AudioPlayer or AudioRecorder object associated
267e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean *   with the ConfigurationItf has not been realized.
268e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean */
269053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLeanstatic SLresult IAndroidConfiguration_AcquireJavaProxy(SLAndroidConfigurationItf self,
270053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                                                       SLuint32 proxyType,
271053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                                                       jobject* proxyObj)
272e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean{
273e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean    SL_ENTER_INTERFACE
274e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean
275053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    if (self == NULL || proxyObj == NULL || proxyType != SL_ANDROID_JAVA_PROXY_ROUTING) {
276e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean        result =  SL_RESULT_PARAMETER_INVALID;
277e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean    } else {
278053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean        IAndroidConfiguration* iConfig = (IAndroidConfiguration*)self;
279e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean
280053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean        int objID = IObjectToObjectID(InterfaceToIObject(iConfig));
281053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean        switch (objID) {
282e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean        case SL_OBJECTID_AUDIOPLAYER:
283053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean            result = ValidatePlayerConfig(iConfig);
284053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean            if (result == SL_RESULT_SUCCESS) {
285053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                result = AllocPlayerRoutingProxy(iConfig, proxyObj);
286e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean            }
287e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean            break;
288e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean
289e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean        case SL_OBJECTID_AUDIORECORDER:
290053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean            result = ValidateRecorderConfig(iConfig);
291053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean            if (result == SL_RESULT_SUCCESS) {
292053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                result = AllocRecorderRoutingProxy(iConfig, proxyObj);
293e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean            }
294e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean            break;
295e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean
296e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean        default:
297e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean            result = SL_RESULT_PARAMETER_INVALID;
298e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean            break;
299e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean        }
300e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean    }
301e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean
302e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean    SL_LEAVE_INTERFACE
303e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean}
30442309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi
305053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean/*
306053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean * Release a Java proxy object, such as AudioRouting object, (and any resources it is holding).
307053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean * Parameters:
308053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean *   self   An SLAndroidConfigurationItf obtained from either an OpenSL ES AudioPlayer
309053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean *          or AudioRecorder.
310053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean *   j_env  The Java Environment pointer (passed in to the calling JNI function).
311053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean *   proxyType Specifies the type of proxy object. Currently only SL_ANDROID_JAVA_PROXY_ROUTING
312053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean *          is supported.
313053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean * Returns SL_RESULT_SUCCESS is the proxy object is release, SL_RESULT_PARAMETER_INVALID if
314053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean *   there is a problem with the arguments causing the function to fail,
315053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean */
316053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLeanstatic SLresult IAndroidConfiguration_ReleaseJavaProxy(SLAndroidConfigurationItf self,
317053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                                                       SLuint32 proxyType) {
318053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    SL_ENTER_INTERFACE
319053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean
320053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    IAndroidConfiguration* iConfig = (IAndroidConfiguration*)self;
321053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean
322053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    if (self == NULL ||
323053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean            proxyType != SL_ANDROID_JAVA_PROXY_ROUTING ||
324053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean            iConfig->mRoutingProxy == NULL) {
325053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean        result =  SL_RESULT_PARAMETER_INVALID;
326053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    } else {
327053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean        int objID = IObjectToObjectID(InterfaceToIObject(iConfig));
328053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean        switch (objID) {
329053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean        case SL_OBJECTID_AUDIOPLAYER:
330053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean            {
331053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                JNIEnv* j_env = android::AndroidRuntime::getJNIEnv();
332053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean
333053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                // Get the release method for (Java) AudioTrackRoutingProxy
334053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                jclass clsAudioTrackRoutingProxy =
335053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                        j_env->FindClass("android/media/AudioTrackRoutingProxy");
336053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                jmethodID midAudioTrackRoutingProxy_release =
337053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                    j_env->GetMethodID(clsAudioTrackRoutingProxy, "native_release", "()V");
338053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean
339053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                j_env->ExceptionClear();
340053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                j_env->CallVoidMethod(iConfig->mRoutingProxy, midAudioTrackRoutingProxy_release);
341053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                if (j_env->ExceptionCheck()) {
342053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                    SL_LOGE("Java exception releasing recorder routing object.");
343053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                    result = SL_RESULT_INTERNAL_ERROR;
344053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                }
345053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                j_env->DeleteGlobalRef(iConfig->mRoutingProxy);
346053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                iConfig->mRoutingProxy = NULL;
347053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean            }
348053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean            break;
349053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean
350053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean        case SL_OBJECTID_AUDIORECORDER:
351053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean            {
352053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                JNIEnv* j_env = android::AndroidRuntime::getJNIEnv();
353053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean
354053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                // Get the release method for (Java) AudioTrackRoutingProxy
355053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                jclass clsAudioRecordRoutingProxy =
356053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                        j_env->FindClass("android/media/AudioRecordRoutingProxy");
357053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                jmethodID midAudioRecordRoutingProxy_release =
358053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                    j_env->GetMethodID(clsAudioRecordRoutingProxy, "native_release", "()V");
359053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean
360053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                j_env->ExceptionClear();
361053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                j_env->CallVoidMethod(iConfig->mRoutingProxy, midAudioRecordRoutingProxy_release);
362053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                if (j_env->ExceptionCheck()) {
363053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                    SL_LOGE("Java exception releasing recorder routing object.");
364053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                    result = SL_RESULT_INTERNAL_ERROR;
365053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                }
366053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                j_env->DeleteGlobalRef(iConfig->mRoutingProxy);
367053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean                iConfig->mRoutingProxy = NULL;
368053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean            }
369053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean            break;
370053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean        }
37103c708c0b6c04d738aabe45ea7e6615e60f43963Paul McLean
372053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean        result = SL_RESULT_SUCCESS;
373053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    }
374053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean
375053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    SL_LEAVE_INTERFACE
376053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean}
377053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean
37842309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivistatic const struct SLAndroidConfigurationItf_ IAndroidConfiguration_Itf = {
37942309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi    IAndroidConfiguration_SetConfiguration,
380e2a4e0e1e87efb61bb62d08e7744a6d57ec4a38ePaul McLean    IAndroidConfiguration_GetConfiguration,
381053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    IAndroidConfiguration_AcquireJavaProxy,
382053b3c2696e5e1b28dd5e02c54b0e3aedc21168dPaul McLean    IAndroidConfiguration_ReleaseJavaProxy
38342309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi};
38442309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi
38542309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivivoid IAndroidConfiguration_init(void *self)
38642309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi{
387bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    IAndroidConfiguration *thiz = (IAndroidConfiguration *) self;
388bcc5c7225e3b7a1dbf2e9e830987f69167acf06fGlenn Kasten    thiz->mItf = &IAndroidConfiguration_Itf;
38942309377d1ed17b557fab30f1bf26b8ba31a96fdJean-Michel Trivi}
3909f48e6a5f01aa87fab5c5cc867f8b078f96d1a45Paul McLean
3919f48e6a5f01aa87fab5c5cc867f8b078f96d1a45Paul McLeanvoid IAndroidConfiguration_deinit(void *self)
3929f48e6a5f01aa87fab5c5cc867f8b078f96d1a45Paul McLean{
3939f48e6a5f01aa87fab5c5cc867f8b078f96d1a45Paul McLean    IAndroidConfiguration *thiz = (IAndroidConfiguration *) self;
3949f48e6a5f01aa87fab5c5cc867f8b078f96d1a45Paul McLean    if (thiz->mRoutingProxy != NULL) {
3959f48e6a5f01aa87fab5c5cc867f8b078f96d1a45Paul McLean        thiz->mItf->ReleaseJavaProxy(&thiz->mItf, SL_ANDROID_JAVA_PROXY_ROUTING);
3969f48e6a5f01aa87fab5c5cc867f8b078f96d1a45Paul McLean    }
3979f48e6a5f01aa87fab5c5cc867f8b078f96d1a45Paul McLean}
3989f48e6a5f01aa87fab5c5cc867f8b078f96d1a45Paul McLean
399