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