1 /*
2  * Copyright (C) 2022 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 android.os.vibrator;
18 
19 import static android.os.VibrationAttributes.USAGE_ACCESSIBILITY;
20 import static android.os.VibrationAttributes.USAGE_ALARM;
21 import static android.os.VibrationAttributes.USAGE_COMMUNICATION_REQUEST;
22 import static android.os.VibrationAttributes.USAGE_HARDWARE_FEEDBACK;
23 import static android.os.VibrationAttributes.USAGE_MEDIA;
24 import static android.os.VibrationAttributes.USAGE_NOTIFICATION;
25 import static android.os.VibrationAttributes.USAGE_PHYSICAL_EMULATION;
26 import static android.os.VibrationAttributes.USAGE_RINGTONE;
27 import static android.os.VibrationAttributes.USAGE_TOUCH;
28 import static android.os.VibrationAttributes.USAGE_UNKNOWN;
29 
30 import android.annotation.Nullable;
31 import android.content.res.Resources;
32 import android.os.VibrationAttributes;
33 import android.os.Vibrator;
34 import android.os.Vibrator.VibrationIntensity;
35 
36 /**
37  * List of device-specific internal vibration configuration loaded from platform config.xml.
38  *
39  * <p>This should not be public, but some individual values are exposed by {@link Vibrator} by
40  * hidden methods, made available to Settings, SysUI and other platform client code. They can also
41  * be individually exposed with the necessary permissions by the {@link Vibrator} service.
42  *
43  * @hide
44  */
45 public class VibrationConfig {
46 
47     // TODO(b/191150049): move these to vibrator static config file
48     private final float mHapticChannelMaxVibrationAmplitude;
49     private final int mRampStepDurationMs;
50     private final int mRampDownDurationMs;
51 
52     @VibrationIntensity
53     private final int mDefaultAlarmVibrationIntensity;
54     @VibrationIntensity
55     private final int mDefaultHapticFeedbackIntensity;
56     @VibrationIntensity
57     private final int mDefaultMediaVibrationIntensity;
58     @VibrationIntensity
59     private final int mDefaultNotificationVibrationIntensity;
60     @VibrationIntensity
61     private final int mDefaultRingVibrationIntensity;
62 
63     /** @hide */
VibrationConfig(@ullable Resources resources)64     public VibrationConfig(@Nullable Resources resources) {
65         mHapticChannelMaxVibrationAmplitude = loadFloat(resources,
66                 com.android.internal.R.dimen.config_hapticChannelMaxVibrationAmplitude, 0);
67         mRampDownDurationMs = loadInteger(resources,
68                 com.android.internal.R.integer.config_vibrationWaveformRampDownDuration, 0);
69         mRampStepDurationMs = loadInteger(resources,
70                 com.android.internal.R.integer.config_vibrationWaveformRampStepDuration, 0);
71 
72         mDefaultAlarmVibrationIntensity = loadDefaultIntensity(resources,
73                 com.android.internal.R.integer.config_defaultAlarmVibrationIntensity);
74         mDefaultHapticFeedbackIntensity = loadDefaultIntensity(resources,
75                 com.android.internal.R.integer.config_defaultHapticFeedbackIntensity);
76         mDefaultMediaVibrationIntensity = loadDefaultIntensity(resources,
77                 com.android.internal.R.integer.config_defaultMediaVibrationIntensity);
78         mDefaultNotificationVibrationIntensity = loadDefaultIntensity(resources,
79                 com.android.internal.R.integer.config_defaultNotificationVibrationIntensity);
80         mDefaultRingVibrationIntensity = loadDefaultIntensity(resources,
81                 com.android.internal.R.integer.config_defaultRingVibrationIntensity);
82     }
83 
84     @VibrationIntensity
loadDefaultIntensity(@ullable Resources res, int resId)85     private static int loadDefaultIntensity(@Nullable Resources res, int resId) {
86         int defaultIntensity = Vibrator.VIBRATION_INTENSITY_MEDIUM;
87         int value = loadInteger(res, resId, defaultIntensity);
88         if (value < Vibrator.VIBRATION_INTENSITY_OFF || value > Vibrator.VIBRATION_INTENSITY_HIGH) {
89             return defaultIntensity;
90         }
91         return value;
92     }
93 
loadFloat(@ullable Resources res, int resId, float defaultValue)94     private static float loadFloat(@Nullable Resources res, int resId, float defaultValue) {
95         return res != null ? res.getFloat(resId) : defaultValue;
96     }
97 
loadInteger(@ullable Resources res, int resId, int defaultValue)98     private static int loadInteger(@Nullable Resources res, int resId, int defaultValue) {
99         return res != null ? res.getInteger(resId) : defaultValue;
100     }
101 
102     /**
103      * Return the maximum amplitude the vibrator can play using the audio haptic channels.
104      *
105      * @return a positive value representing the maximum absolute value the device can play signals
106      * from audio haptic channels, or {@link Float#NaN NaN} if it's unknown.
107      */
getHapticChannelMaximumAmplitude()108     public float getHapticChannelMaximumAmplitude() {
109         if (mHapticChannelMaxVibrationAmplitude <= 0) {
110             return Float.NaN;
111         }
112         return mHapticChannelMaxVibrationAmplitude;
113     }
114 
115     /**
116      * The duration, in milliseconds, that should be applied to the ramp to turn off the vibrator
117      * when a vibration is cancelled or finished at non-zero amplitude.
118      */
getRampDownDurationMs()119     public int getRampDownDurationMs() {
120         if (mRampDownDurationMs < 0) {
121             return 0;
122         }
123         return mRampDownDurationMs;
124     }
125 
126     /**
127      * The duration, in milliseconds, that should be applied to convert vibration effect's
128      * {@link android.os.vibrator.RampSegment} to a {@link android.os.vibrator.StepSegment} on
129      * devices without PWLE support.
130      */
getRampStepDurationMs()131     public int getRampStepDurationMs() {
132         if (mRampStepDurationMs < 0) {
133             return 0;
134         }
135         return mRampStepDurationMs;
136     }
137 
138     /** Get the default vibration intensity for given usage. */
139     @VibrationIntensity
getDefaultVibrationIntensity(@ibrationAttributes.Usage int usage)140     public int getDefaultVibrationIntensity(@VibrationAttributes.Usage int usage) {
141         switch (usage) {
142             case USAGE_ALARM:
143                 return mDefaultAlarmVibrationIntensity;
144             case USAGE_NOTIFICATION:
145             case USAGE_COMMUNICATION_REQUEST:
146                 return mDefaultNotificationVibrationIntensity;
147             case USAGE_RINGTONE:
148                 return mDefaultRingVibrationIntensity;
149             case USAGE_TOUCH:
150             case USAGE_HARDWARE_FEEDBACK:
151             case USAGE_PHYSICAL_EMULATION:
152             case USAGE_ACCESSIBILITY:
153                 return mDefaultHapticFeedbackIntensity;
154             case USAGE_MEDIA:
155             case USAGE_UNKNOWN:
156                 // fall through
157             default:
158                 return mDefaultMediaVibrationIntensity;
159         }
160     }
161 
162     @Override
toString()163     public String toString() {
164         return "VibrationConfig{"
165                 + "mHapticChannelMaxVibrationAmplitude=" + mHapticChannelMaxVibrationAmplitude
166                 + ", mRampStepDurationMs=" + mRampStepDurationMs
167                 + ", mRampDownDurationMs=" + mRampDownDurationMs
168                 + ", mDefaultAlarmIntensity=" + mDefaultAlarmVibrationIntensity
169                 + ", mDefaultHapticFeedbackIntensity=" + mDefaultHapticFeedbackIntensity
170                 + ", mDefaultMediaIntensity=" + mDefaultMediaVibrationIntensity
171                 + ", mDefaultNotificationIntensity=" + mDefaultNotificationVibrationIntensity
172                 + ", mDefaultRingIntensity=" + mDefaultRingVibrationIntensity
173                 + "}";
174     }
175 }
176