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