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