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