1 /*
2 * Copyright (C) 2020 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 "VibratorController"
18
19 #include <android/hardware/vibrator/1.3/IVibrator.h>
20 #include <android/hardware/vibrator/IVibrator.h>
21
22 #include <nativehelper/JNIHelp.h>
23 #include "android_runtime/AndroidRuntime.h"
24 #include "core_jni_helpers.h"
25 #include "jni.h"
26
27 #include <utils/Log.h>
28 #include <utils/misc.h>
29
30 #include <vibratorservice/VibratorHalController.h>
31
32 #include "com_android_server_vibrator_VibratorManagerService.h"
33
34 namespace V1_0 = android::hardware::vibrator::V1_0;
35 namespace V1_3 = android::hardware::vibrator::V1_3;
36 namespace aidl = android::hardware::vibrator;
37
38 namespace android {
39
40 static JavaVM* sJvm = nullptr;
41 static jmethodID sMethodIdOnComplete;
42 static jclass sFrequencyProfileClass;
43 static jmethodID sFrequencyProfileCtor;
44 static struct {
45 jmethodID setCapabilities;
46 jmethodID setSupportedEffects;
47 jmethodID setSupportedBraking;
48 jmethodID setPwlePrimitiveDurationMax;
49 jmethodID setPwleSizeMax;
50 jmethodID setSupportedPrimitive;
51 jmethodID setPrimitiveDelayMax;
52 jmethodID setCompositionSizeMax;
53 jmethodID setQFactor;
54 jmethodID setFrequencyProfile;
55 } sVibratorInfoBuilderClassInfo;
56 static struct {
57 jfieldID id;
58 jfieldID scale;
59 jfieldID delay;
60 } sPrimitiveClassInfo;
61 static struct {
62 jfieldID startAmplitude;
63 jfieldID endAmplitude;
64 jfieldID startFrequencyHz;
65 jfieldID endFrequencyHz;
66 jfieldID duration;
67 } sRampClassInfo;
68
69 static_assert(static_cast<uint8_t>(V1_0::EffectStrength::LIGHT) ==
70 static_cast<uint8_t>(aidl::EffectStrength::LIGHT));
71 static_assert(static_cast<uint8_t>(V1_0::EffectStrength::MEDIUM) ==
72 static_cast<uint8_t>(aidl::EffectStrength::MEDIUM));
73 static_assert(static_cast<uint8_t>(V1_0::EffectStrength::STRONG) ==
74 static_cast<uint8_t>(aidl::EffectStrength::STRONG));
75
76 static_assert(static_cast<uint8_t>(V1_3::Effect::CLICK) ==
77 static_cast<uint8_t>(aidl::Effect::CLICK));
78 static_assert(static_cast<uint8_t>(V1_3::Effect::DOUBLE_CLICK) ==
79 static_cast<uint8_t>(aidl::Effect::DOUBLE_CLICK));
80 static_assert(static_cast<uint8_t>(V1_3::Effect::TICK) == static_cast<uint8_t>(aidl::Effect::TICK));
81 static_assert(static_cast<uint8_t>(V1_3::Effect::THUD) == static_cast<uint8_t>(aidl::Effect::THUD));
82 static_assert(static_cast<uint8_t>(V1_3::Effect::POP) == static_cast<uint8_t>(aidl::Effect::POP));
83 static_assert(static_cast<uint8_t>(V1_3::Effect::HEAVY_CLICK) ==
84 static_cast<uint8_t>(aidl::Effect::HEAVY_CLICK));
85 static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_1) ==
86 static_cast<uint8_t>(aidl::Effect::RINGTONE_1));
87 static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_2) ==
88 static_cast<uint8_t>(aidl::Effect::RINGTONE_2));
89 static_assert(static_cast<uint8_t>(V1_3::Effect::RINGTONE_15) ==
90 static_cast<uint8_t>(aidl::Effect::RINGTONE_15));
91 static_assert(static_cast<uint8_t>(V1_3::Effect::TEXTURE_TICK) ==
92 static_cast<uint8_t>(aidl::Effect::TEXTURE_TICK));
93
findVibrator(int32_t vibratorId)94 static std::shared_ptr<vibrator::HalController> findVibrator(int32_t vibratorId) {
95 vibrator::ManagerHalController* manager =
96 android_server_vibrator_VibratorManagerService_getManager();
97 if (manager == nullptr) {
98 return nullptr;
99 }
100 auto result = manager->getVibrator(vibratorId);
101 return result.isOk() ? std::move(result.value()) : nullptr;
102 }
103
104 class VibratorControllerWrapper {
105 public:
VibratorControllerWrapper(JNIEnv * env,int32_t vibratorId,jobject callbackListener)106 VibratorControllerWrapper(JNIEnv* env, int32_t vibratorId, jobject callbackListener)
107 : mHal(findVibrator(vibratorId)),
108 mVibratorId(vibratorId),
109 mCallbackListener(env->NewGlobalRef(callbackListener)) {
110 LOG_ALWAYS_FATAL_IF(mHal == nullptr,
111 "Failed to connect to vibrator HAL, or vibratorId is invalid");
112 LOG_ALWAYS_FATAL_IF(mCallbackListener == nullptr,
113 "Unable to create global reference to vibration callback handler");
114 }
115
~VibratorControllerWrapper()116 ~VibratorControllerWrapper() {
117 auto jniEnv = GetOrAttachJNIEnvironment(sJvm);
118 jniEnv->DeleteGlobalRef(mCallbackListener);
119 }
120
getVibratorId() const121 int32_t getVibratorId() const { return mVibratorId; }
122
getVibratorInfo()123 vibrator::Info getVibratorInfo() { return mHal->getInfo(); }
124
initHal()125 void initHal() { mHal->init(); }
126
127 template <typename T>
halCall(const vibrator::HalFunction<vibrator::HalResult<T>> & fn,const char * functionName)128 vibrator::HalResult<T> halCall(const vibrator::HalFunction<vibrator::HalResult<T>>& fn,
129 const char* functionName) {
130 return mHal->doWithRetry(fn, functionName);
131 }
132
createCallback(jlong vibrationId)133 std::function<void()> createCallback(jlong vibrationId) {
134 auto callbackId = ++mCallbackId;
135 return [vibrationId, callbackId, this]() {
136 auto currentCallbackId = mCallbackId.load();
137 if (currentCallbackId != callbackId) {
138 // This callback is from an older HAL call that is no longer relevant to the service
139 return;
140 }
141 auto jniEnv = GetOrAttachJNIEnvironment(sJvm);
142 jniEnv->CallVoidMethod(mCallbackListener, sMethodIdOnComplete, mVibratorId,
143 vibrationId);
144 };
145 }
146
disableOldCallbacks()147 void disableOldCallbacks() {
148 mCallbackId++;
149 }
150
151 private:
152 const std::shared_ptr<vibrator::HalController> mHal;
153 const int32_t mVibratorId;
154 const jobject mCallbackListener;
155 std::atomic<int64_t> mCallbackId;
156 };
157
brakingPwle(aidl::Braking braking,int32_t duration)158 static aidl::BrakingPwle brakingPwle(aidl::Braking braking, int32_t duration) {
159 aidl::BrakingPwle pwle;
160 pwle.braking = braking;
161 pwle.duration = duration;
162 return pwle;
163 }
164
activePwleFromJavaPrimitive(JNIEnv * env,jobject ramp)165 static aidl::ActivePwle activePwleFromJavaPrimitive(JNIEnv* env, jobject ramp) {
166 aidl::ActivePwle pwle;
167 pwle.startAmplitude =
168 static_cast<float>(env->GetFloatField(ramp, sRampClassInfo.startAmplitude));
169 pwle.endAmplitude = static_cast<float>(env->GetFloatField(ramp, sRampClassInfo.endAmplitude));
170 pwle.startFrequency =
171 static_cast<float>(env->GetFloatField(ramp, sRampClassInfo.startFrequencyHz));
172 pwle.endFrequency = static_cast<float>(env->GetFloatField(ramp, sRampClassInfo.endFrequencyHz));
173 pwle.duration = static_cast<int32_t>(env->GetIntField(ramp, sRampClassInfo.duration));
174 return pwle;
175 }
176
177 /* Return true if braking is not NONE and the active PWLE starts and ends with zero amplitude. */
shouldBeReplacedWithBraking(aidl::ActivePwle activePwle,aidl::Braking braking)178 static bool shouldBeReplacedWithBraking(aidl::ActivePwle activePwle, aidl::Braking braking) {
179 return (braking != aidl::Braking::NONE) && (activePwle.startAmplitude == 0) &&
180 (activePwle.endAmplitude == 0);
181 }
182
183 /* Return true if braking is not NONE and the active PWLE only ends with zero amplitude. */
shouldAddLastBraking(aidl::ActivePwle lastActivePwle,aidl::Braking braking)184 static bool shouldAddLastBraking(aidl::ActivePwle lastActivePwle, aidl::Braking braking) {
185 return (braking != aidl::Braking::NONE) && (lastActivePwle.startAmplitude > 0) &&
186 (lastActivePwle.endAmplitude == 0);
187 }
188
effectFromJavaPrimitive(JNIEnv * env,jobject primitive)189 static aidl::CompositeEffect effectFromJavaPrimitive(JNIEnv* env, jobject primitive) {
190 aidl::CompositeEffect effect;
191 effect.primitive = static_cast<aidl::CompositePrimitive>(
192 env->GetIntField(primitive, sPrimitiveClassInfo.id));
193 effect.scale = static_cast<float>(env->GetFloatField(primitive, sPrimitiveClassInfo.scale));
194 effect.delayMs = static_cast<int32_t>(env->GetIntField(primitive, sPrimitiveClassInfo.delay));
195 return effect;
196 }
197
destroyNativeWrapper(void * ptr)198 static void destroyNativeWrapper(void* ptr) {
199 VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
200 if (wrapper) {
201 delete wrapper;
202 }
203 }
204
vibratorNativeInit(JNIEnv * env,jclass,jint vibratorId,jobject callbackListener)205 static jlong vibratorNativeInit(JNIEnv* env, jclass /* clazz */, jint vibratorId,
206 jobject callbackListener) {
207 std::unique_ptr<VibratorControllerWrapper> wrapper =
208 std::make_unique<VibratorControllerWrapper>(env, vibratorId, callbackListener);
209 wrapper->initHal();
210 return reinterpret_cast<jlong>(wrapper.release());
211 }
212
vibratorGetNativeFinalizer(JNIEnv *,jclass)213 static jlong vibratorGetNativeFinalizer(JNIEnv* /* env */, jclass /* clazz */) {
214 return static_cast<jlong>(reinterpret_cast<uintptr_t>(&destroyNativeWrapper));
215 }
216
vibratorIsAvailable(JNIEnv * env,jclass,jlong ptr)217 static jboolean vibratorIsAvailable(JNIEnv* env, jclass /* clazz */, jlong ptr) {
218 VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
219 if (wrapper == nullptr) {
220 ALOGE("vibratorIsAvailable failed because native wrapper was not initialized");
221 return JNI_FALSE;
222 }
223 auto pingFn = [](vibrator::HalWrapper* hal) { return hal->ping(); };
224 return wrapper->halCall<void>(pingFn, "ping").isOk() ? JNI_TRUE : JNI_FALSE;
225 }
226
vibratorOn(JNIEnv * env,jclass,jlong ptr,jlong timeoutMs,jlong vibrationId)227 static jlong vibratorOn(JNIEnv* env, jclass /* clazz */, jlong ptr, jlong timeoutMs,
228 jlong vibrationId) {
229 VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
230 if (wrapper == nullptr) {
231 ALOGE("vibratorOn failed because native wrapper was not initialized");
232 return -1;
233 }
234 auto callback = wrapper->createCallback(vibrationId);
235 auto onFn = [timeoutMs, &callback](vibrator::HalWrapper* hal) {
236 return hal->on(std::chrono::milliseconds(timeoutMs), callback);
237 };
238 auto result = wrapper->halCall<void>(onFn, "on");
239 return result.isOk() ? timeoutMs : (result.isUnsupported() ? 0 : -1);
240 }
241
vibratorOff(JNIEnv * env,jclass,jlong ptr)242 static void vibratorOff(JNIEnv* env, jclass /* clazz */, jlong ptr) {
243 VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
244 if (wrapper == nullptr) {
245 ALOGE("vibratorOff failed because native wrapper was not initialized");
246 return;
247 }
248 auto offFn = [](vibrator::HalWrapper* hal) { return hal->off(); };
249 wrapper->halCall<void>(offFn, "off");
250 wrapper->disableOldCallbacks();
251 }
252
vibratorSetAmplitude(JNIEnv * env,jclass,jlong ptr,jfloat amplitude)253 static void vibratorSetAmplitude(JNIEnv* env, jclass /* clazz */, jlong ptr, jfloat amplitude) {
254 VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
255 if (wrapper == nullptr) {
256 ALOGE("vibratorSetAmplitude failed because native wrapper was not initialized");
257 return;
258 }
259 auto setAmplitudeFn = [amplitude](vibrator::HalWrapper* hal) {
260 return hal->setAmplitude(static_cast<float>(amplitude));
261 };
262 wrapper->halCall<void>(setAmplitudeFn, "setAmplitude");
263 }
264
vibratorSetExternalControl(JNIEnv * env,jclass,jlong ptr,jboolean enabled)265 static void vibratorSetExternalControl(JNIEnv* env, jclass /* clazz */, jlong ptr,
266 jboolean enabled) {
267 VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
268 if (wrapper == nullptr) {
269 ALOGE("vibratorSetExternalControl failed because native wrapper was not initialized");
270 return;
271 }
272 auto setExternalControlFn = [enabled](vibrator::HalWrapper* hal) {
273 return hal->setExternalControl(enabled);
274 };
275 wrapper->halCall<void>(setExternalControlFn, "setExternalControl");
276 }
277
vibratorPerformEffect(JNIEnv * env,jclass,jlong ptr,jlong effect,jlong strength,jlong vibrationId)278 static jlong vibratorPerformEffect(JNIEnv* env, jclass /* clazz */, jlong ptr, jlong effect,
279 jlong strength, jlong vibrationId) {
280 VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
281 if (wrapper == nullptr) {
282 ALOGE("vibratorPerformEffect failed because native wrapper was not initialized");
283 return -1;
284 }
285 aidl::Effect effectType = static_cast<aidl::Effect>(effect);
286 aidl::EffectStrength effectStrength = static_cast<aidl::EffectStrength>(strength);
287 auto callback = wrapper->createCallback(vibrationId);
288 auto performEffectFn = [effectType, effectStrength, &callback](vibrator::HalWrapper* hal) {
289 return hal->performEffect(effectType, effectStrength, callback);
290 };
291 auto result = wrapper->halCall<std::chrono::milliseconds>(performEffectFn, "performEffect");
292 return result.isOk() ? result.value().count() : (result.isUnsupported() ? 0 : -1);
293 }
294
vibratorPerformComposedEffect(JNIEnv * env,jclass,jlong ptr,jobjectArray composition,jlong vibrationId)295 static jlong vibratorPerformComposedEffect(JNIEnv* env, jclass /* clazz */, jlong ptr,
296 jobjectArray composition, jlong vibrationId) {
297 VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
298 if (wrapper == nullptr) {
299 ALOGE("vibratorPerformComposedEffect failed because native wrapper was not initialized");
300 return -1;
301 }
302 size_t size = env->GetArrayLength(composition);
303 std::vector<aidl::CompositeEffect> effects;
304 for (size_t i = 0; i < size; i++) {
305 jobject element = env->GetObjectArrayElement(composition, i);
306 effects.push_back(effectFromJavaPrimitive(env, element));
307 }
308 auto callback = wrapper->createCallback(vibrationId);
309 auto performComposedEffectFn = [&effects, &callback](vibrator::HalWrapper* hal) {
310 return hal->performComposedEffect(effects, callback);
311 };
312 auto result = wrapper->halCall<std::chrono::milliseconds>(performComposedEffectFn,
313 "performComposedEffect");
314 return result.isOk() ? result.value().count() : (result.isUnsupported() ? 0 : -1);
315 }
316
vibratorPerformPwleEffect(JNIEnv * env,jclass,jlong ptr,jobjectArray waveform,jint brakingId,jlong vibrationId)317 static jlong vibratorPerformPwleEffect(JNIEnv* env, jclass /* clazz */, jlong ptr,
318 jobjectArray waveform, jint brakingId, jlong vibrationId) {
319 VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
320 if (wrapper == nullptr) {
321 ALOGE("vibratorPerformPwleEffect failed because native wrapper was not initialized");
322 return -1;
323 }
324 aidl::Braking braking = static_cast<aidl::Braking>(brakingId);
325 size_t size = env->GetArrayLength(waveform);
326 std::vector<aidl::PrimitivePwle> primitives;
327 std::chrono::milliseconds totalDuration(0);
328 for (size_t i = 0; i < size; i++) {
329 jobject element = env->GetObjectArrayElement(waveform, i);
330 aidl::ActivePwle activePwle = activePwleFromJavaPrimitive(env, element);
331 if ((i > 0) && shouldBeReplacedWithBraking(activePwle, braking)) {
332 primitives.push_back(brakingPwle(braking, activePwle.duration));
333 } else {
334 primitives.push_back(activePwle);
335 }
336 totalDuration += std::chrono::milliseconds(activePwle.duration);
337
338 if ((i == (size - 1)) && shouldAddLastBraking(activePwle, braking)) {
339 primitives.push_back(brakingPwle(braking, 0 /* duration */));
340 }
341 }
342
343 auto callback = wrapper->createCallback(vibrationId);
344 auto performPwleEffectFn = [&primitives, &callback](vibrator::HalWrapper* hal) {
345 return hal->performPwleEffect(primitives, callback);
346 };
347 auto result = wrapper->halCall<void>(performPwleEffectFn, "performPwleEffect");
348 return result.isOk() ? totalDuration.count() : (result.isUnsupported() ? 0 : -1);
349 }
350
vibratorAlwaysOnEnable(JNIEnv * env,jclass,jlong ptr,jlong id,jlong effect,jlong strength)351 static void vibratorAlwaysOnEnable(JNIEnv* env, jclass /* clazz */, jlong ptr, jlong id,
352 jlong effect, jlong strength) {
353 VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
354 if (wrapper == nullptr) {
355 ALOGE("vibratorAlwaysOnEnable failed because native wrapper was not initialized");
356 return;
357 }
358 auto alwaysOnEnableFn = [id, effect, strength](vibrator::HalWrapper* hal) {
359 return hal->alwaysOnEnable(static_cast<int32_t>(id), static_cast<aidl::Effect>(effect),
360 static_cast<aidl::EffectStrength>(strength));
361 };
362 wrapper->halCall<void>(alwaysOnEnableFn, "alwaysOnEnable");
363 }
364
vibratorAlwaysOnDisable(JNIEnv * env,jclass,jlong ptr,jlong id)365 static void vibratorAlwaysOnDisable(JNIEnv* env, jclass /* clazz */, jlong ptr, jlong id) {
366 VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
367 if (wrapper == nullptr) {
368 ALOGE("vibratorAlwaysOnDisable failed because native wrapper was not initialized");
369 return;
370 }
371 auto alwaysOnDisableFn = [id](vibrator::HalWrapper* hal) {
372 return hal->alwaysOnDisable(static_cast<int32_t>(id));
373 };
374 wrapper->halCall<void>(alwaysOnDisableFn, "alwaysOnDisable");
375 }
376
vibratorGetInfo(JNIEnv * env,jclass,jlong ptr,jobject vibratorInfoBuilder)377 static jboolean vibratorGetInfo(JNIEnv* env, jclass /* clazz */, jlong ptr,
378 jobject vibratorInfoBuilder) {
379 VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
380 if (wrapper == nullptr) {
381 ALOGE("vibratorGetInfo failed because native wrapper was not initialized");
382 return JNI_FALSE;
383 }
384 vibrator::Info info = wrapper->getVibratorInfo();
385 info.logFailures();
386
387 if (info.capabilities.isOk()) {
388 env->CallObjectMethod(vibratorInfoBuilder, sVibratorInfoBuilderClassInfo.setCapabilities,
389 static_cast<jlong>(info.capabilities.value()));
390 }
391 if (info.supportedEffects.isOk()) {
392 std::vector<aidl::Effect> effects = info.supportedEffects.value();
393 jintArray supportedEffects = env->NewIntArray(effects.size());
394 env->SetIntArrayRegion(supportedEffects, 0, effects.size(),
395 reinterpret_cast<jint*>(effects.data()));
396 env->CallObjectMethod(vibratorInfoBuilder,
397 sVibratorInfoBuilderClassInfo.setSupportedEffects, supportedEffects);
398 }
399 if (info.supportedBraking.isOk()) {
400 std::vector<aidl::Braking> braking = info.supportedBraking.value();
401 jintArray supportedBraking = env->NewIntArray(braking.size());
402 env->SetIntArrayRegion(supportedBraking, 0, braking.size(),
403 reinterpret_cast<jint*>(braking.data()));
404 env->CallObjectMethod(vibratorInfoBuilder,
405 sVibratorInfoBuilderClassInfo.setSupportedBraking, supportedBraking);
406 }
407 if (info.pwlePrimitiveDurationMax.isOk()) {
408 env->CallObjectMethod(vibratorInfoBuilder,
409 sVibratorInfoBuilderClassInfo.setPwlePrimitiveDurationMax,
410 static_cast<jint>(info.pwlePrimitiveDurationMax.value().count()));
411 }
412 if (info.pwleSizeMax.isOk()) {
413 // Use (pwleMaxSize - 1) to account for a possible extra braking segment added by the
414 // vibratorPerformPwleEffect method.
415 env->CallObjectMethod(vibratorInfoBuilder, sVibratorInfoBuilderClassInfo.setPwleSizeMax,
416 static_cast<jint>(info.pwleSizeMax.value() - 1));
417 }
418 if (info.supportedPrimitives.isOk()) {
419 auto durations = info.primitiveDurations.valueOr({});
420 for (auto& primitive : info.supportedPrimitives.value()) {
421 auto primitiveIdx = static_cast<size_t>(primitive);
422 auto duration = durations.size() > primitiveIdx ? durations[primitiveIdx].count() : 0;
423 env->CallObjectMethod(vibratorInfoBuilder,
424 sVibratorInfoBuilderClassInfo.setSupportedPrimitive,
425 static_cast<jint>(primitive), static_cast<jint>(duration));
426 }
427 }
428 if (info.primitiveDelayMax.isOk()) {
429 env->CallObjectMethod(vibratorInfoBuilder,
430 sVibratorInfoBuilderClassInfo.setPrimitiveDelayMax,
431 static_cast<jint>(info.primitiveDelayMax.value().count()));
432 }
433 if (info.compositionSizeMax.isOk()) {
434 env->CallObjectMethod(vibratorInfoBuilder,
435 sVibratorInfoBuilderClassInfo.setCompositionSizeMax,
436 static_cast<jint>(info.compositionSizeMax.value()));
437 }
438 if (info.qFactor.isOk()) {
439 env->CallObjectMethod(vibratorInfoBuilder, sVibratorInfoBuilderClassInfo.setQFactor,
440 static_cast<jfloat>(info.qFactor.value()));
441 }
442
443 jfloat minFrequency = static_cast<jfloat>(info.minFrequency.valueOr(NAN));
444 jfloat resonantFrequency = static_cast<jfloat>(info.resonantFrequency.valueOr(NAN));
445 jfloat frequencyResolution = static_cast<jfloat>(info.frequencyResolution.valueOr(NAN));
446 jfloatArray maxAmplitudes = nullptr;
447 if (info.maxAmplitudes.isOk()) {
448 std::vector<float> amplitudes = info.maxAmplitudes.value();
449 maxAmplitudes = env->NewFloatArray(amplitudes.size());
450 env->SetFloatArrayRegion(maxAmplitudes, 0, amplitudes.size(),
451 reinterpret_cast<jfloat*>(amplitudes.data()));
452 }
453 jobject frequencyProfile =
454 env->NewObject(sFrequencyProfileClass, sFrequencyProfileCtor, resonantFrequency,
455 minFrequency, frequencyResolution, maxAmplitudes);
456 env->CallObjectMethod(vibratorInfoBuilder, sVibratorInfoBuilderClassInfo.setFrequencyProfile,
457 frequencyProfile);
458
459 return info.shouldRetry() ? JNI_FALSE : JNI_TRUE;
460 }
461
462 static const JNINativeMethod method_table[] = {
463 {"nativeInit",
464 "(ILcom/android/server/vibrator/VibratorController$OnVibrationCompleteListener;)J",
465 (void*)vibratorNativeInit},
466 {"getNativeFinalizer", "()J", (void*)vibratorGetNativeFinalizer},
467 {"isAvailable", "(J)Z", (void*)vibratorIsAvailable},
468 {"on", "(JJJ)J", (void*)vibratorOn},
469 {"off", "(J)V", (void*)vibratorOff},
470 {"setAmplitude", "(JF)V", (void*)vibratorSetAmplitude},
471 {"performEffect", "(JJJJ)J", (void*)vibratorPerformEffect},
472 {"performComposedEffect", "(J[Landroid/os/vibrator/PrimitiveSegment;J)J",
473 (void*)vibratorPerformComposedEffect},
474 {"performPwleEffect", "(J[Landroid/os/vibrator/RampSegment;IJ)J",
475 (void*)vibratorPerformPwleEffect},
476 {"setExternalControl", "(JZ)V", (void*)vibratorSetExternalControl},
477 {"alwaysOnEnable", "(JJJJ)V", (void*)vibratorAlwaysOnEnable},
478 {"alwaysOnDisable", "(JJ)V", (void*)vibratorAlwaysOnDisable},
479 {"getInfo", "(JLandroid/os/VibratorInfo$Builder;)Z", (void*)vibratorGetInfo},
480 };
481
register_android_server_vibrator_VibratorController(JavaVM * jvm,JNIEnv * env)482 int register_android_server_vibrator_VibratorController(JavaVM* jvm, JNIEnv* env) {
483 sJvm = jvm;
484 auto listenerClassName =
485 "com/android/server/vibrator/VibratorController$OnVibrationCompleteListener";
486 jclass listenerClass = FindClassOrDie(env, listenerClassName);
487 sMethodIdOnComplete = GetMethodIDOrDie(env, listenerClass, "onComplete", "(IJ)V");
488
489 jclass primitiveClass = FindClassOrDie(env, "android/os/vibrator/PrimitiveSegment");
490 sPrimitiveClassInfo.id = GetFieldIDOrDie(env, primitiveClass, "mPrimitiveId", "I");
491 sPrimitiveClassInfo.scale = GetFieldIDOrDie(env, primitiveClass, "mScale", "F");
492 sPrimitiveClassInfo.delay = GetFieldIDOrDie(env, primitiveClass, "mDelay", "I");
493
494 jclass rampClass = FindClassOrDie(env, "android/os/vibrator/RampSegment");
495 sRampClassInfo.startAmplitude = GetFieldIDOrDie(env, rampClass, "mStartAmplitude", "F");
496 sRampClassInfo.endAmplitude = GetFieldIDOrDie(env, rampClass, "mEndAmplitude", "F");
497 sRampClassInfo.startFrequencyHz = GetFieldIDOrDie(env, rampClass, "mStartFrequencyHz", "F");
498 sRampClassInfo.endFrequencyHz = GetFieldIDOrDie(env, rampClass, "mEndFrequencyHz", "F");
499 sRampClassInfo.duration = GetFieldIDOrDie(env, rampClass, "mDuration", "I");
500
501 jclass frequencyProfileClass = FindClassOrDie(env, "android/os/VibratorInfo$FrequencyProfile");
502 sFrequencyProfileClass = static_cast<jclass>(env->NewGlobalRef(frequencyProfileClass));
503 sFrequencyProfileCtor = GetMethodIDOrDie(env, sFrequencyProfileClass, "<init>", "(FFF[F)V");
504
505 jclass vibratorInfoBuilderClass = FindClassOrDie(env, "android/os/VibratorInfo$Builder");
506 sVibratorInfoBuilderClassInfo.setCapabilities =
507 GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setCapabilities",
508 "(J)Landroid/os/VibratorInfo$Builder;");
509 sVibratorInfoBuilderClassInfo.setSupportedEffects =
510 GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setSupportedEffects",
511 "([I)Landroid/os/VibratorInfo$Builder;");
512 sVibratorInfoBuilderClassInfo.setSupportedBraking =
513 GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setSupportedBraking",
514 "([I)Landroid/os/VibratorInfo$Builder;");
515 sVibratorInfoBuilderClassInfo.setPwlePrimitiveDurationMax =
516 GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setPwlePrimitiveDurationMax",
517 "(I)Landroid/os/VibratorInfo$Builder;");
518 sVibratorInfoBuilderClassInfo.setPwleSizeMax =
519 GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setPwleSizeMax",
520 "(I)Landroid/os/VibratorInfo$Builder;");
521 sVibratorInfoBuilderClassInfo.setSupportedPrimitive =
522 GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setSupportedPrimitive",
523 "(II)Landroid/os/VibratorInfo$Builder;");
524 sVibratorInfoBuilderClassInfo.setPrimitiveDelayMax =
525 GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setPrimitiveDelayMax",
526 "(I)Landroid/os/VibratorInfo$Builder;");
527 sVibratorInfoBuilderClassInfo.setCompositionSizeMax =
528 GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setCompositionSizeMax",
529 "(I)Landroid/os/VibratorInfo$Builder;");
530 sVibratorInfoBuilderClassInfo.setQFactor =
531 GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setQFactor",
532 "(F)Landroid/os/VibratorInfo$Builder;");
533 sVibratorInfoBuilderClassInfo.setFrequencyProfile =
534 GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setFrequencyProfile",
535 "(Landroid/os/VibratorInfo$FrequencyProfile;)"
536 "Landroid/os/VibratorInfo$Builder;");
537
538 return jniRegisterNativeMethods(env,
539 "com/android/server/vibrator/VibratorController$NativeWrapper",
540 method_table, NELEM(method_table));
541 }
542
543 }; // namespace android
544