1/*
2 * Copyright (C) 2014 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.services.telephony;
18
19import android.content.Context;
20import android.media.AudioAttributes;
21import android.media.AudioManager;
22import android.media.ToneGenerator;
23import android.os.SystemVibrator;
24import android.os.Vibrator;
25import android.provider.Settings;
26
27/**
28 * Plays an emergency tone when placing emergency calls on CDMA devices.
29 */
30class EmergencyTonePlayer {
31
32    private static final int EMERGENCY_TONE_OFF = 0;
33    private static final int EMERGENCY_TONE_ALERT = 1;
34    private static final int EMERGENCY_TONE_VIBRATE = 2;
35
36    private static final int ALERT_RELATIVE_VOLUME_PERCENT = 100;
37
38    private static final int VIBRATE_LENGTH_MILLIS = 1000;
39    private static final int VIBRATE_PAUSE_MILLIS = 1000;
40    private static final long[] VIBRATE_PATTERN =
41            new long[] { VIBRATE_LENGTH_MILLIS, VIBRATE_PAUSE_MILLIS};
42
43    private static final AudioAttributes VIBRATION_ATTRIBUTES =
44            new AudioAttributes.Builder()
45                .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
46                .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
47                .build();
48
49    // We don't rely on getSystemService(Context.VIBRATOR_SERVICE) to make sure that this vibrator
50    // object will be isolated from others.
51    private final Vibrator mVibrator = new SystemVibrator();
52    private final Context mContext;
53    private final AudioManager mAudioManager;
54
55    private ToneGenerator mToneGenerator;
56    private int mSavedInCallVolume;
57    private boolean mIsVibrating = false;
58
59    EmergencyTonePlayer(Context context) {
60        mContext = context;
61        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
62    }
63
64    public void start() {
65        switch (getToneSetting()) {
66            case EMERGENCY_TONE_VIBRATE:
67                startVibrate();
68                break;
69            case EMERGENCY_TONE_ALERT:
70                // Only start if we are not in silent mode.
71                int ringerMode = mAudioManager.getRingerMode();
72                if (ringerMode == AudioManager.RINGER_MODE_NORMAL) {
73                    startAlert();
74                }
75                break;
76            case EMERGENCY_TONE_OFF:
77                // nothing;
78                break;
79        }
80    }
81
82    public void stop() {
83        stopVibrate();
84        stopAlert();
85    }
86
87    private void startVibrate() {
88        if (!mIsVibrating) {
89            mVibrator.vibrate(VIBRATE_PATTERN, 0, VIBRATION_ATTRIBUTES);
90            mIsVibrating = true;
91        }
92    }
93
94    private void stopVibrate() {
95        if (mIsVibrating) {
96            mVibrator.cancel();
97            mIsVibrating = false;
98        }
99    }
100
101    private void startAlert() {
102        if (mToneGenerator == null) {
103            mToneGenerator = new ToneGenerator(
104                    AudioManager.STREAM_VOICE_CALL, ALERT_RELATIVE_VOLUME_PERCENT);
105
106            // Set the volume to max and save the old volume setting.
107            mSavedInCallVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL);
108            mAudioManager.setStreamVolume(
109                    AudioManager.STREAM_VOICE_CALL,
110                    mAudioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL),
111                    0);
112            mToneGenerator.startTone(ToneGenerator.TONE_CDMA_EMERGENCY_RINGBACK);
113        } else {
114            Log.d(this, "An alert is already running.");
115        }
116    }
117
118    private void stopAlert() {
119        if (mToneGenerator != null) {
120            mToneGenerator.stopTone();
121            mToneGenerator.release();
122            mToneGenerator = null;
123
124            mAudioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL, mSavedInCallVolume, 0);
125            mSavedInCallVolume = 0;
126        }
127    }
128
129    private int getToneSetting() {
130       return Settings.Global.getInt(
131               mContext.getContentResolver(), Settings.Global.EMERGENCY_TONE, EMERGENCY_TONE_OFF);
132    }
133}
134