• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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.NonNull;
20 import android.os.CombinedVibration;
21 import android.os.VibrationEffect;
22 import android.os.VibratorInfo;
23 import android.os.vibrator.VibrationEffectSegment;
24 import android.util.SparseArray;
25 
26 import java.util.ArrayList;
27 import java.util.Arrays;
28 import java.util.List;
29 
30 /**
31  * Adapts a {@link CombinedVibration} to a device by transforming each {@link VibrationEffect} to
32  * the available device vibrator capabilities defined by {@link VibratorInfo}.
33  */
34 final class DeviceAdapter implements CombinedVibration.VibratorAdapter {
35     private static final String TAG = "DeviceAdapter";
36 
37     /**
38      * The VibratorController.getInfo might trigger HAL method calls, so just keep a reference to
39      * the system controllers until the adaptor is triggered by the VibrationThread.
40      */
41     private final SparseArray<VibratorController> mAvailableVibrators;
42     private final int[] mAvailableVibratorIds;
43 
44     /**
45      * The actual adapters that can replace VibrationEffectSegment entries from a list based on the
46      * VibratorInfo. They can be applied in a chain to a mutable list before a new VibrationEffect
47      * instance is created with the final segment list.
48      */
49     private final List<VibrationSegmentsAdapter> mSegmentAdapters;
50     /**
51      * The vibration segment validators that can validate VibrationEffectSegments entries based on
52      * the VibratorInfo.
53      */
54     private final List<VibrationSegmentsValidator> mSegmentsValidators;
55 
DeviceAdapter(VibrationSettings settings, SparseArray<VibratorController> vibrators)56     DeviceAdapter(VibrationSettings settings, SparseArray<VibratorController> vibrators) {
57         mSegmentAdapters = Arrays.asList(
58                 // TODO(b/167947076): add filter that replaces unsupported prebaked with fallback
59                 // Updates primitive delays to hardware supported pauses
60                 new PrimitiveDelayAdapter(),
61                 // Convert segments based on device capabilities
62                 new RampToStepAdapter(settings.getRampStepDuration()),
63                 new StepToRampAdapter(),
64                 // Add extra ramp down segments as needed
65                 new RampDownAdapter(settings.getRampDownDuration(), settings.getRampStepDuration()),
66                 // Split segments based on their duration and device supported limits
67                 new SplitSegmentsAdapter(),
68                 // Clip amplitudes and frequencies of final segments based on device bandwidth curve
69                 new ClippingAmplitudeAndFrequencyAdapter(),
70                 // Convert BasicPwleSegments to PwleSegments based on device capabilities
71                 new BasicToPwleSegmentAdapter(),
72                 // Split Pwle segments based on their duration and device supported limits
73                 new SplitPwleSegmentsAdapter()
74         );
75         mSegmentsValidators = List.of(
76                 // Validate Pwle segments base on the vibrators frequency range
77                 new PwleSegmentsValidator(),
78                 // Validate primitive segments based on device support
79                 new PrimitiveSegmentsValidator()
80         );
81         mAvailableVibrators = vibrators;
82         mAvailableVibratorIds = new int[vibrators.size()];
83         for (int i = 0; i < vibrators.size(); i++) {
84             mAvailableVibratorIds[i] = vibrators.keyAt(i);
85         }
86     }
87 
getAvailableVibrators()88     SparseArray<VibratorController> getAvailableVibrators() {
89         return mAvailableVibrators;
90     }
91 
92     @Override
getAvailableVibratorIds()93     public int[] getAvailableVibratorIds() {
94         return mAvailableVibratorIds;
95     }
96 
97     @Override
adaptToVibrator(int vibratorId, @NonNull VibrationEffect effect)98     public VibrationEffect adaptToVibrator(int vibratorId, @NonNull VibrationEffect effect) {
99         if (!(effect instanceof VibrationEffect.Composed composed)) {
100             // Segments adapters can only apply to Composed effects.
101             return effect;
102         }
103 
104         VibratorController controller = mAvailableVibrators.get(vibratorId);
105         if (controller == null) {
106             // Effect mapped to nonexistent vibrator, skip adapter.
107             return effect;
108         }
109 
110         VibratorInfo info = controller.getVibratorInfo();
111         List<VibrationEffectSegment> newSegments = new ArrayList<>(composed.getSegments());
112         int newRepeatIndex = composed.getRepeatIndex();
113 
114         int adapterCount = mSegmentAdapters.size();
115         for (int i = 0; i < adapterCount; i++) {
116             newRepeatIndex =
117                     mSegmentAdapters.get(i).adaptToVibrator(info, newSegments, newRepeatIndex);
118         }
119 
120         // Validate the vibration segments. If a segment is not supported, ignore the entire
121         // vibration effect.
122         for (int i = 0; i < mSegmentsValidators.size(); i++) {
123             if (!mSegmentsValidators.get(i).hasValidSegments(info, newSegments)) {
124                 return null;
125             }
126         }
127 
128         return new VibrationEffect.Composed(newSegments, newRepeatIndex);
129     }
130 }
131