1 /*
2  * Copyright (C) 2012 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.inputmethod.latin;
18 
19 import android.content.Context;
20 import android.media.AudioManager;
21 import android.os.Vibrator;
22 import android.view.HapticFeedbackConstants;
23 import android.view.View;
24 
25 import com.android.inputmethod.latin.settings.SettingsValues;
26 
27 /**
28  * This class gathers audio feedback and haptic feedback functions.
29  *
30  * It offers a consistent and simple interface that allows LatinIME to forget about the
31  * complexity of settings and the like.
32  */
33 public final class AudioAndHapticFeedbackManager {
34     private AudioManager mAudioManager;
35     private Vibrator mVibrator;
36 
37     private SettingsValues mSettingsValues;
38     private boolean mSoundOn;
39 
40     private static final AudioAndHapticFeedbackManager sInstance =
41             new AudioAndHapticFeedbackManager();
42 
getInstance()43     public static AudioAndHapticFeedbackManager getInstance() {
44         return sInstance;
45     }
46 
AudioAndHapticFeedbackManager()47     private AudioAndHapticFeedbackManager() {
48         // Intentional empty constructor for singleton.
49     }
50 
init(final Context context)51     public static void init(final Context context) {
52         sInstance.initInternal(context);
53     }
54 
initInternal(final Context context)55     private void initInternal(final Context context) {
56         mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
57         mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
58     }
59 
performHapticAndAudioFeedback(final int code, final View viewToPerformHapticFeedbackOn)60     public void performHapticAndAudioFeedback(final int code,
61             final View viewToPerformHapticFeedbackOn) {
62         performHapticFeedback(viewToPerformHapticFeedbackOn);
63         performAudioFeedback(code);
64     }
65 
hasVibrator()66     public boolean hasVibrator() {
67         return mVibrator != null && mVibrator.hasVibrator();
68     }
69 
vibrate(final long milliseconds)70     public void vibrate(final long milliseconds) {
71         if (mVibrator == null) {
72             return;
73         }
74         mVibrator.vibrate(milliseconds);
75     }
76 
reevaluateIfSoundIsOn()77     private boolean reevaluateIfSoundIsOn() {
78         if (mSettingsValues == null || !mSettingsValues.mSoundOn || mAudioManager == null) {
79             return false;
80         }
81         return mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_NORMAL;
82     }
83 
performAudioFeedback(final int code)84     public void performAudioFeedback(final int code) {
85         // if mAudioManager is null, we can't play a sound anyway, so return
86         if (mAudioManager == null) {
87             return;
88         }
89         if (!mSoundOn) {
90             return;
91         }
92         final int sound;
93         switch (code) {
94         case Constants.CODE_DELETE:
95             sound = AudioManager.FX_KEYPRESS_DELETE;
96             break;
97         case Constants.CODE_ENTER:
98             sound = AudioManager.FX_KEYPRESS_RETURN;
99             break;
100         case Constants.CODE_SPACE:
101             sound = AudioManager.FX_KEYPRESS_SPACEBAR;
102             break;
103         default:
104             sound = AudioManager.FX_KEYPRESS_STANDARD;
105             break;
106         }
107         mAudioManager.playSoundEffect(sound, mSettingsValues.mKeypressSoundVolume);
108     }
109 
performHapticFeedback(final View viewToPerformHapticFeedbackOn)110     public void performHapticFeedback(final View viewToPerformHapticFeedbackOn) {
111         if (!mSettingsValues.mVibrateOn) {
112             return;
113         }
114         if (mSettingsValues.mKeypressVibrationDuration >= 0) {
115             vibrate(mSettingsValues.mKeypressVibrationDuration);
116             return;
117         }
118         // Go ahead with the system default
119         if (viewToPerformHapticFeedbackOn != null) {
120             viewToPerformHapticFeedbackOn.performHapticFeedback(
121                     HapticFeedbackConstants.KEYBOARD_TAP,
122                     HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
123         }
124     }
125 
onSettingsChanged(final SettingsValues settingsValues)126     public void onSettingsChanged(final SettingsValues settingsValues) {
127         mSettingsValues = settingsValues;
128         mSoundOn = reevaluateIfSoundIsOn();
129     }
130 
onRingerModeChanged()131     public void onRingerModeChanged() {
132         mSoundOn = reevaluateIfSoundIsOn();
133     }
134 }
135