1 package org.robolectric.shadows; 2 3 import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1; 4 import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR2; 5 import static android.os.Build.VERSION_CODES.KITKAT_WATCH; 6 import static android.os.Build.VERSION_CODES.LOLLIPOP; 7 import static android.os.Build.VERSION_CODES.N_MR1; 8 import static android.os.Build.VERSION_CODES.O; 9 import static android.os.Build.VERSION_CODES.P; 10 11 import android.media.AudioAttributes; 12 import android.os.Build.VERSION_CODES; 13 import android.os.Handler; 14 import android.os.Looper; 15 import android.os.SystemVibrator; 16 import android.os.VibrationEffect; 17 import org.robolectric.RuntimeEnvironment; 18 import org.robolectric.annotation.Implementation; 19 import org.robolectric.annotation.Implements; 20 import org.robolectric.util.ReflectionHelpers; 21 22 @Implements(value = SystemVibrator.class, isInAndroidSdk = false) 23 public class ShadowSystemVibrator extends ShadowVibrator { 24 25 private Handler handler = new Handler(Looper.myLooper()); 26 private Runnable stopVibratingRunnable = () -> vibrating = false; 27 28 @Implementation 29 protected boolean hasVibrator() { 30 return hasVibrator; 31 } 32 33 @Implementation(minSdk = O) 34 protected boolean hasAmplitudeControl() { 35 return hasAmplitudeControl; 36 } 37 38 @Implementation(maxSdk = JELLY_BEAN_MR1) 39 protected void vibrate(long[] pattern, int repeat) { 40 recordVibratePattern(pattern, repeat); 41 } 42 43 @Implementation(minSdk = JELLY_BEAN_MR2, maxSdk = KITKAT_WATCH) 44 protected void vibrate(int owningUid, String owningPackage, long[] pattern, int repeat) { 45 recordVibratePattern(pattern, repeat); 46 } 47 48 @Implementation(minSdk = LOLLIPOP, maxSdk = N_MR1) 49 protected void vibrate(int uid, String opPkg, long[] pattern, int repeat, AudioAttributes attributes) { 50 recordVibratePattern(pattern, repeat); 51 } 52 53 @Implementation(maxSdk = JELLY_BEAN_MR1) 54 public void vibrate(long milliseconds) { 55 recordVibrate(milliseconds); 56 } 57 58 @Implementation(minSdk = JELLY_BEAN_MR2, maxSdk = KITKAT_WATCH) 59 public void vibrate(int owningUid, String owningPackage, long milliseconds) { 60 recordVibrate(milliseconds); 61 } 62 63 @Implementation(minSdk = LOLLIPOP, maxSdk = N_MR1) 64 protected void vibrate(int uid, String opPkg, long milliseconds, AudioAttributes attributes) { 65 recordVibrate(milliseconds); 66 } 67 68 @Implementation(minSdk = O, maxSdk = VERSION_CODES.P) 69 protected void vibrate(int uid, String opPkg, VibrationEffect effect, AudioAttributes attributes) { 70 vibrate(uid, opPkg, effect, null, attributes); 71 } 72 73 @Implementation(minSdk = VERSION_CODES.CUR_DEVELOPMENT) 74 protected void vibrate(int uid, String opPkg, VibrationEffect effect, 75 String reason, AudioAttributes attributes) { 76 if (effect instanceof VibrationEffect.Waveform) { 77 VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) effect; 78 recordVibratePattern(waveform.getTimings(), waveform.getRepeatIndex()); 79 80 } else { 81 VibrationEffect.OneShot oneShot = (VibrationEffect.OneShot) effect; 82 83 long timing; 84 85 if (RuntimeEnvironment.getApiLevel() >= P) { 86 timing = oneShot.getDuration(); 87 } else { 88 timing = ReflectionHelpers.callInstanceMethod(oneShot, "getTiming"); 89 } 90 91 recordVibrate(timing); 92 } 93 } 94 95 private void recordVibrate(long milliseconds) { 96 vibrating = true; 97 this.milliseconds = milliseconds; 98 handler.removeCallbacks(stopVibratingRunnable); 99 handler.postDelayed(stopVibratingRunnable, this.milliseconds); 100 } 101 102 private void recordVibratePattern(long[] pattern, int repeat) { 103 vibrating = true; 104 this.pattern = pattern; 105 this.repeat = repeat; 106 handler.removeCallbacks(stopVibratingRunnable); 107 if (repeat < 0) { 108 long endDelayMillis = 0; 109 for (long t : pattern) { 110 endDelayMillis += t; 111 } 112 handler.postDelayed(stopVibratingRunnable, endDelayMillis); 113 } 114 } 115 116 @Implementation 117 protected void cancel() { 118 cancelled = true; 119 vibrating = false; 120 handler.removeCallbacks(stopVibratingRunnable); 121 } 122 } 123