blob: 746610df11ae52ffb5fdfa0b748126fd16f2e276 [file] [log] [blame]
Mike Lockwood3a322132009-11-24 00:30:52 -05001/*
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
Steven Moreland5af46952019-11-10 17:56:28 -080019#include <android/hardware/vibrator/1.3/IVibrator.h>
Steven Moreland4a39e5b2019-10-28 13:15:17 -070020#include <android/hardware/vibrator/BnVibratorCallback.h>
21#include <android/hardware/vibrator/IVibrator.h>
22#include <binder/IServiceManager.h>
Prashant Malania9cdaac2016-09-16 13:51:18 -070023
Mike Lockwood3a322132009-11-24 00:30:52 -050024#include "jni.h"
Steven Moreland2279b252017-07-19 09:50:45 -070025#include <nativehelper/JNIHelp.h>
Mike Lockwood3a322132009-11-24 00:30:52 -050026#include "android_runtime/AndroidRuntime.h"
Harpreet "Eli" Sangha89ffc2d2019-07-25 11:32:57 +090027#include "core_jni_helpers.h"
Mike Lockwood3a322132009-11-24 00:30:52 -050028
29#include <utils/misc.h>
30#include <utils/Log.h>
Vincent Beckere6904fb2012-08-10 14:17:33 +020031#include <hardware/vibrator.h>
Mike Lockwood3a322132009-11-24 00:30:52 -050032
Michael Wright71216972017-01-31 18:33:54 +000033#include <inttypes.h>
Mike Lockwood3a322132009-11-24 00:30:52 -050034#include <stdio.h>
35
Michael Wright71216972017-01-31 18:33:54 +000036using android::hardware::Return;
Harpreet "Eli" Sangha89ffc2d2019-07-25 11:32:57 +090037using android::hardware::Void;
Michael Wright71216972017-01-31 18:33:54 +000038using android::hardware::vibrator::V1_0::EffectStrength;
Prashant Malania9cdaac2016-09-16 13:51:18 -070039using android::hardware::vibrator::V1_0::Status;
Michael Wright57d94d92017-05-31 14:44:45 +010040using android::hardware::vibrator::V1_1::Effect_1_1;
Prashant Malania9cdaac2016-09-16 13:51:18 -070041
Michael Wrightf268bf52018-02-07 23:23:34 +000042namespace V1_0 = android::hardware::vibrator::V1_0;
43namespace V1_1 = android::hardware::vibrator::V1_1;
44namespace V1_2 = android::hardware::vibrator::V1_2;
Harpreet "Eli" Sanghaa456f082018-12-14 12:06:10 +090045namespace V1_3 = android::hardware::vibrator::V1_3;
Steven Moreland4a39e5b2019-10-28 13:15:17 -070046namespace aidl = android::hardware::vibrator;
Michael Wrightf268bf52018-02-07 23:23:34 +000047
48namespace android {
Mike Lockwood3a322132009-11-24 00:30:52 -050049
Harpreet "Eli" Sangha89ffc2d2019-07-25 11:32:57 +090050static jmethodID sMethodIdOnComplete;
51
Harpreet \"Eli\" Sangha527ed442019-11-07 17:29:36 +090052static_assert(static_cast<uint8_t>(V1_0::EffectStrength::LIGHT) ==
53 static_cast<uint8_t>(aidl::EffectStrength::LIGHT));
54static_assert(static_cast<uint8_t>(V1_0::EffectStrength::MEDIUM) ==
55 static_cast<uint8_t>(aidl::EffectStrength::MEDIUM));
56static_assert(static_cast<uint8_t>(V1_0::EffectStrength::STRONG) ==
57 static_cast<uint8_t>(aidl::EffectStrength::STRONG));
Steven Moreland4a39e5b2019-10-28 13:15:17 -070058
Harpreet \"Eli\" Sangha527ed442019-11-07 17:29:36 +090059static_assert(static_cast<uint8_t>(V1_3::Effect::CLICK) ==
60 static_cast<uint8_t>(aidl::Effect::CLICK));
61static_assert(static_cast<uint8_t>(V1_3::Effect::DOUBLE_CLICK) ==
62 static_cast<uint8_t>(aidl::Effect::DOUBLE_CLICK));
63static_assert(static_cast<uint8_t>(V1_3::Effect::TICK) ==
64 static_cast<uint8_t>(aidl::Effect::TICK));
65static_assert(static_cast<uint8_t>(V1_3::Effect::THUD) ==
66 static_cast<uint8_t>(aidl::Effect::THUD));
67static_assert(static_cast<uint8_t>(V1_3::Effect::POP) ==
68 static_cast<uint8_t>(aidl::Effect::POP));
69static_assert(static_cast<uint8_t>(V1_3::Effect::HEAVY_CLICK) ==
70 static_cast<uint8_t>(aidl::Effect::HEAVY_CLICK));
71static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_1) ==
72 static_cast<uint8_t>(aidl::Effect::RINGTONE_1));
73static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_2) ==
74 static_cast<uint8_t>(aidl::Effect::RINGTONE_2));
75static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_15) ==
76 static_cast<uint8_t>(aidl::Effect::RINGTONE_15));
77static_assert(static_cast<uint8_t>(V1_3::Effect::TEXTURE_TICK) ==
78 static_cast<uint8_t>(aidl::Effect::TEXTURE_TICK));
Steven Moreland4a39e5b2019-10-28 13:15:17 -070079
Harpreet \"Eli\" Sangha527ed442019-11-07 17:29:36 +090080class VibratorCallback {
Harpreet "Eli" Sangha89ffc2d2019-07-25 11:32:57 +090081 public:
82 VibratorCallback(JNIEnv *env, jobject vibration) :
83 mVibration(MakeGlobalRefOrDie(env, vibration)) {}
84
85 ~VibratorCallback() {
86 JNIEnv *env = AndroidRuntime::getJNIEnv();
87 env->DeleteGlobalRef(mVibration);
88 }
89
Harpreet \"Eli\" Sangha527ed442019-11-07 17:29:36 +090090 void onComplete() {
Harpreet "Eli" Sangha89ffc2d2019-07-25 11:32:57 +090091 auto env = AndroidRuntime::getJNIEnv();
92 env->CallVoidMethod(mVibration, sMethodIdOnComplete);
Harpreet "Eli" Sangha89ffc2d2019-07-25 11:32:57 +090093 }
94
95 private:
96 jobject mVibration;
97};
98
Harpreet \"Eli\" Sangha527ed442019-11-07 17:29:36 +090099class AidlVibratorCallback : public aidl::BnVibratorCallback {
100 public:
101 AidlVibratorCallback(JNIEnv *env, jobject vibration) :
102 mCb(env, vibration) {}
103
104 binder::Status onComplete() override {
105 mCb.onComplete();
106 return binder::Status::ok(); // oneway, local call
107 }
108
109 private:
110 VibratorCallback mCb;
111};
112
Tri Voa92c1542017-06-17 14:58:44 -0700113static constexpr int NUM_TRIES = 2;
114
Harpreet \"Eli\" Sangha527ed442019-11-07 17:29:36 +0900115template<class R>
116inline R NoneStatus() {
117 using ::android::hardware::Status;
118 return Status::fromExceptionCode(Status::EX_NONE);
119}
120
121template<>
122inline binder::Status NoneStatus() {
123 using binder::Status;
124 return Status::fromExceptionCode(Status::EX_NONE);
125}
126
Tri Voa92c1542017-06-17 14:58:44 -0700127// Creates a Return<R> with STATUS::EX_NULL_POINTER.
128template<class R>
Harpreet \"Eli\" Sangha527ed442019-11-07 17:29:36 +0900129inline R NullptrStatus() {
Tri Voa92c1542017-06-17 14:58:44 -0700130 using ::android::hardware::Status;
Harpreet \"Eli\" Sangha527ed442019-11-07 17:29:36 +0900131 return Status::fromExceptionCode(Status::EX_NULL_POINTER);
132}
133
134template<>
135inline binder::Status NullptrStatus() {
136 using binder::Status;
137 return Status::fromExceptionCode(Status::EX_NULL_POINTER);
138}
139
140template <typename I>
141sp<I> getService() {
142 return I::getService();
143}
144
145template <>
146sp<aidl::IVibrator> getService() {
147 return waitForVintfService<aidl::IVibrator>();
148}
149
150template <typename I>
151sp<I> tryGetService() {
152 return I::tryGetService();
153}
154
155template <>
156sp<aidl::IVibrator> tryGetService() {
157 return checkVintfService<aidl::IVibrator>();
Tri Voa92c1542017-06-17 14:58:44 -0700158}
159
Harpreet \"Eli\" Sanghace89efb2019-09-02 14:21:49 +0900160template <typename I>
161class HalWrapper {
162 public:
163 static std::unique_ptr<HalWrapper> Create() {
164 // Assume that if getService returns a nullptr, HAL is not available on the
165 // device.
Harpreet \"Eli\" Sangha527ed442019-11-07 17:29:36 +0900166 auto hal = getService<I>();
Harpreet \"Eli\" Sanghace89efb2019-09-02 14:21:49 +0900167 return hal ? std::unique_ptr<HalWrapper>(new HalWrapper(std::move(hal))) : nullptr;
168 }
169
170 // Helper used to transparently deal with the vibrator HAL becoming unavailable.
171 template<class R, class... Args0, class... Args1>
Harpreet \"Eli\" Sangha527ed442019-11-07 17:29:36 +0900172 R call(R (I::* fn)(Args0...), Args1&&... args1) {
Harpreet \"Eli\" Sanghace89efb2019-09-02 14:21:49 +0900173 // Return<R> doesn't have a default constructor, so make a Return<R> with
174 // STATUS::EX_NONE.
Harpreet \"Eli\" Sangha527ed442019-11-07 17:29:36 +0900175 R ret{NoneStatus<R>()};
Harpreet \"Eli\" Sanghace89efb2019-09-02 14:21:49 +0900176
177 // Note that ret is guaranteed to be changed after this loop.
178 for (int i = 0; i < NUM_TRIES; ++i) {
179 ret = (mHal == nullptr) ? NullptrStatus<R>()
180 : (*mHal.*fn)(std::forward<Args1>(args1)...);
181
182 if (ret.isOk()) {
183 break;
184 }
185
186 ALOGE("Failed to issue command to vibrator HAL. Retrying.");
Steven Morelandee3a5892019-11-05 16:11:59 -0800187
Harpreet \"Eli\" Sanghace89efb2019-09-02 14:21:49 +0900188 // Restoring connection to the HAL.
Harpreet \"Eli\" Sangha527ed442019-11-07 17:29:36 +0900189 mHal = tryGetService<I>();
Harpreet \"Eli\" Sanghace89efb2019-09-02 14:21:49 +0900190 }
191 return ret;
192 }
193
194 private:
195 HalWrapper(sp<I> &&hal) : mHal(std::move(hal)) {}
196
197 private:
198 sp<I> mHal;
199};
200
201template <typename I>
202static auto getHal() {
203 static auto sHalWrapper = HalWrapper<I>::Create();
204 return sHalWrapper.get();
205}
206
Tri Voa92c1542017-06-17 14:58:44 -0700207template<class R, class I, class... Args0, class... Args1>
Harpreet \"Eli\" Sangha527ed442019-11-07 17:29:36 +0900208R halCall(R (I::* fn)(Args0...), Args1&&... args1) {
Harpreet \"Eli\" Sanghace89efb2019-09-02 14:21:49 +0900209 auto hal = getHal<I>();
210 return hal ? hal->call(fn, std::forward<Args1>(args1)...) : NullptrStatus<R>();
Tri Voa92c1542017-06-17 14:58:44 -0700211}
Vincent Beckere6904fb2012-08-10 14:17:33 +0200212
Michael Wrightf268bf52018-02-07 23:23:34 +0000213template<class R>
214bool isValidEffect(jlong effect) {
215 if (effect < 0) {
216 return false;
217 }
218 R val = static_cast<R>(effect);
Steven Moreland620e5222018-05-01 16:54:00 -0700219 auto iter = hardware::hidl_enum_range<R>();
Michael Wright950bd772019-03-21 21:26:05 +0000220 return val >= *iter.begin() && val <= *std::prev(iter.end());
Michael Wrightf268bf52018-02-07 23:23:34 +0000221}
222
Harpreet "Eli" Sangha89ffc2d2019-07-25 11:32:57 +0900223static void vibratorInit(JNIEnv *env, jclass clazz)
Vincent Beckere6904fb2012-08-10 14:17:33 +0200224{
Harpreet \"Eli\" Sangha527ed442019-11-07 17:29:36 +0900225 if (auto hal = getHal<aidl::IVibrator>()) {
226 // IBinder::pingBinder isn't accessible as a pointer function
227 // but getCapabilities can serve the same purpose
228 int32_t cap;
229 hal->call(&aidl::IVibrator::getCapabilities, &cap).isOk();
230 } else {
231 halCall(&V1_0::IVibrator::ping).isOk();
232 }
Vincent Beckere6904fb2012-08-10 14:17:33 +0200233}
234
Harpreet "Eli" Sangha89ffc2d2019-07-25 11:32:57 +0900235static jboolean vibratorExists(JNIEnv* /* env */, jclass /* clazz */)
Dianne Hackbornea9020e2010-11-04 11:39:12 -0700236{
Harpreet \"Eli\" Sangha527ed442019-11-07 17:29:36 +0900237 bool ok;
238
239 if (auto hal = getHal<aidl::IVibrator>()) {
240 // IBinder::pingBinder isn't accessible as a pointer function
241 // but getCapabilities can serve the same purpose
242 int32_t cap;
243 ok = hal->call(&aidl::IVibrator::getCapabilities, &cap).isOk();
244 } else {
245 ok = halCall(&V1_0::IVibrator::ping).isOk();
246 }
247 return ok ? JNI_TRUE : JNI_FALSE;
Dianne Hackbornea9020e2010-11-04 11:39:12 -0700248}
249
Harpreet "Eli" Sangha89ffc2d2019-07-25 11:32:57 +0900250static void vibratorOn(JNIEnv* /* env */, jclass /* clazz */, jlong timeout_ms)
Mike Lockwood3a322132009-11-24 00:30:52 -0500251{
Harpreet \"Eli\" Sangha527ed442019-11-07 17:29:36 +0900252 if (auto hal = getHal<aidl::IVibrator>()) {
253 auto status = hal->call(&aidl::IVibrator::on, timeout_ms, nullptr);
254 if (!status.isOk()) {
255 ALOGE("vibratorOn command failed: %s", status.toString8().string());
256 }
257 } else {
258 Status retStatus = halCall(&V1_0::IVibrator::on, timeout_ms).withDefault(Status::UNKNOWN_ERROR);
259 if (retStatus != Status::OK) {
260 ALOGE("vibratorOn command failed (%" PRIu32 ").", static_cast<uint32_t>(retStatus));
261 }
Vincent Beckere6904fb2012-08-10 14:17:33 +0200262 }
Mike Lockwood3a322132009-11-24 00:30:52 -0500263}
264
Harpreet "Eli" Sangha89ffc2d2019-07-25 11:32:57 +0900265static void vibratorOff(JNIEnv* /* env */, jclass /* clazz */)
Mike Lockwood3a322132009-11-24 00:30:52 -0500266{
Harpreet \"Eli\" Sangha527ed442019-11-07 17:29:36 +0900267 if (auto hal = getHal<aidl::IVibrator>()) {
268 auto status = hal->call(&aidl::IVibrator::off);
269 if (!status.isOk()) {
270 ALOGE("vibratorOff command failed: %s", status.toString8().string());
271 }
272 } else {
273 Status retStatus = halCall(&V1_0::IVibrator::off).withDefault(Status::UNKNOWN_ERROR);
274 if (retStatus != Status::OK) {
275 ALOGE("vibratorOff command failed (%" PRIu32 ").", static_cast<uint32_t>(retStatus));
276 }
Vincent Beckere6904fb2012-08-10 14:17:33 +0200277 }
Mike Lockwood3a322132009-11-24 00:30:52 -0500278}
279
Harpreet "Eli" Sangha89ffc2d2019-07-25 11:32:57 +0900280static jlong vibratorSupportsAmplitudeControl(JNIEnv*, jclass) {
Harpreet \"Eli\" Sangha527ed442019-11-07 17:29:36 +0900281 if (auto hal = getHal<aidl::IVibrator>()) {
282 int32_t cap = 0;
283 if (!hal->call(&aidl::IVibrator::getCapabilities, &cap).isOk()) {
284 return false;
285 }
286 return (cap & aidl::IVibrator::CAP_AMPLITUDE_CONTROL) > 0;
287 } else {
288 return halCall(&V1_0::IVibrator::supportsAmplitudeControl).withDefault(false);
289 }
Michael Wright71216972017-01-31 18:33:54 +0000290}
291
Harpreet "Eli" Sangha89ffc2d2019-07-25 11:32:57 +0900292static void vibratorSetAmplitude(JNIEnv*, jclass, jint amplitude) {
Harpreet \"Eli\" Sangha527ed442019-11-07 17:29:36 +0900293 if (auto hal = getHal<aidl::IVibrator>()) {
294 auto status = hal->call(&aidl::IVibrator::IVibrator::setAmplitude, amplitude);
295 if (!status.isOk()) {
296 ALOGE("Failed to set vibrator amplitude: %s", status.toString8().string());
297 }
298 } else {
299 Status status = halCall(&V1_0::IVibrator::setAmplitude, static_cast<uint32_t>(amplitude))
300 .withDefault(Status::UNKNOWN_ERROR);
301 if (status != Status::OK) {
302 ALOGE("Failed to set vibrator amplitude (%" PRIu32 ").",
303 static_cast<uint32_t>(status));
304 }
Michael Wright71216972017-01-31 18:33:54 +0000305 }
306}
307
Harpreet "Eli" Sangha89ffc2d2019-07-25 11:32:57 +0900308static jboolean vibratorSupportsExternalControl(JNIEnv*, jclass) {
Harpreet \"Eli\" Sangha527ed442019-11-07 17:29:36 +0900309 if (auto hal = getHal<aidl::IVibrator>()) {
310 int32_t cap = 0;
311 if (!hal->call(&aidl::IVibrator::getCapabilities, &cap).isOk()) {
312 return false;
313 }
314 return (cap & aidl::IVibrator::CAP_EXTERNAL_CONTROL) > 0;
315 } else {
316 return halCall(&V1_3::IVibrator::supportsExternalControl).withDefault(false);
317 }
Harpreet "Eli" Sanghaa456f082018-12-14 12:06:10 +0900318}
319
Harpreet "Eli" Sangha89ffc2d2019-07-25 11:32:57 +0900320static void vibratorSetExternalControl(JNIEnv*, jclass, jboolean enabled) {
Harpreet \"Eli\" Sangha527ed442019-11-07 17:29:36 +0900321 if (auto hal = getHal<aidl::IVibrator>()) {
322 auto status = hal->call(&aidl::IVibrator::IVibrator::setExternalControl, enabled);
323 if (!status.isOk()) {
324 ALOGE("Failed to set vibrator external control: %s", status.toString8().string());
325 }
326 } else {
327 Status status = halCall(&V1_3::IVibrator::setExternalControl, static_cast<uint32_t>(enabled))
328 .withDefault(Status::UNKNOWN_ERROR);
329 if (status != Status::OK) {
330 ALOGE("Failed to set vibrator external control (%" PRIu32 ").",
331 static_cast<uint32_t>(status));
332 }
Harpreet "Eli" Sanghaa456f082018-12-14 12:06:10 +0900333 }
334}
335
Harpreet "Eli" Sangha89ffc2d2019-07-25 11:32:57 +0900336static jlong vibratorPerformEffect(JNIEnv* env, jclass, jlong effect, jlong strength,
337 jobject vibration) {
Harpreet \"Eli\" Sangha527ed442019-11-07 17:29:36 +0900338 if (auto hal = getHal<aidl::IVibrator>()) {
339 int32_t lengthMs;
340 sp<AidlVibratorCallback> effectCallback = new AidlVibratorCallback(env, vibration);
341 aidl::Effect effectType(static_cast<aidl::Effect>(strength));
342 aidl::EffectStrength effectStrength(static_cast<aidl::EffectStrength>(strength));
Michael Wright57d94d92017-05-31 14:44:45 +0100343
Harpreet \"Eli\" Sangha527ed442019-11-07 17:29:36 +0900344 auto status = hal->call(&aidl::IVibrator::perform, effectType, effectStrength, effectCallback, &lengthMs);
345 if (!status.isOk()) {
346 if (status.exceptionCode() != binder::Status::EX_UNSUPPORTED_OPERATION) {
347 ALOGE("Failed to perform haptic effect: effect=%" PRId64 ", strength=%" PRId32
348 ": %s", static_cast<int64_t>(effect), static_cast<int32_t>(strength), status.toString8().string());
349 }
350 return -1;
351 }
Tri Voa92c1542017-06-17 14:58:44 -0700352 return lengthMs;
Harpreet \"Eli\" Sangha527ed442019-11-07 17:29:36 +0900353 } else {
354 Status status;
355 uint32_t lengthMs;
356 auto callback = [&status, &lengthMs](Status retStatus, uint32_t retLengthMs) {
357 status = retStatus;
358 lengthMs = retLengthMs;
359 };
360 EffectStrength effectStrength(static_cast<EffectStrength>(strength));
361
362 Return<void> ret;
Steven Moreland5af46952019-11-10 17:56:28 -0800363 if (isValidEffect<V1_0::Effect>(effect)) {
Harpreet \"Eli\" Sangha527ed442019-11-07 17:29:36 +0900364 ret = halCall(&V1_0::IVibrator::perform, static_cast<V1_0::Effect>(effect),
365 effectStrength, callback);
366 } else if (isValidEffect<Effect_1_1>(effect)) {
367 ret = halCall(&V1_1::IVibrator::perform_1_1, static_cast<Effect_1_1>(effect),
368 effectStrength, callback);
369 } else if (isValidEffect<V1_2::Effect>(effect)) {
370 ret = halCall(&V1_2::IVibrator::perform_1_2, static_cast<V1_2::Effect>(effect),
371 effectStrength, callback);
372 } else if (isValidEffect<V1_3::Effect>(effect)) {
373 ret = halCall(&V1_3::IVibrator::perform_1_3, static_cast<V1_3::Effect>(effect),
374 effectStrength, callback);
375 } else {
376 ALOGW("Unable to perform haptic effect, invalid effect ID (%" PRId32 ")",
377 static_cast<int32_t>(effect));
378 return -1;
379 }
380
381 if (!ret.isOk()) {
382 ALOGW("Failed to perform effect (%" PRId32 ")", static_cast<int32_t>(effect));
383 return -1;
384 }
385
386 if (status == Status::OK) {
387 return lengthMs;
388 } else if (status != Status::UNSUPPORTED_OPERATION) {
389 // Don't warn on UNSUPPORTED_OPERATION, that's a normal event and just means the motor
390 // doesn't have a pre-defined waveform to perform for it, so we should just give the
391 // opportunity to fall back to the framework waveforms.
392 ALOGE("Failed to perform haptic effect: effect=%" PRId64 ", strength=%" PRId32
393 ", error=%" PRIu32 ").", static_cast<int64_t>(effect),
394 static_cast<int32_t>(strength), static_cast<uint32_t>(status));
395 }
Michael Wright71216972017-01-31 18:33:54 +0000396 }
Michael Wrightf268bf52018-02-07 23:23:34 +0000397
Michael Wright71216972017-01-31 18:33:54 +0000398 return -1;
399}
400
Harpreet "Eli" Sangha89ffc2d2019-07-25 11:32:57 +0900401static jlong vibratorGetCapabilities(JNIEnv*, jclass) {
Harpreet \"Eli\" Sangha527ed442019-11-07 17:29:36 +0900402 if (auto hal = getHal<aidl::IVibrator>()) {
403 int32_t cap = 0;
404 if (!hal->call(&aidl::IVibrator::getCapabilities, &cap).isOk()) {
405 return 0;
406 }
407 return cap;
Harpreet \"Eli\" Sangha527ed442019-11-07 17:29:36 +0900408 }
Steven Moreland5af46952019-11-10 17:56:28 -0800409
410 return 0;
Harpreet "Eli" Sangha89ffc2d2019-07-25 11:32:57 +0900411}
412
Daniel Micay76f6a862015-09-19 17:31:01 -0400413static const JNINativeMethod method_table[] = {
Dianne Hackbornea9020e2010-11-04 11:39:12 -0700414 { "vibratorExists", "()Z", (void*)vibratorExists },
Vincent Beckere6904fb2012-08-10 14:17:33 +0200415 { "vibratorInit", "()V", (void*)vibratorInit },
Mike Lockwood3a322132009-11-24 00:30:52 -0500416 { "vibratorOn", "(J)V", (void*)vibratorOn },
Michael Wright71216972017-01-31 18:33:54 +0000417 { "vibratorOff", "()V", (void*)vibratorOff },
418 { "vibratorSupportsAmplitudeControl", "()Z", (void*)vibratorSupportsAmplitudeControl},
419 { "vibratorSetAmplitude", "(I)V", (void*)vibratorSetAmplitude},
Harpreet "Eli" Sangha89ffc2d2019-07-25 11:32:57 +0900420 { "vibratorPerformEffect", "(JJLcom/android/server/VibratorService$Vibration;)J",
421 (void*)vibratorPerformEffect},
Harpreet "Eli" Sanghaa456f082018-12-14 12:06:10 +0900422 { "vibratorSupportsExternalControl", "()Z", (void*)vibratorSupportsExternalControl},
423 { "vibratorSetExternalControl", "(Z)V", (void*)vibratorSetExternalControl},
Harpreet "Eli" Sangha89ffc2d2019-07-25 11:32:57 +0900424 { "vibratorGetCapabilities", "()J", (void*)vibratorGetCapabilities},
Mike Lockwood3a322132009-11-24 00:30:52 -0500425};
426
427int register_android_server_VibratorService(JNIEnv *env)
428{
Harpreet "Eli" Sangha89ffc2d2019-07-25 11:32:57 +0900429 sMethodIdOnComplete = GetMethodIDOrDie(env,
430 FindClassOrDie(env, "com/android/server/VibratorService$Vibration"),
431 "onComplete", "()V");
Mike Lockwood3a322132009-11-24 00:30:52 -0500432 return jniRegisterNativeMethods(env, "com/android/server/VibratorService",
433 method_table, NELEM(method_table));
434}
435
436};