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 return [vibrationId, this]() {
135 auto jniEnv = GetOrAttachJNIEnvironment(sJvm);
136 jniEnv->CallVoidMethod(mCallbackListener, sMethodIdOnComplete, mVibratorId,
137 vibrationId);
138 };
139 }
140
141 private:
142 const std::shared_ptr<vibrator::HalController> mHal;
143 const int32_t mVibratorId;
144 const jobject mCallbackListener;
145 };
146
brakingPwle(aidl::Braking braking,int32_t duration)147 static aidl::BrakingPwle brakingPwle(aidl::Braking braking, int32_t duration) {
148 aidl::BrakingPwle pwle;
149 pwle.braking = braking;
150 pwle.duration = duration;
151 return pwle;
152 }
153
activePwleFromJavaPrimitive(JNIEnv * env,jobject ramp)154 static aidl::ActivePwle activePwleFromJavaPrimitive(JNIEnv* env, jobject ramp) {
155 aidl::ActivePwle pwle;
156 pwle.startAmplitude =
157 static_cast<float>(env->GetFloatField(ramp, sRampClassInfo.startAmplitude));
158 pwle.endAmplitude = static_cast<float>(env->GetFloatField(ramp, sRampClassInfo.endAmplitude));
159 pwle.startFrequency =
160 static_cast<float>(env->GetFloatField(ramp, sRampClassInfo.startFrequencyHz));
161 pwle.endFrequency = static_cast<float>(env->GetFloatField(ramp, sRampClassInfo.endFrequencyHz));
162 pwle.duration = static_cast<int32_t>(env->GetIntField(ramp, sRampClassInfo.duration));
163 return pwle;
164 }
165
166 /* Return true if braking is not NONE and the active PWLE starts and ends with zero amplitude. */
shouldBeReplacedWithBraking(aidl::ActivePwle activePwle,aidl::Braking braking)167 static bool shouldBeReplacedWithBraking(aidl::ActivePwle activePwle, aidl::Braking braking) {
168 return (braking != aidl::Braking::NONE) && (activePwle.startAmplitude == 0) &&
169 (activePwle.endAmplitude == 0);
170 }
171
172 /* Return true if braking is not NONE and the active PWLE only ends with zero amplitude. */
shouldAddLastBraking(aidl::ActivePwle lastActivePwle,aidl::Braking braking)173 static bool shouldAddLastBraking(aidl::ActivePwle lastActivePwle, aidl::Braking braking) {
174 return (braking != aidl::Braking::NONE) && (lastActivePwle.startAmplitude > 0) &&
175 (lastActivePwle.endAmplitude == 0);
176 }
177
effectFromJavaPrimitive(JNIEnv * env,jobject primitive)178 static aidl::CompositeEffect effectFromJavaPrimitive(JNIEnv* env, jobject primitive) {
179 aidl::CompositeEffect effect;
180 effect.primitive = static_cast<aidl::CompositePrimitive>(
181 env->GetIntField(primitive, sPrimitiveClassInfo.id));
182 effect.scale = static_cast<float>(env->GetFloatField(primitive, sPrimitiveClassInfo.scale));
183 effect.delayMs = static_cast<int32_t>(env->GetIntField(primitive, sPrimitiveClassInfo.delay));
184 return effect;
185 }
186
destroyNativeWrapper(void * ptr)187 static void destroyNativeWrapper(void* ptr) {
188 VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
189 if (wrapper) {
190 delete wrapper;
191 }
192 }
193
vibratorNativeInit(JNIEnv * env,jclass,jint vibratorId,jobject callbackListener)194 static jlong vibratorNativeInit(JNIEnv* env, jclass /* clazz */, jint vibratorId,
195 jobject callbackListener) {
196 std::unique_ptr<VibratorControllerWrapper> wrapper =
197 std::make_unique<VibratorControllerWrapper>(env, vibratorId, callbackListener);
198 wrapper->initHal();
199 return reinterpret_cast<jlong>(wrapper.release());
200 }
201
vibratorGetNativeFinalizer(JNIEnv *,jclass)202 static jlong vibratorGetNativeFinalizer(JNIEnv* /* env */, jclass /* clazz */) {
203 return static_cast<jlong>(reinterpret_cast<uintptr_t>(&destroyNativeWrapper));
204 }
205
vibratorIsAvailable(JNIEnv * env,jclass,jlong ptr)206 static jboolean vibratorIsAvailable(JNIEnv* env, jclass /* clazz */, jlong ptr) {
207 VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
208 if (wrapper == nullptr) {
209 ALOGE("vibratorIsAvailable failed because native wrapper was not initialized");
210 return JNI_FALSE;
211 }
212 auto pingFn = [](vibrator::HalWrapper* hal) { return hal->ping(); };
213 return wrapper->halCall<void>(pingFn, "ping").isOk() ? JNI_TRUE : JNI_FALSE;
214 }
215
vibratorOn(JNIEnv * env,jclass,jlong ptr,jlong timeoutMs,jlong vibrationId)216 static jlong vibratorOn(JNIEnv* env, jclass /* clazz */, jlong ptr, jlong timeoutMs,
217 jlong vibrationId) {
218 VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
219 if (wrapper == nullptr) {
220 ALOGE("vibratorOn failed because native wrapper was not initialized");
221 return -1;
222 }
223 auto callback = wrapper->createCallback(vibrationId);
224 auto onFn = [timeoutMs, &callback](vibrator::HalWrapper* hal) {
225 return hal->on(std::chrono::milliseconds(timeoutMs), callback);
226 };
227 auto result = wrapper->halCall<void>(onFn, "on");
228 return result.isOk() ? timeoutMs : (result.isUnsupported() ? 0 : -1);
229 }
230
vibratorOff(JNIEnv * env,jclass,jlong ptr)231 static void vibratorOff(JNIEnv* env, jclass /* clazz */, jlong ptr) {
232 VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
233 if (wrapper == nullptr) {
234 ALOGE("vibratorOff failed because native wrapper was not initialized");
235 return;
236 }
237 auto offFn = [](vibrator::HalWrapper* hal) { return hal->off(); };
238 wrapper->halCall<void>(offFn, "off");
239 }
240
vibratorSetAmplitude(JNIEnv * env,jclass,jlong ptr,jfloat amplitude)241 static void vibratorSetAmplitude(JNIEnv* env, jclass /* clazz */, jlong ptr, jfloat amplitude) {
242 VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
243 if (wrapper == nullptr) {
244 ALOGE("vibratorSetAmplitude failed because native wrapper was not initialized");
245 return;
246 }
247 auto setAmplitudeFn = [amplitude](vibrator::HalWrapper* hal) {
248 return hal->setAmplitude(static_cast<float>(amplitude));
249 };
250 wrapper->halCall<void>(setAmplitudeFn, "setAmplitude");
251 }
252
vibratorSetExternalControl(JNIEnv * env,jclass,jlong ptr,jboolean enabled)253 static void vibratorSetExternalControl(JNIEnv* env, jclass /* clazz */, jlong ptr,
254 jboolean enabled) {
255 VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
256 if (wrapper == nullptr) {
257 ALOGE("vibratorSetExternalControl failed because native wrapper was not initialized");
258 return;
259 }
260 auto setExternalControlFn = [enabled](vibrator::HalWrapper* hal) {
261 return hal->setExternalControl(enabled);
262 };
263 wrapper->halCall<void>(setExternalControlFn, "setExternalControl");
264 }
265
vibratorPerformEffect(JNIEnv * env,jclass,jlong ptr,jlong effect,jlong strength,jlong vibrationId)266 static jlong vibratorPerformEffect(JNIEnv* env, jclass /* clazz */, jlong ptr, jlong effect,
267 jlong strength, jlong vibrationId) {
268 VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
269 if (wrapper == nullptr) {
270 ALOGE("vibratorPerformEffect failed because native wrapper was not initialized");
271 return -1;
272 }
273 aidl::Effect effectType = static_cast<aidl::Effect>(effect);
274 aidl::EffectStrength effectStrength = static_cast<aidl::EffectStrength>(strength);
275 auto callback = wrapper->createCallback(vibrationId);
276 auto performEffectFn = [effectType, effectStrength, &callback](vibrator::HalWrapper* hal) {
277 return hal->performEffect(effectType, effectStrength, callback);
278 };
279 auto result = wrapper->halCall<std::chrono::milliseconds>(performEffectFn, "performEffect");
280 return result.isOk() ? result.value().count() : (result.isUnsupported() ? 0 : -1);
281 }
282
vibratorPerformComposedEffect(JNIEnv * env,jclass,jlong ptr,jobjectArray composition,jlong vibrationId)283 static jlong vibratorPerformComposedEffect(JNIEnv* env, jclass /* clazz */, jlong ptr,
284 jobjectArray composition, jlong vibrationId) {
285 VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
286 if (wrapper == nullptr) {
287 ALOGE("vibratorPerformComposedEffect failed because native wrapper was not initialized");
288 return -1;
289 }
290 size_t size = env->GetArrayLength(composition);
291 std::vector<aidl::CompositeEffect> effects;
292 for (size_t i = 0; i < size; i++) {
293 jobject element = env->GetObjectArrayElement(composition, i);
294 effects.push_back(effectFromJavaPrimitive(env, element));
295 }
296 auto callback = wrapper->createCallback(vibrationId);
297 auto performComposedEffectFn = [&effects, &callback](vibrator::HalWrapper* hal) {
298 return hal->performComposedEffect(effects, callback);
299 };
300 auto result = wrapper->halCall<std::chrono::milliseconds>(performComposedEffectFn,
301 "performComposedEffect");
302 return result.isOk() ? result.value().count() : (result.isUnsupported() ? 0 : -1);
303 }
304
vibratorPerformPwleEffect(JNIEnv * env,jclass,jlong ptr,jobjectArray waveform,jint brakingId,jlong vibrationId)305 static jlong vibratorPerformPwleEffect(JNIEnv* env, jclass /* clazz */, jlong ptr,
306 jobjectArray waveform, jint brakingId, jlong vibrationId) {
307 VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
308 if (wrapper == nullptr) {
309 ALOGE("vibratorPerformPwleEffect failed because native wrapper was not initialized");
310 return -1;
311 }
312 aidl::Braking braking = static_cast<aidl::Braking>(brakingId);
313 size_t size = env->GetArrayLength(waveform);
314 std::vector<aidl::PrimitivePwle> primitives;
315 std::chrono::milliseconds totalDuration(0);
316 for (size_t i = 0; i < size; i++) {
317 jobject element = env->GetObjectArrayElement(waveform, i);
318 aidl::ActivePwle activePwle = activePwleFromJavaPrimitive(env, element);
319 if ((i > 0) && shouldBeReplacedWithBraking(activePwle, braking)) {
320 primitives.push_back(brakingPwle(braking, activePwle.duration));
321 } else {
322 primitives.push_back(activePwle);
323 }
324 totalDuration += std::chrono::milliseconds(activePwle.duration);
325
326 if ((i == (size - 1)) && shouldAddLastBraking(activePwle, braking)) {
327 primitives.push_back(brakingPwle(braking, 0 /* duration */));
328 }
329 }
330
331 auto callback = wrapper->createCallback(vibrationId);
332 auto performPwleEffectFn = [&primitives, &callback](vibrator::HalWrapper* hal) {
333 return hal->performPwleEffect(primitives, callback);
334 };
335 auto result = wrapper->halCall<void>(performPwleEffectFn, "performPwleEffect");
336 return result.isOk() ? totalDuration.count() : (result.isUnsupported() ? 0 : -1);
337 }
338
vibratorAlwaysOnEnable(JNIEnv * env,jclass,jlong ptr,jlong id,jlong effect,jlong strength)339 static void vibratorAlwaysOnEnable(JNIEnv* env, jclass /* clazz */, jlong ptr, jlong id,
340 jlong effect, jlong strength) {
341 VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
342 if (wrapper == nullptr) {
343 ALOGE("vibratorAlwaysOnEnable failed because native wrapper was not initialized");
344 return;
345 }
346 auto alwaysOnEnableFn = [id, effect, strength](vibrator::HalWrapper* hal) {
347 return hal->alwaysOnEnable(static_cast<int32_t>(id), static_cast<aidl::Effect>(effect),
348 static_cast<aidl::EffectStrength>(strength));
349 };
350 wrapper->halCall<void>(alwaysOnEnableFn, "alwaysOnEnable");
351 }
352
vibratorAlwaysOnDisable(JNIEnv * env,jclass,jlong ptr,jlong id)353 static void vibratorAlwaysOnDisable(JNIEnv* env, jclass /* clazz */, jlong ptr, jlong id) {
354 VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
355 if (wrapper == nullptr) {
356 ALOGE("vibratorAlwaysOnDisable failed because native wrapper was not initialized");
357 return;
358 }
359 auto alwaysOnDisableFn = [id](vibrator::HalWrapper* hal) {
360 return hal->alwaysOnDisable(static_cast<int32_t>(id));
361 };
362 wrapper->halCall<void>(alwaysOnDisableFn, "alwaysOnDisable");
363 }
364
vibratorGetInfo(JNIEnv * env,jclass,jlong ptr,jobject vibratorInfoBuilder)365 static jboolean vibratorGetInfo(JNIEnv* env, jclass /* clazz */, jlong ptr,
366 jobject vibratorInfoBuilder) {
367 VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
368 if (wrapper == nullptr) {
369 ALOGE("vibratorGetInfo failed because native wrapper was not initialized");
370 return JNI_FALSE;
371 }
372 vibrator::Info info = wrapper->getVibratorInfo();
373
374 if (info.capabilities.isOk()) {
375 env->CallObjectMethod(vibratorInfoBuilder, sVibratorInfoBuilderClassInfo.setCapabilities,
376 static_cast<jlong>(info.capabilities.value()));
377 }
378 if (info.supportedEffects.isOk()) {
379 std::vector<aidl::Effect> effects = info.supportedEffects.value();
380 jintArray supportedEffects = env->NewIntArray(effects.size());
381 env->SetIntArrayRegion(supportedEffects, 0, effects.size(),
382 reinterpret_cast<jint*>(effects.data()));
383 env->CallObjectMethod(vibratorInfoBuilder,
384 sVibratorInfoBuilderClassInfo.setSupportedEffects, supportedEffects);
385 }
386 if (info.supportedBraking.isOk()) {
387 std::vector<aidl::Braking> braking = info.supportedBraking.value();
388 jintArray supportedBraking = env->NewIntArray(braking.size());
389 env->SetIntArrayRegion(supportedBraking, 0, braking.size(),
390 reinterpret_cast<jint*>(braking.data()));
391 env->CallObjectMethod(vibratorInfoBuilder,
392 sVibratorInfoBuilderClassInfo.setSupportedBraking, supportedBraking);
393 }
394 if (info.pwlePrimitiveDurationMax.isOk()) {
395 env->CallObjectMethod(vibratorInfoBuilder,
396 sVibratorInfoBuilderClassInfo.setPwlePrimitiveDurationMax,
397 static_cast<jint>(info.pwlePrimitiveDurationMax.value().count()));
398 }
399 if (info.pwleSizeMax.isOk()) {
400 // Use (pwleMaxSize - 1) to account for a possible extra braking segment added by the
401 // vibratorPerformPwleEffect method.
402 env->CallObjectMethod(vibratorInfoBuilder, sVibratorInfoBuilderClassInfo.setPwleSizeMax,
403 static_cast<jint>(info.pwleSizeMax.value() - 1));
404 }
405 if (info.supportedPrimitives.isOk()) {
406 auto durations = info.primitiveDurations.valueOr({});
407 for (auto& primitive : info.supportedPrimitives.value()) {
408 auto primitiveIdx = static_cast<size_t>(primitive);
409 auto duration = durations.size() > primitiveIdx ? durations[primitiveIdx].count() : 0;
410 env->CallObjectMethod(vibratorInfoBuilder,
411 sVibratorInfoBuilderClassInfo.setSupportedPrimitive,
412 static_cast<jint>(primitive), static_cast<jint>(duration));
413 }
414 }
415 if (info.primitiveDelayMax.isOk()) {
416 env->CallObjectMethod(vibratorInfoBuilder,
417 sVibratorInfoBuilderClassInfo.setPrimitiveDelayMax,
418 static_cast<jint>(info.primitiveDelayMax.value().count()));
419 }
420 if (info.compositionSizeMax.isOk()) {
421 env->CallObjectMethod(vibratorInfoBuilder,
422 sVibratorInfoBuilderClassInfo.setCompositionSizeMax,
423 static_cast<jint>(info.compositionSizeMax.value()));
424 }
425 if (info.qFactor.isOk()) {
426 env->CallObjectMethod(vibratorInfoBuilder, sVibratorInfoBuilderClassInfo.setQFactor,
427 static_cast<jfloat>(info.qFactor.value()));
428 }
429
430 jfloat minFrequency = static_cast<jfloat>(info.minFrequency.valueOr(NAN));
431 jfloat resonantFrequency = static_cast<jfloat>(info.resonantFrequency.valueOr(NAN));
432 jfloat frequencyResolution = static_cast<jfloat>(info.frequencyResolution.valueOr(NAN));
433 jfloatArray maxAmplitudes = nullptr;
434 if (info.maxAmplitudes.isOk()) {
435 std::vector<float> amplitudes = info.maxAmplitudes.value();
436 maxAmplitudes = env->NewFloatArray(amplitudes.size());
437 env->SetFloatArrayRegion(maxAmplitudes, 0, amplitudes.size(),
438 reinterpret_cast<jfloat*>(amplitudes.data()));
439 }
440 jobject frequencyProfile =
441 env->NewObject(sFrequencyProfileClass, sFrequencyProfileCtor, resonantFrequency,
442 minFrequency, frequencyResolution, maxAmplitudes);
443 env->CallObjectMethod(vibratorInfoBuilder, sVibratorInfoBuilderClassInfo.setFrequencyProfile,
444 frequencyProfile);
445
446 return info.isFailedLogged("vibratorGetInfo") ? JNI_FALSE : JNI_TRUE;
447 }
448
449 static const JNINativeMethod method_table[] = {
450 {"nativeInit",
451 "(ILcom/android/server/vibrator/VibratorController$OnVibrationCompleteListener;)J",
452 (void*)vibratorNativeInit},
453 {"getNativeFinalizer", "()J", (void*)vibratorGetNativeFinalizer},
454 {"isAvailable", "(J)Z", (void*)vibratorIsAvailable},
455 {"on", "(JJJ)J", (void*)vibratorOn},
456 {"off", "(J)V", (void*)vibratorOff},
457 {"setAmplitude", "(JF)V", (void*)vibratorSetAmplitude},
458 {"performEffect", "(JJJJ)J", (void*)vibratorPerformEffect},
459 {"performComposedEffect", "(J[Landroid/os/vibrator/PrimitiveSegment;J)J",
460 (void*)vibratorPerformComposedEffect},
461 {"performPwleEffect", "(J[Landroid/os/vibrator/RampSegment;IJ)J",
462 (void*)vibratorPerformPwleEffect},
463 {"setExternalControl", "(JZ)V", (void*)vibratorSetExternalControl},
464 {"alwaysOnEnable", "(JJJJ)V", (void*)vibratorAlwaysOnEnable},
465 {"alwaysOnDisable", "(JJ)V", (void*)vibratorAlwaysOnDisable},
466 {"getInfo", "(JLandroid/os/VibratorInfo$Builder;)Z", (void*)vibratorGetInfo},
467 };
468
register_android_server_vibrator_VibratorController(JavaVM * jvm,JNIEnv * env)469 int register_android_server_vibrator_VibratorController(JavaVM* jvm, JNIEnv* env) {
470 sJvm = jvm;
471 auto listenerClassName =
472 "com/android/server/vibrator/VibratorController$OnVibrationCompleteListener";
473 jclass listenerClass = FindClassOrDie(env, listenerClassName);
474 sMethodIdOnComplete = GetMethodIDOrDie(env, listenerClass, "onComplete", "(IJ)V");
475
476 jclass primitiveClass = FindClassOrDie(env, "android/os/vibrator/PrimitiveSegment");
477 sPrimitiveClassInfo.id = GetFieldIDOrDie(env, primitiveClass, "mPrimitiveId", "I");
478 sPrimitiveClassInfo.scale = GetFieldIDOrDie(env, primitiveClass, "mScale", "F");
479 sPrimitiveClassInfo.delay = GetFieldIDOrDie(env, primitiveClass, "mDelay", "I");
480
481 jclass rampClass = FindClassOrDie(env, "android/os/vibrator/RampSegment");
482 sRampClassInfo.startAmplitude = GetFieldIDOrDie(env, rampClass, "mStartAmplitude", "F");
483 sRampClassInfo.endAmplitude = GetFieldIDOrDie(env, rampClass, "mEndAmplitude", "F");
484 sRampClassInfo.startFrequencyHz = GetFieldIDOrDie(env, rampClass, "mStartFrequencyHz", "F");
485 sRampClassInfo.endFrequencyHz = GetFieldIDOrDie(env, rampClass, "mEndFrequencyHz", "F");
486 sRampClassInfo.duration = GetFieldIDOrDie(env, rampClass, "mDuration", "I");
487
488 jclass frequencyProfileClass = FindClassOrDie(env, "android/os/VibratorInfo$FrequencyProfile");
489 sFrequencyProfileClass = static_cast<jclass>(env->NewGlobalRef(frequencyProfileClass));
490 sFrequencyProfileCtor = GetMethodIDOrDie(env, sFrequencyProfileClass, "<init>", "(FFF[F)V");
491
492 jclass vibratorInfoBuilderClass = FindClassOrDie(env, "android/os/VibratorInfo$Builder");
493 sVibratorInfoBuilderClassInfo.setCapabilities =
494 GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setCapabilities",
495 "(J)Landroid/os/VibratorInfo$Builder;");
496 sVibratorInfoBuilderClassInfo.setSupportedEffects =
497 GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setSupportedEffects",
498 "([I)Landroid/os/VibratorInfo$Builder;");
499 sVibratorInfoBuilderClassInfo.setSupportedBraking =
500 GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setSupportedBraking",
501 "([I)Landroid/os/VibratorInfo$Builder;");
502 sVibratorInfoBuilderClassInfo.setPwlePrimitiveDurationMax =
503 GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setPwlePrimitiveDurationMax",
504 "(I)Landroid/os/VibratorInfo$Builder;");
505 sVibratorInfoBuilderClassInfo.setPwleSizeMax =
506 GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setPwleSizeMax",
507 "(I)Landroid/os/VibratorInfo$Builder;");
508 sVibratorInfoBuilderClassInfo.setSupportedPrimitive =
509 GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setSupportedPrimitive",
510 "(II)Landroid/os/VibratorInfo$Builder;");
511 sVibratorInfoBuilderClassInfo.setPrimitiveDelayMax =
512 GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setPrimitiveDelayMax",
513 "(I)Landroid/os/VibratorInfo$Builder;");
514 sVibratorInfoBuilderClassInfo.setCompositionSizeMax =
515 GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setCompositionSizeMax",
516 "(I)Landroid/os/VibratorInfo$Builder;");
517 sVibratorInfoBuilderClassInfo.setQFactor =
518 GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setQFactor",
519 "(F)Landroid/os/VibratorInfo$Builder;");
520 sVibratorInfoBuilderClassInfo.setFrequencyProfile =
521 GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setFrequencyProfile",
522 "(Landroid/os/VibratorInfo$FrequencyProfile;)"
523 "Landroid/os/VibratorInfo$Builder;");
524
525 return jniRegisterNativeMethods(env,
526 "com/android/server/vibrator/VibratorController$NativeWrapper",
527 method_table, NELEM(method_table));
528 }
529
530 }; // namespace android
531