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
check_AudioSystem_Command(status_t status)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
android_media_AudioSystem_muteMicrophone(JNIEnv * env,jobject thiz,jboolean on)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
android_media_AudioSystem_isMicrophoneMuted(JNIEnv * env,jobject thiz)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
android_media_AudioSystem_isStreamActive(JNIEnv * env,jobject thiz,jint stream,jint inPastMs)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
android_media_AudioSystem_isSourceActive(JNIEnv * env,jobject thiz,jint source)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
android_media_AudioSystem_setParameters(JNIEnv * env,jobject thiz,jstring keyValuePairs)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
android_media_AudioSystem_getParameters(JNIEnv * env,jobject thiz,jstring keys)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
android_media_AudioSystem_error_callback(status_t err)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
android_media_AudioSystem_setDeviceConnectionState(JNIEnv * env,jobject thiz,jint device,jint state,jstring device_address)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
android_media_AudioSystem_getDeviceConnectionState(JNIEnv * env,jobject thiz,jint device,jstring device_address)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
android_media_AudioSystem_setPhoneState(JNIEnv * env,jobject thiz,jint state)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
android_media_AudioSystem_setForceUse(JNIEnv * env,jobject thiz,jint usage,jint config)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
android_media_AudioSystem_getForceUse(JNIEnv * env,jobject thiz,jint usage)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
android_media_AudioSystem_initStreamVolume(JNIEnv * env,jobject thiz,jint stream,jint indexMin,jint indexMax)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
android_media_AudioSystem_setStreamVolumeIndex(JNIEnv * env,jobject thiz,jint stream,jint index,jint device)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
android_media_AudioSystem_getStreamVolumeIndex(JNIEnv * env,jobject thiz,jint stream,jint device)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
android_media_AudioSystem_setMasterVolume(JNIEnv * env,jobject thiz,jfloat value)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
android_media_AudioSystem_getMasterVolume(JNIEnv * env,jobject thiz)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
android_media_AudioSystem_setMasterMute(JNIEnv * env,jobject thiz,jboolean mute)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
android_media_AudioSystem_getMasterMute(JNIEnv * env,jobject thiz)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
android_media_AudioSystem_getDevicesForStream(JNIEnv * env,jobject thiz,jint stream)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
android_media_AudioSystem_getPrimaryOutputSamplingRate(JNIEnv * env,jobject clazz)254 android_media_AudioSystem_getPrimaryOutputSamplingRate(JNIEnv *env, jobject clazz)
255 {
256 return (jint) AudioSystem::getPrimaryOutputSamplingRate();
257 }
258
259 static jint
android_media_AudioSystem_getPrimaryOutputFrameCount(JNIEnv * env,jobject clazz)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
register_android_media_AudioSystem(JNIEnv * env)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