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 package com.android.server.vibrator; 18 19 import android.annotation.Nullable; 20 import android.hardware.vibrator.IVibrator; 21 import android.os.Handler; 22 import android.os.Looper; 23 import android.os.Parcel; 24 import android.os.PersistableBundle; 25 import android.os.VibrationEffect; 26 import android.os.VibratorInfo; 27 import android.os.vibrator.PrebakedSegment; 28 import android.os.vibrator.PrimitiveSegment; 29 import android.os.vibrator.PwlePoint; 30 import android.os.vibrator.RampSegment; 31 import android.os.vibrator.StepSegment; 32 import android.os.vibrator.VibrationEffectSegment; 33 34 import com.android.server.vibrator.VibratorController.OnVibrationCompleteListener; 35 36 import java.util.ArrayList; 37 import java.util.Arrays; 38 import java.util.HashMap; 39 import java.util.List; 40 import java.util.Map; 41 import java.util.TreeMap; 42 43 /** 44 * Provides {@link VibratorController} with configurable vibrator hardware capabilities and 45 * fake interactions for tests. 46 */ 47 public final class FakeVibratorControllerProvider { 48 private static final int EFFECT_DURATION = 20; 49 50 private final Map<Long, PrebakedSegment> mEnabledAlwaysOnEffects = new HashMap<>(); 51 private final Map<Long, List<VibrationEffectSegment>> mEffectSegments = new TreeMap<>(); 52 private final Map<Long, List<VibrationEffect.VendorEffect>> mVendorEffects = new TreeMap<>(); 53 private final Map<Long, List<PwlePoint>> mEffectPwlePoints = new TreeMap<>(); 54 private final Map<Long, List<Integer>> mBraking = new HashMap<>(); 55 private final List<Float> mAmplitudes = new ArrayList<>(); 56 private final List<Boolean> mExternalControlStates = new ArrayList<>(); 57 private final Handler mHandler; 58 private final FakeNativeWrapper mNativeWrapper; 59 60 private boolean mIsAvailable = true; 61 private boolean mIsInfoLoadSuccessful = true; 62 private long mCompletionCallbackDelay; 63 private long mOnLatency; 64 private long mOffLatency; 65 private int mOffCount; 66 67 private int mCapabilities; 68 private int[] mSupportedEffects; 69 private int[] mSupportedBraking; 70 private int[] mSupportedPrimitives; 71 private int mCompositionSizeMax; 72 private int mPwleSizeMax; 73 private int mMaxEnvelopeEffectSize; 74 private int mMinEnvelopeEffectControlPointDurationMillis; 75 private int mMaxEnvelopeEffectControlPointDurationMillis; 76 private float mMinFrequency = Float.NaN; 77 private float mResonantFrequency = Float.NaN; 78 private float mFrequencyResolution = Float.NaN; 79 private float mQFactor = Float.NaN; 80 private float[] mMaxAmplitudes; 81 82 private float[] mFrequenciesHz; 83 private float[] mOutputAccelerationsGs; 84 private long mVendorEffectDuration = EFFECT_DURATION; 85 private long mPrimitiveDuration = EFFECT_DURATION; 86 recordEffectSegment(long vibrationId, VibrationEffectSegment segment)87 void recordEffectSegment(long vibrationId, VibrationEffectSegment segment) { 88 mEffectSegments.computeIfAbsent(vibrationId, k -> new ArrayList<>()).add(segment); 89 } 90 recordVendorEffect(long vibrationId, VibrationEffect.VendorEffect vendorEffect)91 void recordVendorEffect(long vibrationId, VibrationEffect.VendorEffect vendorEffect) { 92 mVendorEffects.computeIfAbsent(vibrationId, k -> new ArrayList<>()).add(vendorEffect); 93 } 94 recordEffectPwlePoint(long vibrationId, PwlePoint pwlePoint)95 void recordEffectPwlePoint(long vibrationId, PwlePoint pwlePoint) { 96 mEffectPwlePoints.computeIfAbsent(vibrationId, k -> new ArrayList<>()).add(pwlePoint); 97 } 98 recordBraking(long vibrationId, int braking)99 void recordBraking(long vibrationId, int braking) { 100 mBraking.computeIfAbsent(vibrationId, k -> new ArrayList<>()).add(braking); 101 } 102 103 private final class FakeNativeWrapper extends VibratorController.NativeWrapper { 104 public int vibratorId; 105 public OnVibrationCompleteListener listener; 106 public boolean isInitialized; 107 108 @Override init(int vibratorId, OnVibrationCompleteListener listener)109 public void init(int vibratorId, OnVibrationCompleteListener listener) { 110 isInitialized = true; 111 this.vibratorId = vibratorId; 112 this.listener = listener; 113 } 114 115 @Override isAvailable()116 public boolean isAvailable() { 117 return mIsAvailable; 118 } 119 120 @Override on(long milliseconds, long vibrationId, long stepId)121 public long on(long milliseconds, long vibrationId, long stepId) { 122 recordEffectSegment(vibrationId, new StepSegment(VibrationEffect.DEFAULT_AMPLITUDE, 123 /* frequencyHz= */ 0, (int) milliseconds)); 124 applyLatency(mOnLatency); 125 scheduleListener(milliseconds, vibrationId, stepId); 126 return milliseconds; 127 } 128 129 @Override off()130 public void off() { 131 mOffCount++; 132 applyLatency(mOffLatency); 133 } 134 135 @Override setAmplitude(float amplitude)136 public void setAmplitude(float amplitude) { 137 mAmplitudes.add(amplitude); 138 applyLatency(mOnLatency); 139 } 140 141 @Override perform(long effect, long strength, long vibrationId, long stepId)142 public long perform(long effect, long strength, long vibrationId, long stepId) { 143 if (mSupportedEffects == null 144 || Arrays.binarySearch(mSupportedEffects, (int) effect) < 0) { 145 return 0; 146 } 147 recordEffectSegment(vibrationId, 148 new PrebakedSegment((int) effect, false, (int) strength)); 149 applyLatency(mOnLatency); 150 scheduleListener(EFFECT_DURATION, vibrationId, stepId); 151 return EFFECT_DURATION; 152 } 153 154 @Override performVendorEffect(Parcel vendorData, long strength, float scale, float adaptiveScale, long vibrationId, long stepId)155 public long performVendorEffect(Parcel vendorData, long strength, float scale, 156 float adaptiveScale, long vibrationId, long stepId) { 157 if ((mCapabilities & IVibrator.CAP_PERFORM_VENDOR_EFFECTS) == 0) { 158 return 0; 159 } 160 PersistableBundle bundle = PersistableBundle.CREATOR.createFromParcel(vendorData); 161 recordVendorEffect(vibrationId, 162 new VibrationEffect.VendorEffect(bundle, (int) strength, scale, adaptiveScale)); 163 applyLatency(mOnLatency); 164 scheduleListener(mVendorEffectDuration, vibrationId, stepId); 165 // HAL has unknown duration for vendor effects. 166 return Long.MAX_VALUE; 167 } 168 169 @Override compose(PrimitiveSegment[] primitives, long vibrationId, long stepId)170 public long compose(PrimitiveSegment[] primitives, long vibrationId, long stepId) { 171 if (mSupportedPrimitives == null) { 172 return 0; 173 } 174 for (PrimitiveSegment primitive : primitives) { 175 if (Arrays.binarySearch(mSupportedPrimitives, primitive.getPrimitiveId()) < 0) { 176 return 0; 177 } 178 } 179 long duration = 0; 180 for (PrimitiveSegment primitive : primitives) { 181 duration += mPrimitiveDuration + primitive.getDelay(); 182 recordEffectSegment(vibrationId, primitive); 183 } 184 applyLatency(mOnLatency); 185 scheduleListener(duration, vibrationId, stepId); 186 return duration; 187 } 188 189 @Override composePwle(RampSegment[] primitives, int braking, long vibrationId, long stepId)190 public long composePwle(RampSegment[] primitives, int braking, long vibrationId, 191 long stepId) { 192 long duration = 0; 193 for (RampSegment primitive : primitives) { 194 duration += primitive.getDuration(); 195 recordEffectSegment(vibrationId, primitive); 196 } 197 recordBraking(vibrationId, braking); 198 applyLatency(mOnLatency); 199 scheduleListener(duration, vibrationId, stepId); 200 return duration; 201 } 202 203 @Override composePwleV2(PwlePoint[] pwlePoints, long vibrationId, long stepId)204 public long composePwleV2(PwlePoint[] pwlePoints, long vibrationId, long stepId) { 205 long duration = 0; 206 for (PwlePoint pwlePoint: pwlePoints) { 207 duration += pwlePoint.getTimeMillis(); 208 recordEffectPwlePoint(vibrationId, pwlePoint); 209 } 210 applyLatency(mOnLatency); 211 scheduleListener(duration, vibrationId, stepId); 212 213 return duration; 214 } 215 216 @Override setExternalControl(boolean enabled)217 public void setExternalControl(boolean enabled) { 218 mExternalControlStates.add(enabled); 219 } 220 221 @Override alwaysOnEnable(long id, long effect, long strength)222 public void alwaysOnEnable(long id, long effect, long strength) { 223 PrebakedSegment prebaked = new PrebakedSegment((int) effect, false, (int) strength); 224 mEnabledAlwaysOnEffects.put(id, prebaked); 225 } 226 227 @Override alwaysOnDisable(long id)228 public void alwaysOnDisable(long id) { 229 mEnabledAlwaysOnEffects.remove(id); 230 } 231 232 @Override getInfo(VibratorInfo.Builder infoBuilder)233 public boolean getInfo(VibratorInfo.Builder infoBuilder) { 234 infoBuilder.setCapabilities(mCapabilities); 235 infoBuilder.setSupportedBraking(mSupportedBraking); 236 infoBuilder.setPwleSizeMax(mPwleSizeMax); 237 infoBuilder.setSupportedEffects(mSupportedEffects); 238 if (mSupportedPrimitives != null) { 239 for (int primitive : mSupportedPrimitives) { 240 infoBuilder.setSupportedPrimitive(primitive, (int) mPrimitiveDuration); 241 } 242 } 243 infoBuilder.setCompositionSizeMax(mCompositionSizeMax); 244 infoBuilder.setQFactor(mQFactor); 245 infoBuilder.setFrequencyProfileLegacy(new VibratorInfo.FrequencyProfileLegacy( 246 mResonantFrequency, mMinFrequency, mFrequencyResolution, mMaxAmplitudes)); 247 infoBuilder.setFrequencyProfile( 248 new VibratorInfo.FrequencyProfile(mResonantFrequency, mFrequenciesHz, 249 mOutputAccelerationsGs)); 250 infoBuilder.setMaxEnvelopeEffectSize(mMaxEnvelopeEffectSize); 251 infoBuilder.setMinEnvelopeEffectControlPointDurationMillis( 252 mMinEnvelopeEffectControlPointDurationMillis); 253 infoBuilder.setMaxEnvelopeEffectControlPointDurationMillis( 254 mMaxEnvelopeEffectControlPointDurationMillis); 255 return mIsInfoLoadSuccessful; 256 } 257 applyLatency(long latencyMillis)258 private void applyLatency(long latencyMillis) { 259 try { 260 if (latencyMillis > 0) { 261 Thread.sleep(latencyMillis); 262 } 263 } catch (InterruptedException e) { 264 } 265 } 266 scheduleListener(long vibrationDuration, long vibrationId, long stepId)267 private void scheduleListener(long vibrationDuration, long vibrationId, long stepId) { 268 mHandler.postDelayed(() -> listener.onComplete(vibratorId, vibrationId, stepId), 269 vibrationDuration + mCompletionCallbackDelay); 270 } 271 } 272 FakeVibratorControllerProvider(Looper looper)273 public FakeVibratorControllerProvider(Looper looper) { 274 mHandler = new Handler(looper); 275 mNativeWrapper = new FakeNativeWrapper(); 276 } 277 newVibratorController( int vibratorId, OnVibrationCompleteListener listener)278 public VibratorController newVibratorController( 279 int vibratorId, OnVibrationCompleteListener listener) { 280 return new VibratorController(vibratorId, listener, mNativeWrapper); 281 } 282 283 /** Return {@code true} if this controller was initialized. */ isInitialized()284 public boolean isInitialized() { 285 return mNativeWrapper.isInitialized; 286 } 287 288 /** 289 * Disable fake vibrator hardware, mocking a state where the underlying service is unavailable. 290 */ disableVibrators()291 public void disableVibrators() { 292 mIsAvailable = false; 293 } 294 295 /** 296 * Sets the result for the method that loads the {@link VibratorInfo}, for faking a vibrator 297 * that fails to load some of the hardware data. 298 */ setVibratorInfoLoadSuccessful(boolean successful)299 public void setVibratorInfoLoadSuccessful(boolean successful) { 300 mIsInfoLoadSuccessful = successful; 301 } 302 303 /** 304 * Sets the delay this controller should fake for triggering the vibration completed callback. 305 */ setCompletionCallbackDelay(long millis)306 public void setCompletionCallbackDelay(long millis) { 307 mCompletionCallbackDelay = millis; 308 } 309 310 /** 311 * Sets the latency this controller should fake for turning the vibrator hardware on or setting 312 * the vibration amplitude. 313 */ setOnLatency(long millis)314 public void setOnLatency(long millis) { 315 mOnLatency = millis; 316 } 317 318 /** Sets the latency this controller should fake for turning the vibrator off. */ setOffLatency(long millis)319 public void setOffLatency(long millis) { 320 mOffLatency = millis; 321 } 322 323 /** Set the capabilities of the fake vibrator hardware. */ setCapabilities(int... capabilities)324 public void setCapabilities(int... capabilities) { 325 mCapabilities = Arrays.stream(capabilities).reduce(0, (a, b) -> a | b); 326 } 327 328 /** Set the effects supported by the fake vibrator hardware. */ setSupportedEffects(int... effects)329 public void setSupportedEffects(int... effects) { 330 if (effects != null) { 331 effects = Arrays.copyOf(effects, effects.length); 332 Arrays.sort(effects); 333 } 334 mSupportedEffects = effects; 335 } 336 337 /** Set the effects supported by the fake vibrator hardware. */ setSupportedBraking(int... braking)338 public void setSupportedBraking(int... braking) { 339 if (braking != null) { 340 braking = Arrays.copyOf(braking, braking.length); 341 Arrays.sort(braking); 342 } 343 mSupportedBraking = braking; 344 } 345 346 /** Set the primitives supported by the fake vibrator hardware. */ setSupportedPrimitives(int... primitives)347 public void setSupportedPrimitives(int... primitives) { 348 if (primitives != null) { 349 primitives = Arrays.copyOf(primitives, primitives.length); 350 Arrays.sort(primitives); 351 } 352 mSupportedPrimitives = primitives; 353 } 354 355 /** Set the max number of primitives allowed in a composition by the fake vibrator hardware. */ setCompositionSizeMax(int compositionSizeMax)356 public void setCompositionSizeMax(int compositionSizeMax) { 357 mCompositionSizeMax = compositionSizeMax; 358 } 359 360 /** Set the max number of PWLEs allowed in a composition by the fake vibrator hardware. */ setPwleSizeMax(int pwleSizeMax)361 public void setPwleSizeMax(int pwleSizeMax) { 362 mPwleSizeMax = pwleSizeMax; 363 } 364 365 /** Set the resonant frequency of the fake vibrator hardware. */ setResonantFrequency(float frequencyHz)366 public void setResonantFrequency(float frequencyHz) { 367 mResonantFrequency = frequencyHz; 368 } 369 370 /** Set the minimum frequency of the fake vibrator hardware. */ setMinFrequency(float frequencyHz)371 public void setMinFrequency(float frequencyHz) { 372 mMinFrequency = frequencyHz; 373 } 374 375 /** Set the frequency resolution of the fake vibrator hardware. */ setFrequencyResolution(float frequencyHz)376 public void setFrequencyResolution(float frequencyHz) { 377 mFrequencyResolution = frequencyHz; 378 } 379 380 /** Set the Q factor of the fake vibrator hardware. */ setQFactor(float qFactor)381 public void setQFactor(float qFactor) { 382 mQFactor = qFactor; 383 } 384 385 /** Set the max amplitude supported for each frequency f the fake vibrator hardware. */ setMaxAmplitudes(float... maxAmplitudes)386 public void setMaxAmplitudes(float... maxAmplitudes) { 387 mMaxAmplitudes = maxAmplitudes; 388 } 389 390 /** Set the list of available frequencies. */ setFrequenciesHz(float[] frequenciesHz)391 public void setFrequenciesHz(float[] frequenciesHz) { 392 mFrequenciesHz = frequenciesHz; 393 } 394 395 /** Set the max output acceleration achievable by the supported frequencies. */ setOutputAccelerationsGs(float[] outputAccelerationsGs)396 public void setOutputAccelerationsGs(float[] outputAccelerationsGs) { 397 mOutputAccelerationsGs = outputAccelerationsGs; 398 } 399 400 /** Set the duration of vendor effects in fake vibrator hardware. */ setVendorEffectDuration(long durationMs)401 public void setVendorEffectDuration(long durationMs) { 402 mVendorEffectDuration = durationMs; 403 } 404 405 /** Set the duration of primitives in fake vibrator hardware. */ setPrimitiveDuration(long primitiveDuration)406 public void setPrimitiveDuration(long primitiveDuration) { 407 mPrimitiveDuration = primitiveDuration; 408 } 409 410 /** 411 * Set the maximum number of envelope effects control points supported in fake vibrator 412 * hardware. 413 */ setMaxEnvelopeEffectSize(int envelopeEffectControlPointsMax)414 public void setMaxEnvelopeEffectSize(int envelopeEffectControlPointsMax) { 415 mMaxEnvelopeEffectSize = envelopeEffectControlPointsMax; 416 } 417 418 /** Set the envelope effect minimum segment duration in fake vibrator hardware. */ setMinEnvelopeEffectControlPointDurationMillis( int minEnvelopeEffectControlPointDurationMillis)419 public void setMinEnvelopeEffectControlPointDurationMillis( 420 int minEnvelopeEffectControlPointDurationMillis) { 421 mMinEnvelopeEffectControlPointDurationMillis = minEnvelopeEffectControlPointDurationMillis; 422 } 423 424 /** Set the envelope effect maximum segment duration in fake vibrator hardware. */ setMaxEnvelopeEffectControlPointDurationMillis( int maxEnvelopeEffectControlPointDurationMillis)425 public void setMaxEnvelopeEffectControlPointDurationMillis( 426 int maxEnvelopeEffectControlPointDurationMillis) { 427 mMaxEnvelopeEffectControlPointDurationMillis = maxEnvelopeEffectControlPointDurationMillis; 428 } 429 430 /** 431 * Return the amplitudes set by this controller, including zeroes for each time the vibrator was 432 * turned off. 433 */ getAmplitudes()434 public List<Float> getAmplitudes() { 435 return new ArrayList<>(mAmplitudes); 436 } 437 438 /** Return the braking values passed to the compose PWLE method. */ getBraking(long vibrationId)439 public List<Integer> getBraking(long vibrationId) { 440 if (mBraking.containsKey(vibrationId)) { 441 return new ArrayList<>(mBraking.get(vibrationId)); 442 } else { 443 return new ArrayList<>(); 444 } 445 } 446 447 /** Return list of {@link VibrationEffectSegment} played by this controller, in order. */ getEffectSegments(long vibrationId)448 public List<VibrationEffectSegment> getEffectSegments(long vibrationId) { 449 if (mEffectSegments.containsKey(vibrationId)) { 450 return new ArrayList<>(mEffectSegments.get(vibrationId)); 451 } else { 452 return new ArrayList<>(); 453 } 454 } 455 456 /** 457 * Returns a list of all vibrations' effect segments, for external-use where vibration IDs 458 * aren't exposed. 459 */ getAllEffectSegments()460 public List<VibrationEffectSegment> getAllEffectSegments() { 461 // Returns segments in order of vibrationId, which increases over time. TreeMap gives order. 462 ArrayList<VibrationEffectSegment> result = new ArrayList<>(); 463 for (List<VibrationEffectSegment> subList : mEffectSegments.values()) { 464 result.addAll(subList); 465 } 466 return result; 467 } 468 469 /** Return list of {@link VibrationEffect.VendorEffect} played by this controller, in order. */ getVendorEffects(long vibrationId)470 public List<VibrationEffect.VendorEffect> getVendorEffects(long vibrationId) { 471 if (mVendorEffects.containsKey(vibrationId)) { 472 return new ArrayList<>(mVendorEffects.get(vibrationId)); 473 } else { 474 return new ArrayList<>(); 475 } 476 } 477 478 /** 479 * Returns a list of all vibrations' effect segments, for external-use where vibration IDs 480 * aren't exposed. 481 */ getAllVendorEffects()482 public List<VibrationEffect.VendorEffect> getAllVendorEffects() { 483 // Returns segments in order of vibrationId, which increases over time. TreeMap gives order. 484 ArrayList<VibrationEffect.VendorEffect> result = new ArrayList<>(); 485 for (List<VibrationEffect.VendorEffect> subList : mVendorEffects.values()) { 486 result.addAll(subList); 487 } 488 return result; 489 } 490 491 /** Return list of {@link PwlePoint} played by this controller, in order. */ getEffectPwlePoints(long vibrationId)492 public List<PwlePoint> getEffectPwlePoints(long vibrationId) { 493 if (mEffectPwlePoints.containsKey(vibrationId)) { 494 return new ArrayList<>(mEffectPwlePoints.get(vibrationId)); 495 } else { 496 return new ArrayList<>(); 497 } 498 } 499 500 /** 501 * Returns a list of all vibrations' {@link PwlePoint}s, for external-use where vibration 502 * IDs aren't exposed. 503 */ getAllEffectPwlePoints()504 public List<PwlePoint> getAllEffectPwlePoints() { 505 // Returns segments in order of vibrationId, which increases over time. TreeMap gives order. 506 ArrayList<PwlePoint> result = new ArrayList<>(); 507 for (List<PwlePoint> subList : mEffectPwlePoints.values()) { 508 result.addAll(subList); 509 } 510 return result; 511 } 512 513 /** Return list of states set for external control to the fake vibrator hardware. */ getExternalControlStates()514 public List<Boolean> getExternalControlStates() { 515 return mExternalControlStates; 516 } 517 518 /** Returns the number of times the vibrator was turned off. */ getOffCount()519 public int getOffCount() { 520 return mOffCount; 521 } 522 523 /** 524 * Return the {@link PrebakedSegment} effect enabled with given id, or {@code null} if 525 * missing or disabled. 526 */ 527 @Nullable getAlwaysOnEffect(int id)528 public PrebakedSegment getAlwaysOnEffect(int id) { 529 return mEnabledAlwaysOnEffects.get((long) id); 530 } 531 } 532