• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <aidl/android/hardware/vibrator/IVibrator.h>
20 #include <android/binder_parcel.h>
21 #include <android/binder_parcel_jni.h>
22 #include <android/persistable_bundle_aidl.h>
23 #include <android_os_vibrator.h>
24 #include <nativehelper/JNIHelp.h>
25 #include <utils/Log.h>
26 #include <utils/misc.h>
27 #include <vibratorservice/VibratorHalController.h>
28 
29 #include "android_runtime/AndroidRuntime.h"
30 #include "com_android_server_vibrator_VibratorManagerService.h"
31 #include "core_jni_helpers.h"
32 #include "jni.h"
33 
34 namespace Aidl = aidl::android::hardware::vibrator;
35 
36 using aidl::android::os::PersistableBundle;
37 
38 namespace android {
39 
40 static JavaVM* sJvm = nullptr;
41 static jmethodID sMethodIdOnComplete;
42 static jclass sFrequencyProfileLegacyClass;
43 static jmethodID sFrequencyProfileLegacyCtor;
44 static jclass sFrequencyProfileClass;
45 static jmethodID sFrequencyProfileCtor;
46 static struct {
47     jmethodID setCapabilities;
48     jmethodID setSupportedEffects;
49     jmethodID setSupportedBraking;
50     jmethodID setPwlePrimitiveDurationMax;
51     jmethodID setPwleSizeMax;
52     jmethodID setSupportedPrimitive;
53     jmethodID setPrimitiveDelayMax;
54     jmethodID setCompositionSizeMax;
55     jmethodID setQFactor;
56     jmethodID setFrequencyProfileLegacy;
57     jmethodID setFrequencyProfile;
58     jmethodID setMaxEnvelopeEffectSize;
59     jmethodID setMinEnvelopeEffectControlPointDurationMillis;
60     jmethodID setMaxEnvelopeEffectControlPointDurationMillis;
61 } sVibratorInfoBuilderClassInfo;
62 static struct {
63     jfieldID id;
64     jfieldID scale;
65     jfieldID delay;
66 } sPrimitiveClassInfo;
67 static struct {
68     jfieldID startAmplitude;
69     jfieldID endAmplitude;
70     jfieldID startFrequencyHz;
71     jfieldID endFrequencyHz;
72     jfieldID duration;
73 } sRampClassInfo;
74 static struct {
75     jfieldID amplitude;
76     jfieldID frequencyHz;
77     jfieldID timeMillis;
78 } sPwlePointClassInfo;
79 
findVibrator(int32_t vibratorId)80 static std::shared_ptr<vibrator::HalController> findVibrator(int32_t vibratorId) {
81     vibrator::ManagerHalController* manager =
82             android_server_vibrator_VibratorManagerService_getManager();
83     if (manager == nullptr) {
84         return nullptr;
85     }
86     auto result = manager->getVibrator(vibratorId);
87     return result.isOk() ? result.value() : nullptr;
88 }
89 
90 class VibratorControllerWrapper {
91 public:
VibratorControllerWrapper(JNIEnv * env,int32_t vibratorId,jobject callbackListener)92     VibratorControllerWrapper(JNIEnv* env, int32_t vibratorId, jobject callbackListener)
93           : mHal(findVibrator(vibratorId)),
94             mVibratorId(vibratorId),
95             mCallbackListener(env->NewGlobalRef(callbackListener)) {
96         LOG_ALWAYS_FATAL_IF(mHal == nullptr,
97                             "Failed to connect to vibrator HAL, or vibratorId is invalid");
98         LOG_ALWAYS_FATAL_IF(mCallbackListener == nullptr,
99                             "Unable to create global reference to vibration callback handler");
100     }
101 
~VibratorControllerWrapper()102     ~VibratorControllerWrapper() {
103         auto jniEnv = GetOrAttachJNIEnvironment(sJvm);
104         jniEnv->DeleteGlobalRef(mCallbackListener);
105     }
106 
getVibratorId() const107     int32_t getVibratorId() const { return mVibratorId; }
108 
getVibratorInfo()109     vibrator::Info getVibratorInfo() { return mHal->getInfo(); }
110 
initHal()111     void initHal() { mHal->init(); }
112 
113     template <typename T>
halCall(const vibrator::HalFunction<vibrator::HalResult<T>> & fn,const char * functionName)114     vibrator::HalResult<T> halCall(const vibrator::HalFunction<vibrator::HalResult<T>>& fn,
115                                    const char* functionName) {
116         return mHal->doWithRetry(fn, functionName);
117     }
118 
createCallback(jlong vibrationId,jlong stepId)119     std::function<void()> createCallback(jlong vibrationId, jlong stepId) {
120         auto callbackId = ++mCallbackId;
121         return [vibrationId, stepId, callbackId, this]() {
122             auto currentCallbackId = mCallbackId.load();
123             if (!android_os_vibrator_fix_vibration_thread_callback_handling() &&
124                 currentCallbackId != callbackId) {
125                 // This callback is from an older HAL call that is no longer relevant
126                 return;
127             }
128             auto jniEnv = GetOrAttachJNIEnvironment(sJvm);
129             jniEnv->CallVoidMethod(mCallbackListener, sMethodIdOnComplete, mVibratorId, vibrationId,
130                                    stepId);
131         };
132     }
133 
disableOldCallbacks()134     void disableOldCallbacks() {
135         // TODO remove this once android_os_vibrator_fix_vibration_thread_callback_handling removed
136         mCallbackId++;
137     }
138 
139 private:
140     const std::shared_ptr<vibrator::HalController> mHal;
141     const int32_t mVibratorId;
142     const jobject mCallbackListener;
143     // TODO remove this once android_os_vibrator_fix_vibration_thread_callback_handling removed
144     std::atomic<int64_t> mCallbackId;
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 
pwleV2PrimitiveFromJavaPrimitive(JNIEnv * env,jobject pwleObj)166 static Aidl::PwleV2Primitive pwleV2PrimitiveFromJavaPrimitive(JNIEnv* env, jobject pwleObj) {
167     Aidl::PwleV2Primitive pwle;
168     pwle.amplitude = static_cast<float>(env->GetFloatField(pwleObj, sPwlePointClassInfo.amplitude));
169     pwle.frequencyHz =
170             static_cast<float>(env->GetFloatField(pwleObj, sPwlePointClassInfo.frequencyHz));
171     pwle.timeMillis =
172             static_cast<int32_t>(env->GetIntField(pwleObj, sPwlePointClassInfo.timeMillis));
173     return pwle;
174 }
175 
176 /* Return true if braking is not NONE and the active PWLE starts and ends with zero amplitude. */
shouldBeReplacedWithBraking(Aidl::ActivePwle activePwle,Aidl::Braking braking)177 static bool shouldBeReplacedWithBraking(Aidl::ActivePwle activePwle, Aidl::Braking braking) {
178     return (braking != Aidl::Braking::NONE) && (activePwle.startAmplitude == 0) &&
179             (activePwle.endAmplitude == 0);
180 }
181 
182 /* Return true if braking is not NONE and the active PWLE only ends with zero amplitude. */
shouldAddLastBraking(Aidl::ActivePwle lastActivePwle,Aidl::Braking braking)183 static bool shouldAddLastBraking(Aidl::ActivePwle lastActivePwle, Aidl::Braking braking) {
184     return (braking != Aidl::Braking::NONE) && (lastActivePwle.startAmplitude > 0) &&
185             (lastActivePwle.endAmplitude == 0);
186 }
187 
effectFromJavaPrimitive(JNIEnv * env,jobject primitive)188 static Aidl::CompositeEffect effectFromJavaPrimitive(JNIEnv* env, jobject primitive) {
189     Aidl::CompositeEffect effect;
190     effect.primitive = static_cast<Aidl::CompositePrimitive>(
191             env->GetIntField(primitive, sPrimitiveClassInfo.id));
192     effect.scale = static_cast<float>(env->GetFloatField(primitive, sPrimitiveClassInfo.scale));
193     effect.delayMs = static_cast<int32_t>(env->GetIntField(primitive, sPrimitiveClassInfo.delay));
194     return effect;
195 }
196 
vendorEffectFromJavaParcel(JNIEnv * env,jobject vendorData,jlong strength,jfloat scale,jfloat adaptiveScale)197 static Aidl::VendorEffect vendorEffectFromJavaParcel(JNIEnv* env, jobject vendorData,
198                                                      jlong strength, jfloat scale,
199                                                      jfloat adaptiveScale) {
200     PersistableBundle bundle;
201     if (AParcel* parcel = AParcel_fromJavaParcel(env, vendorData); parcel != nullptr) {
202         if (binder_status_t status = bundle.readFromParcel(parcel); status == STATUS_OK) {
203             AParcel_delete(parcel);
204         } else {
205             jniThrowExceptionFmt(env, "android/os/BadParcelableException",
206                                  "Failed to readFromParcel, status %d (%s)", status,
207                                  strerror(-status));
208         }
209     } else {
210         jniThrowExceptionFmt(env, "android/os/BadParcelableException",
211                              "Failed to AParcel_fromJavaParcel, for nullptr");
212     }
213 
214     Aidl::VendorEffect effect;
215     effect.vendorData = bundle;
216     effect.strength = static_cast<Aidl::EffectStrength>(strength);
217     effect.scale = static_cast<float>(scale);
218     effect.vendorScale = static_cast<float>(adaptiveScale);
219     return effect;
220 }
221 
destroyNativeWrapper(void * ptr)222 static void destroyNativeWrapper(void* ptr) {
223     VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
224     if (wrapper) {
225         delete wrapper;
226     }
227 }
228 
vibratorNativeInit(JNIEnv * env,jclass,jint vibratorId,jobject callbackListener)229 static jlong vibratorNativeInit(JNIEnv* env, jclass /* clazz */, jint vibratorId,
230                                 jobject callbackListener) {
231     std::unique_ptr<VibratorControllerWrapper> wrapper =
232             std::make_unique<VibratorControllerWrapper>(env, vibratorId, callbackListener);
233     wrapper->initHal();
234     return reinterpret_cast<jlong>(wrapper.release());
235 }
236 
vibratorGetNativeFinalizer(JNIEnv *,jclass)237 static jlong vibratorGetNativeFinalizer(JNIEnv* /* env */, jclass /* clazz */) {
238     return static_cast<jlong>(reinterpret_cast<uintptr_t>(&destroyNativeWrapper));
239 }
240 
vibratorIsAvailable(JNIEnv * env,jclass,jlong ptr)241 static jboolean vibratorIsAvailable(JNIEnv* env, jclass /* clazz */, jlong ptr) {
242     VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
243     if (wrapper == nullptr) {
244         ALOGE("vibratorIsAvailable failed because native wrapper was not initialized");
245         return JNI_FALSE;
246     }
247     auto pingFn = [](vibrator::HalWrapper* hal) { return hal->ping(); };
248     return wrapper->halCall<void>(pingFn, "ping").isOk() ? JNI_TRUE : JNI_FALSE;
249 }
250 
vibratorOn(JNIEnv * env,jclass,jlong ptr,jlong timeoutMs,jlong vibrationId,jlong stepId)251 static jlong vibratorOn(JNIEnv* env, jclass /* clazz */, jlong ptr, jlong timeoutMs,
252                         jlong vibrationId, jlong stepId) {
253     VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
254     if (wrapper == nullptr) {
255         ALOGE("vibratorOn failed because native wrapper was not initialized");
256         return -1;
257     }
258     auto callback = wrapper->createCallback(vibrationId, stepId);
259     auto onFn = [timeoutMs, &callback](vibrator::HalWrapper* hal) {
260         return hal->on(std::chrono::milliseconds(timeoutMs), callback);
261     };
262     auto result = wrapper->halCall<void>(onFn, "on");
263     return result.isOk() ? timeoutMs : (result.isUnsupported() ? 0 : -1);
264 }
265 
vibratorOff(JNIEnv * env,jclass,jlong ptr)266 static void vibratorOff(JNIEnv* env, jclass /* clazz */, jlong ptr) {
267     VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
268     if (wrapper == nullptr) {
269         ALOGE("vibratorOff failed because native wrapper was not initialized");
270         return;
271     }
272     auto offFn = [](vibrator::HalWrapper* hal) { return hal->off(); };
273     wrapper->halCall<void>(offFn, "off");
274     wrapper->disableOldCallbacks();
275 }
276 
vibratorSetAmplitude(JNIEnv * env,jclass,jlong ptr,jfloat amplitude)277 static void vibratorSetAmplitude(JNIEnv* env, jclass /* clazz */, jlong ptr, jfloat amplitude) {
278     VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
279     if (wrapper == nullptr) {
280         ALOGE("vibratorSetAmplitude failed because native wrapper was not initialized");
281         return;
282     }
283     auto setAmplitudeFn = [amplitude](vibrator::HalWrapper* hal) {
284         return hal->setAmplitude(static_cast<float>(amplitude));
285     };
286     wrapper->halCall<void>(setAmplitudeFn, "setAmplitude");
287 }
288 
vibratorSetExternalControl(JNIEnv * env,jclass,jlong ptr,jboolean enabled)289 static void vibratorSetExternalControl(JNIEnv* env, jclass /* clazz */, jlong ptr,
290                                        jboolean enabled) {
291     VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
292     if (wrapper == nullptr) {
293         ALOGE("vibratorSetExternalControl failed because native wrapper was not initialized");
294         return;
295     }
296     auto setExternalControlFn = [enabled](vibrator::HalWrapper* hal) {
297         return hal->setExternalControl(enabled);
298     };
299     wrapper->halCall<void>(setExternalControlFn, "setExternalControl");
300 }
301 
vibratorPerformEffect(JNIEnv * env,jclass,jlong ptr,jlong effect,jlong strength,jlong vibrationId,jlong stepId)302 static jlong vibratorPerformEffect(JNIEnv* env, jclass /* clazz */, jlong ptr, jlong effect,
303                                    jlong strength, jlong vibrationId, jlong stepId) {
304     VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
305     if (wrapper == nullptr) {
306         ALOGE("vibratorPerformEffect failed because native wrapper was not initialized");
307         return -1;
308     }
309     Aidl::Effect effectType = static_cast<Aidl::Effect>(effect);
310     Aidl::EffectStrength effectStrength = static_cast<Aidl::EffectStrength>(strength);
311     auto callback = wrapper->createCallback(vibrationId, stepId);
312     auto performEffectFn = [effectType, effectStrength, &callback](vibrator::HalWrapper* hal) {
313         return hal->performEffect(effectType, effectStrength, callback);
314     };
315     auto result = wrapper->halCall<std::chrono::milliseconds>(performEffectFn, "performEffect");
316     return result.isOk() ? result.value().count() : (result.isUnsupported() ? 0 : -1);
317 }
318 
vibratorPerformVendorEffect(JNIEnv * env,jclass,jlong ptr,jobject vendorData,jlong strength,jfloat scale,jfloat adaptiveScale,jlong vibrationId,jlong stepId)319 static jlong vibratorPerformVendorEffect(JNIEnv* env, jclass /* clazz */, jlong ptr,
320                                          jobject vendorData, jlong strength, jfloat scale,
321                                          jfloat adaptiveScale, jlong vibrationId, jlong stepId) {
322     VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
323     if (wrapper == nullptr) {
324         ALOGE("vibratorPerformVendorEffect failed because native wrapper was not initialized");
325         return -1;
326     }
327     Aidl::VendorEffect effect =
328             vendorEffectFromJavaParcel(env, vendorData, strength, scale, adaptiveScale);
329     auto callback = wrapper->createCallback(vibrationId, stepId);
330     auto performVendorEffectFn = [&effect, &callback](vibrator::HalWrapper* hal) {
331         return hal->performVendorEffect(effect, callback);
332     };
333     auto result = wrapper->halCall<void>(performVendorEffectFn, "performVendorEffect");
334     return result.isOk() ? std::numeric_limits<int64_t>::max() : (result.isUnsupported() ? 0 : -1);
335 }
336 
vibratorPerformComposedEffect(JNIEnv * env,jclass,jlong ptr,jobjectArray composition,jlong vibrationId,jlong stepId)337 static jlong vibratorPerformComposedEffect(JNIEnv* env, jclass /* clazz */, jlong ptr,
338                                            jobjectArray composition, jlong vibrationId,
339                                            jlong stepId) {
340     VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
341     if (wrapper == nullptr) {
342         ALOGE("vibratorPerformComposedEffect failed because native wrapper was not initialized");
343         return -1;
344     }
345     size_t size = env->GetArrayLength(composition);
346     std::vector<Aidl::CompositeEffect> effects;
347     for (size_t i = 0; i < size; i++) {
348         jobject element = env->GetObjectArrayElement(composition, i);
349         effects.push_back(effectFromJavaPrimitive(env, element));
350     }
351     auto callback = wrapper->createCallback(vibrationId, stepId);
352     auto performComposedEffectFn = [&effects, &callback](vibrator::HalWrapper* hal) {
353         return hal->performComposedEffect(effects, callback);
354     };
355     auto result = wrapper->halCall<std::chrono::milliseconds>(performComposedEffectFn,
356                                                               "performComposedEffect");
357     return result.isOk() ? result.value().count() : (result.isUnsupported() ? 0 : -1);
358 }
359 
vibratorPerformPwleEffect(JNIEnv * env,jclass,jlong ptr,jobjectArray waveform,jint brakingId,jlong vibrationId,jlong stepId)360 static jlong vibratorPerformPwleEffect(JNIEnv* env, jclass /* clazz */, jlong ptr,
361                                        jobjectArray waveform, jint brakingId, jlong vibrationId,
362                                        jlong stepId) {
363     VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
364     if (wrapper == nullptr) {
365         ALOGE("vibratorPerformPwleEffect failed because native wrapper was not initialized");
366         return -1;
367     }
368     Aidl::Braking braking = static_cast<Aidl::Braking>(brakingId);
369     size_t size = env->GetArrayLength(waveform);
370     std::vector<Aidl::PrimitivePwle> primitives;
371     std::chrono::milliseconds totalDuration(0);
372     for (size_t i = 0; i < size; i++) {
373         jobject element = env->GetObjectArrayElement(waveform, i);
374         Aidl::ActivePwle activePwle = activePwleFromJavaPrimitive(env, element);
375         if ((i > 0) && shouldBeReplacedWithBraking(activePwle, braking)) {
376             primitives.push_back(brakingPwle(braking, activePwle.duration));
377         } else {
378             primitives.push_back(activePwle);
379         }
380         totalDuration += std::chrono::milliseconds(activePwle.duration);
381 
382         if ((i == (size - 1)) && shouldAddLastBraking(activePwle, braking)) {
383             primitives.push_back(brakingPwle(braking, 0 /* duration */));
384         }
385     }
386 
387     auto callback = wrapper->createCallback(vibrationId, stepId);
388     auto performPwleEffectFn = [&primitives, &callback](vibrator::HalWrapper* hal) {
389         return hal->performPwleEffect(primitives, callback);
390     };
391     auto result = wrapper->halCall<void>(performPwleEffectFn, "performPwleEffect");
392     return result.isOk() ? totalDuration.count() : (result.isUnsupported() ? 0 : -1);
393 }
394 
vibratorPerformPwleV2Effect(JNIEnv * env,jclass,jlong ptr,jobjectArray waveform,jlong vibrationId,jlong stepId)395 static jlong vibratorPerformPwleV2Effect(JNIEnv* env, jclass /* clazz */, jlong ptr,
396                                          jobjectArray waveform, jlong vibrationId, jlong stepId) {
397     VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
398     if (wrapper == nullptr) {
399         ALOGE("vibratorPerformPwleV2Effect failed because native wrapper was not initialized");
400         return -1;
401     }
402     size_t size = env->GetArrayLength(waveform);
403     Aidl::CompositePwleV2 composite;
404     std::vector<Aidl::PwleV2Primitive> primitives;
405     for (size_t i = 0; i < size; i++) {
406         jobject element = env->GetObjectArrayElement(waveform, i);
407         Aidl::PwleV2Primitive pwle = pwleV2PrimitiveFromJavaPrimitive(env, element);
408         primitives.push_back(pwle);
409     }
410     composite.pwlePrimitives = primitives;
411 
412     auto callback = wrapper->createCallback(vibrationId, stepId);
413     auto composePwleV2Fn = [&composite, &callback](vibrator::HalWrapper* hal) {
414         return hal->composePwleV2(composite, callback);
415     };
416     auto result = wrapper->halCall<std::chrono::milliseconds>(composePwleV2Fn, "composePwleV2");
417     return result.isOk() ? result.value().count() : (result.isUnsupported() ? 0 : -1);
418 }
419 
vibratorAlwaysOnEnable(JNIEnv * env,jclass,jlong ptr,jlong id,jlong effect,jlong strength)420 static void vibratorAlwaysOnEnable(JNIEnv* env, jclass /* clazz */, jlong ptr, jlong id,
421                                    jlong effect, jlong strength) {
422     VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
423     if (wrapper == nullptr) {
424         ALOGE("vibratorAlwaysOnEnable failed because native wrapper was not initialized");
425         return;
426     }
427     auto alwaysOnEnableFn = [id, effect, strength](vibrator::HalWrapper* hal) {
428         return hal->alwaysOnEnable(static_cast<int32_t>(id), static_cast<Aidl::Effect>(effect),
429                                    static_cast<Aidl::EffectStrength>(strength));
430     };
431     wrapper->halCall<void>(alwaysOnEnableFn, "alwaysOnEnable");
432 }
433 
vibratorAlwaysOnDisable(JNIEnv * env,jclass,jlong ptr,jlong id)434 static void vibratorAlwaysOnDisable(JNIEnv* env, jclass /* clazz */, jlong ptr, jlong id) {
435     VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
436     if (wrapper == nullptr) {
437         ALOGE("vibratorAlwaysOnDisable failed because native wrapper was not initialized");
438         return;
439     }
440     auto alwaysOnDisableFn = [id](vibrator::HalWrapper* hal) {
441         return hal->alwaysOnDisable(static_cast<int32_t>(id));
442     };
443     wrapper->halCall<void>(alwaysOnDisableFn, "alwaysOnDisable");
444 }
445 
vibratorGetInfo(JNIEnv * env,jclass,jlong ptr,jobject vibratorInfoBuilder)446 static jboolean vibratorGetInfo(JNIEnv* env, jclass /* clazz */, jlong ptr,
447                                 jobject vibratorInfoBuilder) {
448     VibratorControllerWrapper* wrapper = reinterpret_cast<VibratorControllerWrapper*>(ptr);
449     if (wrapper == nullptr) {
450         ALOGE("vibratorGetInfo failed because native wrapper was not initialized");
451         return JNI_FALSE;
452     }
453     vibrator::Info info = wrapper->getVibratorInfo();
454     info.logFailures();
455 
456     if (info.capabilities.isOk()) {
457         env->CallObjectMethod(vibratorInfoBuilder, sVibratorInfoBuilderClassInfo.setCapabilities,
458                               static_cast<jlong>(info.capabilities.value()));
459     }
460     if (info.supportedEffects.isOk()) {
461         std::vector<Aidl::Effect> effects = info.supportedEffects.value();
462         jintArray supportedEffects = env->NewIntArray(effects.size());
463         env->SetIntArrayRegion(supportedEffects, 0, effects.size(),
464                                reinterpret_cast<jint*>(effects.data()));
465         env->CallObjectMethod(vibratorInfoBuilder,
466                               sVibratorInfoBuilderClassInfo.setSupportedEffects, supportedEffects);
467     }
468     if (info.supportedBraking.isOk()) {
469         std::vector<Aidl::Braking> braking = info.supportedBraking.value();
470         jintArray supportedBraking = env->NewIntArray(braking.size());
471         env->SetIntArrayRegion(supportedBraking, 0, braking.size(),
472                                reinterpret_cast<jint*>(braking.data()));
473         env->CallObjectMethod(vibratorInfoBuilder,
474                               sVibratorInfoBuilderClassInfo.setSupportedBraking, supportedBraking);
475     }
476     if (info.pwlePrimitiveDurationMax.isOk()) {
477         env->CallObjectMethod(vibratorInfoBuilder,
478                               sVibratorInfoBuilderClassInfo.setPwlePrimitiveDurationMax,
479                               static_cast<jint>(info.pwlePrimitiveDurationMax.value().count()));
480     }
481     if (info.pwleSizeMax.isOk()) {
482         // Use (pwleMaxSize - 1) to account for a possible extra braking segment added by the
483         // vibratorPerformPwleEffect method.
484         env->CallObjectMethod(vibratorInfoBuilder, sVibratorInfoBuilderClassInfo.setPwleSizeMax,
485                               static_cast<jint>(info.pwleSizeMax.value() - 1));
486     }
487     if (info.supportedPrimitives.isOk()) {
488         auto durations = info.primitiveDurations.valueOr({});
489         for (auto& primitive : info.supportedPrimitives.value()) {
490             auto primitiveIdx = static_cast<size_t>(primitive);
491             auto duration = durations.size() > primitiveIdx ? durations[primitiveIdx].count() : 0;
492             env->CallObjectMethod(vibratorInfoBuilder,
493                                   sVibratorInfoBuilderClassInfo.setSupportedPrimitive,
494                                   static_cast<jint>(primitive), static_cast<jint>(duration));
495         }
496     }
497     if (info.primitiveDelayMax.isOk()) {
498         env->CallObjectMethod(vibratorInfoBuilder,
499                               sVibratorInfoBuilderClassInfo.setPrimitiveDelayMax,
500                               static_cast<jint>(info.primitiveDelayMax.value().count()));
501     }
502     if (info.compositionSizeMax.isOk()) {
503         env->CallObjectMethod(vibratorInfoBuilder,
504                               sVibratorInfoBuilderClassInfo.setCompositionSizeMax,
505                               static_cast<jint>(info.compositionSizeMax.value()));
506     }
507     if (info.qFactor.isOk()) {
508         env->CallObjectMethod(vibratorInfoBuilder, sVibratorInfoBuilderClassInfo.setQFactor,
509                               static_cast<jfloat>(info.qFactor.value()));
510     }
511     if (info.maxEnvelopeEffectSize.isOk()) {
512         env->CallObjectMethod(vibratorInfoBuilder,
513                               sVibratorInfoBuilderClassInfo.setMaxEnvelopeEffectSize,
514                               static_cast<jint>(info.maxEnvelopeEffectSize.value()));
515     }
516     if (info.minEnvelopeEffectControlPointDuration.isOk()) {
517         env->CallObjectMethod(vibratorInfoBuilder,
518                               sVibratorInfoBuilderClassInfo
519                                       .setMinEnvelopeEffectControlPointDurationMillis,
520                               static_cast<jint>(
521                                       info.minEnvelopeEffectControlPointDuration.value().count()));
522     }
523     if (info.maxEnvelopeEffectControlPointDuration.isOk()) {
524         env->CallObjectMethod(vibratorInfoBuilder,
525                               sVibratorInfoBuilderClassInfo
526                                       .setMaxEnvelopeEffectControlPointDurationMillis,
527                               static_cast<jint>(
528                                       info.maxEnvelopeEffectControlPointDuration.value().count()));
529     }
530 
531     jfloat minFrequency = static_cast<jfloat>(info.minFrequency.valueOr(NAN));
532     jfloat resonantFrequency = static_cast<jfloat>(info.resonantFrequency.valueOr(NAN));
533     jfloat frequencyResolution = static_cast<jfloat>(info.frequencyResolution.valueOr(NAN));
534     jfloatArray maxAmplitudes = nullptr;
535     if (info.maxAmplitudes.isOk()) {
536         std::vector<float> amplitudes = info.maxAmplitudes.value();
537         maxAmplitudes = env->NewFloatArray(amplitudes.size());
538         env->SetFloatArrayRegion(maxAmplitudes, 0, amplitudes.size(),
539                                  reinterpret_cast<jfloat*>(amplitudes.data()));
540     }
541     jobject frequencyProfileLegacy =
542             env->NewObject(sFrequencyProfileLegacyClass, sFrequencyProfileLegacyCtor,
543                            resonantFrequency, minFrequency, frequencyResolution, maxAmplitudes);
544     env->CallObjectMethod(vibratorInfoBuilder,
545                           sVibratorInfoBuilderClassInfo.setFrequencyProfileLegacy,
546                           frequencyProfileLegacy);
547 
548     if (info.frequencyToOutputAccelerationMap.isOk()) {
549         size_t mapSize = info.frequencyToOutputAccelerationMap.value().size();
550 
551         jfloatArray frequenciesHz = env->NewFloatArray(mapSize);
552         jfloatArray outputAccelerationsGs = env->NewFloatArray(mapSize);
553 
554         jfloat* frequenciesHzPtr = env->GetFloatArrayElements(frequenciesHz, nullptr);
555         jfloat* outputAccelerationsGsPtr =
556                 env->GetFloatArrayElements(outputAccelerationsGs, nullptr);
557 
558         size_t i = 0;
559         for (auto const& dataEntry : info.frequencyToOutputAccelerationMap.value()) {
560             frequenciesHzPtr[i] = static_cast<jfloat>(dataEntry.frequencyHz);
561             outputAccelerationsGsPtr[i] = static_cast<jfloat>(dataEntry.maxOutputAccelerationGs);
562             i++;
563         }
564 
565         // Release the float pointers
566         env->ReleaseFloatArrayElements(frequenciesHz, frequenciesHzPtr, 0);
567         env->ReleaseFloatArrayElements(outputAccelerationsGs, outputAccelerationsGsPtr, 0);
568 
569         jobject frequencyProfile =
570                 env->NewObject(sFrequencyProfileClass, sFrequencyProfileCtor, resonantFrequency,
571                                frequenciesHz, outputAccelerationsGs);
572 
573         env->CallObjectMethod(vibratorInfoBuilder,
574                               sVibratorInfoBuilderClassInfo.setFrequencyProfile, frequencyProfile);
575 
576         // Delete local references to avoid memory leaks
577         env->DeleteLocalRef(frequenciesHz);
578         env->DeleteLocalRef(outputAccelerationsGs);
579         env->DeleteLocalRef(frequencyProfile);
580     }
581 
582     return info.shouldRetry() ? JNI_FALSE : JNI_TRUE;
583 }
584 
585 static const JNINativeMethod method_table[] = {
nativeInit(ILcom/android/server/vibrator/VibratorController$OnVibrationCompleteListener;)586         {"nativeInit",
587          "(ILcom/android/server/vibrator/VibratorController$OnVibrationCompleteListener;)J",
588          (void*)vibratorNativeInit},
getNativeFinalizer()589         {"getNativeFinalizer", "()J", (void*)vibratorGetNativeFinalizer},
isAvailable(J)590         {"isAvailable", "(J)Z", (void*)vibratorIsAvailable},
on(JJJJ)591         {"on", "(JJJJ)J", (void*)vibratorOn},
off(J)592         {"off", "(J)V", (void*)vibratorOff},
setAmplitude(JF)593         {"setAmplitude", "(JF)V", (void*)vibratorSetAmplitude},
performEffect(JJJJJ)594         {"performEffect", "(JJJJJ)J", (void*)vibratorPerformEffect},
performVendorEffect(JLandroid/os/Parcel;JFFJJ)595         {"performVendorEffect", "(JLandroid/os/Parcel;JFFJJ)J", (void*)vibratorPerformVendorEffect},
performComposedEffect(J[Landroid/os/vibrator/PrimitiveSegment;JJ)596         {"performComposedEffect", "(J[Landroid/os/vibrator/PrimitiveSegment;JJ)J",
597          (void*)vibratorPerformComposedEffect},
performPwleEffect(J[Landroid/os/vibrator/RampSegment;IJJ)598         {"performPwleEffect", "(J[Landroid/os/vibrator/RampSegment;IJJ)J",
599          (void*)vibratorPerformPwleEffect},
performPwleV2Effect(J[Landroid/os/vibrator/PwlePoint;JJ)600         {"performPwleV2Effect", "(J[Landroid/os/vibrator/PwlePoint;JJ)J",
601          (void*)vibratorPerformPwleV2Effect},
setExternalControl(JZ)602         {"setExternalControl", "(JZ)V", (void*)vibratorSetExternalControl},
alwaysOnEnable(JJJJ)603         {"alwaysOnEnable", "(JJJJ)V", (void*)vibratorAlwaysOnEnable},
alwaysOnDisable(JJ)604         {"alwaysOnDisable", "(JJ)V", (void*)vibratorAlwaysOnDisable},
getInfo(JLandroid/os/VibratorInfo$Builder;)605         {"getInfo", "(JLandroid/os/VibratorInfo$Builder;)Z", (void*)vibratorGetInfo},
606 };
607 
register_android_server_vibrator_VibratorController(JavaVM * jvm,JNIEnv * env)608 int register_android_server_vibrator_VibratorController(JavaVM* jvm, JNIEnv* env) {
609     sJvm = jvm;
610     auto listenerClassName =
611             "com/android/server/vibrator/VibratorController$OnVibrationCompleteListener";
612     jclass listenerClass = FindClassOrDie(env, listenerClassName);
613     sMethodIdOnComplete = GetMethodIDOrDie(env, listenerClass, "onComplete", "(IJJ)V");
614 
615     jclass primitiveClass = FindClassOrDie(env, "android/os/vibrator/PrimitiveSegment");
616     sPrimitiveClassInfo.id = GetFieldIDOrDie(env, primitiveClass, "mPrimitiveId", "I");
617     sPrimitiveClassInfo.scale = GetFieldIDOrDie(env, primitiveClass, "mScale", "F");
618     sPrimitiveClassInfo.delay = GetFieldIDOrDie(env, primitiveClass, "mDelay", "I");
619 
620     jclass rampClass = FindClassOrDie(env, "android/os/vibrator/RampSegment");
621     sRampClassInfo.startAmplitude = GetFieldIDOrDie(env, rampClass, "mStartAmplitude", "F");
622     sRampClassInfo.endAmplitude = GetFieldIDOrDie(env, rampClass, "mEndAmplitude", "F");
623     sRampClassInfo.startFrequencyHz = GetFieldIDOrDie(env, rampClass, "mStartFrequencyHz", "F");
624     sRampClassInfo.endFrequencyHz = GetFieldIDOrDie(env, rampClass, "mEndFrequencyHz", "F");
625     sRampClassInfo.duration = GetFieldIDOrDie(env, rampClass, "mDuration", "I");
626 
627     jclass pwlePointClass = FindClassOrDie(env, "android/os/vibrator/PwlePoint");
628     sPwlePointClassInfo.amplitude = GetFieldIDOrDie(env, pwlePointClass, "mAmplitude", "F");
629     sPwlePointClassInfo.frequencyHz = GetFieldIDOrDie(env, pwlePointClass, "mFrequencyHz", "F");
630     sPwlePointClassInfo.timeMillis = GetFieldIDOrDie(env, pwlePointClass, "mTimeMillis", "I");
631 
632     jclass frequencyProfileLegacyClass =
633             FindClassOrDie(env, "android/os/VibratorInfo$FrequencyProfileLegacy");
634     sFrequencyProfileLegacyClass =
635             static_cast<jclass>(env->NewGlobalRef(frequencyProfileLegacyClass));
636     sFrequencyProfileLegacyCtor =
637             GetMethodIDOrDie(env, sFrequencyProfileLegacyClass, "<init>", "(FFF[F)V");
638 
639     jclass frequencyProfileClass = FindClassOrDie(env, "android/os/VibratorInfo$FrequencyProfile");
640     sFrequencyProfileClass = static_cast<jclass>(env->NewGlobalRef(frequencyProfileClass));
641     sFrequencyProfileCtor = GetMethodIDOrDie(env, sFrequencyProfileClass, "<init>", "(F[F[F)V");
642 
643     jclass vibratorInfoBuilderClass = FindClassOrDie(env, "android/os/VibratorInfo$Builder");
644     sVibratorInfoBuilderClassInfo.setCapabilities =
645             GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setCapabilities",
646                              "(J)Landroid/os/VibratorInfo$Builder;");
647     sVibratorInfoBuilderClassInfo.setSupportedEffects =
648             GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setSupportedEffects",
649                              "([I)Landroid/os/VibratorInfo$Builder;");
650     sVibratorInfoBuilderClassInfo.setSupportedBraking =
651             GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setSupportedBraking",
652                              "([I)Landroid/os/VibratorInfo$Builder;");
653     sVibratorInfoBuilderClassInfo.setPwlePrimitiveDurationMax =
654             GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setPwlePrimitiveDurationMax",
655                              "(I)Landroid/os/VibratorInfo$Builder;");
656     sVibratorInfoBuilderClassInfo.setPwleSizeMax =
657             GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setPwleSizeMax",
658                              "(I)Landroid/os/VibratorInfo$Builder;");
659     sVibratorInfoBuilderClassInfo.setSupportedPrimitive =
660             GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setSupportedPrimitive",
661                              "(II)Landroid/os/VibratorInfo$Builder;");
662     sVibratorInfoBuilderClassInfo.setPrimitiveDelayMax =
663             GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setPrimitiveDelayMax",
664                              "(I)Landroid/os/VibratorInfo$Builder;");
665     sVibratorInfoBuilderClassInfo.setCompositionSizeMax =
666             GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setCompositionSizeMax",
667                              "(I)Landroid/os/VibratorInfo$Builder;");
668     sVibratorInfoBuilderClassInfo.setQFactor =
669             GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setQFactor",
670                              "(F)Landroid/os/VibratorInfo$Builder;");
671     sVibratorInfoBuilderClassInfo.setFrequencyProfileLegacy =
672             GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setFrequencyProfileLegacy",
673                              "(Landroid/os/VibratorInfo$FrequencyProfileLegacy;)"
674                              "Landroid/os/VibratorInfo$Builder;");
675     sVibratorInfoBuilderClassInfo.setFrequencyProfile =
676             GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setFrequencyProfile",
677                              "(Landroid/os/VibratorInfo$FrequencyProfile;)"
678                              "Landroid/os/VibratorInfo$Builder;");
679     sVibratorInfoBuilderClassInfo.setMaxEnvelopeEffectSize =
680             GetMethodIDOrDie(env, vibratorInfoBuilderClass, "setMaxEnvelopeEffectSize",
681                              "(I)Landroid/os/VibratorInfo$Builder;");
682     sVibratorInfoBuilderClassInfo.setMinEnvelopeEffectControlPointDurationMillis =
683             GetMethodIDOrDie(env, vibratorInfoBuilderClass,
684                              "setMinEnvelopeEffectControlPointDurationMillis",
685                              "(I)Landroid/os/VibratorInfo$Builder;");
686     sVibratorInfoBuilderClassInfo.setMaxEnvelopeEffectControlPointDurationMillis =
687             GetMethodIDOrDie(env, vibratorInfoBuilderClass,
688                              "setMaxEnvelopeEffectControlPointDurationMillis",
689                              "(I)Landroid/os/VibratorInfo$Builder;");
690 
691     return jniRegisterNativeMethods(env,
692                                     "com/android/server/vibrator/VibratorController$NativeWrapper",
693                                     method_table, NELEM(method_table));
694 }
695 
696 }; // namespace android
697