1cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondepackage com.android.bluetooth.sap; 2cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 3cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport java.io.BufferedInputStream; 4cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport java.io.BufferedOutputStream; 5cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport java.io.IOException; 6cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport java.io.InputStream; 7cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport java.io.OutputStream; 8cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport java.util.concurrent.CountDownLatch; 9cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 10cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport com.android.bluetooth.R; 11cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport android.app.AlarmManager; 12cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport android.app.Notification; 13cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport android.app.NotificationManager; 14cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport android.app.PendingIntent; 15cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport android.bluetooth.BluetoothDevice; 16cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport android.bluetooth.BluetoothSocket; 17cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport android.content.BroadcastReceiver; 18cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport android.content.Context; 19cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport android.content.Intent; 20cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport android.content.IntentFilter; 21cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport android.content.SyncResult; 22cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport android.os.Handler; 23cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport android.os.Handler.Callback; 24cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport android.os.HandlerThread; 25cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport android.os.Looper; 26cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport android.os.Message; 27cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport android.os.Parcel; 28cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport android.os.SystemClock; 29cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport android.telephony.TelephonyManager; 30cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport android.util.Log; 31cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde//import com.android.internal.telephony.RIL; 32cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondeimport com.google.protobuf.micro.CodedOutputStreamMicro; 33cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 34cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 35cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde/** 36cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * The SapServer uses two threads, one for reading messages from the RFCOMM socket and 37cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * one for writing the responses. 38cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * Incoming requests are decoded in the "main" SapServer, by the decoder build into SapMEssage. 39cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * The relevant RIL calls are made from the message handler thread through the rild-bt socket. 40cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * The RIL replies are read in the SapRilReceiver, and passed to the SapServer message handler 41cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * to be written to the RFCOMM socket. 42cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * All writes to the RFCOMM and rild-bt socket must be synchronized, hence to write e.g. an error 43cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * response, send a message to the Sap Handler thread. (There are helper functions to do this) 44cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * Communication to the RIL is through an intent, and a BroadcastReceiver. 45cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde */ 46cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bondepublic class SapServer extends Thread implements Callback { 47cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde private static final String TAG = "SapServer"; 48cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde private static final String TAG_HANDLER = "SapServerHandler"; 49cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde public static final boolean DEBUG = SapService.DEBUG; 50cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde public static final boolean VERBOSE = SapService.VERBOSE; 51cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde public static final boolean PTS_TEST = SapService.PTS_TEST; 52cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 53cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde private enum SAP_STATE { 54cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde DISCONNECTED, CONNECTING, CONNECTING_CALL_ONGOING, CONNECTED, 55cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde CONNECTED_BUSY, DISCONNECTING; 56cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 57cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 58cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde private SAP_STATE mState = SAP_STATE.DISCONNECTED; 59cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 60cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde private Context mContext = null; 61cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /* RFCOMM socket I/O streams */ 62cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde private BufferedOutputStream mRfcommOut = null; 63cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde private BufferedInputStream mRfcommIn = null; 64cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /* The RIL output stream - the input stream is owned by the SapRilReceiver object */ 65cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde private CodedOutputStreamMicro mRilBtOutStream = null; 66cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /* References to the SapRilReceiver object */ 67cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde private SapRilReceiver mRilBtReceiver = null; 68cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde private Thread mRilBtReceiverThread = null; 69cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /* The message handler members */ 70cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde private Handler mSapHandler = null; 71cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde private HandlerThread mHandlerThread = null; 72cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /* Reference to the SAP service - which created this instance of the SAP server */ 73cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde private Handler mSapServiceHandler = null; 74cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 75cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /* flag for when user forces disconnect of rfcomm */ 76cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde private boolean mIsLocalInitDisconnect = false; 77cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde private CountDownLatch mDeinitSignal = new CountDownLatch(1); 78cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 79cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /* Message ID's handled by the message handler */ 80cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde public static final int SAP_MSG_RFC_REPLY = 0x00; 81cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde public static final int SAP_MSG_RIL_CONNECT = 0x01; 82cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde public static final int SAP_MSG_RIL_REQ = 0x02; 83a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde public static final int SAP_MSG_RIL_IND = 0x03; 84a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde public static final int SAP_RIL_SOCK_CLOSED = 0x04; 85cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 86b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde public static final String SAP_DISCONNECT_ACTION = 87b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde "com.android.bluetooth.sap.action.DISCONNECT_ACTION"; 88b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde public static final String SAP_DISCONNECT_TYPE_EXTRA = 89b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde "com.android.bluetooth.sap.extra.DISCONNECT_TYPE"; 90cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde public static final int NOTIFICATION_ID = android.R.drawable.stat_sys_data_bluetooth; 91cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde private static final int DISCONNECT_TIMEOUT_IMMEDIATE = 5000; /* ms */ 92cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde private static final int DISCONNECT_TIMEOUT_RFCOMM = 2000; /* ms */ 93cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde private PendingIntent pDiscIntent = null; // Holds a reference to disconnect timeout intents 94b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde 95cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /* We store the mMaxMessageSize, as we need a copy of it when the init. sequence completes */ 96cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde private int mMaxMsgSize = 0; 97cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /* keep track of the current RIL test mode */ 98cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde private int mTestMode = SapMessage.INVALID_VALUE; // used to set the RIL in test mode 99cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 100cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /** 101cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * SapServer constructor 102cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * @param serviceHandler The handler to send a SapService.MSG_SERVERSESSION_CLOSE when closing 103cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * @param inStream The socket input stream 104cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * @param outStream The socket output stream 105cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde */ 106b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde public SapServer(Handler serviceHandler, Context context, InputStream inStream, 107b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde OutputStream outStream) { 108cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde mContext = context; 109cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde mSapServiceHandler = serviceHandler; 110cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 111cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /* Open in- and output streams */ 112cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde mRfcommIn = new BufferedInputStream(inStream); 113cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde mRfcommOut = new BufferedOutputStream(outStream); 114cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 115cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /* Register for phone state change and the RIL cfm message */ 116cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde IntentFilter filter = new IntentFilter(); 117cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED); 118cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde filter.addAction(SAP_DISCONNECT_ACTION); 119cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde mContext.registerReceiver(mIntentReceiver, filter); 120cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 121cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 122cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /** 123cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * This handles the response from RIL. 124cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde */ 125cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 126cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde @Override 127cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde public void onReceive(Context context, Intent intent) { 128cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(intent.getAction().equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED)) { 129cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(VERBOSE) Log.i(TAG, "ACTION_PHONE_STATE_CHANGED intent received in state " 130cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde + mState.name() 131cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde + "PhoneState: " 132cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde + intent.getStringExtra(TelephonyManager.EXTRA_STATE)); 133cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(mState == SAP_STATE.CONNECTING_CALL_ONGOING) { 134cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE); 135cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(state != null) { 136cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(state.equals(TelephonyManager.EXTRA_STATE_IDLE)) { 137cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(DEBUG) Log.i(TAG, "sending RIL.ACTION_RIL_RECONNECT_OFF_REQ intent"); 138cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde SapMessage fakeConReq = new SapMessage(SapMessage.ID_CONNECT_REQ); 139cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde fakeConReq.setMaxMsgSize(mMaxMsgSize); 140cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde onConnectRequest(fakeConReq); 141cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 142cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 143cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 144a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde } else if (intent.getAction().equals(SAP_DISCONNECT_ACTION)) { 145a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde int disconnectType = intent.getIntExtra(SapServer.SAP_DISCONNECT_TYPE_EXTRA, 146a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde SapMessage.DISC_GRACEFULL); 147cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde Log.v(TAG, " - Received SAP_DISCONNECT_ACTION type: " + disconnectType); 148cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 149a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde if(disconnectType == SapMessage.DISC_RFCOMM) { 150a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde // At timeout we need to close the RFCOMM socket to complete shutdown 151a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde shutdown(); 152a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde } else if( mState != SAP_STATE.DISCONNECTED 153a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde && mState != SAP_STATE.DISCONNECTING ) { 154a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde // The user pressed disconnect - initiate disconnect sequence. 155a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde sendDisconnectInd(disconnectType); 156a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde } 157cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } else { 158cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde Log.w(TAG, "RIL-BT received unexpected Intent: " + intent.getAction()); 159cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 160cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 161cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde }; 162cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 163cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /** 164cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * Set RIL driver in test mode - only possible if SapMessage is build with TEST == true 165cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * The value set by this function will take effect at the next connect request received 166cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * in DISCONNECTED state. 167cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * @param testMode Use SapMessage.TEST_MODE_XXX 168cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde */ 169cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde public void setTestMode(int testMode) { 170cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(SapMessage.TEST) { 171cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde mTestMode = testMode; 172cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 173cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 174cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 175cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde private void sendDisconnectInd(int discType) { 176cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(VERBOSE) Log.v(TAG, "in sendDisconnectInd()"); 177cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 178cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(discType != SapMessage.DISC_FORCED){ 179cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(VERBOSE) Log.d(TAG, "Sending disconnect ("+discType+") indication to client"); 180cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /* Send disconnect to client */ 181cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde SapMessage discInd = new SapMessage(SapMessage.ID_DISCONNECT_IND); 182cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde discInd.setDisconnectionType(discType); 183cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde sendClientMessage(discInd); 184cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 185cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /* Handle local disconnect procedures */ 186cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if (discType == SapMessage.DISC_GRACEFULL) 187cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde { 188cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /* Update the notification to allow the user to initiate a force disconnect */ 189cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde setNotification(SapMessage.DISC_IMMEDIATE, PendingIntent.FLAG_CANCEL_CURRENT); 190cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 191cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } else if (discType == SapMessage.DISC_IMMEDIATE){ 192b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde /* Request an immediate disconnect, but start a timer to force disconnect if the 193b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde * client do not obey our request. */ 194cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde startDisconnectTimer(SapMessage.DISC_FORCED, DISCONNECT_TIMEOUT_IMMEDIATE); 195cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 196cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 197cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } else { 198cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde SapMessage msg = new SapMessage(SapMessage.ID_DISCONNECT_REQ); 199cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /* Force disconnect of RFCOMM - but first we need to clean up. */ 200cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde clearPendingRilResponses(msg); 201cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 202b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde /* We simply need to forward to RIL, but not change state to busy - hence send and set 203b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde message to null. */ 204cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde changeState(SAP_STATE.DISCONNECTING); 205cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde sendRilThreadMessage(msg); 206cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde mIsLocalInitDisconnect = true; 207cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 208cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 209cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 210cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde void setNotification(int type, int flags) 211cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde { 212cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde String title, text, button, ticker; 213cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde Notification notification; 214cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(VERBOSE) Log.i(TAG, "setNotification type: " + type); 215cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /* put notification up for the user to be able to disconnect from the client*/ 216cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde Intent sapDisconnectIntent = new Intent(SapServer.SAP_DISCONNECT_ACTION); 217cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(type == SapMessage.DISC_GRACEFULL){ 218cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde title = mContext.getString(R.string.bluetooth_sap_notif_title); 219cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde button = mContext.getString(R.string.bluetooth_sap_notif_disconnect_button); 220cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde text = mContext.getString(R.string.bluetooth_sap_notif_message); 221cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde ticker = mContext.getString(R.string.bluetooth_sap_notif_ticker); 222cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde }else{ 223cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde title = mContext.getString(R.string.bluetooth_sap_notif_title); 224cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde button = mContext.getString(R.string.bluetooth_sap_notif_force_disconnect_button); 225cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde text = mContext.getString(R.string.bluetooth_sap_notif_disconnecting); 226cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde ticker = mContext.getString(R.string.bluetooth_sap_notif_ticker); 227cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 228cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(!PTS_TEST) 229cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde { 230cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde sapDisconnectIntent.putExtra(SapServer.SAP_DISCONNECT_TYPE_EXTRA, type); 231b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde PendingIntent pIntentDisconnect = PendingIntent.getBroadcast(mContext, type, 232b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde sapDisconnectIntent,flags); 233cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde notification = new Notification.Builder(mContext).setOngoing(true) 234cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde .addAction(android.R.drawable.stat_sys_data_bluetooth, button, pIntentDisconnect) 235cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde .setContentTitle(title) 236cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde .setTicker(ticker) 237cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde .setContentText(text) 238cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde .setSmallIcon(android.R.drawable.stat_sys_data_bluetooth) 239cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde .setAutoCancel(false) 240cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde .setPriority(Notification.PRIORITY_MAX) 241cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde .setOnlyAlertOnce(true) 242cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde .build(); 243cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde }else{ 244cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 245b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde sapDisconnectIntent.putExtra(SapServer.SAP_DISCONNECT_TYPE_EXTRA, 246b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde SapMessage.DISC_GRACEFULL); 247cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde Intent sapForceDisconnectIntent = new Intent(SapServer.SAP_DISCONNECT_ACTION); 248b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde sapForceDisconnectIntent.putExtra(SapServer.SAP_DISCONNECT_TYPE_EXTRA, 249b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde SapMessage.DISC_IMMEDIATE); 250b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde PendingIntent pIntentDisconnect = PendingIntent.getBroadcast(mContext, 251b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde SapMessage.DISC_GRACEFULL, sapDisconnectIntent,flags); 252b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde PendingIntent pIntentForceDisconnect = PendingIntent.getBroadcast(mContext, 253b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde SapMessage.DISC_IMMEDIATE, sapForceDisconnectIntent,flags); 254cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde notification = new Notification.Builder(mContext).setOngoing(true) 255b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde .addAction(android.R.drawable.stat_sys_data_bluetooth, 256b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde mContext.getString(R.string.bluetooth_sap_notif_disconnect_button), 257b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde pIntentDisconnect) 258b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde .addAction(android.R.drawable.stat_sys_data_bluetooth, 259b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde mContext.getString(R.string.bluetooth_sap_notif_force_disconnect_button), 260b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde pIntentForceDisconnect) 261cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde .setContentTitle(title) 262cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde .setTicker(ticker) 263cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde .setContentText(text) 264cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde .setSmallIcon(android.R.drawable.stat_sys_data_bluetooth) 265cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde .setAutoCancel(false) 266cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde .setPriority(Notification.PRIORITY_MAX) 267cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde .setOnlyAlertOnce(true) 268cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde .build(); 269cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 270cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 271a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde // cannot be set with the builder 272a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde notification.flags |= Notification.FLAG_NO_CLEAR |Notification.FLAG_ONLY_ALERT_ONCE; 273cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 274cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde NotificationManager notificationManager = 275cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); 276cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 277cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde notificationManager.notify(NOTIFICATION_ID, notification); 278cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 279a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde 280a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde void clearNotification() { 281a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde NotificationManager notificationManager = 282a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); 283a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde notificationManager.cancel(SapServer.NOTIFICATION_ID); 284a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde } 285a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde 286cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /** 287cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * The SapServer RFCOMM reader thread. Sets up the handler thread and handle 288cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * all read from the RFCOMM in-socket. This thread also handle writes to the RIL socket. 289cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde */ 290cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde @Override 291cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde public void run() { 292cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde try { 293b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde /* SAP is not time critical, hence lowering priority to ensure critical tasks are 294b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde * executed in a timely manner. */ 295cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND); 296cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 297cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /* Start the SAP message handler thread */ 298b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde mHandlerThread = new HandlerThread("SapServerHandler", 299b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde android.os.Process.THREAD_PRIORITY_BACKGROUND); 300cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde mHandlerThread.start(); 301b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde 302b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde // This will return when the looper is ready 303b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde Looper sapLooper = mHandlerThread.getLooper(); 304cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde mSapHandler = new Handler(sapLooper, this); 305cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 306bbb071e6d73df46230ec654e3066a46f6e35a88dCasper Bonde mRilBtReceiver = new SapRilReceiver(mSapHandler, mSapServiceHandler); 307cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde mRilBtReceiverThread = new Thread(mRilBtReceiver, "RilBtReceiver"); 308cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde setNotification(SapMessage.DISC_GRACEFULL,0); 309cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde boolean done = false; 310cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde while (!done) { 311cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(VERBOSE) Log.i(TAG, "Waiting for incomming RFCOMM message..."); 312cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde int requestType = mRfcommIn.read(); 313cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(requestType == -1) { 314cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde done = true; // EOF reached 315cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } else { 316cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde SapMessage msg = SapMessage.readMessage(requestType, mRfcommIn); 317bbb071e6d73df46230ec654e3066a46f6e35a88dCasper Bonde /* notify about an incoming message from the BT Client */ 318bbb071e6d73df46230ec654e3066a46f6e35a88dCasper Bonde SapService.notifyUpdateWakeLock(mSapServiceHandler); 319cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(msg != null && mState != SAP_STATE.DISCONNECTING) 320cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde { 321cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde switch (requestType) { 322cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde case SapMessage.ID_CONNECT_REQ: 323b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde if(VERBOSE) Log.d(TAG, "CONNECT_REQ - MaxMsgSize: " 324b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde + msg.getMaxMsgSize()); 325cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde onConnectRequest(msg); 326cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde msg = null; /* don't send ril connect yet */ 327cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde break; 328cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde case SapMessage.ID_DISCONNECT_REQ: /* No params */ 329cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /* 330b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde * 1) send RIL_REQUEST_SIM_SAP_DISCONNECT 331b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde * (block for all incoming requests, as they are not 332b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde * allowed, don't even send an error_resp) 333cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * 2) on response disconnect ril socket. 334cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * 3) when disconnected send RIL.ACTION_RIL_RECONNECT_OFF_REQ 335b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde * 4) on RIL.ACTION_RIL_RECONNECT_CFM 336b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde * send SAP_DISCONNECT_RESP to client. 337cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * 5) Start RFCOMM disconnect timer 338b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde * 6.a) on rfcomm disconnect: 339b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde * cancel timer and initiate cleanup 340b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde * 6.b) on rfcomm disc. timeout: 341b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde * close socket-streams and initiate cleanup */ 342cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(VERBOSE) Log.d(TAG, "DISCONNECT_REQ"); 343cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 344cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde clearPendingRilResponses(msg); 345b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde 346b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde changeState(SAP_STATE.DISCONNECTING); 347b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde 348cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde sendRilThreadMessage(msg); 349b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde /* We simply need to forward to RIL, but not change state to busy 350b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde * - hence send and set message to null. */ 351cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde msg = null; // don't send twice 352cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /*cancel the timer for the hard-disconnect intent*/ 353cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde stopDisconnectTimer(); 354cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde break; 355cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde case SapMessage.ID_POWER_SIM_OFF_REQ: // Fall through 356cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde case SapMessage.ID_RESET_SIM_REQ: 357b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde /* Forward these to the RIL regardless of the state, and clear any 358b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde * pending resp */ 359cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde clearPendingRilResponses(msg); 360cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde break; 361a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde case SapMessage.ID_SET_TRANSPORT_PROTOCOL_REQ: 362a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde /* The RIL might support more protocols that specified in the SAP, 363b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde * allow only the valid values. */ 364a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde if(mState == SAP_STATE.CONNECTED 365a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde && msg.getTransportProtocol() != 0 366a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde && msg.getTransportProtocol() != 1) { 367a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde Log.w(TAG, "Invalid TransportProtocol received:" 368a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde + msg.getTransportProtocol()); 369a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde // We shall only handle one request at the time, hence return error 370a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde SapMessage errorReply = new SapMessage(SapMessage.ID_ERROR_RESP); 371a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde sendClientMessage(errorReply); 372a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde msg = null; 373a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde } 374a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde // Fall through 375cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde default: 376b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde /* Remaining cases just needs to be forwarded to the RIL unless we are 377b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde * in busy state. */ 378cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(mState != SAP_STATE.CONNECTED) { 379b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde Log.w(TAG, "Message received in STATE != CONNECTED - state = " 380b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde + mState.name()); 381b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde // We shall only handle one request at the time, hence return error 382a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde SapMessage errorReply = new SapMessage(SapMessage.ID_ERROR_RESP); 383a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde sendClientMessage(errorReply); 384cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde msg = null; 385cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 386cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 387cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 388cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(msg != null && msg.getSendToRil() == true) { 389cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde changeState(SAP_STATE.CONNECTED_BUSY); 390cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde sendRilThreadMessage(msg); 391cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 392cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 393b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde } else { 394b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde //An unknown message or in disconnecting state - send error indication 395cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde Log.e(TAG, "Unable to parse message."); 396cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde SapMessage atrReply = new SapMessage(SapMessage.ID_ERROR_RESP); 397cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde sendClientMessage(atrReply); 398cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 399cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 400cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } // end while 401cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } catch (NullPointerException e) { 402cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde Log.w(TAG, e); 403cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } catch (IOException e) { 404cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /* This is expected during shutdown */ 405cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde Log.i(TAG, "IOException received, this is probably a shutdown signal, cleaning up..."); 406cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } catch (Exception e) { 407cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /* TODO: Change to the needed Exception types when done testing */ 408cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde Log.w(TAG, e); 409cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } finally { 410cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde // Do cleanup even if an exception occurs 411cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde stopDisconnectTimer(); 412cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /* In case of e.g. a RFCOMM close while connected: 413cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * - Initiate a FORCED shutdown 414cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * - Wait for RIL deinit to complete 415cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde */ 416cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(mState != SAP_STATE.DISCONNECTED) { 417cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(mState != SAP_STATE.DISCONNECTING && 418cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde mIsLocalInitDisconnect != true) { 419cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde sendDisconnectInd(SapMessage.DISC_FORCED); 420cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 421cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(DEBUG) Log.i(TAG, "Waiting for deinit to complete"); 422cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde try { 423cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde mDeinitSignal.await(); 424cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } catch (InterruptedException e) { 425cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde Log.e(TAG, "Interrupt received while waitinf for de-init to complete", e); 426cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 427cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 428a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde 429a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde if(mIntentReceiver != null) { 430a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde mContext.unregisterReceiver(mIntentReceiver); 431a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde mIntentReceiver = null; 432a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde } 433a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde stopDisconnectTimer(); 434a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde clearNotification(); 435a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde 436cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(mHandlerThread != null) try { 437cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde mHandlerThread.quit(); 438cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde mHandlerThread.join(); 439a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde mHandlerThread = null; 440cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } catch (InterruptedException e) {} 441cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(mRilBtReceiverThread != null) try { 442a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde if(mRilBtReceiver != null) { 443a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde mRilBtReceiver.shutdown(); 444a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde mRilBtReceiver = null; 445a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde } 446cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde mRilBtReceiverThread.join(); 447a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde mRilBtReceiverThread = null; 448cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } catch (InterruptedException e) {} 449cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 450cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(mRfcommIn != null) try { 451cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(VERBOSE) Log.i(TAG, "Closing mRfcommIn..."); 452cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde mRfcommIn.close(); 453a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde mRfcommIn = null; 454cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } catch (IOException e) {} 455cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 456cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(mRfcommOut != null) try { 457cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(VERBOSE) Log.i(TAG, "Closing mRfcommOut..."); 458cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde mRfcommOut.close(); 459a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde mRfcommOut = null; 460cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } catch (IOException e) {} 461cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 462cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if (mSapServiceHandler != null) { 463cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde Message msg = Message.obtain(mSapServiceHandler); 464cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde msg.what = SapService.MSG_SERVERSESSION_CLOSE; 465cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde msg.sendToTarget(); 466cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if (DEBUG) Log.d(TAG, "MSG_SERVERSESSION_CLOSE sent out."); 467cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 468cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde Log.i(TAG, "All done exiting thread..."); 469cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 470cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 471cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 472cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 473cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /** 474cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * This function needs to determine: 475b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde * - if the maxMsgSize is acceptable - else reply CON_STATUS_ERROR_MAX_MSG_SIZE_UNSUPPORTED 476b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde * + new maxMsgSize if too big 477cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * - connect to the RIL-BT socket 478cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * - if a call is ongoing reply CON_STATUS_OK_ONGOING_CALL. 479cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * - if all ok, just respond CON_STATUS_OK. 480cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * 481cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * @param msg the incoming SapMessage 482cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde */ 483cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde private void onConnectRequest(SapMessage msg) { 484cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde SapMessage reply = new SapMessage(SapMessage.ID_CONNECT_RESP); 485cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 486cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(mState == SAP_STATE.CONNECTING) { 487cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /* A connect request might have been rejected because of maxMessageSize negotiation, and 488cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * this is a new connect request. Simply forward to RIL, and stay in connecting state. 489cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * */ 490cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde reply = null; 491cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde sendRilMessage(msg); 492cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde stopDisconnectTimer(); 493cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 494cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } else if(mState != SAP_STATE.DISCONNECTED && mState != SAP_STATE.CONNECTING_CALL_ONGOING) { 495cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde reply.setConnectionStatus(SapMessage.CON_STATUS_ERROR_CONNECTION); 496cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } else { 497cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde // Store the MaxMsgSize for future use 498cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde mMaxMsgSize = msg.getMaxMsgSize(); 499b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde // All parameters OK, examine if a call is ongoing and start the RIL-BT listener thread 500cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if (isCallOngoing() == true) { 501b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde /* If a call is ongoing we set the state, inform the SAP client and wait for a state 502b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde * change intent from the TelephonyManager with state IDLE. */ 503cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde changeState(SAP_STATE.CONNECTING_CALL_ONGOING); 504cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde reply.setConnectionStatus(SapMessage.CON_STATUS_OK_ONGOING_CALL); 505cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } else { 506cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /* no call is ongoing, initiate the connect sequence: 507cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * 1) Start the SapRilReceiver thread (open the rild-bt socket) 508cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * 2) Send a RIL_SIM_SAP_CONNECT request to RILD 509cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * 3) Send a RIL_SIM_RESET request and a connect confirm to the SAP client */ 510cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde changeState(SAP_STATE.CONNECTING); 511cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(mRilBtReceiverThread != null) { 512b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde // Open the RIL socket, and wait for the complete message: SAP_MSG_RIL_CONNECT 513cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde mRilBtReceiverThread.start(); 514cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde // Don't send reply yet 515cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde reply = null; 516cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } else { 517cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde reply = new SapMessage(SapMessage.ID_CONNECT_RESP); 518cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde reply.setConnectionStatus(SapMessage.CON_STATUS_ERROR_CONNECTION); 519cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde sendClientMessage(reply); 520cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 521cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 522cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 523cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(reply != null) 524cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde sendClientMessage(reply); 525cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 526cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 527cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde private void clearPendingRilResponses(SapMessage msg) { 528cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(mState == SAP_STATE.CONNECTED_BUSY) { 529cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde msg.setClearRilQueue(true); 530cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 531cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 532cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /** 533cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * Send RFCOMM message to the Sap Server Handler Thread 534cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * @param sapMsg The message to send 535cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde */ 536cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde private void sendClientMessage(SapMessage sapMsg) { 537cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde Message newMsg = mSapHandler.obtainMessage(SAP_MSG_RFC_REPLY, sapMsg); 538cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde mSapHandler.sendMessage(newMsg); 539cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 540cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 541cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /** 542cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * Send a RIL message to the SapServer message handler thread 543cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * @param sapMsg 544cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde */ 545cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde private void sendRilThreadMessage(SapMessage sapMsg) { 546cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde Message newMsg = mSapHandler.obtainMessage(SAP_MSG_RIL_REQ, sapMsg); 547cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde mSapHandler.sendMessage(newMsg); 548cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 549cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 550cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /** 551cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * Examine if a call is ongoing, by asking the telephony manager 552cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * @return false if the phone is IDLE (can be used for SAP), true otherwise. 553cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde */ 554cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde private boolean isCallOngoing() { 555b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde TelephonyManager tManager = 556b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde (TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE); 557cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(tManager.getCallState() == TelephonyManager.CALL_STATE_IDLE) { 558cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde return false; 559cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 560cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde return true; 561cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 562cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 563cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /** 564cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * Change the SAP Server state. 565cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * We add thread protection, as we access the state from two threads. 566cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * @param newState 567cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde */ 568cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde private void changeState(SAP_STATE newState) { 569cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(DEBUG) Log.i(TAG_HANDLER,"Changing state from " + mState.name() + 570cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde " to " + newState.name()); 571cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde synchronized (this) { 572cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde mState = newState; 573cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 574cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 575cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 576cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 577cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /************************************************************************* 578cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * SAP Server Message Handler Thread Functions 579cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde *************************************************************************/ 580cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 581cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /** 582cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * The SapServer message handler thread implements the SAP state machine. 583cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * - Handle all outgoing communication to the out-socket. Either replies from the RIL or direct 584cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * messages send from the SapServe (e.g. connect_resp). 585cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * - Handle all outgoing communication to the RIL-BT socket. 586cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * - Handle all replies from the RIL 587cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde */ 588cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde @Override 589cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde public boolean handleMessage(Message msg) { 590b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde if(VERBOSE) Log.i(TAG_HANDLER,"Handling message (ID: " + msg.what + "): " 591b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde + getMessageName(msg.what)); 592cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 593cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde SapMessage sapMsg = null; 594cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 595cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde switch(msg.what) { 596cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde case SAP_MSG_RFC_REPLY: 597cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde sapMsg = (SapMessage) msg.obj; 598cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde handleRfcommReply(sapMsg); 599cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde break; 600cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde case SAP_MSG_RIL_CONNECT: 601cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /* The connection to rild-bt have been established. Store the outStream handle 602cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * and send the connect request. */ 603cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde mRilBtOutStream = mRilBtReceiver.getRilBtOutStream(); 604cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(mTestMode != SapMessage.INVALID_VALUE) { 605cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde SapMessage rilTestModeReq = new SapMessage(SapMessage.ID_RIL_SIM_ACCESS_TEST_REQ); 606cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde rilTestModeReq.setTestMode(mTestMode); 607cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde sendRilMessage(rilTestModeReq); 608cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde mTestMode = SapMessage.INVALID_VALUE; 609cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 610cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde SapMessage rilSapConnect = new SapMessage(SapMessage.ID_CONNECT_REQ); 611cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde rilSapConnect.setMaxMsgSize(mMaxMsgSize); 612cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde sendRilMessage(rilSapConnect); 613cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde break; 614cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde case SAP_MSG_RIL_REQ: 615cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde sapMsg = (SapMessage) msg.obj; 616cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(sapMsg != null) { 617cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde sendRilMessage(sapMsg); 618cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 619cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde break; 620cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde case SAP_MSG_RIL_IND: 621cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde sapMsg = (SapMessage) msg.obj; 622cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde handleRilInd(sapMsg); 623cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde break; 624a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde case SAP_RIL_SOCK_CLOSED: 625a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde /* The RIL socket was closed unexpectedly, send immediate disconnect indication 626a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde - close RFCOMM after timeout if no response. */ 627a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde sendDisconnectInd(SapMessage.DISC_IMMEDIATE); 628a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde startDisconnectTimer(SapMessage.DISC_RFCOMM, DISCONNECT_TIMEOUT_RFCOMM); 629a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde break; 630cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde default: 631cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /* Message not handled */ 632cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde return false; 633cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 634cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde return true; // Message handles 635cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 636cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 637cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /** 638cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * Close the in/out rfcomm streams, to trigger a shutdown of the SapServer main thread. 639cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * Use this after completing the deinit sequence. 640cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde */ 641cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde private void shutdown() { 642cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 643cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(DEBUG) Log.i(TAG_HANDLER, "in Shutdown()"); 644cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde try { 645cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde mRfcommOut.close(); 646cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } catch (IOException e) {} 647cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde try { 648cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde mRfcommIn.close(); 649cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 650cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } catch (IOException e) {} 651cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde mRfcommIn = null; 652cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde mRfcommOut = null; 653cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde stopDisconnectTimer(); 654a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde clearNotification(); 655cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 656cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 657cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde private void startDisconnectTimer(int discType, int timeMs) { 658cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 659cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde stopDisconnectTimer(); 660cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde synchronized (this) { 661cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde Intent sapDisconnectIntent = new Intent(SapServer.SAP_DISCONNECT_ACTION); 662cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde sapDisconnectIntent.putExtra(SAP_DISCONNECT_TYPE_EXTRA, discType); 663cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde AlarmManager alarmManager = 664cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); 665cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde pDiscIntent = PendingIntent.getBroadcast(mContext, 666cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde discType, 667b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde sapDisconnectIntent, 668b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde PendingIntent.FLAG_CANCEL_CURRENT); 669b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 670b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde SystemClock.elapsedRealtime() + timeMs, pDiscIntent); 671cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 672cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(VERBOSE) Log.d(TAG_HANDLER, "Setting alarm for " + timeMs + 673cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde " ms to activate disconnect type " + discType); 674cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 675cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 676cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 677cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde private void stopDisconnectTimer() { 678cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde synchronized (this) { 679cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(pDiscIntent != null) 680cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde { 681cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde AlarmManager alarmManager = 682cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE); 683cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde alarmManager.cancel(pDiscIntent); 684cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde pDiscIntent.cancel(); 685cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(VERBOSE) { 686cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde Log.d(TAG_HANDLER, "Canceling disconnect alarm"); 687cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 688cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde pDiscIntent = null; 689cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 690cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 691cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 692cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 693cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /** 694cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * Here we handle the replies to the SAP client, normally forwarded directly from the RIL. 695cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * We do need to handle some of the messages in the SAP profile, hence we look at the messages 696cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * here before they go to the client 697cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * @param sapMsg the message to send to the SAP client 698cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde */ 699cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde private void handleRfcommReply(SapMessage sapMsg) { 700cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(sapMsg != null) { 701cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 702b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde if(DEBUG) Log.i(TAG_HANDLER, "handleRfcommReply() handling " 703b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde + SapMessage.getMsgTypeName(sapMsg.getMsgType())); 704cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 705cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde switch(sapMsg.getMsgType()) { 706cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 707cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde case SapMessage.ID_CONNECT_RESP: 708cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if (sapMsg.getConnectionStatus() == SapMessage.CON_STATUS_OK) { 709cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde // This is successful connect response from RIL/modem. 710cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde changeState(SAP_STATE.CONNECTED); 711cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } else if(sapMsg.getConnectionStatus() == SapMessage.CON_STATUS_OK_ONGOING_CALL 712cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde && mState != SAP_STATE.CONNECTING_CALL_ONGOING) { 713cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde changeState(SAP_STATE.CONNECTING_CALL_ONGOING); 714cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } else if(mState == SAP_STATE.CONNECTING_CALL_ONGOING) { 715b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde /* Hold back the connect resp if a call was ongoing when the connect req 716b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde * was received. 717b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde */ 718b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde if(VERBOSE) Log.i(TAG, "Hold back the connect resp, as a call was ongoing" + 719b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde " when the initial response were sent."); 720cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde sapMsg = null; 721cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } else if(sapMsg.getConnectionStatus() != SapMessage.CON_STATUS_OK) { 722b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde /* Most likely the peer will try to connect again, hence we keep the 723b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde * connection to RIL open and stay in connecting state. 724b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde * 725b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde * Start timer to do shutdown if a new connect request is not received in 726b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde * time. */ 727cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde startDisconnectTimer(SapMessage.DISC_FORCED, DISCONNECT_TIMEOUT_RFCOMM); 728cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 729cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde break; 730cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde case SapMessage.ID_DISCONNECT_RESP: 731cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(mState == SAP_STATE.DISCONNECTING) { 732a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde /* Close the RIL-BT output Stream and signal to SapRilReceiver to close 733a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde * down the input stream. */ 734a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde if(DEBUG) Log.i(TAG, "ID_DISCONNECT_RESP received in SAP_STATE." + 735a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde "DISCONNECTING."); 736a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde 737a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde /* Send the disconnect resp, and wait for the client to close the Rfcomm, 738a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde * but start a timeout timer, just to be sure. Use alarm, to ensure we wake 739a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde * the host to close the connection to minimize power consumption. */ 740cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde SapMessage disconnectResp = new SapMessage(SapMessage.ID_DISCONNECT_RESP); 741cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde changeState(SAP_STATE.DISCONNECTED); 742cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde sapMsg = disconnectResp; 743a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde startDisconnectTimer(SapMessage.DISC_RFCOMM, DISCONNECT_TIMEOUT_RFCOMM); 744a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde mDeinitSignal.countDown(); /* Signal deinit complete */ 745cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } else { /* DISCONNECTED */ 746cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde mDeinitSignal.countDown(); /* Signal deinit complete */ 747cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(mIsLocalInitDisconnect == true) { 748cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(VERBOSE) Log.i(TAG_HANDLER, "This is a FORCED disconnect."); 749b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde /* We needed to force the disconnect, hence no hope for the client to 750b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde * close the RFCOMM connection, hence we do it here. */ 751cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde shutdown(); 752cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde sapMsg = null; 753cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } else { 754b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde /* The client must disconnect the RFCOMM, but in case it does not, we 755b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde * need to do it. 756b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde * We start an alarm, and if it triggers, we must send the 757b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde * MSG_SERVERSESSION_CLOSE */ 758cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(VERBOSE) Log.i(TAG_HANDLER, "This is a NORMAL disconnect."); 759cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde startDisconnectTimer(SapMessage.DISC_RFCOMM, DISCONNECT_TIMEOUT_RFCOMM); 760cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 761cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 762cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde break; 763cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde case SapMessage.ID_STATUS_IND: 764cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /* Some car-kits only "likes" status indication when connected, hence discard 765cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * any arriving outside this state */ 766cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(mState == SAP_STATE.DISCONNECTED || 767cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde mState == SAP_STATE.CONNECTING || 768cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde mState == SAP_STATE.DISCONNECTING) { 769cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde sapMsg = null; 770cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 771cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde break; 772cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde default: 773cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde // Nothing special, just send the message 774cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 775cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 776cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 777cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /* Update state variable based on the number of pending commands. We are only able to 778cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * handle one request at the time, except from disconnect, sim off and sim reset. 779cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * Hence if one of these are received while in busy state, we might have a crossing 780cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * response, hence we must stay in BUSY state if we have an ongoing RIL request. */ 781cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(mState == SAP_STATE.CONNECTED_BUSY) { 782cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(SapMessage.getNumPendingRilMessages() == 0) { 783cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde changeState(SAP_STATE.CONNECTED); 784cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 785cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 786cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 787cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde // This is the default case - just send the message to the SAP client. 788cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(sapMsg != null) 789cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde sendReply(sapMsg); 790cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 791cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 792cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde private void handleRilInd(SapMessage sapMsg) { 793cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(sapMsg == null) 794cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde return; 795cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 796cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde switch(sapMsg.getMsgType()) { 797cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde case SapMessage.ID_DISCONNECT_IND: 798cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde { 799cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde if(mState != SAP_STATE.DISCONNECTED && mState != SAP_STATE.DISCONNECTING){ 800cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /* we only send disconnect indication to the client if we are actually connected*/ 801cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde SapMessage reply = new SapMessage(SapMessage.ID_DISCONNECT_IND); 802cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde reply.setDisconnectionType(sapMsg.getDisconnectionType()) ; 803cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde sendClientMessage(reply); 804cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } else { 805cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /* TODO: This was introduced to handle disconnect indication from RIL */ 806cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde sendDisconnectInd(sapMsg.getDisconnectionType()); 807cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 808cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde break; 809cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 810cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 811cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde default: 812b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde if(DEBUG) Log.w(TAG_HANDLER,"Unhandled message - type: " 813b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde + SapMessage.getMsgTypeName(sapMsg.getMsgType())); 814cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 815cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 816cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 817cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /** 818cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * This is only to be called from the handlerThread, else use sendRilThreadMessage(); 819cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * @param sapMsg 820cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde */ 821cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde private void sendRilMessage(SapMessage sapMsg) { 822b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde if(VERBOSE) Log.i(TAG_HANDLER, "sendRilMessage() - " 823b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde + SapMessage.getMsgTypeName(sapMsg.getMsgType())); 824cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde try { 825cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde sapMsg.writeReqToStream(mRilBtOutStream); 826cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } catch (IOException e) { 827cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde Log.e(TAG_HANDLER, "Unable to send message to RIL", e); 828cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde SapMessage errorReply = new SapMessage(SapMessage.ID_ERROR_RESP); 829cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde sendClientMessage(errorReply); 830cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 831cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 832cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 833cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde /** 834cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde * Only call this from the sapHandler thread. 835cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde */ 836cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde private void sendReply(SapMessage msg) { 837b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde if(VERBOSE) Log.i(TAG_HANDLER, "sendReply() RFCOMM - " 838b6791189b3c8be04b521b8520aed006f012304d1Casper Bonde + SapMessage.getMsgTypeName(msg.getMsgType())); 839a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde if(mRfcommOut != null) { // Needed to handle brutal shutdown from car-kit and out of range 840a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde try { 841a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde msg.write(mRfcommOut); 842a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde mRfcommOut.flush(); 843a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde } catch (IOException e) { 844a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde Log.w(TAG_HANDLER, e); 845a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde /* As we cannot write to the rfcomm channel we are disconnected. 846a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde Shutdown and prepare for a new connect. */ 847a49b4e45faf378e3848c4f6eb468e0a14565aa6cCasper Bonde } 848cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 849cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 850cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 851cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde private static String getMessageName(int messageId) { 852cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde switch (messageId) { 853cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde case SAP_MSG_RFC_REPLY: 854cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde return "SAP_MSG_REPLY"; 855cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde case SAP_MSG_RIL_CONNECT: 856cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde return "SAP_MSG_RIL_CONNECT"; 857cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde case SAP_MSG_RIL_REQ: 858cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde return "SAP_MSG_RIL_REQ"; 859cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde case SAP_MSG_RIL_IND: 860cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde return "SAP_MSG_RIL_IND"; 861cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde default: 862cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde return "Unknown message ID"; 863cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 864cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde } 865cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde 866cee0d1b1f13b4401a895be650605fa307e70bdb6Casper Bonde} 867