Loading android/app/src/com/android/bluetooth/hfp/AtPhonebook.java +3 −6 Original line number Diff line number Diff line Loading @@ -104,11 +104,8 @@ public class AtPhonebook { mPhonebooks.put("RC", new PhonebookResult()); // received calls mPhonebooks.put("MC", new PhonebookResult()); // missed calls mPhonebooks.put("ME", new PhonebookResult()); // mobile phonebook mCurrentPhonebook = "ME"; // default to mobile phonebook mCpbrIndex1 = mCpbrIndex2 = -1; mCheckingAccessPermission = false; } public void cleanup() { Loading Loading @@ -172,7 +169,7 @@ public class AtPhonebook { case TYPE_SET: // Set log("handleCscsCommand - Set Command"); String[] args = atString.split("="); if (args.length < 2 || !(args[1] instanceof String)) { if (args.length < 2 || args[1] == null) { mNativeInterface.atResponseCode(device, atCommandResult, atCommandErrorCode); break; } Loading Loading @@ -234,7 +231,7 @@ public class AtPhonebook { log("handleCpbsCommand - set command"); String[] args = atString.split("="); // Select phonebook memory if (args.length < 2 || !(args[1] instanceof String)) { if (args.length < 2 || args[1] == null) { atCommandErrorCode = BluetoothCmeError.OPERATION_NOT_SUPPORTED; break; } Loading Loading @@ -266,7 +263,7 @@ public class AtPhonebook { mNativeInterface.atResponseCode(device, atCommandResult, atCommandErrorCode); } public void handleCpbrCommand(String atString, int type, BluetoothDevice remoteDevice) { void handleCpbrCommand(String atString, int type, BluetoothDevice remoteDevice) { log("handleCpbrCommand - atString = " + atString); int atCommandResult = HeadsetHalConstants.AT_RESPONSE_ERROR; int atCommandErrorCode = -1; Loading android/app/src/com/android/bluetooth/hfp/HeadsetPhoneState.java +255 −293 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Looper; import android.support.annotation.VisibleForTesting; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; import android.telephony.SignalStrength; Loading @@ -33,6 +34,8 @@ import android.util.Log; import com.android.internal.telephony.IccCardConstants; import com.android.internal.telephony.TelephonyIntents; import java.util.Objects; /** * Class that manages Telephony states Loading @@ -45,142 +48,106 @@ import com.android.internal.telephony.TelephonyIntents; public class HeadsetPhoneState { private static final String TAG = "HeadsetPhoneState"; private final Context mContext; private final HeadsetStateMachine mStateMachine; private final HeadsetService mHeadsetService; private final TelephonyManager mTelephonyManager; private final SubscriptionManager mSubMgr; private final SubscriptionManager mSubscriptionManager; private ServiceState mServiceState; // HFP 1.6 CIND service value private int mService = HeadsetHalConstants.NETWORK_STATE_NOT_AVAILABLE; private int mCindService = HeadsetHalConstants.NETWORK_STATE_NOT_AVAILABLE; // Check this before sending out service state to the device -- if the SIM isn't fully // loaded, don't expose that the network is available. private boolean mIsSimStateLoaded; // Number of active (foreground) calls private int mNumActive; // Current Call Setup State private int mCallState = HeadsetHalConstants.CALL_STATE_IDLE; // Number of held (background) calls private int mNumHeld; // HFP 1.6 CIND signal private int mSignal; // HFP 1.6 CIND roam private int mRoam = HeadsetHalConstants.SERVICE_TYPE_HOME; // HFP 1.6 CIND battchg private int mBatteryCharge; private int mSpeakerVolume; private int mMicVolume; // HFP 1.6 CIND signal value private int mCindSignal; // HFP 1.6 CIND roam value private int mCindRoam = HeadsetHalConstants.SERVICE_TYPE_HOME; // HFP 1.6 CIND battchg value private int mCindBatteryCharge; private boolean mListening; // when HFP Service Level Connection is established private boolean mSlcReady; private PhoneStateListener mPhoneStateListener; private OnSubscriptionsChangedListener mOnSubscriptionsChangedListener; private class HeadsetPhoneStateOnSubscriptionChangedListener extends OnSubscriptionsChangedListener { HeadsetPhoneStateOnSubscriptionChangedListener(Looper looper) { super(looper); } @Override public void onSubscriptionsChanged() { listenForPhoneState(false); listenForPhoneState(true); } } HeadsetPhoneState(Context context, HeadsetStateMachine stateMachine) { mStateMachine = stateMachine; mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); if (mTelephonyManager == null) { Log.e(TAG, "getSystemService(Context.TELEPHONY_SERVICE) failed, " + "cannot register for SubscriptionInfo changes"); } mContext = context; // Register for SubscriptionInfo list changes which is guaranteed // to invoke onSubscriptionInfoChanged and which in turns calls // loadInBackgroud. mSubMgr = SubscriptionManager.from(mContext); private final OnSubscriptionsChangedListener mOnSubscriptionsChangedListener; HeadsetPhoneState(HeadsetService headsetService) { Objects.requireNonNull(headsetService, "headsetService is null"); mHeadsetService = headsetService; mTelephonyManager = (TelephonyManager) mHeadsetService.getSystemService(Context.TELEPHONY_SERVICE); Objects.requireNonNull(mTelephonyManager, "TELEPHONY_SERVICE is null"); // Register for SubscriptionInfo list changes which is guaranteed to invoke // onSubscriptionInfoChanged and which in turns calls loadInBackgroud. mSubscriptionManager = SubscriptionManager.from(mHeadsetService); Objects.requireNonNull(mSubscriptionManager, "TELEPHONY_SUBSCRIPTION_SERVICE is null"); // Initialize subscription on the handler thread mOnSubscriptionsChangedListener = new HeadsetPhoneStateOnSubscriptionChangedListener( stateMachine.getHandler().getLooper()); mSubMgr.addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener); headsetService.getStateMachinesThreadLooper()); mSubscriptionManager.addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener); } /** * Cleanup this instance. Instance can no longer be used after calling this method. */ public void cleanup() { listenForPhoneState(false); if (mOnSubscriptionsChangedListener != null) { mSubMgr.removeOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener); mOnSubscriptionsChangedListener = null; } mSubscriptionManager.removeOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener); } @Override public String toString() { return "HeadsetPhoneState [mService=" + mService + ", mNumActive=" + mNumActive + ", mCallState=" + mCallState + ", mNumHeld=" + mNumHeld + ", mSignal=" + mSignal + ", mRoam=" + mRoam + ", mBatteryCharge=" + mBatteryCharge + ", mSpeakerVolume=" + mSpeakerVolume + ", mMicVolume=" + mMicVolume + ", mListening=" + mListening + ", mSlcReady=" + mSlcReady + "]"; return "HeadsetPhoneState [mTelephonyServiceAvailability=" + mCindService + ", mNumActive=" + mNumActive + ", mCallState=" + mCallState + ", mNumHeld=" + mNumHeld + ", mSignal=" + mCindSignal + ", mRoam=" + mCindRoam + ", mBatteryCharge=" + mCindBatteryCharge + ", mListening=" + mListening + "]"; } void listenForPhoneState(boolean start) { mSlcReady = start; /** * Start or stop listening for phone state change * @param start True to start, False to stop */ @VisibleForTesting public void listenForPhoneState(boolean start) { synchronized (mTelephonyManager) { if (start) { startListenForPhoneState(); } else { stopListenForPhoneState(); } } } private void startListenForPhoneState() { if (!mListening && mSlcReady && mTelephonyManager != null) { if (!mListening) { int subId = SubscriptionManager.getDefaultSubscriptionId(); if (SubscriptionManager.isValidSubscriptionId(subId)) { mPhoneStateListener = getPhoneStateListener(subId); if (mTelephonyManager == null) { Log.e(TAG, "mTelephonyManager is null, " + "cannot start listening for phone state changes"); } else { mPhoneStateListener = new HeadsetPhoneStateListener(subId, mHeadsetService.getStateMachinesThreadLooper()); mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS); mListening = true; } } else { Log.w(TAG, "startListenForPhoneState, invalid subscription ID " + subId); } } } private void stopListenForPhoneState() { if (mListening && mTelephonyManager != null) { if (mTelephonyManager == null) { Log.e(TAG, "mTelephonyManager is null, " + "cannot send request to stop listening for phone state changes"); } else { if (mListening) { mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE); mListening = false; } } } int getService() { return mService; int getCindService() { return mCindService; } int getNumActiveCall() { Loading @@ -207,97 +174,94 @@ public class HeadsetPhoneState { mNumHeld = numHeldCall; } int getSignal() { return mSignal; int getCindSignal() { return mCindSignal; } int getRoam() { return mRoam; int getCindRoam() { return mCindRoam; } void setRoam(int roam) { if (mRoam != roam) { mRoam = roam; void setCindRoam(int cindRoam) { if (mCindRoam != cindRoam) { mCindRoam = cindRoam; sendDeviceStateChanged(); } } void setBatteryCharge(int batteryLevel) { if (mBatteryCharge != batteryLevel) { mBatteryCharge = batteryLevel; void setCindBatteryCharge(int batteryLevel) { if (mCindBatteryCharge != batteryLevel) { mCindBatteryCharge = batteryLevel; sendDeviceStateChanged(); } } int getBatteryCharge() { return mBatteryCharge; } void setSpeakerVolume(int volume) { mSpeakerVolume = volume; } int getSpeakerVolume() { return mSpeakerVolume; } void setMicVolume(int volume) { mMicVolume = volume; } int getMicVolume() { return mMicVolume; int getCindBatteryCharge() { return mCindBatteryCharge; } boolean isInCall() { return (mNumActive >= 1); } void sendDeviceStateChanged() { private void sendDeviceStateChanged() { int service = mIsSimStateLoaded ? mService : HeadsetHalConstants.NETWORK_STATE_NOT_AVAILABLE; mIsSimStateLoaded ? mCindService : HeadsetHalConstants.NETWORK_STATE_NOT_AVAILABLE; // When out of service, send signal strength as 0. Some devices don't // use the service indicator, but only the signal indicator int signal = service == HeadsetHalConstants.NETWORK_STATE_AVAILABLE ? mSignal : 0; int signal = service == HeadsetHalConstants.NETWORK_STATE_AVAILABLE ? mCindSignal : 0; Log.d(TAG, "sendDeviceStateChanged. mService=" + mService + " mIsSimStateLoaded=" + mIsSimStateLoaded + " mSignal=" + signal + " mRoam=" + mRoam + " mBatteryCharge=" + mBatteryCharge); HeadsetStateMachine sm = mStateMachine; if (sm != null) { sm.sendMessage(HeadsetStateMachine.DEVICE_STATE_CHANGED, new HeadsetDeviceState(service, mRoam, signal, mBatteryCharge)); Log.d(TAG, "sendDeviceStateChanged. mService=" + mCindService + " mIsSimStateLoaded=" + mIsSimStateLoaded + " mSignal=" + signal + " mRoam=" + mCindRoam + " mBatteryCharge=" + mCindBatteryCharge); mHeadsetService.onDeviceStateChanged( new HeadsetDeviceState(service, mCindRoam, signal, mCindBatteryCharge)); } private class HeadsetPhoneStateOnSubscriptionChangedListener extends OnSubscriptionsChangedListener { HeadsetPhoneStateOnSubscriptionChangedListener(Looper looper) { super(looper); } @Override public void onSubscriptionsChanged() { listenForPhoneState(false); listenForPhoneState(true); } } private PhoneStateListener getPhoneStateListener(int subId) { PhoneStateListener mPhoneStateListener = new PhoneStateListener(subId) { private class HeadsetPhoneStateListener extends PhoneStateListener { HeadsetPhoneStateListener(Integer subId, Looper looper) { super(subId, looper); } @Override public void onServiceStateChanged(ServiceState serviceState) { public synchronized void onServiceStateChanged(ServiceState serviceState) { mServiceState = serviceState; int newService = (serviceState.getState() == ServiceState.STATE_IN_SERVICE) int cindService = (serviceState.getState() == ServiceState.STATE_IN_SERVICE) ? HeadsetHalConstants.NETWORK_STATE_AVAILABLE : HeadsetHalConstants.NETWORK_STATE_NOT_AVAILABLE; int newRoam = serviceState.getRoaming() ? HeadsetHalConstants.SERVICE_TYPE_ROAMING : HeadsetHalConstants.SERVICE_TYPE_HOME; if (newService == mService && newRoam == mRoam) { // Debounce the state change if (cindService == mCindService && newRoam == mCindRoam) { // De-bounce the state change return; } mService = newService; mRoam = newRoam; mCindService = cindService; mCindRoam = newRoam; // If this is due to a SIM insertion, we want to defer sending device state changed // until all the SIM config is loaded. if (newService == HeadsetHalConstants.NETWORK_STATE_NOT_AVAILABLE) { if (cindService == HeadsetHalConstants.NETWORK_STATE_NOT_AVAILABLE) { mIsSimStateLoaded = false; sendDeviceStateChanged(); return; } IntentFilter simStateChangedFilter = new IntentFilter(TelephonyIntents.ACTION_SIM_STATE_CHANGED); mContext.registerReceiver(new BroadcastReceiver() { mHeadsetService.registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(intent.getAction())) { Loading @@ -307,36 +271,37 @@ public class HeadsetPhoneState { intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE))) { mIsSimStateLoaded = true; sendDeviceStateChanged(); mContext.unregisterReceiver(this); mHeadsetService.unregisterReceiver(this); } } } }, simStateChangedFilter); } @Override public void onSignalStrengthsChanged(SignalStrength signalStrength) { int prevSignal = mSignal; if (mService == HeadsetHalConstants.NETWORK_STATE_NOT_AVAILABLE) { mSignal = 0; int prevSignal = mCindSignal; if (mCindService == HeadsetHalConstants.NETWORK_STATE_NOT_AVAILABLE) { mCindSignal = 0; } else if (signalStrength.isGsm()) { mSignal = signalStrength.getLteLevel(); if (mSignal == SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) { mSignal = gsmAsuToSignal(signalStrength); mCindSignal = signalStrength.getLteLevel(); if (mCindSignal == SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) { mCindSignal = gsmAsuToSignal(signalStrength); } else { // SignalStrength#getLteLevel returns the scale from 0-4 // Bluetooth signal scales at 0-5 // Let's match up the larger side mSignal++; mCindSignal++; } } else { mSignal = cdmaDbmEcioToSignal(signalStrength); mCindSignal = cdmaDbmEcioToSignal(signalStrength); } // network signal strength is scaled to BT 1-5 levels. // This results in a lot of duplicate messages, hence this check if (prevSignal != mSignal) { if (prevSignal != mCindSignal) { sendDeviceStateChanged(); } } Loading Loading @@ -367,8 +332,8 @@ public class HeadsetPhoneState { * Convert the cdma / evdo db levels to appropriate icon level. * The scale is similar to the one used in status bar policy. * * @param signalStrength * @return the icon level * @param signalStrength signal strength level * @return the icon level for remote device */ private int cdmaDbmEcioToSignal(SignalStrength signalStrength) { int levelDbm = 0; Loading Loading @@ -406,8 +371,8 @@ public class HeadsetPhoneState { cdmaIconLevel = (levelDbm < levelEcio) ? levelDbm : levelEcio; // STOPSHIP: Change back to getRilVoiceRadioTechnology if (mServiceState != null && (mServiceState.getRadioTechnology() == ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_0 if (mServiceState != null && ( mServiceState.getRadioTechnology() == ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_0 || mServiceState.getRadioTechnology() == ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_A)) { int evdoEcio = signalStrength.getEvdoEcio(); Loading Loading @@ -445,10 +410,7 @@ public class HeadsetPhoneState { // TODO(): There is a bug open regarding what should be sent. return (cdmaIconLevel > evdoIconLevel) ? cdmaIconLevel : evdoIconLevel; } }; return mPhoneStateListener; } } class HeadsetDeviceState { Loading Loading
android/app/src/com/android/bluetooth/hfp/AtPhonebook.java +3 −6 Original line number Diff line number Diff line Loading @@ -104,11 +104,8 @@ public class AtPhonebook { mPhonebooks.put("RC", new PhonebookResult()); // received calls mPhonebooks.put("MC", new PhonebookResult()); // missed calls mPhonebooks.put("ME", new PhonebookResult()); // mobile phonebook mCurrentPhonebook = "ME"; // default to mobile phonebook mCpbrIndex1 = mCpbrIndex2 = -1; mCheckingAccessPermission = false; } public void cleanup() { Loading Loading @@ -172,7 +169,7 @@ public class AtPhonebook { case TYPE_SET: // Set log("handleCscsCommand - Set Command"); String[] args = atString.split("="); if (args.length < 2 || !(args[1] instanceof String)) { if (args.length < 2 || args[1] == null) { mNativeInterface.atResponseCode(device, atCommandResult, atCommandErrorCode); break; } Loading Loading @@ -234,7 +231,7 @@ public class AtPhonebook { log("handleCpbsCommand - set command"); String[] args = atString.split("="); // Select phonebook memory if (args.length < 2 || !(args[1] instanceof String)) { if (args.length < 2 || args[1] == null) { atCommandErrorCode = BluetoothCmeError.OPERATION_NOT_SUPPORTED; break; } Loading Loading @@ -266,7 +263,7 @@ public class AtPhonebook { mNativeInterface.atResponseCode(device, atCommandResult, atCommandErrorCode); } public void handleCpbrCommand(String atString, int type, BluetoothDevice remoteDevice) { void handleCpbrCommand(String atString, int type, BluetoothDevice remoteDevice) { log("handleCpbrCommand - atString = " + atString); int atCommandResult = HeadsetHalConstants.AT_RESPONSE_ERROR; int atCommandErrorCode = -1; Loading
android/app/src/com/android/bluetooth/hfp/HeadsetPhoneState.java +255 −293 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Looper; import android.support.annotation.VisibleForTesting; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; import android.telephony.SignalStrength; Loading @@ -33,6 +34,8 @@ import android.util.Log; import com.android.internal.telephony.IccCardConstants; import com.android.internal.telephony.TelephonyIntents; import java.util.Objects; /** * Class that manages Telephony states Loading @@ -45,142 +48,106 @@ import com.android.internal.telephony.TelephonyIntents; public class HeadsetPhoneState { private static final String TAG = "HeadsetPhoneState"; private final Context mContext; private final HeadsetStateMachine mStateMachine; private final HeadsetService mHeadsetService; private final TelephonyManager mTelephonyManager; private final SubscriptionManager mSubMgr; private final SubscriptionManager mSubscriptionManager; private ServiceState mServiceState; // HFP 1.6 CIND service value private int mService = HeadsetHalConstants.NETWORK_STATE_NOT_AVAILABLE; private int mCindService = HeadsetHalConstants.NETWORK_STATE_NOT_AVAILABLE; // Check this before sending out service state to the device -- if the SIM isn't fully // loaded, don't expose that the network is available. private boolean mIsSimStateLoaded; // Number of active (foreground) calls private int mNumActive; // Current Call Setup State private int mCallState = HeadsetHalConstants.CALL_STATE_IDLE; // Number of held (background) calls private int mNumHeld; // HFP 1.6 CIND signal private int mSignal; // HFP 1.6 CIND roam private int mRoam = HeadsetHalConstants.SERVICE_TYPE_HOME; // HFP 1.6 CIND battchg private int mBatteryCharge; private int mSpeakerVolume; private int mMicVolume; // HFP 1.6 CIND signal value private int mCindSignal; // HFP 1.6 CIND roam value private int mCindRoam = HeadsetHalConstants.SERVICE_TYPE_HOME; // HFP 1.6 CIND battchg value private int mCindBatteryCharge; private boolean mListening; // when HFP Service Level Connection is established private boolean mSlcReady; private PhoneStateListener mPhoneStateListener; private OnSubscriptionsChangedListener mOnSubscriptionsChangedListener; private class HeadsetPhoneStateOnSubscriptionChangedListener extends OnSubscriptionsChangedListener { HeadsetPhoneStateOnSubscriptionChangedListener(Looper looper) { super(looper); } @Override public void onSubscriptionsChanged() { listenForPhoneState(false); listenForPhoneState(true); } } HeadsetPhoneState(Context context, HeadsetStateMachine stateMachine) { mStateMachine = stateMachine; mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); if (mTelephonyManager == null) { Log.e(TAG, "getSystemService(Context.TELEPHONY_SERVICE) failed, " + "cannot register for SubscriptionInfo changes"); } mContext = context; // Register for SubscriptionInfo list changes which is guaranteed // to invoke onSubscriptionInfoChanged and which in turns calls // loadInBackgroud. mSubMgr = SubscriptionManager.from(mContext); private final OnSubscriptionsChangedListener mOnSubscriptionsChangedListener; HeadsetPhoneState(HeadsetService headsetService) { Objects.requireNonNull(headsetService, "headsetService is null"); mHeadsetService = headsetService; mTelephonyManager = (TelephonyManager) mHeadsetService.getSystemService(Context.TELEPHONY_SERVICE); Objects.requireNonNull(mTelephonyManager, "TELEPHONY_SERVICE is null"); // Register for SubscriptionInfo list changes which is guaranteed to invoke // onSubscriptionInfoChanged and which in turns calls loadInBackgroud. mSubscriptionManager = SubscriptionManager.from(mHeadsetService); Objects.requireNonNull(mSubscriptionManager, "TELEPHONY_SUBSCRIPTION_SERVICE is null"); // Initialize subscription on the handler thread mOnSubscriptionsChangedListener = new HeadsetPhoneStateOnSubscriptionChangedListener( stateMachine.getHandler().getLooper()); mSubMgr.addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener); headsetService.getStateMachinesThreadLooper()); mSubscriptionManager.addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener); } /** * Cleanup this instance. Instance can no longer be used after calling this method. */ public void cleanup() { listenForPhoneState(false); if (mOnSubscriptionsChangedListener != null) { mSubMgr.removeOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener); mOnSubscriptionsChangedListener = null; } mSubscriptionManager.removeOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener); } @Override public String toString() { return "HeadsetPhoneState [mService=" + mService + ", mNumActive=" + mNumActive + ", mCallState=" + mCallState + ", mNumHeld=" + mNumHeld + ", mSignal=" + mSignal + ", mRoam=" + mRoam + ", mBatteryCharge=" + mBatteryCharge + ", mSpeakerVolume=" + mSpeakerVolume + ", mMicVolume=" + mMicVolume + ", mListening=" + mListening + ", mSlcReady=" + mSlcReady + "]"; return "HeadsetPhoneState [mTelephonyServiceAvailability=" + mCindService + ", mNumActive=" + mNumActive + ", mCallState=" + mCallState + ", mNumHeld=" + mNumHeld + ", mSignal=" + mCindSignal + ", mRoam=" + mCindRoam + ", mBatteryCharge=" + mCindBatteryCharge + ", mListening=" + mListening + "]"; } void listenForPhoneState(boolean start) { mSlcReady = start; /** * Start or stop listening for phone state change * @param start True to start, False to stop */ @VisibleForTesting public void listenForPhoneState(boolean start) { synchronized (mTelephonyManager) { if (start) { startListenForPhoneState(); } else { stopListenForPhoneState(); } } } private void startListenForPhoneState() { if (!mListening && mSlcReady && mTelephonyManager != null) { if (!mListening) { int subId = SubscriptionManager.getDefaultSubscriptionId(); if (SubscriptionManager.isValidSubscriptionId(subId)) { mPhoneStateListener = getPhoneStateListener(subId); if (mTelephonyManager == null) { Log.e(TAG, "mTelephonyManager is null, " + "cannot start listening for phone state changes"); } else { mPhoneStateListener = new HeadsetPhoneStateListener(subId, mHeadsetService.getStateMachinesThreadLooper()); mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS); mListening = true; } } else { Log.w(TAG, "startListenForPhoneState, invalid subscription ID " + subId); } } } private void stopListenForPhoneState() { if (mListening && mTelephonyManager != null) { if (mTelephonyManager == null) { Log.e(TAG, "mTelephonyManager is null, " + "cannot send request to stop listening for phone state changes"); } else { if (mListening) { mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE); mListening = false; } } } int getService() { return mService; int getCindService() { return mCindService; } int getNumActiveCall() { Loading @@ -207,97 +174,94 @@ public class HeadsetPhoneState { mNumHeld = numHeldCall; } int getSignal() { return mSignal; int getCindSignal() { return mCindSignal; } int getRoam() { return mRoam; int getCindRoam() { return mCindRoam; } void setRoam(int roam) { if (mRoam != roam) { mRoam = roam; void setCindRoam(int cindRoam) { if (mCindRoam != cindRoam) { mCindRoam = cindRoam; sendDeviceStateChanged(); } } void setBatteryCharge(int batteryLevel) { if (mBatteryCharge != batteryLevel) { mBatteryCharge = batteryLevel; void setCindBatteryCharge(int batteryLevel) { if (mCindBatteryCharge != batteryLevel) { mCindBatteryCharge = batteryLevel; sendDeviceStateChanged(); } } int getBatteryCharge() { return mBatteryCharge; } void setSpeakerVolume(int volume) { mSpeakerVolume = volume; } int getSpeakerVolume() { return mSpeakerVolume; } void setMicVolume(int volume) { mMicVolume = volume; } int getMicVolume() { return mMicVolume; int getCindBatteryCharge() { return mCindBatteryCharge; } boolean isInCall() { return (mNumActive >= 1); } void sendDeviceStateChanged() { private void sendDeviceStateChanged() { int service = mIsSimStateLoaded ? mService : HeadsetHalConstants.NETWORK_STATE_NOT_AVAILABLE; mIsSimStateLoaded ? mCindService : HeadsetHalConstants.NETWORK_STATE_NOT_AVAILABLE; // When out of service, send signal strength as 0. Some devices don't // use the service indicator, but only the signal indicator int signal = service == HeadsetHalConstants.NETWORK_STATE_AVAILABLE ? mSignal : 0; int signal = service == HeadsetHalConstants.NETWORK_STATE_AVAILABLE ? mCindSignal : 0; Log.d(TAG, "sendDeviceStateChanged. mService=" + mService + " mIsSimStateLoaded=" + mIsSimStateLoaded + " mSignal=" + signal + " mRoam=" + mRoam + " mBatteryCharge=" + mBatteryCharge); HeadsetStateMachine sm = mStateMachine; if (sm != null) { sm.sendMessage(HeadsetStateMachine.DEVICE_STATE_CHANGED, new HeadsetDeviceState(service, mRoam, signal, mBatteryCharge)); Log.d(TAG, "sendDeviceStateChanged. mService=" + mCindService + " mIsSimStateLoaded=" + mIsSimStateLoaded + " mSignal=" + signal + " mRoam=" + mCindRoam + " mBatteryCharge=" + mCindBatteryCharge); mHeadsetService.onDeviceStateChanged( new HeadsetDeviceState(service, mCindRoam, signal, mCindBatteryCharge)); } private class HeadsetPhoneStateOnSubscriptionChangedListener extends OnSubscriptionsChangedListener { HeadsetPhoneStateOnSubscriptionChangedListener(Looper looper) { super(looper); } @Override public void onSubscriptionsChanged() { listenForPhoneState(false); listenForPhoneState(true); } } private PhoneStateListener getPhoneStateListener(int subId) { PhoneStateListener mPhoneStateListener = new PhoneStateListener(subId) { private class HeadsetPhoneStateListener extends PhoneStateListener { HeadsetPhoneStateListener(Integer subId, Looper looper) { super(subId, looper); } @Override public void onServiceStateChanged(ServiceState serviceState) { public synchronized void onServiceStateChanged(ServiceState serviceState) { mServiceState = serviceState; int newService = (serviceState.getState() == ServiceState.STATE_IN_SERVICE) int cindService = (serviceState.getState() == ServiceState.STATE_IN_SERVICE) ? HeadsetHalConstants.NETWORK_STATE_AVAILABLE : HeadsetHalConstants.NETWORK_STATE_NOT_AVAILABLE; int newRoam = serviceState.getRoaming() ? HeadsetHalConstants.SERVICE_TYPE_ROAMING : HeadsetHalConstants.SERVICE_TYPE_HOME; if (newService == mService && newRoam == mRoam) { // Debounce the state change if (cindService == mCindService && newRoam == mCindRoam) { // De-bounce the state change return; } mService = newService; mRoam = newRoam; mCindService = cindService; mCindRoam = newRoam; // If this is due to a SIM insertion, we want to defer sending device state changed // until all the SIM config is loaded. if (newService == HeadsetHalConstants.NETWORK_STATE_NOT_AVAILABLE) { if (cindService == HeadsetHalConstants.NETWORK_STATE_NOT_AVAILABLE) { mIsSimStateLoaded = false; sendDeviceStateChanged(); return; } IntentFilter simStateChangedFilter = new IntentFilter(TelephonyIntents.ACTION_SIM_STATE_CHANGED); mContext.registerReceiver(new BroadcastReceiver() { mHeadsetService.registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (TelephonyIntents.ACTION_SIM_STATE_CHANGED.equals(intent.getAction())) { Loading @@ -307,36 +271,37 @@ public class HeadsetPhoneState { intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE))) { mIsSimStateLoaded = true; sendDeviceStateChanged(); mContext.unregisterReceiver(this); mHeadsetService.unregisterReceiver(this); } } } }, simStateChangedFilter); } @Override public void onSignalStrengthsChanged(SignalStrength signalStrength) { int prevSignal = mSignal; if (mService == HeadsetHalConstants.NETWORK_STATE_NOT_AVAILABLE) { mSignal = 0; int prevSignal = mCindSignal; if (mCindService == HeadsetHalConstants.NETWORK_STATE_NOT_AVAILABLE) { mCindSignal = 0; } else if (signalStrength.isGsm()) { mSignal = signalStrength.getLteLevel(); if (mSignal == SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) { mSignal = gsmAsuToSignal(signalStrength); mCindSignal = signalStrength.getLteLevel(); if (mCindSignal == SignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN) { mCindSignal = gsmAsuToSignal(signalStrength); } else { // SignalStrength#getLteLevel returns the scale from 0-4 // Bluetooth signal scales at 0-5 // Let's match up the larger side mSignal++; mCindSignal++; } } else { mSignal = cdmaDbmEcioToSignal(signalStrength); mCindSignal = cdmaDbmEcioToSignal(signalStrength); } // network signal strength is scaled to BT 1-5 levels. // This results in a lot of duplicate messages, hence this check if (prevSignal != mSignal) { if (prevSignal != mCindSignal) { sendDeviceStateChanged(); } } Loading Loading @@ -367,8 +332,8 @@ public class HeadsetPhoneState { * Convert the cdma / evdo db levels to appropriate icon level. * The scale is similar to the one used in status bar policy. * * @param signalStrength * @return the icon level * @param signalStrength signal strength level * @return the icon level for remote device */ private int cdmaDbmEcioToSignal(SignalStrength signalStrength) { int levelDbm = 0; Loading Loading @@ -406,8 +371,8 @@ public class HeadsetPhoneState { cdmaIconLevel = (levelDbm < levelEcio) ? levelDbm : levelEcio; // STOPSHIP: Change back to getRilVoiceRadioTechnology if (mServiceState != null && (mServiceState.getRadioTechnology() == ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_0 if (mServiceState != null && ( mServiceState.getRadioTechnology() == ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_0 || mServiceState.getRadioTechnology() == ServiceState.RIL_RADIO_TECHNOLOGY_EVDO_A)) { int evdoEcio = signalStrength.getEvdoEcio(); Loading Loading @@ -445,10 +410,7 @@ public class HeadsetPhoneState { // TODO(): There is a bug open regarding what should be sent. return (cdmaIconLevel > evdoIconLevel) ? cdmaIconLevel : evdoIconLevel; } }; return mPhoneStateListener; } } class HeadsetDeviceState { Loading