Home | History | Annotate | Download | only in telephony
      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