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