TTY: Telephony changes

This CL makes the following changes:
  1. Deleted the tty_enabled config. This config is now
     stored in Telecomm. Telephony stills needs to access
     this value so it now uses TelecommManager to get it.

  2. Deleted the code to set the Phoen's TTY mode based on
     TTY_PREFERRED_MODE_CHANGE_ACTION action. This code is
     now in Telecomm. Telecomm will send a
     ACTION_CURRENT_TTY_MODE_CHANGED action when the devices
     actual TTY mode changes. The actual mode is based on
     the preferred mdoe and the wired headset state.

  3. Added TtyManager which listens for
     ACTION_CURRENT_TTY_MODE_CHANGED and changes the phone's
     TTY state. The old code would update the audio TTY mode
     when the phone's state had finished changing. I've
     moved this code into Telecomm.

Change-Id: I652b095af30cc2732a06829dc23492e5355660da
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;
+        }
+    }
+}