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_isStreamActiveRemotely(JNIEnv * env,jobject thiz,jint stream,jint inPastMs)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
android_media_AudioSystem_isSourceActive(JNIEnv * env,jobject thiz,jint source)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
android_media_AudioSystem_setParameters(JNIEnv * env,jobject thiz,jstring keyValuePairs)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
android_media_AudioSystem_getParameters(JNIEnv * env,jobject thiz,jstring keys)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
android_media_AudioSystem_error_callback(status_t err)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
android_media_AudioSystem_setDeviceConnectionState(JNIEnv * env,jobject thiz,jint device,jint state,jstring device_address)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
android_media_AudioSystem_getDeviceConnectionState(JNIEnv * env,jobject thiz,jint device,jstring device_address)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
android_media_AudioSystem_setPhoneState(JNIEnv * env,jobject thiz,jint state)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
android_media_AudioSystem_setForceUse(JNIEnv * env,jobject thiz,jint usage,jint config)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
android_media_AudioSystem_getForceUse(JNIEnv * env,jobject thiz,jint usage)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
android_media_AudioSystem_initStreamVolume(JNIEnv * env,jobject thiz,jint stream,jint indexMin,jint indexMax)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
android_media_AudioSystem_setStreamVolumeIndex(JNIEnv * env,jobject thiz,jint stream,jint index,jint device)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
android_media_AudioSystem_getStreamVolumeIndex(JNIEnv * env,jobject thiz,jint stream,jint device)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
android_media_AudioSystem_setMasterVolume(JNIEnv * env,jobject thiz,jfloat value)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
android_media_AudioSystem_getMasterVolume(JNIEnv * env,jobject thiz)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
android_media_AudioSystem_setMasterMute(JNIEnv * env,jobject thiz,jboolean mute)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
android_media_AudioSystem_getMasterMute(JNIEnv * env,jobject thiz)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
android_media_AudioSystem_getDevicesForStream(JNIEnv * env,jobject thiz,jint stream)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
android_media_AudioSystem_getPrimaryOutputSamplingRate(JNIEnv * env,jobject clazz)263 android_media_AudioSystem_getPrimaryOutputSamplingRate(JNIEnv *env, jobject clazz)
264 {
265 return (jint) AudioSystem::getPrimaryOutputSamplingRate();
266 }
267
268 static jint
android_media_AudioSystem_getPrimaryOutputFrameCount(JNIEnv * env,jobject clazz)269 android_media_AudioSystem_getPrimaryOutputFrameCount(JNIEnv *env, jobject clazz)
270 {
271 return (jint) AudioSystem::getPrimaryOutputFrameCount();
272 }
273
274 static jint
android_media_AudioSystem_getOutputLatency(JNIEnv * env,jobject clazz,jint stream)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
register_android_media_AudioSystem(JNIEnv * env)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