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