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 android.content.Context;
     20 import android.media.AudioAttributes;
     21 import android.media.AudioManager;
     22 import android.media.ToneGenerator;
     23 import android.os.SystemVibrator;
     24 import android.os.Vibrator;
     25 import android.provider.Settings;
     26 
     27 /**
     28  * Plays an emergency tone when placing emergency calls on CDMA devices.
     29  */
     30 class 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