Merge changes I3447b591,Ic54a8307

* changes:
  Fixed that emergency alert text-to-speech does not work
  Fixed that emergency alert does not vibrate in DnD mode
diff --git a/res/raw-zh-rTW b/res/raw-zh-rTW
new file mode 120000
index 0000000..cef6542
--- /dev/null
+++ b/res/raw-zh-rTW
@@ -0,0 +1 @@
+raw-zh
\ No newline at end of file
diff --git a/src/com/android/cellbroadcastreceiver/CellBroadcastAlertAudio.java b/src/com/android/cellbroadcastreceiver/CellBroadcastAlertAudio.java
index bb869f5..abb3235 100644
--- a/src/com/android/cellbroadcastreceiver/CellBroadcastAlertAudio.java
+++ b/src/com/android/cellbroadcastreceiver/CellBroadcastAlertAudio.java
@@ -17,11 +17,11 @@
 package com.android.cellbroadcastreceiver;
 
 import static com.android.cellbroadcastreceiver.CellBroadcastReceiver.DBG;
-import static com.android.cellbroadcastreceiver.CellBroadcastReceiver.VDBG;
 
 import android.app.Service;
 import android.content.Context;
 import android.content.Intent;
+import android.content.SharedPreferences;
 import android.content.res.AssetFileDescriptor;
 import android.content.res.Resources;
 import android.media.AudioAttributes;
@@ -30,22 +30,22 @@
 import android.media.MediaPlayer;
 import android.media.MediaPlayer.OnCompletionListener;
 import android.media.MediaPlayer.OnErrorListener;
-import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
+import android.os.VibrationEffect;
 import android.os.Vibrator;
 import android.preference.PreferenceManager;
 import android.provider.Settings;
 import android.speech.tts.TextToSpeech;
 import android.telephony.PhoneStateListener;
 import android.telephony.TelephonyManager;
+import android.text.TextUtils;
 import android.util.Log;
 
 import com.android.cellbroadcastreceiver.CellBroadcastAlertService.AlertType;
 
 import java.util.Locale;
-import java.util.MissingResourceException;
 
 /**
  * Manages alert audio and vibration and text-to-speech. Runs as a service so that
@@ -63,22 +63,13 @@
             "com.android.cellbroadcastreceiver.ALERT_AUDIO_MESSAGE_BODY";
 
     /** Extra for text-to-speech preferred language (if speech enabled in settings). */
-    public static final String ALERT_AUDIO_MESSAGE_PREFERRED_LANGUAGE =
-            "com.android.cellbroadcastreceiver.ALERT_AUDIO_MESSAGE_PREFERRED_LANGUAGE";
-
-    /** Extra for text-to-speech default language when preferred language is
-        not available (if speech enabled in settings). */
-    public static final String ALERT_AUDIO_MESSAGE_DEFAULT_LANGUAGE =
-            "com.android.cellbroadcastreceiver.ALERT_AUDIO_MESSAGE_DEFAULT_LANGUAGE";
+    public static final String ALERT_AUDIO_MESSAGE_LANGUAGE =
+            "com.android.cellbroadcastreceiver.ALERT_AUDIO_MESSAGE_LANGUAGE";
 
     /** Extra for alert tone type */
     public static final String ALERT_AUDIO_TONE_TYPE =
             "com.android.cellbroadcastreceiver.ALERT_AUDIO_TONE_TYPE";
 
-    /** Extra for alert audio vibration enabled (from settings). */
-    public static final String ALERT_AUDIO_VIBRATE_EXTRA =
-            "com.android.cellbroadcastreceiver.ALERT_AUDIO_VIBRATE";
-
     /** Extra for alert vibration pattern (unless master volume is silent). */
     public static final String ALERT_AUDIO_VIBRATION_PATTERN_EXTRA =
             "com.android.cellbroadcastreceiver.ALERT_VIBRATION_PATTERN";
@@ -99,8 +90,7 @@
     private boolean mTtsEngineReady;
 
     private String mMessageBody;
-    private String mMessagePreferredLanguage;
-    private String mMessageDefaultLanguage;
+    private String mMessageLanguage;
     private boolean mTtsLanguageSupported;
     private boolean mEnableVibrate;
     private boolean mEnableAudio;
@@ -147,16 +137,8 @@
                     if (mMessageBody != null && mTtsEngineReady && mTtsLanguageSupported) {
                         if (DBG) log("Speaking broadcast text: " + mMessageBody);
 
-                        Bundle params = new Bundle();
-                        // Play TTS in the alarm stream, which we use for playing alert tones as
-                        // well.
-                        params.putInt(TextToSpeech.Engine.KEY_PARAM_STREAM,
-                                AudioManager.STREAM_ALARM);
-                        // Use the non-public parameter 2 --> TextToSpeech.QUEUE_DESTROY for TTS.
-                        // The entire playback queue is purged. This is different from QUEUE_FLUSH
-                        // in that all entries are purged, not just entries from a given caller.
-                        // This is for emergency so we want to kill all other TTS sessions.
-                        res = mTts.speak(mMessageBody, 2, params, TTS_UTTERANCE_ID);
+                        mTts.setAudioAttributes(getAlertAudioAttributes());
+                        res = mTts.speak(mMessageBody, 2, null, TTS_UTTERANCE_ID);
                         mState = STATE_SPEAKING;
                     }
                     if (res != TextToSpeech.SUCCESS) {
@@ -189,7 +171,7 @@
      */
     @Override
     public void onInit(int status) {
-        if (VDBG) log("onInit() TTS engine status: " + status);
+        if (DBG) log("onInit() TTS engine status: " + status);
         if (status == TextToSpeech.SUCCESS) {
             mTtsEngineReady = true;
             mTts.setOnUtteranceCompletedListener(this);
@@ -207,31 +189,20 @@
      * it to the default language. mTtsLanguageSupported will be updated based on the response.
      */
     private void setTtsLanguage() {
-
-        String language = mMessagePreferredLanguage;
-        if (language == null || language.isEmpty() ||
-                TextToSpeech.LANG_AVAILABLE != mTts.isLanguageAvailable(new Locale(language))) {
-            language = mMessageDefaultLanguage;
-            if (language == null || language.isEmpty() ||
-                    TextToSpeech.LANG_AVAILABLE != mTts.isLanguageAvailable(new Locale(language))) {
-                mTtsLanguageSupported = false;
-                return;
-            }
-            if (DBG) log("Language '" + mMessagePreferredLanguage + "' is not available, using" +
-                    "the default language '" + mMessageDefaultLanguage + "'");
+        Locale locale;
+        if (!TextUtils.isEmpty(mMessageLanguage)) {
+            locale = new Locale(mMessageLanguage);
+        } else {
+            // If the cell broadcast message does not specify the language, use device's default
+            // language.
+            locale = Locale.getDefault();
         }
 
-        if (DBG) log("Setting TTS language to '" + language + '\'');
+        if (DBG) log("Setting TTS language to '" + locale + '\'');
 
-        try {
-            int result = mTts.setLanguage(new Locale(language));
-            if (DBG) log("TTS setLanguage() returned: " + result);
-            mTtsLanguageSupported = (result == TextToSpeech.LANG_AVAILABLE);
-        }
-        catch (MissingResourceException e) {
-            mTtsLanguageSupported = false;
-            loge("Language '" + language + "' is not available.");
-        }
+        int result = mTts.setLanguage(locale);
+        if (DBG) log("TTS setLanguage() returned: " + result);
+        mTtsLanguageSupported = (result >= TextToSpeech.LANG_AVAILABLE);
     }
 
     /**
@@ -300,27 +271,33 @@
 
         // Get text to speak (if enabled by user)
         mMessageBody = intent.getStringExtra(ALERT_AUDIO_MESSAGE_BODY);
-        mMessagePreferredLanguage = intent.getStringExtra(ALERT_AUDIO_MESSAGE_PREFERRED_LANGUAGE);
-        mMessageDefaultLanguage = intent.getStringExtra(ALERT_AUDIO_MESSAGE_DEFAULT_LANGUAGE);
+        mMessageLanguage = intent.getStringExtra(ALERT_AUDIO_MESSAGE_LANGUAGE);
+
+        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
 
         // Get config of whether to always sound CBS alerts at full volume.
-        mUseFullVolume = PreferenceManager.getDefaultSharedPreferences(this)
-                .getBoolean(CellBroadcastSettings.KEY_USE_FULL_VOLUME, false);
+        mUseFullVolume = prefs.getBoolean(CellBroadcastSettings.KEY_USE_FULL_VOLUME, false);
 
         // retrieve the vibrate settings from cellbroadcast receiver settings.
-        mEnableVibrate = intent.getBooleanExtra(ALERT_AUDIO_VIBRATE_EXTRA, true);
+        mEnableVibrate = prefs.getBoolean(CellBroadcastSettings.KEY_ENABLE_ALERT_VIBRATE, true);
         // retrieve the vibration patterns
         mVibrationPattern = intent.getIntArrayExtra(ALERT_AUDIO_VIBRATION_PATTERN_EXTRA);
 
         switch (mAudioManager.getRingerMode()) {
             case AudioManager.RINGER_MODE_SILENT:
                 if (DBG) log("Ringer mode: silent");
-                mEnableAudio = false;
-                mEnableVibrate = false;
+                if (!mUseFullVolume) {
+                    mEnableVibrate = false;
+                }
+                // If the phone is in silent mode, we only enable the audio when use full volume
+                // setting is turned on.
+                mEnableAudio = mUseFullVolume;
                 break;
             case AudioManager.RINGER_MODE_VIBRATE:
                 if (DBG) log("Ringer mode: vibrate");
-                mEnableAudio = false;
+                // If the phone is in vibration mode, we only enable the audio when use full volume
+                // setting is turned on.
+                mEnableAudio = mUseFullVolume;
                 break;
             case AudioManager.RINGER_MODE_NORMAL:
             default:
@@ -329,10 +306,6 @@
                 break;
         }
 
-        if (mUseFullVolume) {
-            mEnableAudio = true;
-        }
-
         if (mMessageBody != null && mEnableAudio) {
             if (mTts == null) {
                 mTts = new TextToSpeech(this, this);
@@ -386,7 +359,15 @@
                 vibrationPattern[i] = patternArray[i];
                 vibrateDuration += patternArray[i];
             }
-            mVibrator.vibrate(vibrationPattern, 0);
+
+            // Use the alarm channel so it can vibrate in DnD mode, unless alarms are
+            // specifically disabled in DnD.
+            AudioAttributes.Builder attrBuilder = new AudioAttributes.Builder();
+            attrBuilder.setUsage(AudioAttributes.USAGE_ALARM);
+            AudioAttributes attr = attrBuilder.build();
+            VibrationEffect effect = VibrationEffect.createWaveform(vibrationPattern, 0);
+            log("vibrate: effect=" + effect + ", attr=" + attr);
+            mVibrator.vibrate(effect, attr);
         }
 
 
@@ -455,9 +436,7 @@
                 // Request audio focus (though we're going to play even if we don't get it)
                 mAudioManager.requestAudioFocus(null, AudioManager.STREAM_ALARM,
                         AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
-                mMediaPlayer.setAudioStreamType(AudioManager.STREAM_ALARM);
-
-                setAlertAudioAttributes();
+                mMediaPlayer.setAudioAttributes(getAlertAudioAttributes());
                 setAlertVolume();
 
                 // If we are using the custom alert duration, set looping to true so we can repeat
@@ -533,10 +512,9 @@
     }
 
     /**
-     * Set AudioAttributes for mMediaPlayer. Replacement of deprecated
-     * mMediaPlayer.setAudioStreamType.
+     * Get audio attribute for the alarm.
      */
-    private void setAlertAudioAttributes() {
+    private AudioAttributes getAlertAudioAttributes() {
         AudioAttributes.Builder builder = new AudioAttributes.Builder();
 
         builder.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION);
@@ -548,7 +526,7 @@
                     | AudioAttributes.FLAG_BYPASS_MUTE);
         }
 
-        mMediaPlayer.setAudioAttributes(builder.build());
+        return builder.build();
     }
 
     /**
diff --git a/src/com/android/cellbroadcastreceiver/CellBroadcastAlertService.java b/src/com/android/cellbroadcastreceiver/CellBroadcastAlertService.java
index b969f62..c779043 100644
--- a/src/com/android/cellbroadcastreceiver/CellBroadcastAlertService.java
+++ b/src/com/android/cellbroadcastreceiver/CellBroadcastAlertService.java
@@ -578,8 +578,6 @@
         CellBroadcastChannelRange range = CellBroadcastChannelManager
                 .getCellBroadcastChannelRangeFromMessage(getApplicationContext(), message);
         audioIntent.putExtra(CellBroadcastAlertAudio.ALERT_AUDIO_TONE_TYPE, alertType);
-        audioIntent.putExtra(CellBroadcastAlertAudio.ALERT_AUDIO_VIBRATE_EXTRA,
-                prefs.getBoolean(CellBroadcastSettings.KEY_ENABLE_ALERT_VIBRATE, true));
         audioIntent.putExtra(CellBroadcastAlertAudio.ALERT_AUDIO_VIBRATION_PATTERN_EXTRA,
                 (range != null) ? range.mVibrationPattern
                         : getApplicationContext().getResources().getIntArray(
@@ -590,34 +588,11 @@
         if (prefs.getBoolean(CellBroadcastSettings.KEY_ENABLE_ALERT_SPEECH, true)) {
             audioIntent.putExtra(CellBroadcastAlertAudio.ALERT_AUDIO_MESSAGE_BODY, messageBody);
 
-            String preferredLanguage = message.getLanguageCode();
-            String defaultLanguage = null;
-            if (message.isEtwsMessage()) {
-                // Only do TTS for ETWS secondary message.
-                // There is no text in ETWS primary message. When we construct the ETWS primary
-                // message, we hardcode "ETWS" as the body hence we don't want to speak that out
-                // here.
+            String language = message.getLanguageCode();
 
-                // Also in many cases we see the secondary message comes few milliseconds after
-                // the primary one. If we play TTS for the primary one, It will be overwritten by
-                // the secondary one immediately anyway.
-                if (!message.getEtwsWarningInfo().isPrimary()) {
-                    // Since only Japanese carriers are using ETWS, if there is no language
-                    // specified in the ETWS message, we'll use Japanese as the default language.
-                    defaultLanguage = "ja";
-                }
-            } else {
-                // If there is no language specified in the CMAS message, use device's
-                // default language.
-                defaultLanguage = Locale.getDefault().getLanguage();
-            }
-
-            Log.d(TAG, "Preferred language = " + preferredLanguage +
-                    ", Default language = " + defaultLanguage);
-            audioIntent.putExtra(CellBroadcastAlertAudio.ALERT_AUDIO_MESSAGE_PREFERRED_LANGUAGE,
-                    preferredLanguage);
-            audioIntent.putExtra(CellBroadcastAlertAudio.ALERT_AUDIO_MESSAGE_DEFAULT_LANGUAGE,
-                    defaultLanguage);
+            Log.d(TAG, "Message language = " + language);
+            audioIntent.putExtra(CellBroadcastAlertAudio.ALERT_AUDIO_MESSAGE_LANGUAGE,
+                    language);
         }
         startService(audioIntent);