/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.services.telephony;

import static android.media.AudioManager.RINGER_MODE_NORMAL;
import static android.media.AudioManager.RINGER_MODE_SILENT;

import android.content.Context;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.ToneGenerator;
import android.os.SystemVibrator;
import android.os.Vibrator;
import android.provider.Settings;

/**
 * Plays an emergency tone when placing emergency calls on CDMA devices.
 */
class EmergencyTonePlayer {

    private static final int EMERGENCY_TONE_OFF = 0;
    private static final int EMERGENCY_TONE_ALERT = 1;
    private static final int EMERGENCY_TONE_VIBRATE = 2;

    private static final int ALERT_RELATIVE_VOLUME_PERCENT = 100;

    private static final int VIBRATE_LENGTH_MILLIS = 1000;
    private static final int VIBRATE_PAUSE_MILLIS = 1000;
    private static final long[] VIBRATE_PATTERN =
            new long[] { VIBRATE_LENGTH_MILLIS, VIBRATE_PAUSE_MILLIS};

    private static final AudioAttributes VIBRATION_ATTRIBUTES =
            new AudioAttributes.Builder()
                .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
                .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION)
                .build();

    // We don't rely on getSystemService(Context.VIBRATOR_SERVICE) to make sure that this vibrator
    // object will be isolated from others.
    private final Vibrator mVibrator = new SystemVibrator();
    private final Context mContext;
    private final AudioManager mAudioManager;

    private ToneGenerator mToneGenerator;
    private int mSavedInCallVolume;
    private boolean mIsVibrating = false;

    EmergencyTonePlayer(Context context) {
        mContext = context;
        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
    }

    public void start() {
        switch (getToneSetting()) {
            case EMERGENCY_TONE_VIBRATE:
                startVibrate();
                break;
            case EMERGENCY_TONE_ALERT:
                startAlert();
                break;
            case EMERGENCY_TONE_OFF:
                // nothing;
                break;
        }
    }

    public void stop() {
        stopVibrate();
        stopAlert();
    }

    private void startVibrate() {
        int ringerMode = mAudioManager.getRingerMode();
        if (ringerMode == RINGER_MODE_SILENT) {
            Log.i(this, "startVibrate: skipping vibrate tone due to ringer mode %d", ringerMode);
            return;
        }

        if (!mIsVibrating) {
            mVibrator.vibrate(VIBRATE_PATTERN, 0, VIBRATION_ATTRIBUTES);
            mIsVibrating = true;
        }
    }

    private void stopVibrate() {
        if (mIsVibrating) {
            mVibrator.cancel();
            mIsVibrating = false;
        }
    }

    private void startAlert() {
        int ringerMode = mAudioManager.getRingerMode();
        if (ringerMode != RINGER_MODE_NORMAL) {
            Log.i(this, "startAlert: skipping emergency tone due to ringer mode %d", ringerMode);
            return;
        }

        if (mToneGenerator == null) {
            mToneGenerator = new ToneGenerator(
                    AudioManager.STREAM_VOICE_CALL, ALERT_RELATIVE_VOLUME_PERCENT);

            // Set the volume to max and save the old volume setting.
            mSavedInCallVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL);
            mAudioManager.setStreamVolume(
                    AudioManager.STREAM_VOICE_CALL,
                    mAudioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL),
                    0);
            mToneGenerator.startTone(ToneGenerator.TONE_CDMA_EMERGENCY_RINGBACK);
        }
    }

    private void stopAlert() {
        if (mToneGenerator != null) {
            mToneGenerator.stopTone();
            mToneGenerator.release();
            mToneGenerator = null;

            mAudioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL, mSavedInCallVolume, 0);
            mSavedInCallVolume = 0;
        }
    }

    private int getToneSetting() {
       return Settings.Global.getInt(
               mContext.getContentResolver(), Settings.Global.EMERGENCY_TONE, EMERGENCY_TONE_OFF);
    }
}
