1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define LOG_TAG "VibratorService" 18 19 #include <android/hardware/vibrator/1.0/IVibrator.h> 20 #include <android/hardware/vibrator/1.0/types.h> 21 22 #include "jni.h" 23 #include "JNIHelp.h" 24 #include "android_runtime/AndroidRuntime.h" 25 26 #include <utils/misc.h> 27 #include <utils/Log.h> 28 #include <hardware/vibrator.h> 29 30 #include <inttypes.h> 31 #include <stdio.h> 32 33 using android::hardware::Return; 34 using android::hardware::vibrator::V1_0::Effect; 35 using android::hardware::vibrator::V1_0::EffectStrength; 36 using android::hardware::vibrator::V1_0::IVibrator; 37 using android::hardware::vibrator::V1_0::Status; 38 39 namespace android 40 { 41 42 static sp<IVibrator> mHal; 43 44 static void vibratorInit(JNIEnv /* env */, jobject /* clazz */) 45 { 46 /* TODO(b/31632518) */ 47 if (mHal != nullptr) { 48 return; 49 } 50 mHal = IVibrator::getService(); 51 } 52 53 static jboolean vibratorExists(JNIEnv* /* env */, jobject /* clazz */) 54 { 55 if (mHal != nullptr) { 56 return JNI_TRUE; 57 } else { 58 return JNI_FALSE; 59 } 60 } 61 62 static void vibratorOn(JNIEnv* /* env */, jobject /* clazz */, jlong timeout_ms) 63 { 64 if (mHal != nullptr) { 65 Status retStatus = mHal->on(timeout_ms); 66 if (retStatus != Status::OK) { 67 ALOGE("vibratorOn command failed (%" PRIu32 ").", static_cast<uint32_t>(retStatus)); 68 } 69 } else { 70 ALOGW("Tried to vibrate but there is no vibrator device."); 71 } 72 } 73 74 static void vibratorOff(JNIEnv* /* env */, jobject /* clazz */) 75 { 76 if (mHal != nullptr) { 77 Status retStatus = mHal->off(); 78 if (retStatus != Status::OK) { 79 ALOGE("vibratorOff command failed (%" PRIu32 ").", static_cast<uint32_t>(retStatus)); 80 } 81 } else { 82 ALOGW("Tried to stop vibrating but there is no vibrator device."); 83 } 84 } 85 86 static jlong vibratorSupportsAmplitudeControl(JNIEnv*, jobject) { 87 if (mHal != nullptr) { 88 return mHal->supportsAmplitudeControl(); 89 } else { 90 ALOGW("Unable to get max vibration amplitude, there is no vibrator device."); 91 } 92 return false; 93 } 94 95 static void vibratorSetAmplitude(JNIEnv*, jobject, jint amplitude) { 96 if (mHal != nullptr) { 97 Status status = mHal->setAmplitude(static_cast<uint32_t>(amplitude)); 98 if (status != Status::OK) { 99 ALOGE("Failed to set vibrator amplitude (%" PRIu32 ").", 100 static_cast<uint32_t>(status)); 101 } 102 } else { 103 ALOGW("Unable to set vibration amplitude, there is no vibrator device."); 104 } 105 } 106 107 static jlong vibratorPerformEffect(JNIEnv*, jobject, jlong effect, jint strength) { 108 if (mHal != nullptr) { 109 Status status; 110 uint32_t lengthMs; 111 mHal->perform(static_cast<Effect>(effect), static_cast<EffectStrength>(strength), 112 [&status, &lengthMs](Status retStatus, uint32_t retLengthMs) { 113 status = retStatus; 114 lengthMs = retLengthMs; 115 }); 116 if (status == Status::OK) { 117 return lengthMs; 118 } else if (status != Status::UNSUPPORTED_OPERATION) { 119 // Don't warn on UNSUPPORTED_OPERATION, that's a normal even and just means the motor 120 // doesn't have a pre-defined waveform to perform for it, so we should just fall back 121 // to the framework waveforms. 122 ALOGE("Failed to perform haptic effect: effect=%" PRId64 ", strength=%" PRId32 123 ", error=%" PRIu32 ").", static_cast<int64_t>(effect), 124 static_cast<int32_t>(strength), static_cast<uint32_t>(status)); 125 } 126 } else { 127 ALOGW("Unable to perform haptic effect, there is no vibrator device."); 128 } 129 return -1; 130 } 131 132 static const JNINativeMethod method_table[] = { 133 { "vibratorExists", "()Z", (void*)vibratorExists }, 134 { "vibratorInit", "()V", (void*)vibratorInit }, 135 { "vibratorOn", "(J)V", (void*)vibratorOn }, 136 { "vibratorOff", "()V", (void*)vibratorOff }, 137 { "vibratorSupportsAmplitudeControl", "()Z", (void*)vibratorSupportsAmplitudeControl}, 138 { "vibratorSetAmplitude", "(I)V", (void*)vibratorSetAmplitude}, 139 { "vibratorPerformEffect", "(JJ)J", (void*)vibratorPerformEffect} 140 }; 141 142 int register_android_server_VibratorService(JNIEnv *env) 143 { 144 return jniRegisterNativeMethods(env, "com/android/server/VibratorService", 145 method_table, NELEM(method_table)); 146 } 147 148 }; 149