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