summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--res/values/strings.xml5
-rw-r--r--res/xml/preferences.xml5
-rw-r--r--src/com/android/cellbroadcastreceiver/CellBroadcastAlertAudio.java137
-rw-r--r--src/com/android/cellbroadcastreceiver/CellBroadcastAlertFullScreen.java20
-rw-r--r--src/com/android/cellbroadcastreceiver/CellBroadcastAlertService.java18
-rw-r--r--src/com/android/cellbroadcastreceiver/CellBroadcastSettings.java3
6 files changed, 141 insertions, 47 deletions
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 1c985049..e3714bab 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -123,6 +123,11 @@
<!-- Preference summary for enable CMAS test alerts checkbox. [CHAR LIMIT=100] -->
<string name="enable_cmas_test_alerts_summary">Display test broadcasts for Commercial Mobile Alert System</string>
+ <!-- Preference title for CMAS vibration on/off. [CHAR LIMIT=30] -->
+ <string name="enable_alert_vibrate_title">Vibrate</string>
+ <!-- Preference summary for CMAS vibration on/off. [CHAR LIMIT=60] -->
+ <string name="enable_alert_vibrate_summary">Vibrate on alert</string>
+
<!-- Preference category title for Brazil settings. [CHAR LIMIT=50] -->
<string name="category_brazil_settings_title">Settings for Brazil</string>
<!-- Preference title for enable channel 50 alerts (Brazil only). [CHAR LIMIT=30] -->
diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml
index 6d8a54db..5c29f08e 100644
--- a/res/xml/preferences.xml
+++ b/res/xml/preferences.xml
@@ -53,6 +53,11 @@
android:dialogTitle="@string/alert_sound_duration_title" />
<CheckBoxPreference android:defaultValue="true"
+ android:key="enable_alert_vibrate"
+ android:summary="@string/enable_alert_vibrate_summary"
+ android:title="@string/enable_alert_vibrate_title" />
+
+ <CheckBoxPreference android:defaultValue="true"
android:key="enable_alert_speech"
android:summary="@string/enable_alert_speech_summary"
android:title="@string/enable_alert_speech_title" />
diff --git a/src/com/android/cellbroadcastreceiver/CellBroadcastAlertAudio.java b/src/com/android/cellbroadcastreceiver/CellBroadcastAlertAudio.java
index f817fc95..d4530723 100644
--- a/src/com/android/cellbroadcastreceiver/CellBroadcastAlertAudio.java
+++ b/src/com/android/cellbroadcastreceiver/CellBroadcastAlertAudio.java
@@ -61,11 +61,16 @@ public class CellBroadcastAlertAudio extends Service implements TextToSpeech.OnI
public static final String ALERT_AUDIO_MESSAGE_LANGUAGE =
"com.android.cellbroadcastreceiver.ALERT_AUDIO_MESSAGE_LANGUAGE";
+ /** Extra for alert audio vibration enabled (from settings). */
+ public static final String ALERT_AUDIO_VIBRATE_EXTRA =
+ "com.android.cellbroadcastreceiver.ALERT_AUDIO_VIBRATE";
+
/** Pause duration between alert sound and alert speech. */
private static final int PAUSE_DURATION_BEFORE_SPEAKING_MSEC = 1000;
/** Vibration uses the same on/off pattern as the CMAS alert tone */
- private static final long[] sVibratePattern = new long[] { 0, 2000, 500, 1000, 500, 1000, 500 };
+ private static final long[] sVibratePattern = { 0, 2000, 500, 1000, 500, 1000, 500,
+ 2000, 500, 1000, 500, 1000};
/** CPU wake lock while playing audio. */
private PowerManager.WakeLock mWakeLock;
@@ -83,6 +88,8 @@ public class CellBroadcastAlertAudio extends Service implements TextToSpeech.OnI
private String mMessageBody;
private String mMessageLanguage;
private boolean mTtsLanguageSupported;
+ private boolean mEnableVibrate;
+ private boolean mEnableAudio;
private Vibrator mVibrator;
private MediaPlayer mMediaPlayer;
@@ -204,13 +211,18 @@ public class CellBroadcastAlertAudio extends Service implements TextToSpeech.OnI
@Override
public void onDestroy() {
+ // stop audio, vibration and TTS
stop();
// Stop listening for incoming calls.
mTelephonyManager.listen(mPhoneStateListener, 0);
// shutdown TTS engine
if (mTts != null) {
- mTts.stop();
- mTts.shutdown();
+ try {
+ mTts.shutdown();
+ } catch (IllegalStateException e) {
+ // catch "Unable to retrieve AudioTrack pointer for stop()" exception
+ Log.e(TAG, "exception trying to shutdown text-to-speech");
+ }
}
// release CPU wake lock
mWakeLock.release();
@@ -230,14 +242,34 @@ public class CellBroadcastAlertAudio extends Service implements TextToSpeech.OnI
}
// This extra should always be provided by CellBroadcastAlertService,
- // but default to 4 seconds just to be safe
- int duration = intent.getIntExtra(ALERT_AUDIO_DURATION_EXTRA, 4);
+ // but default to 10.5 seconds just to be safe (CMAS requirement).
+ int duration = intent.getIntExtra(ALERT_AUDIO_DURATION_EXTRA, 10500);
// Get text to speak (if enabled by user)
mMessageBody = intent.getStringExtra(ALERT_AUDIO_MESSAGE_BODY);
mMessageLanguage = intent.getStringExtra(ALERT_AUDIO_MESSAGE_LANGUAGE);
+ mEnableVibrate = intent.getBooleanExtra(ALERT_AUDIO_VIBRATE_EXTRA, true);
+
+ switch (mAudioManager.getRingerMode()) {
+ case AudioManager.RINGER_MODE_SILENT:
+ if (DBG) log("Ringer mode: silent");
+ mEnableVibrate = false;
+ mEnableAudio = false;
+ break;
+
+ case AudioManager.RINGER_MODE_VIBRATE:
+ if (DBG) log("Ringer mode: vibrate");
+ mEnableAudio = false;
+ break;
+
+ case AudioManager.RINGER_MODE_NORMAL:
+ default:
+ if (DBG) log("Ringer mode: normal");
+ mEnableAudio = true;
+ break;
+ }
- if (mMessageBody != null) {
+ if (mMessageBody != null && mEnableAudio) {
if (mTts == null) {
mTts = new TextToSpeech(this, this);
} else if (mTtsEngineReady) {
@@ -245,7 +277,12 @@ public class CellBroadcastAlertAudio extends Service implements TextToSpeech.OnI
}
}
- play(duration * 1000); // convert to milliseconds
+ if (mEnableAudio || mEnableVibrate) {
+ play(duration); // in milliseconds
+ } else {
+ stopSelf();
+ return START_NOT_STICKY;
+ }
// Record the initial call state here so that the new alarm has the
// newest state.
@@ -267,38 +304,43 @@ public class CellBroadcastAlertAudio extends Service implements TextToSpeech.OnI
if (DBG) log("play()");
- // future optimization: reuse media player object
- mMediaPlayer = new MediaPlayer();
- mMediaPlayer.setOnErrorListener(new OnErrorListener() {
- public boolean onError(MediaPlayer mp, int what, int extra) {
- Log.e(TAG, "Error occurred while playing audio.");
- mp.stop();
- mp.release();
- mMediaPlayer = null;
- return true;
- }
- });
-
- try {
- // Check if we are in a call. If we are, play the alert
- // sound at a low volume to not disrupt the call.
- if (mTelephonyManager.getCallState()
- != TelephonyManager.CALL_STATE_IDLE) {
- Log.v(TAG, "in call: reducing volume");
- mMediaPlayer.setVolume(IN_CALL_VOLUME, IN_CALL_VOLUME);
- }
- // start playing alert audio
- setDataSourceFromResource(getResources(), mMediaPlayer,
- R.raw.attention_signal);
- mAudioManager.requestAudioFocus(null, AudioManager.STREAM_ALARM,
- AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
- startAlarm(mMediaPlayer);
- } catch (Exception ex) {
- Log.e(TAG, "Failed to play alert sound", ex);
+ // Start the vibration first.
+ if (mEnableVibrate) {
+ mVibrator.vibrate(sVibratePattern, -1);
}
- /* Start the vibrator after everything is ok with the media player */
- mVibrator.vibrate(sVibratePattern, 1);
+ if (mEnableAudio) {
+ // future optimization: reuse media player object
+ mMediaPlayer = new MediaPlayer();
+ mMediaPlayer.setOnErrorListener(new OnErrorListener() {
+ public boolean onError(MediaPlayer mp, int what, int extra) {
+ Log.e(TAG, "Error occurred while playing audio.");
+ mp.stop();
+ mp.release();
+ mMediaPlayer = null;
+ return true;
+ }
+ });
+
+ try {
+ // Check if we are in a call. If we are, play the alert
+ // sound at a low volume to not disrupt the call.
+ if (mTelephonyManager.getCallState()
+ != TelephonyManager.CALL_STATE_IDLE) {
+ Log.v(TAG, "in call: reducing volume");
+ mMediaPlayer.setVolume(IN_CALL_VOLUME, IN_CALL_VOLUME);
+ }
+
+ // start playing alert audio (unless master volume is vibrate only or silent).
+ setDataSourceFromResource(getResources(), mMediaPlayer,
+ R.raw.attention_signal);
+ mAudioManager.requestAudioFocus(null, AudioManager.STREAM_NOTIFICATION,
+ AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
+ startAlarm(mMediaPlayer);
+ } catch (Exception ex) {
+ Log.e(TAG, "Failed to play alert sound", ex);
+ }
+ }
// stop alert after the specified duration
mHandler.sendMessageDelayed(mHandler.obtainMessage(ALERT_SOUND_FINISHED), duration);
@@ -307,9 +349,8 @@ public class CellBroadcastAlertAudio extends Service implements TextToSpeech.OnI
// Do the common stuff when starting the alarm.
private static void startAlarm(MediaPlayer player)
- throws java.io.IOException, IllegalArgumentException,
- IllegalStateException {
- player.setAudioStreamType(AudioManager.STREAM_ALARM);
+ throws java.io.IOException, IllegalArgumentException, IllegalStateException {
+ player.setAudioStreamType(AudioManager.STREAM_NOTIFICATION);
player.setLooping(true);
player.prepare();
player.start();
@@ -337,15 +378,25 @@ public class CellBroadcastAlertAudio extends Service implements TextToSpeech.OnI
if (mState == STATE_ALERTING) {
// Stop audio playing
if (mMediaPlayer != null) {
- mMediaPlayer.stop();
- mMediaPlayer.release();
+ try {
+ mMediaPlayer.stop();
+ mMediaPlayer.release();
+ } catch (IllegalStateException e) {
+ // catch "Unable to retrieve AudioTrack pointer for stop()" exception
+ Log.e(TAG, "exception trying to stop media player");
+ }
mMediaPlayer = null;
}
// Stop vibrator
mVibrator.cancel();
} else if (mState == STATE_SPEAKING && mTts != null) {
- mTts.stop();
+ try {
+ mTts.stop();
+ } catch (IllegalStateException e) {
+ // catch "Unable to retrieve AudioTrack pointer for stop()" exception
+ Log.e(TAG, "exception trying to stop text-to-speech");
+ }
}
mAudioManager.abandonAudioFocus(null);
mState = STATE_IDLE;
diff --git a/src/com/android/cellbroadcastreceiver/CellBroadcastAlertFullScreen.java b/src/com/android/cellbroadcastreceiver/CellBroadcastAlertFullScreen.java
index a8337f30..5bc2ba54 100644
--- a/src/com/android/cellbroadcastreceiver/CellBroadcastAlertFullScreen.java
+++ b/src/com/android/cellbroadcastreceiver/CellBroadcastAlertFullScreen.java
@@ -26,6 +26,7 @@ import android.os.Handler;
import android.os.Message;
import android.provider.Telephony;
import android.telephony.CellBroadcastMessage;
+import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Window;
@@ -200,6 +201,25 @@ public class CellBroadcastAlertFullScreen extends Activity {
finish();
}
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ switch (event.getKeyCode()) {
+ // Volume keys and camera keys mute the alert sound/vibration.
+ case KeyEvent.KEYCODE_VOLUME_UP:
+ case KeyEvent.KEYCODE_VOLUME_DOWN:
+ case KeyEvent.KEYCODE_VOLUME_MUTE:
+ case KeyEvent.KEYCODE_CAMERA:
+ case KeyEvent.KEYCODE_FOCUS:
+ // Stop playing alert sound/vibration/speech (if started)
+ stopService(new Intent(this, CellBroadcastAlertAudio.class));
+ return true;
+
+ default:
+ break;
+ }
+ return super.dispatchKeyEvent(event);
+ }
+
/**
* Ignore the back button for emergency alerts (overridden by alert dialog so that the dialog
* is dismissed).
diff --git a/src/com/android/cellbroadcastreceiver/CellBroadcastAlertService.java b/src/com/android/cellbroadcastreceiver/CellBroadcastAlertService.java
index dc1021fb..08b21544 100644
--- a/src/com/android/cellbroadcastreceiver/CellBroadcastAlertService.java
+++ b/src/com/android/cellbroadcastreceiver/CellBroadcastAlertService.java
@@ -261,10 +261,20 @@ public class CellBroadcastAlertService extends Service {
Intent audioIntent = new Intent(this, CellBroadcastAlertAudio.class);
audioIntent.setAction(CellBroadcastAlertAudio.ACTION_START_ALERT_AUDIO);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
- String duration = prefs.getString(CellBroadcastSettings.KEY_ALERT_SOUND_DURATION,
- CellBroadcastSettings.ALERT_SOUND_DEFAULT_DURATION);
- audioIntent.putExtra(CellBroadcastAlertAudio.ALERT_AUDIO_DURATION_EXTRA,
- Integer.parseInt(duration));
+
+ int duration; // alert audio duration in ms
+ if (message.isCmasMessage()) {
+ // CMAS requirement: duration of the audio attention signal is 10.5 seconds.
+ duration = 10500;
+ } else {
+ duration = Integer.parseInt(prefs.getString(
+ CellBroadcastSettings.KEY_ALERT_SOUND_DURATION,
+ CellBroadcastSettings.ALERT_SOUND_DEFAULT_DURATION)) * 1000;
+ }
+ audioIntent.putExtra(CellBroadcastAlertAudio.ALERT_AUDIO_DURATION_EXTRA, duration);
+
+ audioIntent.putExtra(CellBroadcastAlertAudio.ALERT_AUDIO_VIBRATE_EXTRA,
+ prefs.getBoolean(CellBroadcastSettings.KEY_ENABLE_ALERT_VIBRATE, true));
int channelTitleId = CellBroadcastResources.getDialogTitleResource(message);
CharSequence channelName = getText(channelTitleId);
diff --git a/src/com/android/cellbroadcastreceiver/CellBroadcastSettings.java b/src/com/android/cellbroadcastreceiver/CellBroadcastSettings.java
index 973cb312..cd372a44 100644
--- a/src/com/android/cellbroadcastreceiver/CellBroadcastSettings.java
+++ b/src/com/android/cellbroadcastreceiver/CellBroadcastSettings.java
@@ -40,6 +40,9 @@ public class CellBroadcastSettings extends PreferenceActivity {
// Default alert duration (in seconds).
public static final String ALERT_SOUND_DEFAULT_DURATION = "4";
+ // Enable vibration on alert (unless master volume is silent).
+ public static final String KEY_ENABLE_ALERT_VIBRATE = "enable_alert_vibrate";
+
// Speak contents of alert after playing the alert sound.
public static final String KEY_ENABLE_ALERT_SPEECH = "enable_alert_speech";