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