package org.thoughtcrime.securesms.webrtc.audio; import android.annotation.TargetApi; import android.content.Context; import android.media.AudioManager; import android.media.MediaPlayer; import android.media.RingtoneManager; import android.net.Uri; import android.os.Build; import android.os.Vibrator; import android.provider.Settings; import android.util.Log; import org.thoughtcrime.securesms.util.ServiceUtil; import java.io.IOException; public class IncomingRinger { private static final String TAG = IncomingRinger.class.getSimpleName(); private static final long[] VIBRATE_PATTERN = {0, 1000, 1000}; private final Context context; private final Vibrator vibrator; private MediaPlayer player; public IncomingRinger(Context context) { this.context = context.getApplicationContext(); this.vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); } public void start(boolean speakerphone) { AudioManager audioManager = ServiceUtil.getAudioManager(context); if (player != null) player.release(); player = createPlayer(); int ringerMode = audioManager.getRingerMode(); if (shouldVibrate(context, player, ringerMode)) { Log.i(TAG, "Starting vibration"); vibrator.vibrate(VIBRATE_PATTERN, 1); } if (player != null && ringerMode == AudioManager.RINGER_MODE_NORMAL) { try { if (!player.isPlaying()) { player.prepare(); player.start(); Log.w(TAG, "Playing ringtone now..."); } else { Log.w(TAG, "Ringtone is already playing, declining to restart."); } } catch (IllegalStateException | IOException e) { Log.w(TAG, e); player = null; } } else { Log.w(TAG, "Not ringing, mode: " + ringerMode); } if (speakerphone) { audioManager.setSpeakerphoneOn(true); } } public void stop() { if (player != null) { Log.w(TAG, "Stopping ringer"); player.release(); player = null; } Log.w(TAG, "Cancelling vibrator"); vibrator.cancel(); } private boolean shouldVibrate(Context context, MediaPlayer player, int ringerMode) { if (player == null) { return true; } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { return shouldVibrateNew(context, ringerMode); } else { return shouldVibrateOld(context); } } @TargetApi(Build.VERSION_CODES.HONEYCOMB) private boolean shouldVibrateNew(Context context, int ringerMode) { Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); if (vibrator == null || !vibrator.hasVibrator()) { return false; } boolean vibrateWhenRinging = Settings.System.getInt(context.getContentResolver(), "vibrate_when_ringing", 0) != 0; if (vibrateWhenRinging) { return ringerMode != AudioManager.RINGER_MODE_SILENT; } else { return ringerMode == AudioManager.RINGER_MODE_VIBRATE; } } private boolean shouldVibrateOld(Context context) { AudioManager audioManager = ServiceUtil.getAudioManager(context); return audioManager.shouldVibrate(AudioManager.VIBRATE_TYPE_RINGER); } private MediaPlayer createPlayer() { try { MediaPlayer mediaPlayer = new MediaPlayer(); Uri ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE); mediaPlayer.setOnErrorListener(new MediaPlayerErrorListener()); mediaPlayer.setDataSource(context, ringtoneUri); mediaPlayer.setLooping(true); mediaPlayer.setAudioStreamType(AudioManager.STREAM_VOICE_CALL); return mediaPlayer; } catch (IOException e) { Log.e(TAG, "Failed to create player for incoming call ringer"); return null; } } private class MediaPlayerErrorListener implements MediaPlayer.OnErrorListener { @Override public boolean onError(MediaPlayer mp, int what, int extra) { Log.w(TAG, "onError(" + mp + ", " + what + ", " + extra); player = null; return false; } } }