• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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