1 /*
<lambda>null2  * Copyright 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 androidx.core.haptics
18 
19 import android.content.Context
20 import android.os.Vibrator
21 import androidx.annotation.RequiresPermission
22 import androidx.annotation.VisibleForTesting
23 import androidx.core.content.ContextCompat
24 import androidx.core.haptics.device.HapticDeviceProfile
25 import androidx.core.haptics.impl.HapticManagerImpl
26 import androidx.core.haptics.impl.VibratorWrapperImpl
27 import androidx.core.haptics.signal.HapticSignal
28 import androidx.core.haptics.signal.ResolvableSignal
29 
30 /**
31  * Manager for interactions with a device vibrator.
32  *
33  * <p>If your process exits, any vibration you started will stop.
34  */
35 public interface HapticManager {
36 
37     public companion object {
38 
39         /**
40          * Creates a haptic manager for the system vibrator.
41          *
42          * This returns a manager instance only if the device has a vibrator motor, i.e. the system
43          * vibrator check [Vibrator.hasVibrator] returns true, and returns null otherwise.
44          *
45          * @sample androidx.core.haptics.samples.PlaySystemStandardClick
46          * @param context Context to load the device vibrator.
47          * @return a new instance of HapticManager for the system vibrator, or null if the device
48          *   does not have a vibrator motor.
49          */
50         @JvmStatic
51         public fun create(context: Context): HapticManager? {
52             return requireNotNull(ContextCompat.getSystemService(context, Vibrator::class.java)) {
53                     "Vibrator service not found"
54                 }
55                 .let { systemVibrator ->
56                     if (systemVibrator.hasVibrator()) {
57                         HapticManagerImpl(VibratorWrapperImpl(systemVibrator))
58                     } else {
59                         null
60                     }
61                 }
62         }
63 
64         /** Creates a haptic manager for the given vibrator. */
65         @VisibleForTesting
66         internal fun createForVibrator(vibrator: VibratorWrapper): HapticManager? {
67             return if (vibrator.hasVibrator()) {
68                 HapticManagerImpl(vibrator)
69             } else {
70                 null
71             }
72         }
73     }
74 
75     /** A [HapticDeviceProfile] describing the vibrator hardware capabilities for the device. */
76     public val deviceProfile: HapticDeviceProfile
77 
78     /**
79      * Play a [HapticSignal].
80      *
81      * @sample androidx.core.haptics.samples.PlayHapticSignal
82      * @param signal The haptic signal to be played.
83      * @param attrs The attributes corresponding to the haptic signal. For example, specify
84      *   [HapticAttributes.USAGE_NOTIFICATION] for notification vibrations or
85      *   [HapticAttributes.USAGE_TOUCH] for touch feedback haptics.
86      */
87     @RequiresPermission(android.Manifest.permission.VIBRATE)
88     public fun play(signal: HapticSignal, attrs: HapticAttributes)
89 
90     /**
91      * Resolves and plays a given [ResolvableSignal].
92      *
93      * If the same signal will be played by this vibrator multiple times then consider resolving the
94      * [HapticSignal] only once using this [deviceProfile] and then reusing it.
95      *
96      * @sample androidx.core.haptics.samples.PlayResolvableHapticSignal
97      * @param signal The haptic signal to be resolved using this device profile and played.
98      * @param attrs The attributes corresponding to the haptic signal. For example, specify
99      *   [HapticAttributes.USAGE_NOTIFICATION] for notification vibrations or
100      *   [HapticAttributes.USAGE_TOUCH] for touch feedback haptics.
101      */
102     @RequiresPermission(android.Manifest.permission.VIBRATE)
103     public fun play(signal: ResolvableSignal, attrs: HapticAttributes) {
104         signal.resolve(deviceProfile)?.let { resolvedSignal -> play(resolvedSignal, attrs) }
105     }
106 
107     /**
108      * Cancel any [HapticSignal] currently playing.
109      *
110      * @sample androidx.core.haptics.samples.PlayThenCancel
111      */
112     @RequiresPermission(android.Manifest.permission.VIBRATE) public fun cancel()
113 }
114