1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /* AndroidConfiguration implementation */ 18 19 #include <android/log.h> 20 21 #include "sles_allinclusive.h" 22 #include <SLES/OpenSLES_Android.h> 23 24 #include <android_runtime/AndroidRuntime.h> 25 26 extern jmethodID gMidAudioTrackRoutingProxy_ctor; 27 extern jmethodID gMidAudioTrackRoutingProxy_release; 28 extern jmethodID gMidAudioRecordRoutingProxy_ctor; 29 extern jmethodID gMidAudioRecordRoutingProxy_release; 30 31 extern jclass gClsAudioTrackRoutingProxy; 32 extern jclass gClsAudioRecordRoutingProxy; 33 34 static SLresult IAndroidConfiguration_SetConfiguration(SLAndroidConfigurationItf self, 35 const SLchar *configKey, 36 const void *pConfigValue, 37 SLuint32 valueSize) 38 { 39 SL_ENTER_INTERFACE 40 41 // object-specific code will check that valueSize is large enough for the key 42 if (NULL == configKey || NULL == pConfigValue || valueSize == 0) { 43 result = SL_RESULT_PARAMETER_INVALID; 44 45 } else { 46 IAndroidConfiguration *thiz = (IAndroidConfiguration *) self; 47 interface_lock_exclusive(thiz); 48 49 // route configuration to the appropriate object 50 switch (IObjectToObjectID((thiz)->mThis)) { 51 case SL_OBJECTID_AUDIORECORDER: 52 SL_LOGV("SetConfiguration issued for AudioRecorder key=%s valueSize=%u", 53 configKey, valueSize); 54 result = android_audioRecorder_setConfig((CAudioRecorder *) thiz->mThis, configKey, 55 pConfigValue, valueSize); 56 break; 57 case SL_OBJECTID_AUDIOPLAYER: 58 SL_LOGV("SetConfiguration issued for AudioPlayer key=%s valueSize=%u", 59 configKey, valueSize); 60 result = android_audioPlayer_setConfig((CAudioPlayer *) thiz->mThis, configKey, 61 pConfigValue, valueSize); 62 break; 63 default: 64 result = SL_RESULT_FEATURE_UNSUPPORTED; 65 break; 66 } 67 68 interface_unlock_exclusive(thiz); 69 } 70 71 SL_LEAVE_INTERFACE 72 } 73 74 75 static SLresult IAndroidConfiguration_GetConfiguration(SLAndroidConfigurationItf self, 76 const SLchar *configKey, 77 SLuint32 *pValueSize, 78 void *pConfigValue) 79 { 80 SL_ENTER_INTERFACE 81 82 // non-NULL pValueSize is required, but a NULL pConfigValue is allowed, so 83 // that we can report the actual value size without returning the value itself 84 if (NULL == configKey || NULL == pValueSize) { 85 result = SL_RESULT_PARAMETER_INVALID; 86 } else { 87 IAndroidConfiguration *thiz = (IAndroidConfiguration *) self; 88 interface_lock_exclusive(thiz); 89 90 // route configuration request to the appropriate object 91 switch (IObjectToObjectID((thiz)->mThis)) { 92 case SL_OBJECTID_AUDIORECORDER: 93 result = android_audioRecorder_getConfig((CAudioRecorder *) thiz->mThis, configKey, 94 pValueSize, pConfigValue); 95 break; 96 case SL_OBJECTID_AUDIOPLAYER: 97 result = android_audioPlayer_getConfig((CAudioPlayer *) thiz->mThis, configKey, 98 pValueSize, pConfigValue); 99 break; 100 default: 101 result = SL_RESULT_FEATURE_UNSUPPORTED; 102 break; 103 } 104 105 interface_unlock_exclusive(thiz); 106 } 107 108 SL_LEAVE_INTERFACE 109 } 110 111 /* 112 * Native Routing API 113 */ 114 static SLresult ValidatePlayerConfig(IAndroidConfiguration* iConfig) { 115 SLresult result; 116 117 if (iConfig->mRoutingProxy != NULL) { 118 result = SL_RESULT_PRECONDITIONS_VIOLATED; 119 SL_LOGE("Error creating player routing object - Routing Proxy Already Acquired."); 120 } 121 else { 122 IObject* configObj = iConfig->mThis; // get corresponding object 123 CAudioPlayer* player = (CAudioPlayer*)configObj; // get the native player 124 125 switch (player->mAndroidObjType) { 126 case AUDIOPLAYER_FROM_PCM_BUFFERQUEUE: 127 //TODO remove these commented out lines when our comfort level is good 128 // if (player->mObject.mState != SL_OBJECT_STATE_REALIZED) { 129 // // Make sure the player has been realized. 130 // result = SL_RESULT_PRECONDITIONS_VIOLATED; 131 // SL_LOGE("Error creating routing object - Player not realized."); 132 // } else { 133 // android::AudioTrack* pAudioTrack = player->mAudioTrack.get(); 134 // if (pAudioTrack == NULL) { 135 // result = SL_RESULT_INTERNAL_ERROR; 136 // SL_LOGE("Error creating routing object - Couldn't get AudioTrack."); 137 // } else { 138 result = SL_RESULT_SUCCESS; 139 // } 140 // } 141 break; 142 143 default: 144 result = SL_RESULT_PARAMETER_INVALID; 145 SL_LOGE("Error creating routing object - Player is not a buffer-queue player."); 146 break; 147 } 148 } 149 150 return result; 151 } 152 153 static SLresult AllocPlayerRoutingProxy(IAndroidConfiguration* iConfig, jobject* proxyObj) { 154 SLresult result; 155 156 IObject* configObj = iConfig->mThis; // get corresponding object 157 android::AudioTrack* pAudioTrack = ((CAudioPlayer*)configObj)->mTrackPlayer->mAudioTrack.get(); 158 159 JNIEnv* j_env = android::AndroidRuntime::getJNIEnv(); 160 161 j_env->ExceptionClear(); 162 163 jobject localObjRef = 164 j_env->NewObject(gClsAudioTrackRoutingProxy, 165 gMidAudioTrackRoutingProxy_ctor, 166 (jlong)pAudioTrack /*audioTrackObjInLong*/); 167 168 *proxyObj = j_env->NewGlobalRef(localObjRef); 169 170 if (j_env->ExceptionCheck()) { 171 SL_LOGE("Java exception creating player routing object."); 172 result = SL_RESULT_INTERNAL_ERROR; 173 } else { 174 // stash it in the Interface object 175 iConfig->mRoutingProxy = *proxyObj; 176 result = SL_RESULT_SUCCESS; 177 } 178 179 return result; 180 } 181 182 static SLresult ValidateRecorderConfig(IAndroidConfiguration* iConfig) { 183 SLresult result; 184 185 if (iConfig->mRoutingProxy != NULL) { 186 result = SL_RESULT_PRECONDITIONS_VIOLATED; 187 SL_LOGE("Error creating record routing object - Routing Proxy Already Acquired."); 188 } else { 189 IObject* configObj = iConfig->mThis; // get corresponding object 190 CAudioRecorder* recorder = (CAudioRecorder*)configObj; // get the native recorder 191 switch (recorder->mAndroidObjType) { 192 case AUDIORECORDER_FROM_MIC_TO_PCM_BUFFERQUEUE: 193 //TODO remove these commented out lines when our comfort level is good 194 // if (recorder->mObject.mState != SL_OBJECT_STATE_REALIZED) { 195 // // Make sure the recorder has been realized. 196 // result = SL_RESULT_PRECONDITIONS_VIOLATED; 197 // SL_LOGE("Error creating routing object - Recorder not realized."); 198 // } else { 199 // android::AudioRecord* pAudioRecord = recorder->mAudioRecord.get(); 200 // if (pAudioRecord == NULL) { 201 // result = SL_RESULT_INTERNAL_ERROR; 202 // SL_LOGE("Error creating routing object - Couldn't get AudioRecord."); 203 // } else if (iConfig->mRoutingProxy != NULL) { 204 // result = SL_RESULT_PRECONDITIONS_VIOLATED; 205 // SL_LOGE("Error creating routing object - Routing Proxy Already Acquired." 206 // ); 207 // } else { 208 result = SL_RESULT_SUCCESS; 209 // } 210 // } 211 break; 212 213 default: 214 result = SL_RESULT_PARAMETER_INVALID; 215 SL_LOGE("Error creating routing object - Recorder is not a buffer-queue recorder."); 216 break; 217 } 218 } 219 220 return result; 221 } 222 223 static SLresult AllocRecorderRoutingProxy(IAndroidConfiguration* iConfig, jobject* proxyObj) { 224 SLresult result; 225 226 IObject* configObj = iConfig->mThis; // get corresponding object 227 android::AudioRecord* pAudioRecord = ((CAudioRecorder*)configObj)->mAudioRecord.get(); 228 229 JNIEnv* j_env = android::AndroidRuntime::getJNIEnv(); 230 231 j_env->ExceptionClear(); 232 jobject localObjRef = 233 j_env->NewObject(gClsAudioRecordRoutingProxy, 234 gMidAudioRecordRoutingProxy_ctor, 235 (jlong)pAudioRecord /*audioRecordObjInLong*/); 236 237 *proxyObj = j_env->NewGlobalRef(localObjRef); 238 if (j_env->ExceptionCheck()) { 239 SL_LOGE("Java exception creating recorder routing object."); 240 result = SL_RESULT_INTERNAL_ERROR; 241 } else { 242 // stash it in the Interface object 243 iConfig->mRoutingProxy = *proxyObj; 244 result = SL_RESULT_SUCCESS; 245 } 246 247 return result; 248 } 249 250 /* 251 * Acquires a Java proxy object, such as AudioRouting object which can be used to control 252 * aspects of the associated native player or recorder. 253 * Parameters: 254 * self An SLAndroidConfigurationItf obtained from either an OpenSL ES AudioPlayer 255 * or AudioRecorder. 256 * j_env The Java Environment pointer (passed in to the calling JNI function). 257 * proxyType Specifies the type of proxy desired. Currently only SL_ANDROID_JAVA_PROXY_ROUTING 258 * is supported. 259 * proxyObj 260 * Points to the jobject to receive the acquired Java proxy object (as a GlobalRef). 261 * Returns SL_RESULT_SUCCESS is the proxy object is acquired, SL_RESULT_PARAMETER_INVALID if 262 * there is a problem with the arguments causing the function to fail, 263 * <working on this> 264 * SL_RESULT_PRECONDITIONS_VIOLATED it the AudioPlayer or AudioRecorder object associated 265 * with the ConfigurationItf has not been realized. 266 */ 267 static SLresult IAndroidConfiguration_AcquireJavaProxy(SLAndroidConfigurationItf self, 268 SLuint32 proxyType, 269 jobject* proxyObj) 270 { 271 SL_ENTER_INTERFACE 272 273 if (self == NULL || proxyObj == NULL || proxyType != SL_ANDROID_JAVA_PROXY_ROUTING) { 274 result = SL_RESULT_PARAMETER_INVALID; 275 } else { 276 IAndroidConfiguration* iConfig = (IAndroidConfiguration*)self; 277 278 int objID = IObjectToObjectID(InterfaceToIObject(iConfig)); 279 switch (objID) { 280 case SL_OBJECTID_AUDIOPLAYER: 281 result = ValidatePlayerConfig(iConfig); 282 if (result == SL_RESULT_SUCCESS) { 283 result = AllocPlayerRoutingProxy(iConfig, proxyObj); 284 } 285 break; 286 287 case SL_OBJECTID_AUDIORECORDER: 288 result = ValidateRecorderConfig(iConfig); 289 if (result == SL_RESULT_SUCCESS) { 290 result = AllocRecorderRoutingProxy(iConfig, proxyObj); 291 } 292 break; 293 294 default: 295 result = SL_RESULT_PARAMETER_INVALID; 296 break; 297 } 298 } 299 300 SL_LEAVE_INTERFACE 301 } 302 303 /* 304 * Release a Java proxy object, such as AudioRouting object, (and any resources it is holding). 305 * Parameters: 306 * self An SLAndroidConfigurationItf obtained from either an OpenSL ES AudioPlayer 307 * or AudioRecorder. 308 * j_env The Java Environment pointer (passed in to the calling JNI function). 309 * proxyType Specifies the type of proxy object. Currently only SL_ANDROID_JAVA_PROXY_ROUTING 310 * is supported. 311 * Returns SL_RESULT_SUCCESS is the proxy object is release, SL_RESULT_PARAMETER_INVALID if 312 * there is a problem with the arguments causing the function to fail, 313 */ 314 static SLresult IAndroidConfiguration_ReleaseJavaProxy(SLAndroidConfigurationItf self, 315 SLuint32 proxyType) { 316 SL_ENTER_INTERFACE 317 318 IAndroidConfiguration* iConfig = (IAndroidConfiguration*)self; 319 320 if (self == NULL || 321 proxyType != SL_ANDROID_JAVA_PROXY_ROUTING || 322 iConfig->mRoutingProxy == NULL) { 323 result = SL_RESULT_PARAMETER_INVALID; 324 } else { 325 int objID = IObjectToObjectID(InterfaceToIObject(iConfig)); 326 switch (objID) { 327 case SL_OBJECTID_AUDIOPLAYER: 328 { 329 JNIEnv* j_env = android::AndroidRuntime::getJNIEnv(); 330 331 j_env->ExceptionClear(); 332 j_env->CallVoidMethod(iConfig->mRoutingProxy, gMidAudioTrackRoutingProxy_release); 333 if (j_env->ExceptionCheck()) { 334 SL_LOGE("Java exception releasing recorder routing object."); 335 result = SL_RESULT_INTERNAL_ERROR; 336 } 337 j_env->DeleteGlobalRef(iConfig->mRoutingProxy); 338 iConfig->mRoutingProxy = NULL; 339 } 340 break; 341 342 case SL_OBJECTID_AUDIORECORDER: 343 { 344 JNIEnv* j_env = android::AndroidRuntime::getJNIEnv(); 345 346 j_env->ExceptionClear(); 347 j_env->CallVoidMethod(iConfig->mRoutingProxy, gMidAudioRecordRoutingProxy_release); 348 if (j_env->ExceptionCheck()) { 349 SL_LOGE("Java exception releasing recorder routing object."); 350 result = SL_RESULT_INTERNAL_ERROR; 351 } 352 j_env->DeleteGlobalRef(iConfig->mRoutingProxy); 353 iConfig->mRoutingProxy = NULL; 354 } 355 break; 356 } 357 358 result = SL_RESULT_SUCCESS; 359 } 360 361 SL_LEAVE_INTERFACE 362 } 363 364 static const struct SLAndroidConfigurationItf_ IAndroidConfiguration_Itf = { 365 IAndroidConfiguration_SetConfiguration, 366 IAndroidConfiguration_GetConfiguration, 367 IAndroidConfiguration_AcquireJavaProxy, 368 IAndroidConfiguration_ReleaseJavaProxy 369 }; 370 371 void IAndroidConfiguration_init(void *self) 372 { 373 IAndroidConfiguration *thiz = (IAndroidConfiguration *) self; 374 thiz->mItf = &IAndroidConfiguration_Itf; 375 } 376 377 void IAndroidConfiguration_deinit(void *self) 378 { 379 IAndroidConfiguration *thiz = (IAndroidConfiguration *) self; 380 if (thiz->mRoutingProxy != NULL) { 381 thiz->mItf->ReleaseJavaProxy(&thiz->mItf, SL_ANDROID_JAVA_PROXY_ROUTING); 382 } 383 } 384 385