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