HeadsetPhoneState.java revision ede67c26e7b2564ea35db6d9b3027a269c150e13
1/* 2 * Copyright (C) 2012 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 17package com.android.bluetooth.hfp; 18 19import android.content.Context; 20import android.telephony.PhoneStateListener; 21import android.telephony.ServiceState; 22import android.telephony.SignalStrength; 23import android.telephony.TelephonyManager; 24import android.util.Log; 25 26// Note: 27// All methods in this class are not thread safe, donot call them from 28// multiple threads. Call them from the HeadsetPhoneStateMachine message 29// handler only. 30class HeadsetPhoneState { 31 private static final String TAG = "HeadsetPhoneState"; 32 33 private HeadsetStateMachine mStateMachine; 34 private TelephonyManager mTelephonyManager; 35 private ServiceState mServiceState; 36 37 // HFP 1.6 CIND service 38 private int mService = HeadsetHalConstants.NETWORK_STATE_NOT_AVAILABLE; 39 40 // Number of active (foreground) calls 41 private int mNumActive = 0; 42 43 // Current Call Setup State 44 private int mCallState = HeadsetHalConstants.CALL_STATE_IDLE; 45 46 // Number of held (background) calls 47 private int mNumHeld = 0; 48 49 // HFP 1.6 CIND signal 50 private int mSignal = 0; 51 52 // HFP 1.6 CIND roam 53 private int mRoam = HeadsetHalConstants.SERVICE_TYPE_HOME; 54 55 // HFP 1.6 CIND battchg 56 private int mBatteryCharge = 0; 57 58 private int mSpeakerVolume = 0; 59 60 private int mMicVolume = 0; 61 62 private boolean mListening = false; 63 64 HeadsetPhoneState(Context context, HeadsetStateMachine stateMachine) { 65 mStateMachine = stateMachine; 66 mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); 67 } 68 69 public void cleanup() { 70 listenForPhoneState(false); 71 mTelephonyManager = null; 72 mStateMachine = null; 73 } 74 75 void listenForPhoneState(boolean start) { 76 if (start) { 77 if (!mListening) { 78 mTelephonyManager.listen(mPhoneStateListener, 79 PhoneStateListener.LISTEN_SERVICE_STATE | 80 PhoneStateListener.LISTEN_SIGNAL_STRENGTHS); 81 mListening = true; 82 } 83 } else { 84 if (mListening) { 85 mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE); 86 mListening = false; 87 } 88 } 89 } 90 91 int getService() { 92 return mService; 93 } 94 95 int getNumActiveCall() { 96 return mNumActive; 97 } 98 99 void setNumActiveCall(int numActive) { 100 mNumActive = numActive; 101 } 102 103 int getCallState() { 104 return mCallState; 105 } 106 107 void setCallState(int callState) { 108 mCallState = callState; 109 } 110 111 int getNumHeldCall() { 112 return mNumHeld; 113 } 114 115 void setNumHeldCall(int numHeldCall) { 116 mNumHeld = numHeldCall; 117 } 118 119 int getSignal() { 120 return mSignal; 121 } 122 123 int getRoam() { 124 return mRoam; 125 } 126 127 void setRoam(int roam) { 128 mRoam = roam; 129 } 130 131 void setBatteryCharge(int batteryLevel) { 132 if (mBatteryCharge != batteryLevel) { 133 mBatteryCharge = batteryLevel; 134 sendDeviceStateChanged(); 135 } 136 } 137 138 int getBatteryCharge() { 139 return mBatteryCharge; 140 } 141 142 void setSpeakerVolume(int volume) { 143 mSpeakerVolume = volume; 144 } 145 146 int getSpeakerVolume() { 147 return mSpeakerVolume; 148 } 149 150 void setMicVolume(int volume) { 151 mMicVolume = volume; 152 } 153 154 int getMicVolume() { 155 return mMicVolume; 156 } 157 158 boolean isInCall() { 159 return (mNumActive >= 1); 160 } 161 162 void sendDeviceStateChanged() 163 { 164 Log.d(TAG, "sendDeviceStateChanged. mService="+ mService + 165 " mSignal="+mSignal +" mRoam="+mRoam + 166 " mBatteryCharge=" + mBatteryCharge); 167 HeadsetStateMachine sm = mStateMachine; 168 if (sm != null) { 169 sm.sendMessage(HeadsetStateMachine.DEVICE_STATE_CHANGED, 170 new HeadsetDeviceState(mService, mRoam, mSignal, mBatteryCharge)); 171 } 172 } 173 174 private PhoneStateListener mPhoneStateListener = new PhoneStateListener() { 175 @Override 176 public void onServiceStateChanged(ServiceState serviceState) { 177 mServiceState = serviceState; 178 mService = (serviceState.getState() == ServiceState.STATE_IN_SERVICE) ? 179 HeadsetHalConstants.NETWORK_STATE_AVAILABLE : 180 HeadsetHalConstants.NETWORK_STATE_NOT_AVAILABLE; 181 sendDeviceStateChanged(); 182 } 183 184 @Override 185 public void onSignalStrengthsChanged(SignalStrength signalStrength) { 186 int prevSignal = mSignal; 187 if (signalStrength.isGsm()) { 188 mSignal = gsmAsuToSignal(signalStrength); 189 } else { 190 mSignal = cdmaDbmEcioToSignal(signalStrength); 191 } 192 // network signal strength is scaled to BT 1-5 levels. 193 // This results in a lot of duplicate messages, hence this check 194 if (prevSignal != mSignal) 195 sendDeviceStateChanged(); 196 } 197 198 /* convert [0,31] ASU signal strength to the [0,5] expected by 199 * bluetooth devices. Scale is similar to status bar policy 200 */ 201 private int gsmAsuToSignal(SignalStrength signalStrength) { 202 int asu = signalStrength.getGsmSignalStrength(); 203 if (asu >= 16) return 5; 204 else if (asu >= 8) return 4; 205 else if (asu >= 4) return 3; 206 else if (asu >= 2) return 2; 207 else if (asu >= 1) return 1; 208 else return 0; 209 } 210 211 /** 212 * Convert the cdma / evdo db levels to appropriate icon level. 213 * The scale is similar to the one used in status bar policy. 214 * 215 * @param signalStrength 216 * @return the icon level 217 */ 218 private int cdmaDbmEcioToSignal(SignalStrength signalStrength) { 219 int levelDbm = 0; 220 int levelEcio = 0; 221 int cdmaIconLevel = 0; 222 int evdoIconLevel = 0; 223 int cdmaDbm = signalStrength.getCdmaDbm(); 224 int cdmaEcio = signalStrength.getCdmaEcio(); 225 226 if (cdmaDbm >= -75) levelDbm = 4; 227 else if (cdmaDbm >= -85) levelDbm = 3; 228 else if (cdmaDbm >= -95) levelDbm = 2; 229 else if (cdmaDbm >= -100) levelDbm = 1; 230 else levelDbm = 0; 231 232 // Ec/Io are in dB*10 233 if (cdmaEcio >= -90) levelEcio = 4; 234 else if (cdmaEcio >= -110) levelEcio = 3; 235 else if (cdmaEcio >= -130) levelEcio = 2; 236 else if (cdmaEcio >= -150) levelEcio = 1; 237 else levelEcio = 0; 238 239 cdmaIconLevel = (levelDbm < levelEcio) ? levelDbm : levelEcio; 240 241 if (mServiceState != null && 242 (mServiceState.getRadioTechnology() == ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_0 || 243 mServiceState.getRadioTechnology() == ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_A)) { 244 int evdoEcio = signalStrength.getEvdoEcio(); 245 int evdoSnr = signalStrength.getEvdoSnr(); 246 int levelEvdoEcio = 0; 247 int levelEvdoSnr = 0; 248 249 // Ec/Io are in dB*10 250 if (evdoEcio >= -650) levelEvdoEcio = 4; 251 else if (evdoEcio >= -750) levelEvdoEcio = 3; 252 else if (evdoEcio >= -900) levelEvdoEcio = 2; 253 else if (evdoEcio >= -1050) levelEvdoEcio = 1; 254 else levelEvdoEcio = 0; 255 256 if (evdoSnr > 7) levelEvdoSnr = 4; 257 else if (evdoSnr > 5) levelEvdoSnr = 3; 258 else if (evdoSnr > 3) levelEvdoSnr = 2; 259 else if (evdoSnr > 1) levelEvdoSnr = 1; 260 else levelEvdoSnr = 0; 261 262 evdoIconLevel = (levelEvdoEcio < levelEvdoSnr) ? levelEvdoEcio : levelEvdoSnr; 263 } 264 // TODO(): There is a bug open regarding what should be sent. 265 return (cdmaIconLevel > evdoIconLevel) ? cdmaIconLevel : evdoIconLevel; 266 } 267 }; 268 269} 270 271class HeadsetDeviceState { 272 int mService; 273 int mRoam; 274 int mSignal; 275 int mBatteryCharge; 276 277 HeadsetDeviceState(int service, int roam, int signal, int batteryCharge) { 278 mService = service; 279 mRoam = roam; 280 mSignal = signal; 281 mBatteryCharge = batteryCharge; 282 } 283} 284 285class HeadsetCallState { 286 int mNumActive; 287 int mNumHeld; 288 int mCallState; 289 String mNumber; 290 int mType; 291 292 public HeadsetCallState(int numActive, int numHeld, int callState, String number, int type) { 293 mNumActive = numActive; 294 mNumHeld = numHeld; 295 mCallState = callState; 296 mNumber = number; 297 mType = type; 298 } 299} 300 301class HeadsetClccResponse { 302 int mIndex; 303 int mDirection; 304 int mStatus; 305 int mMode; 306 boolean mMpty; 307 String mNumber; 308 int mType; 309 310 public HeadsetClccResponse(int index, int direction, int status, int mode, boolean mpty, 311 String number, int type) { 312 mIndex = index; 313 mDirection = direction; 314 mStatus = status; 315 mMode = mode; 316 mMpty = mpty; 317 mNumber = number; 318 mType = type; 319 } 320} 321