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