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