AudioAndHapticFeedbackManager.java revision a7d2fc6befa1b16883200a653fc01deb4d94944d
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
17package com.android.inputmethod.latin;
18
19import com.android.inputmethod.latin.settings.SettingsValues;
20
21import android.content.Context;
22import android.media.AudioManager;
23import android.os.Vibrator;
24import android.view.HapticFeedbackConstants;
25import android.view.View;
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 */
33public 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
43    public static AudioAndHapticFeedbackManager getInstance() {
44        return sInstance;
45    }
46
47    private AudioAndHapticFeedbackManager() {
48        // Intentional empty constructor for singleton.
49    }
50
51    public static void init(final Context context) {
52        sInstance.initInternal(context);
53    }
54
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
60    public void hapticAndAudioFeedback(final int primaryCode,
61            final View viewToPerformHapticFeedbackOn) {
62        vibrateInternal(viewToPerformHapticFeedbackOn);
63        playKeyClick(primaryCode);
64    }
65
66    public boolean hasVibrator() {
67        return mVibrator != null && mVibrator.hasVibrator();
68    }
69
70    public void vibrate(final long milliseconds) {
71        if (mVibrator == null) {
72            return;
73        }
74        mVibrator.vibrate(milliseconds);
75    }
76
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
84    private void playKeyClick(final int primaryCode) {
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            final int sound;
91            switch (primaryCode) {
92            case Constants.CODE_DELETE:
93                sound = AudioManager.FX_KEYPRESS_DELETE;
94                break;
95            case Constants.CODE_ENTER:
96                sound = AudioManager.FX_KEYPRESS_RETURN;
97                break;
98            case Constants.CODE_SPACE:
99                sound = AudioManager.FX_KEYPRESS_SPACEBAR;
100                break;
101            default:
102                sound = AudioManager.FX_KEYPRESS_STANDARD;
103                break;
104            }
105            mAudioManager.playSoundEffect(sound, mSettingsValues.mKeypressSoundVolume);
106        }
107    }
108
109    private void vibrateInternal(final View viewToPerformHapticFeedbackOn) {
110        if (!mSettingsValues.mVibrateOn) {
111            return;
112        }
113        if (mSettingsValues.mKeypressVibrationDuration < 0) {
114            // Go ahead with the system default
115            if (viewToPerformHapticFeedbackOn != null) {
116                viewToPerformHapticFeedbackOn.performHapticFeedback(
117                        HapticFeedbackConstants.KEYBOARD_TAP,
118                        HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
119            }
120            return;
121        }
122        vibrate(mSettingsValues.mKeypressVibrationDuration);
123    }
124
125    public void onSettingsChanged(final SettingsValues settingsValues) {
126        mSettingsValues = settingsValues;
127        mSoundOn = reevaluateIfSoundIsOn();
128    }
129
130    public void onRingerModeChanged() {
131        mSoundOn = reevaluateIfSoundIsOn();
132    }
133}
134