android_media_AudioSystem.cpp revision 6824a143c90a2cd05c5f4f05830fa53527e856b8
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_TAG "AudioSystem" 19#include <utils/Log.h> 20 21#include <jni.h> 22#include <JNIHelp.h> 23#include <android_runtime/AndroidRuntime.h> 24 25#include <media/AudioSystem.h> 26 27#include <system/audio.h> 28#include <system/audio_policy.h> 29 30// ---------------------------------------------------------------------------- 31 32using namespace android; 33 34static const char* const kClassPathName = "android/media/AudioSystem"; 35 36enum AudioError { 37 kAudioStatusOk = 0, 38 kAudioStatusError = 1, 39 kAudioStatusMediaServerDied = 100 40}; 41 42static int check_AudioSystem_Command(status_t status) 43{ 44 if (status == NO_ERROR) { 45 return kAudioStatusOk; 46 } else { 47 return kAudioStatusError; 48 } 49} 50 51static int 52android_media_AudioSystem_muteMicrophone(JNIEnv *env, jobject thiz, jboolean on) 53{ 54 return check_AudioSystem_Command(AudioSystem::muteMicrophone(on)); 55} 56 57static jboolean 58android_media_AudioSystem_isMicrophoneMuted(JNIEnv *env, jobject thiz) 59{ 60 bool state = false; 61 AudioSystem::isMicrophoneMuted(&state); 62 return state; 63} 64 65static jboolean 66android_media_AudioSystem_isStreamActive(JNIEnv *env, jobject thiz, jint stream, jint inPastMs) 67{ 68 bool state = false; 69 AudioSystem::isStreamActive((audio_stream_type_t) stream, &state, inPastMs); 70 return state; 71} 72 73static jboolean 74android_media_AudioSystem_isStreamActiveRemotely(JNIEnv *env, jobject thiz, jint stream, 75 jint inPastMs) 76{ 77 bool state = false; 78 AudioSystem::isStreamActiveRemotely((audio_stream_type_t) stream, &state, inPastMs); 79 return state; 80} 81 82static jboolean 83android_media_AudioSystem_isSourceActive(JNIEnv *env, jobject thiz, jint source) 84{ 85 bool state = false; 86 AudioSystem::isSourceActive((audio_source_t) source, &state); 87 return state; 88} 89 90static int 91android_media_AudioSystem_setParameters(JNIEnv *env, jobject thiz, jstring keyValuePairs) 92{ 93 const jchar* c_keyValuePairs = env->GetStringCritical(keyValuePairs, 0); 94 String8 c_keyValuePairs8; 95 if (keyValuePairs) { 96 c_keyValuePairs8 = String8(c_keyValuePairs, env->GetStringLength(keyValuePairs)); 97 env->ReleaseStringCritical(keyValuePairs, c_keyValuePairs); 98 } 99 int status = check_AudioSystem_Command(AudioSystem::setParameters(0, c_keyValuePairs8)); 100 return status; 101} 102 103static jstring 104android_media_AudioSystem_getParameters(JNIEnv *env, jobject thiz, jstring keys) 105{ 106 const jchar* c_keys = env->GetStringCritical(keys, 0); 107 String8 c_keys8; 108 if (keys) { 109 c_keys8 = String8(c_keys, env->GetStringLength(keys)); 110 env->ReleaseStringCritical(keys, c_keys); 111 } 112 return env->NewStringUTF(AudioSystem::getParameters(0, c_keys8).string()); 113} 114 115static JNIEnv* AudioSystem_getJNIEnv(bool* needsDetach) { 116 *needsDetach = false; 117 JNIEnv* env = AndroidRuntime::getJNIEnv(); 118 if (env == NULL) { 119 JavaVMAttachArgs args = {JNI_VERSION_1_4, NULL, NULL}; 120 JavaVM* vm = AndroidRuntime::getJavaVM(); 121 int result = vm->AttachCurrentThread(&env, (void*) &args); 122 if (result != JNI_OK) { 123 ALOGE("thread attach failed: %#x", result); 124 return NULL; 125 } 126 *needsDetach = true; 127 } 128 return env; 129} 130 131static void AudioSystem_detachJNI() { 132 JavaVM* vm = AndroidRuntime::getJavaVM(); 133 int result = vm->DetachCurrentThread(); 134 if (result != JNI_OK) { 135 ALOGE("thread detach failed: %#x", result); 136 } 137} 138 139static void 140android_media_AudioSystem_error_callback(status_t err) 141{ 142 bool needsDetach = false; 143 JNIEnv *env = AudioSystem_getJNIEnv(&needsDetach); 144 145 if (env == NULL) { 146 return; 147 } 148 149 jclass clazz = env->FindClass(kClassPathName); 150 151 int error; 152 153 switch (err) { 154 case DEAD_OBJECT: 155 error = kAudioStatusMediaServerDied; 156 break; 157 case NO_ERROR: 158 error = kAudioStatusOk; 159 break; 160 default: 161 error = kAudioStatusError; 162 break; 163 } 164 165 env->CallStaticVoidMethod(clazz, env->GetStaticMethodID(clazz, "errorCallbackFromNative","(I)V"), error); 166 167 if (needsDetach) { 168 AudioSystem_detachJNI(); 169 } 170} 171 172static int 173android_media_AudioSystem_setDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jint state, jstring device_address) 174{ 175 const char *c_address = env->GetStringUTFChars(device_address, NULL); 176 int status = check_AudioSystem_Command(AudioSystem::setDeviceConnectionState(static_cast <audio_devices_t>(device), 177 static_cast <audio_policy_dev_state_t>(state), 178 c_address)); 179 env->ReleaseStringUTFChars(device_address, c_address); 180 return status; 181} 182 183static int 184android_media_AudioSystem_getDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jstring device_address) 185{ 186 const char *c_address = env->GetStringUTFChars(device_address, NULL); 187 int state = static_cast <int>(AudioSystem::getDeviceConnectionState(static_cast <audio_devices_t>(device), 188 c_address)); 189 env->ReleaseStringUTFChars(device_address, c_address); 190 return state; 191} 192 193static int 194android_media_AudioSystem_setPhoneState(JNIEnv *env, jobject thiz, jint state) 195{ 196 return check_AudioSystem_Command(AudioSystem::setPhoneState((audio_mode_t) state)); 197} 198 199static int 200android_media_AudioSystem_setForceUse(JNIEnv *env, jobject thiz, jint usage, jint config) 201{ 202 return check_AudioSystem_Command(AudioSystem::setForceUse(static_cast <audio_policy_force_use_t>(usage), 203 static_cast <audio_policy_forced_cfg_t>(config))); 204} 205 206static int 207android_media_AudioSystem_getForceUse(JNIEnv *env, jobject thiz, jint usage) 208{ 209 return static_cast <int>(AudioSystem::getForceUse(static_cast <audio_policy_force_use_t>(usage))); 210} 211 212static int 213android_media_AudioSystem_initStreamVolume(JNIEnv *env, jobject thiz, jint stream, jint indexMin, jint indexMax) 214{ 215 return check_AudioSystem_Command(AudioSystem::initStreamVolume(static_cast <audio_stream_type_t>(stream), 216 indexMin, 217 indexMax)); 218} 219 220static int 221android_media_AudioSystem_setStreamVolumeIndex(JNIEnv *env, 222 jobject thiz, 223 jint stream, 224 jint index, 225 jint device) 226{ 227 return check_AudioSystem_Command( 228 AudioSystem::setStreamVolumeIndex(static_cast <audio_stream_type_t>(stream), 229 index, 230 (audio_devices_t)device)); 231} 232 233static int 234android_media_AudioSystem_getStreamVolumeIndex(JNIEnv *env, 235 jobject thiz, 236 jint stream, 237 jint device) 238{ 239 int index; 240 if (AudioSystem::getStreamVolumeIndex(static_cast <audio_stream_type_t>(stream), 241 &index, 242 (audio_devices_t)device) 243 != NO_ERROR) { 244 index = -1; 245 } 246 return index; 247} 248 249static int 250android_media_AudioSystem_setMasterVolume(JNIEnv *env, jobject thiz, jfloat value) 251{ 252 return check_AudioSystem_Command(AudioSystem::setMasterVolume(value)); 253} 254 255static jfloat 256android_media_AudioSystem_getMasterVolume(JNIEnv *env, jobject thiz) 257{ 258 float value; 259 if (AudioSystem::getMasterVolume(&value) != NO_ERROR) { 260 value = -1.0; 261 } 262 return value; 263} 264 265static int 266android_media_AudioSystem_setMasterMute(JNIEnv *env, jobject thiz, jboolean mute) 267{ 268 return check_AudioSystem_Command(AudioSystem::setMasterMute(mute)); 269} 270 271static jfloat 272android_media_AudioSystem_getMasterMute(JNIEnv *env, jobject thiz) 273{ 274 bool mute; 275 if (AudioSystem::getMasterMute(&mute) != NO_ERROR) { 276 mute = false; 277 } 278 return mute; 279} 280 281static jint 282android_media_AudioSystem_getDevicesForStream(JNIEnv *env, jobject thiz, jint stream) 283{ 284 return (jint) AudioSystem::getDevicesForStream(static_cast <audio_stream_type_t>(stream)); 285} 286 287static jint 288android_media_AudioSystem_getPrimaryOutputSamplingRate(JNIEnv *env, jobject clazz) 289{ 290 return (jint) AudioSystem::getPrimaryOutputSamplingRate(); 291} 292 293static jint 294android_media_AudioSystem_getPrimaryOutputFrameCount(JNIEnv *env, jobject clazz) 295{ 296 return (jint) AudioSystem::getPrimaryOutputFrameCount(); 297} 298 299static jint 300android_media_AudioSystem_getOutputLatency(JNIEnv *env, jobject clazz, jint stream) 301{ 302 uint32_t afLatency; 303 if (AudioSystem::getOutputLatency(&afLatency, static_cast <audio_stream_type_t>(stream)) 304 != NO_ERROR) { 305 afLatency = -1; 306 } 307 return (jint) afLatency; 308} 309 310static jint 311android_media_AudioSystem_setLowRamDevice(JNIEnv *env, jobject clazz, jboolean isLowRamDevice) 312{ 313 return (jint) AudioSystem::setLowRamDevice((bool) isLowRamDevice); 314} 315 316// ---------------------------------------------------------------------------- 317 318static JNINativeMethod gMethods[] = { 319 {"setParameters", "(Ljava/lang/String;)I", (void *)android_media_AudioSystem_setParameters}, 320 {"getParameters", "(Ljava/lang/String;)Ljava/lang/String;", (void *)android_media_AudioSystem_getParameters}, 321 {"muteMicrophone", "(Z)I", (void *)android_media_AudioSystem_muteMicrophone}, 322 {"isMicrophoneMuted", "()Z", (void *)android_media_AudioSystem_isMicrophoneMuted}, 323 {"isStreamActive", "(II)Z", (void *)android_media_AudioSystem_isStreamActive}, 324 {"isStreamActiveRemotely","(II)Z", (void *)android_media_AudioSystem_isStreamActiveRemotely}, 325 {"isSourceActive", "(I)Z", (void *)android_media_AudioSystem_isSourceActive}, 326 {"setDeviceConnectionState", "(IILjava/lang/String;)I", (void *)android_media_AudioSystem_setDeviceConnectionState}, 327 {"getDeviceConnectionState", "(ILjava/lang/String;)I", (void *)android_media_AudioSystem_getDeviceConnectionState}, 328 {"setPhoneState", "(I)I", (void *)android_media_AudioSystem_setPhoneState}, 329 {"setForceUse", "(II)I", (void *)android_media_AudioSystem_setForceUse}, 330 {"getForceUse", "(I)I", (void *)android_media_AudioSystem_getForceUse}, 331 {"initStreamVolume", "(III)I", (void *)android_media_AudioSystem_initStreamVolume}, 332 {"setStreamVolumeIndex","(III)I", (void *)android_media_AudioSystem_setStreamVolumeIndex}, 333 {"getStreamVolumeIndex","(II)I", (void *)android_media_AudioSystem_getStreamVolumeIndex}, 334 {"setMasterVolume", "(F)I", (void *)android_media_AudioSystem_setMasterVolume}, 335 {"getMasterVolume", "()F", (void *)android_media_AudioSystem_getMasterVolume}, 336 {"setMasterMute", "(Z)I", (void *)android_media_AudioSystem_setMasterMute}, 337 {"getMasterMute", "()Z", (void *)android_media_AudioSystem_getMasterMute}, 338 {"getDevicesForStream", "(I)I", (void *)android_media_AudioSystem_getDevicesForStream}, 339 {"getPrimaryOutputSamplingRate", "()I", (void *)android_media_AudioSystem_getPrimaryOutputSamplingRate}, 340 {"getPrimaryOutputFrameCount", "()I", (void *)android_media_AudioSystem_getPrimaryOutputFrameCount}, 341 {"getOutputLatency", "(I)I", (void *)android_media_AudioSystem_getOutputLatency}, 342 {"setLowRamDevice", "(Z)I", (void *)android_media_AudioSystem_setLowRamDevice}, 343}; 344 345int register_android_media_AudioSystem(JNIEnv *env) 346{ 347 AudioSystem::setErrorCallback(android_media_AudioSystem_error_callback); 348 349 return AndroidRuntime::registerNativeMethods(env, 350 kClassPathName, gMethods, NELEM(gMethods)); 351} 352