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 <JNIHelp.h> 26 #include <android_runtime/AndroidRuntime.h> 27 28 #include <utils/Log.h> 29 #include <media/AudioSystem.h> 30 #include <media/ToneGenerator.h> 31 32 // ---------------------------------------------------------------------------- 33 34 using namespace android; 35 36 struct fields_t { 37 jfieldID context; 38 }; 39 static fields_t fields; 40 41 static jboolean android_media_ToneGenerator_startTone(JNIEnv *env, jobject thiz, jint toneType, jint durationMs) { 42 ALOGV("android_media_ToneGenerator_startTone: %x", (int)thiz); 43 44 ToneGenerator *lpToneGen = (ToneGenerator *)env->GetIntField(thiz, 45 fields.context); 46 if (lpToneGen == NULL) { 47 jniThrowRuntimeException(env, "Method called after release()"); 48 return false; 49 } 50 51 return lpToneGen->startTone((ToneGenerator::tone_type) toneType, durationMs); 52 } 53 54 static void android_media_ToneGenerator_stopTone(JNIEnv *env, jobject thiz) { 55 ALOGV("android_media_ToneGenerator_stopTone: %x", (int)thiz); 56 57 ToneGenerator *lpToneGen = (ToneGenerator *)env->GetIntField(thiz, 58 fields.context); 59 60 ALOGV("ToneGenerator lpToneGen: %x", (unsigned int)lpToneGen); 61 if (lpToneGen == NULL) { 62 jniThrowRuntimeException(env, "Method called after release()"); 63 return; 64 } 65 lpToneGen->stopTone(); 66 } 67 68 static jint android_media_ToneGenerator_getAudioSessionId(JNIEnv *env, jobject thiz) { 69 ToneGenerator *lpToneGen = (ToneGenerator *)env->GetIntField(thiz, 70 fields.context); 71 if (lpToneGen == NULL) { 72 jniThrowRuntimeException(env, "Method called after release()"); 73 return 0; 74 } 75 return lpToneGen->getSessionId(); 76 } 77 78 static void android_media_ToneGenerator_release(JNIEnv *env, jobject thiz) { 79 ToneGenerator *lpToneGen = (ToneGenerator *)env->GetIntField(thiz, 80 fields.context); 81 ALOGV("android_media_ToneGenerator_release lpToneGen: %x", (int)lpToneGen); 82 83 env->SetIntField(thiz, fields.context, 0); 84 85 delete lpToneGen; 86 } 87 88 static void android_media_ToneGenerator_native_setup(JNIEnv *env, jobject thiz, 89 jint streamType, jint volume) { 90 ToneGenerator *lpToneGen = new ToneGenerator((audio_stream_type_t) streamType, AudioSystem::linearToLog(volume), true); 91 92 env->SetIntField(thiz, fields.context, 0); 93 94 ALOGV("android_media_ToneGenerator_native_setup jobject: %x", (int)thiz); 95 96 if (lpToneGen == NULL) { 97 ALOGE("ToneGenerator creation failed"); 98 jniThrowException(env, "java/lang/OutOfMemoryError", NULL); 99 return; 100 } 101 ALOGV("ToneGenerator lpToneGen: %x", (unsigned int)lpToneGen); 102 103 if (!lpToneGen->isInited()) { 104 ALOGE("ToneGenerator init failed"); 105 jniThrowRuntimeException(env, "Init failed"); 106 return; 107 } 108 109 // Stow our new C++ ToneGenerator in an opaque field in the Java object. 110 env->SetIntField(thiz, fields.context, (int)lpToneGen); 111 112 ALOGV("ToneGenerator fields.context: %x", env->GetIntField(thiz, fields.context)); 113 } 114 115 static void android_media_ToneGenerator_native_finalize(JNIEnv *env, 116 jobject thiz) { 117 ALOGV("android_media_ToneGenerator_native_finalize jobject: %x", (int)thiz); 118 119 ToneGenerator *lpToneGen = (ToneGenerator *)env->GetIntField(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 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", "(II)V", (void *)android_media_ToneGenerator_native_setup }, 136 { "native_finalize", "()V", (void *)android_media_ToneGenerator_native_finalize } 137 }; 138 139 140 int register_android_media_ToneGenerator(JNIEnv *env) { 141 jclass clazz; 142 143 clazz = env->FindClass("android/media/ToneGenerator"); 144 if (clazz == NULL) { 145 ALOGE("Can't find %s", "android/media/ToneGenerator"); 146 return -1; 147 } 148 149 fields.context = env->GetFieldID(clazz, "mNativeContext", "I"); 150 if (fields.context == NULL) { 151 ALOGE("Can't find ToneGenerator.mNativeContext"); 152 return -1; 153 } 154 ALOGV("register_android_media_ToneGenerator ToneGenerator fields.context: %x", (unsigned int)fields.context); 155 156 return AndroidRuntime::registerNativeMethods(env, 157 "android/media/ToneGenerator", gMethods, NELEM(gMethods)); 158 } 159