Merge "TTY: Telephony changes" into lmp-dev
diff --git a/res/values/config.xml b/res/values/config.xml
index 59d9728..cc0cf1a 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -61,9 +61,6 @@
          apps/Contacts. -->
     <bool name="config_enable_dialer_key_vibration">true</bool>
 
-    <!-- Flag indicating if the tty is enabled -->
-    <bool name="tty_enabled">false</bool>
-
     <!-- Flag indicating if hac is enabled -->
     <bool name="hac_enabled">false</bool>
 
diff --git a/src/com/android/phone/CallFeaturesSetting.java b/src/com/android/phone/CallFeaturesSetting.java
index c3d0191..d6a2a66 100644
--- a/src/com/android/phone/CallFeaturesSetting.java
+++ b/src/com/android/phone/CallFeaturesSetting.java
@@ -57,6 +57,7 @@
 import android.provider.MediaStore;
 import android.provider.Settings;
 import android.telecomm.TelecommConstants;
+import android.telecomm.TelecommManager;
 import android.telephony.PhoneNumberUtils;
 import android.text.TextUtils;
 import android.util.Log;
@@ -68,7 +69,6 @@
 import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneConstants;
-import com.android.internal.telephony.cdma.TtyIntent;
 import com.android.services.telephony.sip.SipSharedPreferences;
 import com.android.services.telephony.sip.SipUtil;
 
@@ -210,10 +210,6 @@
     private static final int MSG_UPDATE_RINGTONE_SUMMARY = 1;
     private static final int MSG_UPDATE_VOICEMAIL_RINGTONE_SUMMARY = 2;
 
-    // preferred TTY mode
-    // Phone.TTY_MODE_xxx
-    static final int preferredTtyMode = Phone.TTY_MODE_OFF;
-
     public static final String HAC_KEY = "HACSetting";
     public static final String HAC_VAL_ON = "ON";
     public static final String HAC_VAL_OFF = "OFF";
@@ -1604,7 +1600,8 @@
         }
 
         if (mButtonTTY != null) {
-            if (getResources().getBoolean(R.bool.tty_enabled)) {
+            TelecommManager telecommManager = TelecommManager.from(this);
+            if (telecommManager != null && telecommManager.isTtySupported()) {
                 mButtonTTY.setOnPreferenceChangeListener(this);
             } else {
                 prefSet.removePreference(mButtonTTY);
@@ -1833,7 +1830,7 @@
         if (mButtonTTY != null) {
             int settingsTtyMode = Settings.Secure.getInt(getContentResolver(),
                     Settings.Secure.PREFERRED_TTY_MODE,
-                    Phone.TTY_MODE_OFF);
+                    TelecommConstants.TTY_MODE_OFF);
             mButtonTTY.setValue(Integer.toString(settingsTtyMode));
             updatePreferredTtyModeSummary(settingsTtyMode);
         }
@@ -1899,27 +1896,28 @@
         buttonTtyMode = Integer.valueOf((String) objValue).intValue();
         int settingsTtyMode = android.provider.Settings.Secure.getInt(
                 getContentResolver(),
-                android.provider.Settings.Secure.PREFERRED_TTY_MODE, preferredTtyMode);
+                android.provider.Settings.Secure.PREFERRED_TTY_MODE,
+                TelecommConstants.TTY_MODE_OFF);
         if (DBG) log("handleTTYChange: requesting set TTY mode enable (TTY) to" +
                 Integer.toString(buttonTtyMode));
 
         if (buttonTtyMode != settingsTtyMode) {
             switch(buttonTtyMode) {
-            case Phone.TTY_MODE_OFF:
-            case Phone.TTY_MODE_FULL:
-            case Phone.TTY_MODE_HCO:
-            case Phone.TTY_MODE_VCO:
+            case TelecommConstants.TTY_MODE_OFF:
+            case TelecommConstants.TTY_MODE_FULL:
+            case TelecommConstants.TTY_MODE_HCO:
+            case TelecommConstants.TTY_MODE_VCO:
                 android.provider.Settings.Secure.putInt(getContentResolver(),
                         android.provider.Settings.Secure.PREFERRED_TTY_MODE, buttonTtyMode);
                 break;
             default:
-                buttonTtyMode = Phone.TTY_MODE_OFF;
+                buttonTtyMode = TelecommConstants.TTY_MODE_OFF;
             }
 
             mButtonTTY.setValue(Integer.toString(buttonTtyMode));
             updatePreferredTtyModeSummary(buttonTtyMode);
-            Intent ttyModeChanged = new Intent(TtyIntent.TTY_PREFERRED_MODE_CHANGE_ACTION);
-            ttyModeChanged.putExtra(TtyIntent.TTY_PREFFERED_MODE, buttonTtyMode);
+            Intent ttyModeChanged = new Intent(TelecommConstants.ACTION_TTY_PREFERRED_MODE_CHANGED);
+            ttyModeChanged.putExtra(TelecommConstants.EXTRA_TTY_PREFERRED_MODE, buttonTtyMode);
             sendBroadcastAsUser(ttyModeChanged, UserHandle.ALL);
         }
     }
@@ -1944,15 +1942,16 @@
     private void updatePreferredTtyModeSummary(int TtyMode) {
         String [] txts = getResources().getStringArray(R.array.tty_mode_entries);
         switch(TtyMode) {
-            case Phone.TTY_MODE_OFF:
-            case Phone.TTY_MODE_HCO:
-            case Phone.TTY_MODE_VCO:
-            case Phone.TTY_MODE_FULL:
+            case TelecommConstants.TTY_MODE_OFF:
+            case TelecommConstants.TTY_MODE_HCO:
+            case TelecommConstants.TTY_MODE_VCO:
+            case TelecommConstants.TTY_MODE_FULL:
                 mButtonTTY.setSummary(txts[TtyMode]);
                 break;
             default:
                 mButtonTTY.setEnabled(false);
-                mButtonTTY.setSummary(txts[Phone.TTY_MODE_OFF]);
+                mButtonTTY.setSummary(txts[TelecommConstants.TTY_MODE_OFF]);
+                break;
         }
     }
 
diff --git a/src/com/android/phone/PhoneGlobals.java b/src/com/android/phone/PhoneGlobals.java
index 0c29bc9..df25684 100644
--- a/src/com/android/phone/PhoneGlobals.java
+++ b/src/com/android/phone/PhoneGlobals.java
@@ -60,7 +60,6 @@
 import com.android.internal.telephony.PhoneFactory;
 import com.android.internal.telephony.TelephonyCapabilities;
 import com.android.internal.telephony.TelephonyIntents;
-import com.android.internal.telephony.cdma.TtyIntent;
 import com.android.phone.WiredHeadsetManager.WiredHeadsetListener;
 import com.android.phone.common.CallLogAsync;
 import com.android.server.sip.SipService;
@@ -69,7 +68,7 @@
  * Global state for the telephony subsystem when running in the primary
  * phone process.
  */
-public class PhoneGlobals extends ContextWrapper implements WiredHeadsetListener {
+public class PhoneGlobals extends ContextWrapper {
     /* package */ static final String LOG_TAG = "PhoneApp";
 
     /**
@@ -101,10 +100,7 @@
     private static final int EVENT_DATA_ROAMING_OK = 11;
     private static final int EVENT_UNSOL_CDMA_INFO_RECORD = 12;
     private static final int EVENT_DOCK_STATE_CHANGED = 13;
-    private static final int EVENT_TTY_PREFERRED_MODE_CHANGED = 14;
-    private static final int EVENT_TTY_MODE_GET = 15;
-    private static final int EVENT_TTY_MODE_SET = 16;
-    private static final int EVENT_START_SIP_SERVICE = 17;
+    private static final int EVENT_START_SIP_SERVICE = 14;
 
     // The MMI codes are also used by the InCallScreen.
     public static final int MMI_INITIATE = 51;
@@ -211,11 +207,6 @@
     public OtaUtils.CdmaOtaScreenState cdmaOtaScreenState;
     public OtaUtils.CdmaOtaInCallScreenUiState cdmaOtaInCallScreenUiState;
 
-    // TTY feature enabled on this platform
-    private boolean mTtyEnabled;
-    // Current TTY operating mode selected by user
-    private int mPreferredTtyMode = Phone.TTY_MODE_OFF;
-
     /**
      * Set the restore mute state flag. Used when we are setting the mute state
      * OUTSIDE of user interaction {@link PhoneUtils#startNewCall(Phone)}
@@ -314,25 +305,6 @@
                         PhoneUtils.turnOnSpeaker(getApplicationContext(), inDockMode, true);
                     }
                     break;
-
-                case EVENT_TTY_PREFERRED_MODE_CHANGED:
-                    // TTY mode is only applied if a headset is connected
-                    int ttyMode;
-                    if (wiredHeadsetManager.isHeadsetPlugged()) {
-                        ttyMode = mPreferredTtyMode;
-                    } else {
-                        ttyMode = Phone.TTY_MODE_OFF;
-                    }
-                    phone.setTTYMode(ttyMode, mHandler.obtainMessage(EVENT_TTY_MODE_SET));
-                    break;
-
-                case EVENT_TTY_MODE_GET:
-                    handleQueryTTYModeResponse(msg);
-                    break;
-
-                case EVENT_TTY_MODE_SET:
-                    handleSetTTYModeResponse(msg);
-                    break;
             }
         }
     };
@@ -436,7 +408,6 @@
 
             // Manages wired headset state
             wiredHeadsetManager = new WiredHeadsetManager(this);
-            wiredHeadsetManager.addWiredHeadsetListener(this);
 
             // Bluetooth manager
             bluetoothManager = new BluetoothManager();
@@ -468,9 +439,6 @@
             // register connection tracking to PhoneUtils
             PhoneUtils.initializeConnectionHandler(mCM);
 
-            // Read platform settings for TTY feature
-            mTtyEnabled = getResources().getBoolean(R.bool.tty_enabled);
-
             // Register for misc other intent broadcasts.
             IntentFilter intentFilter =
                     new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);
@@ -480,9 +448,6 @@
             intentFilter.addAction(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
             intentFilter.addAction(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
             intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
-            if (mTtyEnabled) {
-                intentFilter.addAction(TtyIntent.TTY_PREFERRED_MODE_CHANGE_ACTION);
-            }
             intentFilter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
             registerReceiver(mReceiver, intentFilter);
 
@@ -513,17 +478,6 @@
         // TODO: Register for Cdma Information Records
         // phone.registerCdmaInformationRecord(mHandler, EVENT_UNSOL_CDMA_INFO_RECORD, null);
 
-        // Read TTY settings and store it into BP NV.
-        // AP owns (i.e. stores) the TTY setting in AP settings database and pushes the setting
-        // to BP at power up (BP does not need to make the TTY setting persistent storage).
-        // This way, there is a single owner (i.e AP) for the TTY setting in the phone.
-        if (mTtyEnabled) {
-            mPreferredTtyMode = android.provider.Settings.Secure.getInt(
-                    phone.getContext().getContentResolver(),
-                    android.provider.Settings.Secure.PREFERRED_TTY_MODE,
-                    Phone.TTY_MODE_OFF);
-            mHandler.sendMessage(mHandler.obtainMessage(EVENT_TTY_PREFERRED_MODE_CHANGED, 0));
-        }
         // Read HAC settings and configure audio hardware
         if (getResources().getBoolean(R.bool.hac_enabled)) {
             int hac = android.provider.Settings.System.getInt(phone.getContext().getContentResolver(),
@@ -890,20 +844,6 @@
         }
     }
 
-
-    /**
-     * This is called when the wired headset state changes.
-     */
-    @Override
-    public void onWiredHeadsetConnection(boolean pluggedIn) {
-        PhoneConstants.State phoneState = mCM.getState();
-
-        // Force TTY state update according to new headset state
-        if (mTtyEnabled) {
-            mHandler.sendMessage(mHandler.obtainMessage(EVENT_TTY_PREFERRED_MODE_CHANGED, 0));
-        }
-    }
-
     /**
      * Receiver for misc intent broadcasts the Phone app cares about.
      */
@@ -965,12 +905,6 @@
                         Intent.EXTRA_DOCK_STATE_UNDOCKED);
                 if (VDBG) Log.d(LOG_TAG, "ACTION_DOCK_EVENT -> mDockState = " + mDockState);
                 mHandler.sendMessage(mHandler.obtainMessage(EVENT_DOCK_STATE_CHANGED, 0));
-            } else if (action.equals(TtyIntent.TTY_PREFERRED_MODE_CHANGE_ACTION)) {
-                mPreferredTtyMode = intent.getIntExtra(TtyIntent.TTY_PREFFERED_MODE,
-                                                       Phone.TTY_MODE_OFF);
-                if (VDBG) Log.d(LOG_TAG, "mReceiver: TTY_PREFERRED_MODE_CHANGE_ACTION");
-                if (VDBG) Log.d(LOG_TAG, "    mode: " + mPreferredTtyMode);
-                mHandler.sendMessage(mHandler.obtainMessage(EVENT_TTY_PREFERRED_MODE_CHANGED, 0));
             } else if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) {
                 int ringerMode = intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE,
                         AudioManager.RINGER_MODE_NORMAL);
@@ -1051,53 +985,6 @@
         }
     }
 
-    private void handleQueryTTYModeResponse(Message msg) {
-        AsyncResult ar = (AsyncResult) msg.obj;
-        if (ar.exception != null) {
-            if (DBG) Log.d(LOG_TAG, "handleQueryTTYModeResponse: Error getting TTY state.");
-        } else {
-            if (DBG) Log.d(LOG_TAG,
-                           "handleQueryTTYModeResponse: TTY enable state successfully queried.");
-
-            int ttymode = ((int[]) ar.result)[0];
-            if (DBG) Log.d(LOG_TAG, "handleQueryTTYModeResponse:ttymode=" + ttymode);
-
-            Intent ttyModeChanged = new Intent(TtyIntent.TTY_ENABLED_CHANGE_ACTION);
-            ttyModeChanged.putExtra("ttyEnabled", ttymode != Phone.TTY_MODE_OFF);
-            sendBroadcastAsUser(ttyModeChanged, UserHandle.ALL);
-
-            String audioTtyMode;
-            switch (ttymode) {
-            case Phone.TTY_MODE_FULL:
-                audioTtyMode = "tty_full";
-                break;
-            case Phone.TTY_MODE_VCO:
-                audioTtyMode = "tty_vco";
-                break;
-            case Phone.TTY_MODE_HCO:
-                audioTtyMode = "tty_hco";
-                break;
-            case Phone.TTY_MODE_OFF:
-            default:
-                audioTtyMode = "tty_off";
-                break;
-            }
-            AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
-            audioManager.setParameters("tty_mode="+audioTtyMode);
-        }
-    }
-
-    private void handleSetTTYModeResponse(Message msg) {
-        AsyncResult ar = (AsyncResult) msg.obj;
-
-        if (ar.exception != null) {
-            if (DBG) Log.d (LOG_TAG,
-                    "handleSetTTYModeResponse: Error setting TTY mode, ar.exception"
-                    + ar.exception);
-        }
-        phone.queryTTYMode(mHandler.obtainMessage(EVENT_TTY_MODE_GET));
-    }
-
     /**
      * "Call origin" may be used by Contacts app to specify where the phone call comes from.
      * Currently, the only permitted value for this extra is {@link #ALLOWED_EXTRA_CALL_ORIGIN}.
diff --git a/src/com/android/services/telephony/TelephonyGlobals.java b/src/com/android/services/telephony/TelephonyGlobals.java
index 59e0dd5..daf370b 100644
--- a/src/com/android/services/telephony/TelephonyGlobals.java
+++ b/src/com/android/services/telephony/TelephonyGlobals.java
@@ -18,12 +18,13 @@
 
 import android.content.Context;
 
+import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneFactory;
 import com.android.internal.telephony.PhoneProxy;
 
 /**
  * Singleton entry point for the telephony-services app. Initializes ongoing systems relating to
- * PSTN and SIP calls. This is started when the device starts and will be restarted automatically
+ * PSTN calls. This is started when the device starts and will be restarted automatically
  * if it goes away for any reason (e.g., crashes).
  * This is separate from the actual Application class because we only support one instance of this
  * app - running as the default user. {@link com.android.phone.PhoneApp} determines whether or not
@@ -37,6 +38,8 @@
     /** Handles incoming calls for PSTN calls. */
     private PstnIncomingCallNotifier mPtsnIncomingCallNotifier;
 
+    private TtyManager mTtyManager;
+
     /**
      * Persists the specified parameters.
      *
@@ -48,6 +51,11 @@
 
     public void onCreate() {
         setupIncomingCallNotifiers();
+
+        Phone phone = PhoneFactory.getDefaultPhone();
+        if (phone != null) {
+            mTtyManager = new TtyManager(mContext, phone);
+        }
     }
 
     /**
@@ -59,10 +67,5 @@
 
         Log.i(this, "Registering the PSTN listener.");
         mPtsnIncomingCallNotifier = new PstnIncomingCallNotifier(defaultPhone);
-
-        // TODO(santoscordon): Do SIP.  SIP will require a slightly different solution since it
-        // doesn't have a phone object in the same way as PSTN calls. Additionally, the user can
-        // set up SIP to do outgoing calls, but not listen for incoming calls (uses extra battery).
-        // We need to make sure we take all of that into account.
     }
 }
diff --git a/src/com/android/services/telephony/TtyManager.java b/src/com/android/services/telephony/TtyManager.java
new file mode 100644
index 0000000..a58ea2b
--- /dev/null
+++ b/src/com/android/services/telephony/TtyManager.java
@@ -0,0 +1,134 @@
+/*
+ * 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 android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.AsyncResult;
+import android.os.Handler;
+import android.os.Message;
+import android.telecomm.TelecommConstants;
+import android.telecomm.TelecommManager;
+
+import com.android.internal.telephony.Phone;
+
+final class TtyManager {
+    private final static int MSG_SET_TTY_MODE_RESPONSE = 1;
+    private final static int MSG_GET_TTY_MODE_RESPONSE = 2;
+
+    private final TtyBroadcastReceiver mReceiver = new TtyBroadcastReceiver();
+    private final Phone mPhone;
+    private int mTtyMode;
+
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_SET_TTY_MODE_RESPONSE: {
+                    Log.v(TtyManager.this, "got setTtyMode response");
+                    AsyncResult ar = (AsyncResult) msg.obj;
+                    if (ar.exception != null) {
+                        Log.d(TtyManager.this, "setTTYMode exception: %s", ar.exception);
+                    }
+                    mPhone.queryTTYMode(obtainMessage(MSG_GET_TTY_MODE_RESPONSE));
+                    break;
+                }
+                case MSG_GET_TTY_MODE_RESPONSE: {
+                    Log.v(TtyManager.this, "got queryTTYMode response");
+                    AsyncResult ar = (AsyncResult) msg.obj;
+                    if (ar.exception != null) {
+                        Log.d(TtyManager.this, "queryTTYMode exception: %s", ar.exception);
+                    } else {
+                        int ttyMode = phoneModeToTelecommMode(((int[]) ar.result)[0]);
+                        if (ttyMode != mTtyMode) {
+                            Log.d(TtyManager.this, "setting TTY mode failed, attempted %d, got: %d",
+                                    mTtyMode, ttyMode);
+                        } else {
+                            Log.d(TtyManager.this, "setting TTY mode to %d succeeded", ttyMode);
+                        }
+                    }
+                    break;
+                }
+            }
+        }
+    };
+
+    TtyManager(Context context, Phone phone) {
+        mPhone = phone;
+
+        IntentFilter intentFilter = new IntentFilter(
+                TelecommConstants.ACTION_CURRENT_TTY_MODE_CHANGED);
+        context.registerReceiver(mReceiver, intentFilter);
+
+        int ttyMode = TelecommConstants.TTY_MODE_OFF;
+        TelecommManager telecommManager = TelecommManager.from(context);
+        if (telecommManager != null) {
+            ttyMode = telecommManager.getCurrentTtyMode();
+        }
+        updateTtyMode(ttyMode);
+    }
+
+    private void updateTtyMode(int ttyMode) {
+        Log.v(this, "updateTtyMode %d -> %d", mTtyMode, ttyMode);
+        mTtyMode = ttyMode;
+        mPhone.setTTYMode(telecommModeToPhoneMode(ttyMode),
+                mHandler.obtainMessage(MSG_SET_TTY_MODE_RESPONSE));
+    }
+
+    private final class TtyBroadcastReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            Log.v(TtyManager.this, "onReceive, action: %s", action);
+            if (action.equals(TelecommConstants.ACTION_CURRENT_TTY_MODE_CHANGED)) {
+                int ttyMode = intent.getIntExtra(
+                        TelecommConstants.EXTRA_CURRENT_TTY_MODE, TelecommConstants.TTY_MODE_OFF);
+                updateTtyMode(ttyMode);
+            }
+        }
+    }
+
+    private static int telecommModeToPhoneMode(int telecommMode) {
+        switch (telecommMode) {
+            case TelecommConstants.TTY_MODE_FULL:
+                return Phone.TTY_MODE_FULL;
+            case TelecommConstants.TTY_MODE_VCO:
+                return Phone.TTY_MODE_VCO;
+            case TelecommConstants.TTY_MODE_HCO:
+                return Phone.TTY_MODE_HCO;
+            case TelecommConstants.TTY_MODE_OFF:
+            default:
+                return Phone.TTY_MODE_OFF;
+        }
+    }
+
+    private static int phoneModeToTelecommMode(int phoneMode) {
+        switch (phoneMode) {
+            case Phone.TTY_MODE_FULL:
+                return TelecommConstants.TTY_MODE_FULL;
+            case Phone.TTY_MODE_VCO:
+                return TelecommConstants.TTY_MODE_VCO;
+            case Phone.TTY_MODE_HCO:
+                return TelecommConstants.TTY_MODE_HCO;
+            case Phone.TTY_MODE_OFF:
+            default:
+                return TelecommConstants.TTY_MODE_OFF;
+        }
+    }
+}