1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.telecom;
18 
19 import android.content.BroadcastReceiver;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.IntentFilter;
23 import android.media.AudioManager;
24 import android.os.UserHandle;
25 import android.provider.Settings;
26 import android.telecom.Log;
27 import android.telecom.TelecomManager;
28 
29 import com.android.internal.util.IndentingPrintWriter;
30 
31 // TODO: Needed for move to system service: import com.android.internal.R;
32 
33 final class TtyManager implements WiredHeadsetManager.Listener {
34     private final TtyBroadcastReceiver mReceiver = new TtyBroadcastReceiver();
35     private final Context mContext;
36     private final WiredHeadsetManager mWiredHeadsetManager;
37     private int mPreferredTtyMode = TelecomManager.TTY_MODE_OFF;
38     private int mCurrentTtyMode = TelecomManager.TTY_MODE_OFF;
39 
TtyManager(Context context, WiredHeadsetManager wiredHeadsetManager)40     TtyManager(Context context, WiredHeadsetManager wiredHeadsetManager) {
41         mContext = context;
42         mWiredHeadsetManager = wiredHeadsetManager;
43         mWiredHeadsetManager.addListener(this);
44 
45         mPreferredTtyMode = Settings.Secure.getIntForUser(
46                 mContext.getContentResolver(),
47                 Settings.Secure.PREFERRED_TTY_MODE,
48                 TelecomManager.TTY_MODE_OFF,
49                 mContext.getUserId());
50 
51         IntentFilter intentFilter = new IntentFilter(
52                 TelecomManager.ACTION_TTY_PREFERRED_MODE_CHANGED);
53         intentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
54         mContext.registerReceiver(mReceiver, intentFilter,
55                 android.Manifest.permission.MODIFY_PHONE_STATE,
56                 null, Context.RECEIVER_EXPORTED);
57 
58         updateCurrentTtyMode();
59     }
60 
isTtySupported()61     boolean isTtySupported() {
62         boolean isEnabled = mContext.getResources().getBoolean(R.bool.tty_enabled);
63         Log.v(this, "isTtySupported: %b", isEnabled);
64         return isEnabled;
65     }
66 
getCurrentTtyMode()67     int getCurrentTtyMode() {
68         return mCurrentTtyMode;
69     }
70 
71     @Override
onWiredHeadsetPluggedInChanged(boolean oldIsPluggedIn, boolean newIsPluggedIn)72     public void onWiredHeadsetPluggedInChanged(boolean oldIsPluggedIn, boolean newIsPluggedIn) {
73         Log.v(this, "onWiredHeadsetPluggedInChanged");
74         updateCurrentTtyMode();
75     }
76 
updateCurrentTtyMode()77     private void updateCurrentTtyMode() {
78         int newTtyMode = TelecomManager.TTY_MODE_OFF;
79         if (isTtySupported() && mWiredHeadsetManager.isPluggedIn()) {
80             newTtyMode = mPreferredTtyMode;
81         }
82         Log.v(this, "updateCurrentTtyMode, %d -> %d", mCurrentTtyMode, newTtyMode);
83 
84         if (mCurrentTtyMode != newTtyMode) {
85             mCurrentTtyMode = newTtyMode;
86             Intent ttyModeChanged = new Intent(TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED);
87             ttyModeChanged.putExtra(TelecomManager.EXTRA_CURRENT_TTY_MODE, mCurrentTtyMode);
88             mContext.sendBroadcastAsUser(ttyModeChanged, UserHandle.ALL,
89                     android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
90 
91             updateAudioTtyMode();
92         }
93     }
94 
updateAudioTtyMode()95     private void updateAudioTtyMode() {
96         String audioTtyMode;
97         switch (mCurrentTtyMode) {
98             case TelecomManager.TTY_MODE_FULL:
99                 audioTtyMode = "tty_full";
100                 break;
101             case TelecomManager.TTY_MODE_VCO:
102                 audioTtyMode = "tty_vco";
103                 break;
104             case TelecomManager.TTY_MODE_HCO:
105                 audioTtyMode = "tty_hco";
106                 break;
107             case TelecomManager.TTY_MODE_OFF:
108             default:
109                 audioTtyMode = "tty_off";
110                 break;
111         }
112         Log.v(this, "updateAudioTtyMode, %s", audioTtyMode);
113 
114         AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
115         audioManager.setParameters("tty_mode=" + audioTtyMode);
116     }
117 
118     private final class TtyBroadcastReceiver extends BroadcastReceiver {
119         @Override
onReceive(Context context, Intent intent)120         public void onReceive(Context context, Intent intent) {
121             Log.startSession("TBR.oR");
122             try {
123                 String action = intent.getAction();
124                 Log.v(TtyManager.this, "onReceive, action: %s", action);
125                 if (action.equals(TelecomManager.ACTION_TTY_PREFERRED_MODE_CHANGED)) {
126                     int newPreferredTtyMode = intent.getIntExtra(
127                             TelecomManager.EXTRA_TTY_PREFERRED_MODE, TelecomManager.TTY_MODE_OFF);
128                     if (mPreferredTtyMode != newPreferredTtyMode) {
129                         mPreferredTtyMode = newPreferredTtyMode;
130                         updateCurrentTtyMode();
131                     }
132                 }
133             } finally {
134                 Log.endSession();
135             }
136         }
137     }
138 
139     /**
140      * Dumps the state of the {@link TtyManager}.
141      *
142      * @param pw The {@code IndentingPrintWriter} to write the state to.
143      */
dump(IndentingPrintWriter pw)144     public void dump(IndentingPrintWriter pw) {
145         pw.println("mCurrentTtyMode: " + mCurrentTtyMode);
146     }
147 }
148