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