1 /*
2  **
3  ** Copyright 2008, 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 "ToneGenerator"
19 
20 #include <stdio.h>
21 #include <unistd.h>
22 #include <fcntl.h>
23 
24 #include <jni.h>
25 #include <nativehelper/JNIHelp.h>
26 #include <nativehelper/ScopedUtfChars.h>
27 #include "core_jni_helpers.h"
28 
29 #include <utils/Log.h>
30 #include <media/AudioSystem.h>
31 #include <media/ToneGenerator.h>
32 
33 // ----------------------------------------------------------------------------
34 
35 using namespace android;
36 
37 struct fields_t {
38     jfieldID context;
39 };
40 static fields_t fields;
41 
android_media_ToneGenerator_startTone(JNIEnv * env,jobject thiz,jint toneType,jint durationMs)42 static jboolean android_media_ToneGenerator_startTone(JNIEnv *env, jobject thiz, jint toneType, jint durationMs) {
43     ALOGV("android_media_ToneGenerator_startTone: %p", thiz);
44 
45     ToneGenerator *lpToneGen = (ToneGenerator *)env->GetLongField(thiz,
46             fields.context);
47     if (lpToneGen == NULL) {
48         jniThrowRuntimeException(env, "Method called after release()");
49         return false;
50     }
51 
52     return lpToneGen->startTone((ToneGenerator::tone_type) toneType, durationMs);
53 }
54 
android_media_ToneGenerator_stopTone(JNIEnv * env,jobject thiz)55 static void android_media_ToneGenerator_stopTone(JNIEnv *env, jobject thiz) {
56     ALOGV("android_media_ToneGenerator_stopTone: %p", thiz);
57 
58     ToneGenerator *lpToneGen = (ToneGenerator *)env->GetLongField(thiz,
59             fields.context);
60 
61     ALOGV("ToneGenerator lpToneGen: %p", lpToneGen);
62     if (lpToneGen == NULL) {
63         jniThrowRuntimeException(env, "Method called after release()");
64         return;
65     }
66     lpToneGen->stopTone();
67 }
68 
android_media_ToneGenerator_getAudioSessionId(JNIEnv * env,jobject thiz)69 static jint android_media_ToneGenerator_getAudioSessionId(JNIEnv *env, jobject thiz) {
70     ToneGenerator *lpToneGen = (ToneGenerator *)env->GetLongField(thiz,
71             fields.context);
72     if (lpToneGen == NULL) {
73         jniThrowRuntimeException(env, "Method called after release()");
74         return 0;
75     }
76     return lpToneGen->getSessionId();
77 }
78 
android_media_ToneGenerator_release(JNIEnv * env,jobject thiz)79 static void android_media_ToneGenerator_release(JNIEnv *env, jobject thiz) {
80     ToneGenerator *lpToneGen = (ToneGenerator *)env->GetLongField(thiz,
81             fields.context);
82     ALOGV("android_media_ToneGenerator_release lpToneGen: %p", lpToneGen);
83 
84     env->SetLongField(thiz, fields.context, 0);
85 
86     delete lpToneGen;
87 }
88 
android_media_ToneGenerator_native_setup(JNIEnv * env,jobject thiz,jint streamType,jint volume,jstring opPackageName)89 static void android_media_ToneGenerator_native_setup(JNIEnv *env, jobject thiz, jint streamType,
90                                                      jint volume, jstring opPackageName) {
91     ScopedUtfChars opPackageNameStr(env, opPackageName);
92     ToneGenerator *lpToneGen =
93             new ToneGenerator((audio_stream_type_t)streamType, AudioSystem::linearToLog(volume),
94                               true /*threadCanCallJava*/, opPackageNameStr.c_str());
95 
96     env->SetLongField(thiz, fields.context, 0);
97 
98     ALOGV("android_media_ToneGenerator_native_setup jobject: %p", thiz);
99 
100     ALOGV("ToneGenerator lpToneGen: %p", lpToneGen);
101 
102     if (!lpToneGen->isInited()) {
103         ALOGE("ToneGenerator init failed");
104         jniThrowRuntimeException(env, "Init failed");
105         delete lpToneGen;
106         return;
107     }
108 
109     // Stow our new C++ ToneGenerator in an opaque field in the Java object.
110     env->SetLongField(thiz, fields.context, (jlong)lpToneGen);
111 
112     ALOGV("ToneGenerator fields.context: %p", (void*) env->GetLongField(thiz, fields.context));
113 }
114 
android_media_ToneGenerator_native_finalize(JNIEnv * env,jobject thiz)115 static void android_media_ToneGenerator_native_finalize(JNIEnv *env,
116         jobject thiz) {
117     ALOGV("android_media_ToneGenerator_native_finalize jobject: %p", thiz);
118 
119     ToneGenerator *lpToneGen = (ToneGenerator *)env->GetLongField(thiz,
120             fields.context);
121 
122     if (lpToneGen != NULL) {
123         ALOGV("delete lpToneGen: %p", lpToneGen);
124         delete lpToneGen;
125     }
126 }
127 
128 // ----------------------------------------------------------------------------
129 
130 static const JNINativeMethod gMethods[] =
131         {{"startTone", "(II)Z", (void *)android_media_ToneGenerator_startTone},
132          {"stopTone", "()V", (void *)android_media_ToneGenerator_stopTone},
133          {"getAudioSessionId", "()I", (void *)android_media_ToneGenerator_getAudioSessionId},
134          {"release", "()V", (void *)android_media_ToneGenerator_release},
135          {"native_setup", "(IILjava/lang/String;)V",
136           (void *)android_media_ToneGenerator_native_setup},
137          {"native_finalize", "()V", (void *)android_media_ToneGenerator_native_finalize}};
138 
register_android_media_ToneGenerator(JNIEnv * env)139 int register_android_media_ToneGenerator(JNIEnv *env) {
140     jclass clazz = FindClassOrDie(env, "android/media/ToneGenerator");
141 
142     fields.context = GetFieldIDOrDie(env, clazz, "mNativeContext", "J");
143     ALOGV("register_android_media_ToneGenerator ToneGenerator fields.context: %p", fields.context);
144 
145     return RegisterMethodsOrDie(env, "android/media/ToneGenerator", gMethods, NELEM(gMethods));
146 }
147