gt:                 sock = device.createRfcommSocketToServiceRecord(MY_UUID);
context: /*
   * Copyright (C) 2013 jonas.oreland@gmail.com
   *
   *  This program is free software: you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License as published by
   *  the Free Software Foundation, either version 3 of the License, or
   *  (at your option) any later version.
   *
   *  This program is distributed in the hope that it will be useful,
   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   *  GNU General Public License for more details.
   *
   *  You should have received a copy of the GNU General Public License
   *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
   */
  
  package org.runnerup.hr;
  
  import android.annotation.TargetApi;
  import android.app.Activity;
  import android.bluetooth.BluetoothAdapter;
  import android.bluetooth.BluetoothDevice;
  import android.bluetooth.BluetoothSocket;
  import android.content.Context;
  import android.content.Intent;
  import android.os.Build;
  import android.os.Handler;
  
  import java.io.IOException;
  import java.io.InputStream;
  import java.lang.reflect.InvocationTargetException;
  import java.lang.reflect.Method;
  import java.util.HashSet;
  import java.util.Set;
  import java.util.UUID;
  
  /**
   * Base class for BT 2.0 HR providers. It has a thread for connecting with a
   * bluetooth device and a thread for performing data transmission when
   * connected.
   */
  @TargetApi(Build.VERSION_CODES.GINGERBREAD_MR1)
  public abstract class Bt20Base extends BtHRBase {
  
      public boolean isEnabled() {
          return isEnabledImpl();
      }
  
      public static boolean isEnabledImpl() {
          if (BluetoothAdapter.getDefaultAdapter() != null)
              return BluetoothAdapter.getDefaultAdapter().isEnabled();
          return false;
      }
  
      public boolean startEnableIntent(Activity activity, int requestCode) {
          return startEnableIntentImpl(activity, requestCode);
      }
  
      public static boolean startEnableIntentImpl(Activity activity, int requestCode) {
          activity.startActivityForResult(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE),
                  requestCode);
          return true;
      }
  
      public static boolean checkLibrary(Context ctx) {
  
          // Don't bother if createInsecureRfcommSocketToServiceRecord isn't
          // available
          if (Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD_MR1)
              return false;
  
          return true;
      }
  
      // UUID
      public static final UUID MY_UUID = UUID
              .fromString("00001101-0000-1000-8000-00805F9B34FB");
      private ConnectThread connectThread;
      private ConnectedThread connectedThread;
  
      private int hrValue = 0;
      private long hrTimestamp = 0;
      private BluetoothAdapter btAdapter = null;
  
      // private Context context = null;
  
      public Bt20Base(Context ctx) {
          // context = ctx;
      }
  
      @Override
      public void open(Handler handler, HRClient hrClient) {
          this.hrClient = hrClient;
          this.hrClientHandler = handler;
  
          if (btAdapter == null) {
              btAdapter = BluetoothAdapter.getDefaultAdapter();
          }
          if (btAdapter == null) {
              hrClient.onOpenResult(false);
              return;
          }
  
          hrClient.onOpenResult(true);
      }
  
      @Override
      public void close() {
          reset();
          btAdapter = null;
      }
  
      private boolean mIsConnecting;
      private boolean mIsConnected;
      private boolean mIsScanning;
  
      public void disconnect() {
          reset();
          hrClient.onDisconnectResult(true);
      }
  
      private void reset() {
          cancelThreads();
          mIsConnecting = false;
          mIsConnected = false;
          mIsScanning = false;
      }
  
      @Override
      public boolean isScanning() {
          return mIsScanning;
      }
  
      @Override
      public boolean isConnected() {
          return mIsConnected;
      }
  
      @Override
      public boolean isConnecting() {
          return mIsConnecting;
      }
  
      @Override
      public int getHRValue() {
          return hrValue;
      }
  
      @Override
      public long getHRValueTimestamp() {
          return hrTimestamp;
      }
  
      @Override
      public HRData getHRData() {
          if (hrValue <= 0) {
              return null;
          }
  
          return new HRData().setHeartRate(hrValue).setTimestampEstimate(hrTimestamp);
      }
  
      @Override
      public int getBatteryLevel() {
          return -1;
      }
  
      /**
       * Cancels all the threads.
       */
      private void cancelThreads() {
          if (connectThread != null) {
              connectThread.cancel();
              connectThread = null;
          }
          if (connectedThread != null) {
              connectedThread.cancel();
              connectedThread = null;
          }
      }
  
      @Override
      public boolean isBondingDevice() {
          return true;
      }
  
      @Override
      public void startScan() {
          if (btAdapter == null)
              return;
  
          mIsScanning = true;
  
          hrClientHandler.post(new Runnable() {
              @Override
              public void run() {
                  Set<BluetoothDevice> list = new HashSet<BluetoothDevice>();
                  list.addAll(btAdapter.getBondedDevices());
                  publishDevice(list);
              }
          });
      }
  
      private void publishDevice(final Set<BluetoothDevice> list) {
          if (list.isEmpty()) {
              mIsScanning = false;
              return;
          }
  
          if (mIsScanning) {
              BluetoothDevice dev = list.iterator().next();
              list.remove(dev);
              hrClient.onScanResult(createDeviceRef(getProviderName(), dev));
              hrClientHandler.post(new Runnable() {
  
                  @Override
                  public void run() {
                      publishDevice(list);
                  }
              });
          }
      }
  
      @Override
      public void stopScan() {
          mIsScanning = false;
      }
  
      @Override
      public void connect(HRDeviceRef ref) {
          cancelThreads();
  
          if (!isEnabledImpl()) {
              reportConnected(false);
              return;
          }
  
          mIsConnecting = true;
          connectThread = new ConnectThread(btAdapter.getRemoteDevice(ref.deviceAddress),
                  ref.deviceName);
          connectThread.start();
      }
  
      private synchronized void connected(final BluetoothSocket bluetoothSocket,
              final BluetoothDevice bluetoothDevice,
              final String btDeviceName) {
          cancelThreads();
  
          if (hrClient != null) {
              hrClientHandler.post(new Runnable() {
  
                  @Override
                  public void run() {
                      if (mIsConnecting && hrClient != null) {
                          // Start connected thread...
                          connectedThread = new ConnectedThread(bluetoothDevice, btDeviceName,
                                  bluetoothSocket);
                          connectedThread.start();
                      } else {
                          log("closeSocket");
                          closeSocket(bluetoothSocket);
                      }
                  }
              });
          } else {
              log("closeSocket");
              closeSocket(bluetoothSocket);
          }
      }
  
      protected static void closeSocket(BluetoothSocket bluetoothSocket) {
          if (bluetoothSocket != null) {
              try {
                  bluetoothSocket.close();
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
  
      }
  
      protected static void closeStream(InputStream stream) {
          if (stream != null) {
              try {
                  stream.close();
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
      }
  
      private void reportConnected(final boolean result) {
          log("reportConnected(" + result + ") mIsConnecting: " + mIsConnecting
                  + ", mIsConnected: " + mIsConnected + ", hrClient: " + hrClient);
          if (hrClient != null) {
              hrClientHandler.post(new Runnable() {
  
                  @Override
                  public void run() {
                      boolean reset = !result;
                      if (mIsConnecting && hrClient != null) {
                          mIsConnected = result;
                          mIsConnecting = false;
                          hrClient.onConnectResult(result);
                      } else {
                          reset = true;
                      }
  
                      if (reset) {
                          Bt20Base.this.reset();
                      }
                  }
              });
          }
      }
  
      static BluetoothSocket tryConnect(BtHRBase base, final BluetoothDevice device, int i)
              throws IOException {
          BluetoothSocket sock = null;
          base.log("tryConnect(method: " + i + ")");
  
          switch (i) {
              case 0:
  