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)121 public long on(long milliseconds, long vibrationId) { 122 recordEffectSegment(vibrationId, new StepSegment(VibrationEffect.DEFAULT_AMPLITUDE, 123 /* frequencyHz= */ 0, (int) milliseconds)); 124 applyLatency(mOnLatency); 125 scheduleListener(milliseconds, vibrationId); 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)142 public long perform(long effect, long strength, long vibrationId) { 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); 151 return EFFECT_DURATION; 152 } 153 154 @Override performVendorEffect(Parcel vendorData, long strength, float scale, float adaptiveScale, long vibrationId)155 public long performVendorEffect(Parcel vendorData, long strength, float scale, 156 float adaptiveScale, long vibrationId) { 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); 165 // HAL has unknown duration for vendor effects. 166 return Long.MAX_VALUE; 167 } 168 169 @Override compose(PrimitiveSegment[] primitives, long vibrationId)170 public long compose(PrimitiveSegment[] primitives, long vibrationId) { 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); 186 return duration; 187 } 188 189 @Override composePwle(RampSegment[] primitives, int braking, long vibrationId)190 public long composePwle(RampSegment[] primitives, int braking, long vibrationId) { 191 long duration = 0; 192 for (RampSegment primitive : primitives) { 193 duration += primitive.getDuration(); 194 recordEffectSegment(vibrationId, primitive); 195 } 196 recordBraking(vibrationId, braking); 197 applyLatency(mOnLatency); 198 scheduleListener(duration, vibrationId); 199 return duration; 200 } 201 202 @Override composePwleV2(PwlePoint[] pwlePoints, long vibrationId)203 public long composePwleV2(PwlePoint[] pwlePoints, long vibrationId) { 204 long duration = 0; 205 for (PwlePoint pwlePoint: pwlePoints) { 206 duration += pwlePoint.getTimeMillis(); 207 recordEffectPwlePoint(vibrationId, pwlePoint); 208 } 209 applyLatency(mOnLatency); 210 scheduleListener(duration, vibrationId); 211 212 return duration; 213 } 214 215 @Override setExternalControl(boolean enabled)216 public void setExternalControl(boolean enabled) { 217 mExternalControlStates.add(enabled); 218 } 219 220 @Override alwaysOnEnable(long id, long effect, long strength)221 public void alwaysOnEnable(long id, long effect, long strength) { 222 PrebakedSegment prebaked = new PrebakedSegment((int) effect, false, (int) strength); 223 mEnabledAlwaysOnEffects.put(id, prebaked); 224 } 225 226 @Override alwaysOnDisable(long id)227 public void alwaysOnDisable(long id) { 228 mEnabledAlwaysOnEffects.remove(id); 229 } 230 231 @Override getInfo(VibratorInfo.Builder infoBuilder)232 public boolean getInfo(VibratorInfo.Builder infoBuilder) { 233 infoBuilder.setCapabilities(mCapabilities); 234 infoBuilder.setSupportedBraking(mSupportedBraking); 235 infoBuilder.setPwleSizeMax(mPwleSizeMax); 236 infoBuilder.setSupportedEffects(mSupportedEffects); 237 if (mSupportedPrimitives != null) { 238 for (int primitive : mSupportedPrimitives) { 239 infoBuilder.setSupportedPrimitive(primitive, (int) mPrimitiveDuration); 240 } 241 } 242 infoBuilder.setCompositionSizeMax(mCompositionSizeMax); 243 infoBuilder.setQFactor(mQFactor); 244 infoBuilder.setFrequencyProfileLegacy(new VibratorInfo.FrequencyProfileLegacy( 245 mResonantFrequency, mMinFrequency, mFrequencyResolution, mMaxAmplitudes)); 246 infoBuilder.setFrequencyProfile( 247 new VibratorInfo.FrequencyProfile(mResonantFrequency, mFrequenciesHz, 248 mOutputAccelerationsGs)); 249 infoBuilder.setMaxEnvelopeEffectSize(mMaxEnvelopeEffectSize); 250 infoBuilder.setMinEnvelopeEffectControlPointDurationMillis( 251 mMinEnvelopeEffectControlPointDurationMillis); 252 infoBuilder.setMaxEnvelopeEffectControlPointDurationMillis( 253 mMaxEnvelopeEffectControlPointDurationMillis); 254 return mIsInfoLoadSuccessful; 255 } 256 applyLatency(long latencyMillis)257 private void applyLatency(long latencyMillis) { 258 try { 259 if (latencyMillis > 0) { 260 Thread.sleep(latencyMillis); 261 } 262 } catch (InterruptedException e) { 263 } 264 } 265 scheduleListener(long vibrationDuration, long vibrationId)266 private void scheduleListener(long vibrationDuration, long vibrationId) { 267 mHandler.postDelayed(() -> listener.onComplete(vibratorId, vibrationId), 268 vibrationDuration + mCompletionCallbackDelay); 269 } 270 } 271 FakeVibratorControllerProvider(Looper looper)272 public FakeVibratorControllerProvider(Looper looper) { 273 mHandler = new Handler(looper); 274 mNativeWrapper = new FakeNativeWrapper(); 275 } 276 newVibratorController( int vibratorId, OnVibrationCompleteListener listener)277 public VibratorController newVibratorController( 278 int vibratorId, OnVibrationCompleteListener listener) { 279 return new VibratorController(vibratorId, listener, mNativeWrapper); 280 } 281 282 /** Return {@code true} if this controller was initialized. */ isInitialized()283 public boolean isInitialized() { 284 return mNativeWrapper.isInitialized; 285 } 286 287 /** 288 * Disable fake vibrator hardware, mocking a state where the underlying service is unavailable. 289 */ disableVibrators()290 public void disableVibrators() { 291 mIsAvailable = false; 292 } 293 294 /** 295 * Sets the result for the method that loads the {@link VibratorInfo}, for faking a vibrator 296 * that fails to load some of the hardware data. 297 */ setVibratorInfoLoadSuccessful(boolean successful)298 public void setVibratorInfoLoadSuccessful(boolean successful) { 299 mIsInfoLoadSuccessful = successful; 300 } 301 302 /** 303 * Sets the delay this controller should fake for triggering the vibration completed callback. 304 */ setCompletionCallbackDelay(long millis)305 public void setCompletionCallbackDelay(long millis) { 306 mCompletionCallbackDelay = millis; 307 } 308 309 /** 310 * Sets the latency this controller should fake for turning the vibrator hardware on or setting 311 * the vibration amplitude. 312 */ setOnLatency(long millis)313 public void setOnLatency(long millis) { 314 mOnLatency = millis; 315 } 316 317 /** Sets the latency this controller should fake for turning the vibrator off. */ setOffLatency(long millis)318 public void setOffLatency(long millis) { 319 mOffLatency = millis; 320 } 321 322 /** Set the capabilities of the fake vibrator hardware. */ setCapabilities(int... capabilities)323 public void setCapabilities(int... capabilities) { 324 mCapabilities = Arrays.stream(capabilities).reduce(0, (a, b) -> a | b); 325 } 326 327 /** Set the effects supported by the fake vibrator hardware. */ setSupportedEffects(int... effects)328 public void setSupportedEffects(int... effects) { 329 if (effects != null) { 330 effects = Arrays.copyOf(effects, effects.length); 331 Arrays.sort(effects); 332 } 333 mSupportedEffects = effects; 334 } 335 336 /** Set the effects supported by the fake vibrator hardware. */ setSupportedBraking(int... braking)337 public void setSupportedBraking(int... braking) { 338 if (braking != null) { 339 braking = Arrays.copyOf(braking, braking.length); 340 Arrays.sort(braking); 341 } 342 mSupportedBraking = braking; 343 } 344 345 /** Set the primitives supported by the fake vibrator hardware. */ setSupportedPrimitives(int... primitives)346 public void setSupportedPrimitives(int... primitives) { 347 if (primitives != null) { 348 primitives = Arrays.copyOf(primitives, primitives.length); 349 Arrays.sort(primitives); 350 } 351 mSupportedPrimitives = primitives; 352 } 353 354 /** Set the max number of primitives allowed in a composition by the fake vibrator hardware. */ setCompositionSizeMax(int compositionSizeMax)355 public void setCompositionSizeMax(int compositionSizeMax) { 356 mCompositionSizeMax = compositionSizeMax; 357 } 358 359 /** Set the max number of PWLEs allowed in a composition by the fake vibrator hardware. */ setPwleSizeMax(int pwleSizeMax)360 public void setPwleSizeMax(int pwleSizeMax) { 361 mPwleSizeMax = pwleSizeMax; 362 } 363 364 /** Set the resonant frequency of the fake vibrator hardware. */ setResonantFrequency(float frequencyHz)365 public void setResonantFrequency(float frequencyHz) { 366 mResonantFrequency = frequencyHz; 367 } 368 369 /** Set the minimum frequency of the fake vibrator hardware. */ setMinFrequency(float frequencyHz)370 public void setMinFrequency(float frequencyHz) { 371 mMinFrequency = frequencyHz; 372 } 373 374 /** Set the frequency resolution of the fake vibrator hardware. */ setFrequencyResolution(float frequencyHz)375 public void setFrequencyResolution(float frequencyHz) { 376 mFrequencyResolution = frequencyHz; 377 } 378 379 /** Set the Q factor of the fake vibrator hardware. */ setQFactor(float qFactor)380 public void setQFactor(float qFactor) { 381 mQFactor = qFactor; 382 } 383 384 /** Set the max amplitude supported for each frequency f the fake vibrator hardware. */ setMaxAmplitudes(float... maxAmplitudes)385 public void setMaxAmplitudes(float... maxAmplitudes) { 386 mMaxAmplitudes = maxAmplitudes; 387 } 388 389 /** Set the list of available frequencies. */ setFrequenciesHz(float[] frequenciesHz)390 public void setFrequenciesHz(float[] frequenciesHz) { 391 mFrequenciesHz = frequenciesHz; 392 } 393 394 /** Set the max output acceleration achievable by the supported frequencies. */ setOutputAccelerationsGs(float[] outputAccelerationsGs)395 public void setOutputAccelerationsGs(float[] outputAccelerationsGs) { 396 mOutputAccelerationsGs = outputAccelerationsGs; 397 } 398 399 /** Set the duration of vendor effects in fake vibrator hardware. */ setVendorEffectDuration(long durationMs)400 public void setVendorEffectDuration(long durationMs) { 401 mVendorEffectDuration = durationMs; 402 } 403 404 /** Set the duration of primitives in fake vibrator hardware. */ setPrimitiveDuration(long primitiveDuration)405 public void setPrimitiveDuration(long primitiveDuration) { 406 mPrimitiveDuration = primitiveDuration; 407 } 408 409 /** 410 * Set the maximum number of envelope effects control points supported in fake vibrator 411 * hardware. 412 */ setMaxEnvelopeEffectSize(int envelopeEffectControlPointsMax)413 public void setMaxEnvelopeEffectSize(int envelopeEffectControlPointsMax) { 414 mMaxEnvelopeEffectSize = envelopeEffectControlPointsMax; 415 } 416 417 /** Set the envelope effect minimum segment duration in fake vibrator hardware. */ setMinEnvelopeEffectControlPointDurationMillis( int minEnvelopeEffectControlPointDurationMillis)418 public void setMinEnvelopeEffectControlPointDurationMillis( 419 int minEnvelopeEffectControlPointDurationMillis) { 420 mMinEnvelopeEffectControlPointDurationMillis = minEnvelopeEffectControlPointDurationMillis; 421 } 422 423 /** Set the envelope effect maximum segment duration in fake vibrator hardware. */ setMaxEnvelopeEffectControlPointDurationMillis( int maxEnvelopeEffectControlPointDurationMillis)424 public void setMaxEnvelopeEffectControlPointDurationMillis( 425 int maxEnvelopeEffectControlPointDurationMillis) { 426 mMaxEnvelopeEffectControlPointDurationMillis = maxEnvelopeEffectControlPointDurationMillis; 427 } 428 429 /** 430 * Return the amplitudes set by this controller, including zeroes for each time the vibrator was 431 * turned off. 432 */ getAmplitudes()433 public List<Float> getAmplitudes() { 434 return new ArrayList<>(mAmplitudes); 435 } 436 437 /** Return the braking values passed to the compose PWLE method. */ getBraking(long vibrationId)438 public List<Integer> getBraking(long vibrationId) { 439 if (mBraking.containsKey(vibrationId)) { 440 return new ArrayList<>(mBraking.get(vibrationId)); 441 } else { 442 return new ArrayList<>(); 443 } 444 } 445 446 /** Return list of {@link VibrationEffectSegment} played by this controller, in order. */ getEffectSegments(long vibrationId)447 public List<VibrationEffectSegment> getEffectSegments(long vibrationId) { 448 if (mEffectSegments.containsKey(vibrationId)) { 449 return new ArrayList<>(mEffectSegments.get(vibrationId)); 450 } else { 451 return new ArrayList<>(); 452 } 453 } 454 455 /** 456 * Returns a list of all vibrations' effect segments, for external-use where vibration IDs 457 * aren't exposed. 458 */ getAllEffectSegments()459 public List<VibrationEffectSegment> getAllEffectSegments() { 460 // Returns segments in order of vibrationId, which increases over time. TreeMap gives order. 461 ArrayList<VibrationEffectSegment> result = new ArrayList<>(); 462 for (List<VibrationEffectSegment> subList : mEffectSegments.values()) { 463 result.addAll(subList); 464 } 465 return result; 466 } 467 468 /** Return list of {@link VibrationEffect.VendorEffect} played by this controller, in order. */ getVendorEffects(long vibrationId)469 public List<VibrationEffect.VendorEffect> getVendorEffects(long vibrationId) { 470 if (mVendorEffects.containsKey(vibrationId)) { 471 return new ArrayList<>(mVendorEffects.get(vibrationId)); 472 } else { 473 return new ArrayList<>(); 474 } 475 } 476 477 /** 478 * Returns a list of all vibrations' effect segments, for external-use where vibration IDs 479 * aren't exposed. 480 */ getAllVendorEffects()481 public List<VibrationEffect.VendorEffect> getAllVendorEffects() { 482 // Returns segments in order of vibrationId, which increases over time. TreeMap gives order. 483 ArrayList<VibrationEffect.VendorEffect> result = new ArrayList<>(); 484 for (List<VibrationEffect.VendorEffect> subList : mVendorEffects.values()) { 485 result.addAll(subList); 486 } 487 return result; 488 } 489 490 /** Return list of {@link PwlePoint} played by this controller, in order. */ getEffectPwlePoints(long vibrationId)491 public List<PwlePoint> getEffectPwlePoints(long vibrationId) { 492 if (mEffectPwlePoints.containsKey(vibrationId)) { 493 return new ArrayList<>(mEffectPwlePoints.get(vibrationId)); 494 } else { 495 return new ArrayList<>(); 496 } 497 } 498 499 /** 500 * Returns a list of all vibrations' {@link PwlePoint}s, for external-use where vibration 501 * IDs aren't exposed. 502 */ getAllEffectPwlePoints()503 public List<PwlePoint> getAllEffectPwlePoints() { 504 // Returns segments in order of vibrationId, which increases over time. TreeMap gives order. 505 ArrayList<PwlePoint> result = new ArrayList<>(); 506 for (List<PwlePoint> subList : mEffectPwlePoints.values()) { 507 result.addAll(subList); 508 } 509 return result; 510 } 511 512 /** Return list of states set for external control to the fake vibrator hardware. */ getExternalControlStates()513 public List<Boolean> getExternalControlStates() { 514 return mExternalControlStates; 515 } 516 517 /** Returns the number of times the vibrator was turned off. */ getOffCount()518 public int getOffCount() { 519 return mOffCount; 520 } 521 522 /** 523 * Return the {@link PrebakedSegment} effect enabled with given id, or {@code null} if 524 * missing or disabled. 525 */ 526 @Nullable getAlwaysOnEffect(int id)527 public PrebakedSegment getAlwaysOnEffect(int id) { 528 return mEnabledAlwaysOnEffects.get((long) id); 529 } 530 } 531