• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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;
18 
19 import android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.annotation.TestApi;
23 import android.media.AudioAttributes;
24 
25 import java.lang.annotation.Retention;
26 import java.lang.annotation.RetentionPolicy;
27 import java.util.Objects;
28 
29 /**
30  * Encapsulates a collection of attributes describing information about a vibration.
31  */
32 public final class VibrationAttributes implements Parcelable {
33     private static final String TAG = "VibrationAttributes";
34 
35     /** @hide */
36     @IntDef(prefix = { "USAGE_CLASS_" }, value = {
37             USAGE_CLASS_UNKNOWN,
38             USAGE_CLASS_ALARM,
39             USAGE_CLASS_FEEDBACK,
40             USAGE_CLASS_MEDIA,
41     })
42     @Retention(RetentionPolicy.SOURCE)
43     public @interface UsageClass {}
44 
45     /** @hide */
46     @IntDef(prefix = { "USAGE_" }, value = {
47             USAGE_UNKNOWN,
48             USAGE_ACCESSIBILITY,
49             USAGE_ALARM,
50             USAGE_COMMUNICATION_REQUEST,
51             USAGE_HARDWARE_FEEDBACK,
52             USAGE_MEDIA,
53             USAGE_NOTIFICATION,
54             USAGE_PHYSICAL_EMULATION,
55             USAGE_RINGTONE,
56             USAGE_TOUCH,
57     })
58     @Retention(RetentionPolicy.SOURCE)
59     public @interface Usage {}
60 
61     /**
62      * Vibration usage filter value to match all usages.
63      * @hide
64      */
65     public static final int USAGE_FILTER_MATCH_ALL = -1;
66     /**
67      * Vibration usage class value to use when the vibration usage class is unknown.
68      */
69     public static final int USAGE_CLASS_UNKNOWN = 0x0;
70     /**
71      * Vibration usage class value to use when the vibration is initiated to catch user's
72      * attention, such as alarm, ringtone, and notification vibrations.
73      */
74     public static final int USAGE_CLASS_ALARM = 0x1;
75     /**
76      * Vibration usage class value to use when the vibration is initiated as a response to user's
77      * actions, such as emulation of physical effects, and texting feedback vibration.
78      */
79     public static final int USAGE_CLASS_FEEDBACK = 0x2;
80     /**
81      * Vibration usage class value to use when the vibration is part of media, such as music, movie,
82      * soundtrack, game or animations.
83      */
84     public static final int USAGE_CLASS_MEDIA = 0x3;
85 
86     /**
87      * Mask for vibration usage class value.
88      */
89     public static final int USAGE_CLASS_MASK = 0xF;
90 
91     /**
92      * Usage value to use when usage is unknown.
93      */
94     public static final int USAGE_UNKNOWN = 0x0 | USAGE_CLASS_UNKNOWN;
95     /**
96      * Usage value to use for alarm vibrations.
97      */
98     public static final int USAGE_ALARM = 0x10 | USAGE_CLASS_ALARM;
99     /**
100      * Usage value to use for ringtone vibrations.
101      */
102     public static final int USAGE_RINGTONE = 0x20 | USAGE_CLASS_ALARM;
103     /**
104      * Usage value to use for notification vibrations.
105      */
106     public static final int USAGE_NOTIFICATION = 0x30 | USAGE_CLASS_ALARM;
107     /**
108      * Usage value to use for vibrations which mean a request to enter/end a
109      * communication with the user, such as a voice prompt.
110      */
111     public static final int USAGE_COMMUNICATION_REQUEST = 0x40 | USAGE_CLASS_ALARM;
112     /**
113      * Usage value to use for touch vibrations.
114      *
115      * <p>Most typical haptic feedback should be classed as <em>touch</em> feedback. Examples
116      * include vibrations for tap, long press, drag and scroll.
117      */
118     public static final int USAGE_TOUCH = 0x10 | USAGE_CLASS_FEEDBACK;
119     /**
120      * Usage value to use for vibrations which emulate physical hardware reactions,
121      * such as edge squeeze.
122      *
123      * <p>Note that normal screen-touch feedback "click" effects would typically be
124      * classed as {@link #USAGE_TOUCH}, and that on-screen "physical" animations
125      * like bouncing would be {@link #USAGE_MEDIA}.
126      */
127     public static final int USAGE_PHYSICAL_EMULATION = 0x20 | USAGE_CLASS_FEEDBACK;
128     /**
129      * Usage value to use for vibrations which provide a feedback for hardware
130      * component interaction, such as a fingerprint sensor.
131      */
132     public static final int USAGE_HARDWARE_FEEDBACK = 0x30 | USAGE_CLASS_FEEDBACK;
133     /**
134      * Usage value to use for accessibility vibrations, such as with a screen reader.
135      */
136     public static final int USAGE_ACCESSIBILITY = 0x40 | USAGE_CLASS_FEEDBACK;
137     /**
138      * Usage value to use for media vibrations, such as music, movie, soundtrack, animations, games,
139      * or any interactive media that isn't for touch feedback specifically.
140      */
141     public static final int USAGE_MEDIA = 0x10 | USAGE_CLASS_MEDIA;
142 
143     /**
144      * @hide
145      */
146     @IntDef(prefix = { "FLAG_" }, flag = true, value = {
147             FLAG_BYPASS_INTERRUPTION_POLICY,
148             FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF
149     })
150     @Retention(RetentionPolicy.SOURCE)
151     public @interface Flag{}
152 
153     /**
154      * Flag requesting vibration effect to be played even under limited interruptions.
155      */
156     public static final int FLAG_BYPASS_INTERRUPTION_POLICY = 0x1;
157 
158     /**
159      * Flag requesting vibration effect to be played even when user settings are disabling it.
160      *
161      * <p>Flag introduced to represent
162      * {@link android.view.HapticFeedbackConstants#FLAG_IGNORE_GLOBAL_SETTING} and
163      * {@link AudioAttributes#FLAG_BYPASS_MUTE}.
164      *
165      * @hide
166      */
167     public static final int FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF = 0x2;
168 
169     /**
170      * Flag requesting vibration effect to be played with fresh user settings values.
171      *
172      * <p>This flag is not protected by any permission, but vibrations that use it require an extra
173      * query of user vibration intensity settings, ringer mode and other controls that affect the
174      * vibration effect playback, which can increase the latency for the overall request.
175      *
176      * <p>This is intended to be used on scenarios where the user settings might have changed
177      * recently, and needs to be applied to this vibration, like settings controllers that preview
178      * newly set intensities to the user.
179      *
180      * @hide
181      */
182     public static final int FLAG_INVALIDATE_SETTINGS_CACHE = 0x3;
183 
184     /**
185      * All flags supported by vibrator service, update it when adding new flag.
186      * @hide
187      */
188     public static final int FLAG_ALL_SUPPORTED =
189             FLAG_BYPASS_INTERRUPTION_POLICY | FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF
190                     | FLAG_INVALIDATE_SETTINGS_CACHE;
191 
192     /** Creates a new {@link VibrationAttributes} instance with given usage. */
createForUsage(@sage int usage)193     public static @NonNull VibrationAttributes createForUsage(@Usage int usage) {
194         return new VibrationAttributes.Builder().setUsage(usage).build();
195     }
196 
197     private final int mUsage;
198     private final int mFlags;
199     private final int mOriginalAudioUsage;
200 
VibrationAttributes(@sage int usage, @AudioAttributes.AttributeUsage int audioUsage, @Flag int flags)201     private VibrationAttributes(@Usage int usage, @AudioAttributes.AttributeUsage int audioUsage,
202             @Flag int flags) {
203         mUsage = usage;
204         mOriginalAudioUsage = audioUsage;
205         mFlags = flags & FLAG_ALL_SUPPORTED;
206     }
207 
208     /**
209      * Return the vibration usage class.
210      */
211     @UsageClass
getUsageClass()212     public int getUsageClass() {
213         return mUsage & USAGE_CLASS_MASK;
214     }
215 
216     /**
217      * Return the vibration usage.
218      */
219     @Usage
getUsage()220     public int getUsage() {
221         return mUsage;
222     }
223 
224     /**
225      * Return the flags.
226      * @return a combined mask of all flags
227      */
228     @Flag
getFlags()229     public int getFlags() {
230         return mFlags;
231     }
232 
233     /**
234      * Check whether a flag is set
235      * @return true if a flag is set and false otherwise
236      */
isFlagSet(@lag int flag)237     public boolean isFlagSet(@Flag int flag) {
238         return (mFlags & flag) > 0;
239     }
240 
241     /**
242      * Return {@link AudioAttributes} usage equivalent to {@link #getUsage()}.
243      * @return one of {@link AudioAttributes#SDK_USAGES} that represents {@link #getUsage()}
244      * @hide
245      */
246     @TestApi
247     @AudioAttributes.AttributeUsage
getAudioUsage()248     public int getAudioUsage() {
249         if (mOriginalAudioUsage != AudioAttributes.USAGE_UNKNOWN) {
250             // Return same audio usage set in the Builder.
251             return mOriginalAudioUsage;
252         }
253         // Return correct audio usage based on the vibration usage set in the Builder.
254         switch (mUsage) {
255             case USAGE_NOTIFICATION:
256                 return AudioAttributes.USAGE_NOTIFICATION;
257             case USAGE_COMMUNICATION_REQUEST:
258                 return AudioAttributes.USAGE_VOICE_COMMUNICATION;
259             case USAGE_RINGTONE:
260                 return AudioAttributes.USAGE_NOTIFICATION_RINGTONE;
261             case USAGE_TOUCH:
262                 return AudioAttributes.USAGE_ASSISTANCE_SONIFICATION;
263             case USAGE_ALARM:
264                 return AudioAttributes.USAGE_ALARM;
265             case USAGE_ACCESSIBILITY:
266                 return AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY;
267             case USAGE_MEDIA:
268                 return AudioAttributes.USAGE_MEDIA;
269             default:
270                 return AudioAttributes.USAGE_UNKNOWN;
271         }
272     }
273 
274     @Override
describeContents()275     public int describeContents() {
276         return 0;
277     }
278 
279     @Override
writeToParcel(@onNull Parcel dest, int flags)280     public void writeToParcel(@NonNull Parcel dest, int flags) {
281         dest.writeInt(mUsage);
282         dest.writeInt(mOriginalAudioUsage);
283         dest.writeInt(mFlags);
284     }
285 
VibrationAttributes(Parcel src)286     private VibrationAttributes(Parcel src) {
287         mUsage = src.readInt();
288         mOriginalAudioUsage = src.readInt();
289         mFlags = src.readInt();
290     }
291 
292     public static final @NonNull Parcelable.Creator<VibrationAttributes>
293             CREATOR = new Parcelable.Creator<VibrationAttributes>() {
294                 public VibrationAttributes createFromParcel(Parcel p) {
295                     return new VibrationAttributes(p);
296                 }
297                 public VibrationAttributes[] newArray(int size) {
298                     return new VibrationAttributes[size];
299                 }
300             };
301 
302     @Override
equals(@ullable Object o)303     public boolean equals(@Nullable Object o) {
304         if (this == o) {
305             return true;
306         }
307         if (o == null || getClass() != o.getClass()) {
308             return false;
309         }
310         VibrationAttributes rhs = (VibrationAttributes) o;
311         return mUsage == rhs.mUsage && mOriginalAudioUsage == rhs.mOriginalAudioUsage
312                 && mFlags == rhs.mFlags;
313     }
314 
315     @Override
hashCode()316     public int hashCode() {
317         return Objects.hash(mUsage, mOriginalAudioUsage, mFlags);
318     }
319 
320     @Override
toString()321     public String toString() {
322         return "VibrationAttributes:"
323                 + " Usage=" + usageToString()
324                 + " Audio Usage= " + AudioAttributes.usageToString(mOriginalAudioUsage)
325                 + " Flags=" + mFlags;
326     }
327 
328     /** @hide */
usageToString()329     public String usageToString() {
330         return usageToString(mUsage);
331     }
332 
333     /** @hide */
usageToString(@sage int usage)334     public static String usageToString(@Usage int usage) {
335         switch (usage) {
336             case USAGE_UNKNOWN:
337                 return "UNKNOWN";
338             case USAGE_ALARM:
339                 return "ALARM";
340             case USAGE_ACCESSIBILITY:
341                 return "ACCESSIBILITY";
342             case USAGE_RINGTONE:
343                 return "RINGTONE";
344             case USAGE_NOTIFICATION:
345                 return "NOTIFICATION";
346             case USAGE_COMMUNICATION_REQUEST:
347                 return "COMMUNICATION_REQUEST";
348             case USAGE_MEDIA:
349                 return "MEDIA";
350             case USAGE_TOUCH:
351                 return "TOUCH";
352             case USAGE_PHYSICAL_EMULATION:
353                 return "PHYSICAL_EMULATION";
354             case USAGE_HARDWARE_FEEDBACK:
355                 return "HARDWARE_FEEDBACK";
356             default:
357                 return "unknown usage " + usage;
358         }
359     }
360 
361     /**
362      * Builder class for {@link VibrationAttributes} objects.
363      * By default, all information is set to UNKNOWN.
364      */
365     public static final class Builder {
366         private int mUsage = USAGE_UNKNOWN;
367         private int mOriginalAudioUsage = AudioAttributes.USAGE_UNKNOWN;
368         private int mFlags = 0x0;
369 
370         /**
371          * Constructs a new Builder with the defaults.
372          */
Builder()373         public Builder() {
374         }
375 
376         /**
377          * Constructs a new Builder from a given VibrationAttributes.
378          */
Builder(@ullable VibrationAttributes vib)379         public Builder(@Nullable VibrationAttributes vib) {
380             if (vib != null) {
381                 mUsage = vib.mUsage;
382                 mOriginalAudioUsage = vib.mOriginalAudioUsage;
383                 mFlags = vib.mFlags;
384             }
385         }
386 
387         /**
388          * Constructs a new Builder from AudioAttributes.
389          */
Builder(@onNull AudioAttributes audio)390         public Builder(@NonNull AudioAttributes audio) {
391             setUsage(audio);
392             setFlags(audio);
393         }
394 
setUsage(@onNull AudioAttributes audio)395         private void setUsage(@NonNull AudioAttributes audio) {
396             mOriginalAudioUsage = audio.getUsage();
397             switch (audio.getUsage()) {
398                 case AudioAttributes.USAGE_NOTIFICATION:
399                 case AudioAttributes.USAGE_NOTIFICATION_EVENT:
400                 case AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
401                 case AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
402                 case AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
403                     mUsage = USAGE_NOTIFICATION;
404                     break;
405                 case AudioAttributes.USAGE_VOICE_COMMUNICATION:
406                 case AudioAttributes.USAGE_VOICE_COMMUNICATION_SIGNALLING:
407                 case AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
408                 case AudioAttributes.USAGE_ASSISTANT:
409                     mUsage = USAGE_COMMUNICATION_REQUEST;
410                     break;
411                 case AudioAttributes.USAGE_NOTIFICATION_RINGTONE:
412                     mUsage = USAGE_RINGTONE;
413                     break;
414                 case AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY:
415                     mUsage = USAGE_ACCESSIBILITY;
416                     break;
417                 case AudioAttributes.USAGE_ASSISTANCE_SONIFICATION:
418                     mUsage = USAGE_TOUCH;
419                     break;
420                 case AudioAttributes.USAGE_ALARM:
421                     mUsage = USAGE_ALARM;
422                     break;
423                 case AudioAttributes.USAGE_MEDIA:
424                 case AudioAttributes.USAGE_GAME:
425                     mUsage = USAGE_MEDIA;
426                     break;
427                 default:
428                     mUsage = USAGE_UNKNOWN;
429             }
430         }
431 
setFlags(@onNull AudioAttributes audio)432         private void setFlags(@NonNull AudioAttributes audio) {
433             if ((audio.getAllFlags() & AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY) != 0) {
434                 mFlags |= FLAG_BYPASS_INTERRUPTION_POLICY;
435             }
436             if ((audio.getAllFlags() & AudioAttributes.FLAG_BYPASS_MUTE) != 0) {
437                 // Muted audio stream translates to vibration usage having the value
438                 // Vibrator.VIBRATION_INTENSITY_OFF set in the user setting.
439                 mFlags |= FLAG_BYPASS_USER_VIBRATION_INTENSITY_OFF;
440             }
441         }
442 
443         /**
444          * Combines all of the attributes that have been set and returns a new
445          * {@link VibrationAttributes} object.
446          * @return a new {@link VibrationAttributes} object
447          */
build()448         public @NonNull VibrationAttributes build() {
449             VibrationAttributes ans = new VibrationAttributes(mUsage, mOriginalAudioUsage, mFlags);
450             return ans;
451         }
452 
453         /**
454          * Sets the attribute describing the type of the corresponding vibration.
455          * @param usage The type of usage for the vibration
456          * @return the same Builder instance.
457          */
setUsage(@sage int usage)458         public @NonNull Builder setUsage(@Usage int usage) {
459             mOriginalAudioUsage = AudioAttributes.USAGE_UNKNOWN;
460             mUsage = usage;
461             return this;
462         }
463 
464         /**
465          * Sets only the flags specified in the bitmask, leaving the other supported flag values
466          * unchanged in the builder.
467          *
468          * @param flags Combination of flags to be set.
469          * @param mask Bit range that should be changed.
470          * @return the same Builder instance.
471          */
setFlags(@lag int flags, int mask)472         public @NonNull Builder setFlags(@Flag int flags, int mask) {
473             mask &= FLAG_ALL_SUPPORTED;
474             mFlags = (mFlags & ~mask) | (flags & mask);
475             return this;
476         }
477 
478         /**
479          * Set all supported flags with given combination of flags, overriding any previous values
480          * set to this builder.
481          *
482          * @param flags combination of flags to be set.
483          * @return the same Builder instance.
484          *
485          * @hide
486          */
setFlags(@lag int flags)487         public @NonNull Builder setFlags(@Flag int flags) {
488             return setFlags(flags, FLAG_ALL_SUPPORTED);
489         }
490     }
491 }
492