private synchronized void closeConnection() {
   stopBuffersThreads();
   if (connectedThread != null) {
     connectedThread.cancel();
     connectedThread.interrupt();
     connectedThread = null;
   }
   boolean isConnected;
   synchronized (isConnectedLock) {
     isConnected = this.isConnected;
     this.isConnected = false;
   }
   if (callbacksTimeout != null) callbacksTimeout.stopTimer();
   if (exitingCallbacksThread != null && exitingCallbacksThread.isAlive())
     exitingCallbacksThread.interrupt();
   if (enteringCallbacksThread != null && enteringCallbacksThread.isAlive())
     enteringCallbacksThread.interrupt();
   queuedFrames.clear();
   synchronized (arduinoCallbacksLock) {
     isInACallback = false;
   }
   if (isConnected) {
     Log.d("Device " + this.name + ": Device disconnected.");
     onDisconnect();
   }
 }
 private void callbackExited() {
   synchronized (arduinoCallbacksLock) {
     isInACallback = false;
     lastTimeCallbacksExited = SystemClock.elapsedRealtime();
   }
   if (callbacksTimeout != null && !callbacksTimeout.isAlive()) callbacksTimeout.stopTimer();
   if (exitingCallbacksThread != null && exitingCallbacksThread.isAlive()) return;
   exitingCallbacksThread =
       new Thread(
           new Runnable() {
             @Override
             public void run() {
               boolean sent;
               while (!queuedFrames.isEmpty()) {
                 sent = false;
                 synchronized (arduinoCallbacksLock) {
                   if (!isInACallback
                       && lastTimeCallbacksExited != 0
                       && (SystemClock.elapsedRealtime() - lastTimeCallbacksExited > 200)) {
                     sendFrame(queuedFrames.poll());
                     sent = true;
                   }
                 }
                 if (sent)
                   try {
                     Thread.sleep(200);
                   } catch (InterruptedException ignored) {
                   }
               }
             }
           });
   exitingCallbacksThread.start();
 }
 private byte readByteFromSerialBuffer() throws InterruptedException, ShieldFrameNotComplete {
   if (ShieldFrameTimeout != null && ShieldFrameTimeout.isTimeout())
     throw new ShieldFrameNotComplete();
   isSerialBufferWaiting = true;
   byte temp = serialBuffer.take();
   if (ShieldFrameTimeout != null) ShieldFrameTimeout.resetTimer();
   return temp;
 }