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 
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         mContext.registerReceiver(mReceiver, intentFilter,
54                 android.Manifest.permission.MODIFY_PHONE_STATE,
55                 null);
56 
57         updateCurrentTtyMode();
58     }
59 
60     boolean isTtySupported() {
61         boolean isEnabled = mContext.getResources().getBoolean(R.bool.tty_enabled);
62         Log.v(this, "isTtySupported: %b", isEnabled);
63         return isEnabled;
64     }
65 
66     int getCurrentTtyMode() {
67         return mCurrentTtyMode;
68     }
69 
70     @Override
71     public void onWiredHeadsetPluggedInChanged(boolean oldIsPluggedIn, boolean newIsPluggedIn) {
72         Log.v(this, "onWiredHeadsetPluggedInChanged");
73         updateCurrentTtyMode();
74     }
75 
76     private void updateCurrentTtyMode() {
77         int newTtyMode = TelecomManager.TTY_MODE_OFF;
78         if (isTtySupported() && mWiredHeadsetManager.isPluggedIn()) {
79             newTtyMode = mPreferredTtyMode;
80         }
81         Log.v(this, "updateCurrentTtyMode, %d -> %d", mCurrentTtyMode, newTtyMode);
82 
83         if (mCurrentTtyMode != newTtyMode) {
84             mCurrentTtyMode = newTtyMode;
85             Intent ttyModeChanged = new Intent(TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED);
86             ttyModeChanged.putExtra(TelecomManager.EXTRA_CURRENT_TTY_MODE, mCurrentTtyMode);
87             mContext.sendBroadcastAsUser(ttyModeChanged, UserHandle.ALL,
88                     android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
89 
90             updateAudioTtyMode();
91         }
92     }
93 
94     private void updateAudioTtyMode() {
95         String audioTtyMode;
96         switch (mCurrentTtyMode) {
97             case TelecomManager.TTY_MODE_FULL:
98                 audioTtyMode = "tty_full";
99                 break;
100             case TelecomManager.TTY_MODE_VCO:
101                 audioTtyMode = "tty_vco";
102                 break;
103             case TelecomManager.TTY_MODE_HCO:
104                 audioTtyMode = "tty_hco";
105                 break;
106             case TelecomManager.TTY_MODE_OFF:
107             default:
108                 audioTtyMode = "tty_off";
109                 break;
110         }
111         Log.v(this, "updateAudioTtyMode, %s", audioTtyMode);
112 
113         AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
114         audioManager.setParameters("tty_mode=" + audioTtyMode);
115     }
116 
117     private final class TtyBroadcastReceiver extends BroadcastReceiver {
118         @Override
119         public void onReceive(Context context, Intent intent) {
120             Log.startSession("TBR.oR");
121             try {
122                 String action = intent.getAction();
123                 Log.v(TtyManager.this, "onReceive, action: %s", action);
124                 if (action.equals(TelecomManager.ACTION_TTY_PREFERRED_MODE_CHANGED)) {
125                     int newPreferredTtyMode = intent.getIntExtra(
126                             TelecomManager.EXTRA_TTY_PREFERRED_MODE, TelecomManager.TTY_MODE_OFF);
127                     if (mPreferredTtyMode != newPreferredTtyMode) {
128                         mPreferredTtyMode = newPreferredTtyMode;
129                         updateCurrentTtyMode();
130                     }
131                 }
132             } finally {
133                 Log.endSession();
134             }
135         }
136     }
137 
138     /**
139      * Dumps the state of the {@link TtyManager}.
140      *
141      * @param pw The {@code IndentingPrintWriter} to write the state to.
142      */
143     public void dump(IndentingPrintWriter pw) {
144         pw.println("mCurrentTtyMode: " + mCurrentTtyMode);
145     }
146 }
147