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