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_isSourceActive(JNIEnv *env, jobject thiz, jint source) 80 { 81 bool state = false; 82 AudioSystem::isSourceActive((audio_source_t) source, &state); 83 return state; 84 } 85 86 static int 87 android_media_AudioSystem_setParameters(JNIEnv *env, jobject thiz, jstring keyValuePairs) 88 { 89 const jchar* c_keyValuePairs = env->GetStringCritical(keyValuePairs, 0); 90 String8 c_keyValuePairs8; 91 if (keyValuePairs) { 92 c_keyValuePairs8 = String8(c_keyValuePairs, env->GetStringLength(keyValuePairs)); 93 env->ReleaseStringCritical(keyValuePairs, c_keyValuePairs); 94 } 95 int status = check_AudioSystem_Command(AudioSystem::setParameters(0, c_keyValuePairs8)); 96 return status; 97 } 98 99 static jstring 100 android_media_AudioSystem_getParameters(JNIEnv *env, jobject thiz, jstring keys) 101 { 102 const jchar* c_keys = env->GetStringCritical(keys, 0); 103 String8 c_keys8; 104 if (keys) { 105 c_keys8 = String8(c_keys, env->GetStringLength(keys)); 106 env->ReleaseStringCritical(keys, c_keys); 107 } 108 return env->NewStringUTF(AudioSystem::getParameters(0, c_keys8).string()); 109 } 110 111 static void 112 android_media_AudioSystem_error_callback(status_t err) 113 { 114 JNIEnv *env = AndroidRuntime::getJNIEnv(); 115 if (env == NULL) { 116 return; 117 } 118 119 jclass clazz = env->FindClass(kClassPathName); 120 121 int error; 122 123 switch (err) { 124 case DEAD_OBJECT: 125 error = kAudioStatusMediaServerDied; 126 break; 127 case NO_ERROR: 128 error = kAudioStatusOk; 129 break; 130 default: 131 error = kAudioStatusError; 132 break; 133 } 134 135 env->CallStaticVoidMethod(clazz, env->GetStaticMethodID(clazz, "errorCallbackFromNative","(I)V"), error); 136 } 137 138 static int 139 android_media_AudioSystem_setDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jint state, jstring device_address) 140 { 141 const char *c_address = env->GetStringUTFChars(device_address, NULL); 142 int status = check_AudioSystem_Command(AudioSystem::setDeviceConnectionState(static_cast <audio_devices_t>(device), 143 static_cast <audio_policy_dev_state_t>(state), 144 c_address)); 145 env->ReleaseStringUTFChars(device_address, c_address); 146 return status; 147 } 148 149 static int 150 android_media_AudioSystem_getDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jstring device_address) 151 { 152 const char *c_address = env->GetStringUTFChars(device_address, NULL); 153 int state = static_cast <int>(AudioSystem::getDeviceConnectionState(static_cast <audio_devices_t>(device), 154 c_address)); 155 env->ReleaseStringUTFChars(device_address, c_address); 156 return state; 157 } 158 159 static int 160 android_media_AudioSystem_setPhoneState(JNIEnv *env, jobject thiz, jint state) 161 { 162 return check_AudioSystem_Command(AudioSystem::setPhoneState((audio_mode_t) state)); 163 } 164 165 static int 166 android_media_AudioSystem_setForceUse(JNIEnv *env, jobject thiz, jint usage, jint config) 167 { 168 return check_AudioSystem_Command(AudioSystem::setForceUse(static_cast <audio_policy_force_use_t>(usage), 169 static_cast <audio_policy_forced_cfg_t>(config))); 170 } 171 172 static int 173 android_media_AudioSystem_getForceUse(JNIEnv *env, jobject thiz, jint usage) 174 { 175 return static_cast <int>(AudioSystem::getForceUse(static_cast <audio_policy_force_use_t>(usage))); 176 } 177 178 static int 179 android_media_AudioSystem_initStreamVolume(JNIEnv *env, jobject thiz, jint stream, jint indexMin, jint indexMax) 180 { 181 return check_AudioSystem_Command(AudioSystem::initStreamVolume(static_cast <audio_stream_type_t>(stream), 182 indexMin, 183 indexMax)); 184 } 185 186 static int 187 android_media_AudioSystem_setStreamVolumeIndex(JNIEnv *env, 188 jobject thiz, 189 jint stream, 190 jint index, 191 jint device) 192 { 193 return check_AudioSystem_Command( 194 AudioSystem::setStreamVolumeIndex(static_cast <audio_stream_type_t>(stream), 195 index, 196 (audio_devices_t)device)); 197 } 198 199 static int 200 android_media_AudioSystem_getStreamVolumeIndex(JNIEnv *env, 201 jobject thiz, 202 jint stream, 203 jint device) 204 { 205 int index; 206 if (AudioSystem::getStreamVolumeIndex(static_cast <audio_stream_type_t>(stream), 207 &index, 208 (audio_devices_t)device) 209 != NO_ERROR) { 210 index = -1; 211 } 212 return index; 213 } 214 215 static int 216 android_media_AudioSystem_setMasterVolume(JNIEnv *env, jobject thiz, jfloat value) 217 { 218 return check_AudioSystem_Command(AudioSystem::setMasterVolume(value)); 219 } 220 221 static jfloat 222 android_media_AudioSystem_getMasterVolume(JNIEnv *env, jobject thiz) 223 { 224 float value; 225 if (AudioSystem::getMasterVolume(&value) != NO_ERROR) { 226 value = -1.0; 227 } 228 return value; 229 } 230 231 static int 232 android_media_AudioSystem_setMasterMute(JNIEnv *env, jobject thiz, jboolean mute) 233 { 234 return check_AudioSystem_Command(AudioSystem::setMasterMute(mute)); 235 } 236 237 static jfloat 238 android_media_AudioSystem_getMasterMute(JNIEnv *env, jobject thiz) 239 { 240 bool mute; 241 if (AudioSystem::getMasterMute(&mute) != NO_ERROR) { 242 mute = false; 243 } 244 return mute; 245 } 246 247 static jint 248 android_media_AudioSystem_getDevicesForStream(JNIEnv *env, jobject thiz, jint stream) 249 { 250 return (jint) AudioSystem::getDevicesForStream(static_cast <audio_stream_type_t>(stream)); 251 } 252 253 static jint 254 android_media_AudioSystem_getPrimaryOutputSamplingRate(JNIEnv *env, jobject clazz) 255 { 256 return (jint) AudioSystem::getPrimaryOutputSamplingRate(); 257 } 258 259 static jint 260 android_media_AudioSystem_getPrimaryOutputFrameCount(JNIEnv *env, jobject clazz) 261 { 262 return (jint) AudioSystem::getPrimaryOutputFrameCount(); 263 } 264 265 // ---------------------------------------------------------------------------- 266 267 static JNINativeMethod gMethods[] = { 268 {"setParameters", "(Ljava/lang/String;)I", (void *)android_media_AudioSystem_setParameters}, 269 {"getParameters", "(Ljava/lang/String;)Ljava/lang/String;", (void *)android_media_AudioSystem_getParameters}, 270 {"muteMicrophone", "(Z)I", (void *)android_media_AudioSystem_muteMicrophone}, 271 {"isMicrophoneMuted", "()Z", (void *)android_media_AudioSystem_isMicrophoneMuted}, 272 {"isStreamActive", "(II)Z", (void *)android_media_AudioSystem_isStreamActive}, 273 {"isSourceActive", "(I)Z", (void *)android_media_AudioSystem_isSourceActive}, 274 {"setDeviceConnectionState", "(IILjava/lang/String;)I", (void *)android_media_AudioSystem_setDeviceConnectionState}, 275 {"getDeviceConnectionState", "(ILjava/lang/String;)I", (void *)android_media_AudioSystem_getDeviceConnectionState}, 276 {"setPhoneState", "(I)I", (void *)android_media_AudioSystem_setPhoneState}, 277 {"setForceUse", "(II)I", (void *)android_media_AudioSystem_setForceUse}, 278 {"getForceUse", "(I)I", (void *)android_media_AudioSystem_getForceUse}, 279 {"initStreamVolume", "(III)I", (void *)android_media_AudioSystem_initStreamVolume}, 280 {"setStreamVolumeIndex","(III)I", (void *)android_media_AudioSystem_setStreamVolumeIndex}, 281 {"getStreamVolumeIndex","(II)I", (void *)android_media_AudioSystem_getStreamVolumeIndex}, 282 {"setMasterVolume", "(F)I", (void *)android_media_AudioSystem_setMasterVolume}, 283 {"getMasterVolume", "()F", (void *)android_media_AudioSystem_getMasterVolume}, 284 {"setMasterMute", "(Z)I", (void *)android_media_AudioSystem_setMasterMute}, 285 {"getMasterMute", "()Z", (void *)android_media_AudioSystem_getMasterMute}, 286 {"getDevicesForStream", "(I)I", (void *)android_media_AudioSystem_getDevicesForStream}, 287 {"getPrimaryOutputSamplingRate", "()I", (void *)android_media_AudioSystem_getPrimaryOutputSamplingRate}, 288 {"getPrimaryOutputFrameCount", "()I", (void *)android_media_AudioSystem_getPrimaryOutputFrameCount}, 289 }; 290 291 int register_android_media_AudioSystem(JNIEnv *env) 292 { 293 AudioSystem::setErrorCallback(android_media_AudioSystem_error_callback); 294 295 return AndroidRuntime::registerNativeMethods(env, 296 kClassPathName, gMethods, NELEM(gMethods)); 297 } 298