1f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen/* 2f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen * Copyright (C) 2012 The Android Open Source Project 3f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen * 4f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen * Licensed under the Apache License, Version 2.0 (the "License"); 5f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen * you may not use this file except in compliance with the License. 6f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen * You may obtain a copy of the License at 7f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen * 8f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen * http://www.apache.org/licenses/LICENSE-2.0 9f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen * 10f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen * Unless required by applicable law or agreed to in writing, software 11f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen * distributed under the License is distributed on an "AS IS" BASIS, 12f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen * See the License for the specific language governing permissions and 14f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen * limitations under the License. 15f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen */ 16f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenenpackage com.android.nfc.handover; 17f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen 18f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenenimport android.nfc.FormatException; 19f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenenimport android.nfc.NdefMessage; 20f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenenimport android.util.Log; 21f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen 22f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenenimport com.android.nfc.LlcpException; 23f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenenimport com.android.nfc.NfcService; 24f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenenimport com.android.nfc.DeviceHost.LlcpServerSocket; 25f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenenimport com.android.nfc.DeviceHost.LlcpSocket; 26f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen 27f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenenimport java.io.ByteArrayOutputStream; 28f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenenimport java.io.IOException; 29f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenenimport java.util.Arrays; 30f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen 31f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenenpublic final class HandoverServer { 32f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen public static final String HANDOVER_SERVICE_NAME = "urn:nfc:sn:handover"; 33f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen public static final String TAG = "HandoverServer"; 34f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen public static final Boolean DBG = false; 35f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen 36f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen public static final int MIU = 128; 37f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen 38f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen final HandoverManager mHandoverManager; 39f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen final int mSap; 40f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen final Callback mCallback; 41f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen 42f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen ServerThread mServerThread = null; 43f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen boolean mServerRunning = false; 44f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen 45f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen public interface Callback { 46f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen void onHandoverRequestReceived(); 47f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 48f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen 49f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen public HandoverServer(int sap, HandoverManager manager, Callback callback) { 50f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen mSap = sap; 51f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen mHandoverManager = manager; 52f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen mCallback = callback; 53f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 54f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen 55f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen public synchronized void start() { 56f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen if (mServerThread == null) { 57f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen mServerThread = new ServerThread(); 58f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen mServerThread.start(); 59f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen mServerRunning = true; 60f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 61f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 62f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen 63f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen public synchronized void stop() { 64f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen if (mServerThread != null) { 65f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen mServerThread.shutdown(); 66f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen mServerThread = null; 67f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen mServerRunning = false; 68f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 69f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 70f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen 71f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen private class ServerThread extends Thread { 72f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen private boolean mThreadRunning = true; 73f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen LlcpServerSocket mServerSocket; 74f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen 75f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen @Override 76f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen public void run() { 77f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen boolean threadRunning; 78f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen synchronized (HandoverServer.this) { 79f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen threadRunning = mThreadRunning; 80f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 81f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen 82f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen while (threadRunning) { 83f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen try { 84f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen synchronized (HandoverServer.this) { 85f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen mServerSocket = NfcService.getInstance().createLlcpServerSocket(mSap, 86f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen HANDOVER_SERVICE_NAME, MIU, 1, 1024); 87f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 88f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen if (mServerSocket == null) { 89f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen if (DBG) Log.d(TAG, "failed to create LLCP service socket"); 90f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen return; 91f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 92f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen if (DBG) Log.d(TAG, "created LLCP service socket"); 93f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen synchronized (HandoverServer.this) { 94f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen threadRunning = mThreadRunning; 95f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 96f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen 97f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen while (threadRunning) { 98f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen LlcpServerSocket serverSocket; 99f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen synchronized (HandoverServer.this) { 100f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen serverSocket = mServerSocket; 101f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 102f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen 103f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen if (serverSocket == null) { 104f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen if (DBG) Log.d(TAG, "Server socket shut down."); 105f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen return; 106f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 107f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen if (DBG) Log.d(TAG, "about to accept"); 108f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen LlcpSocket communicationSocket = serverSocket.accept(); 109f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen if (DBG) Log.d(TAG, "accept returned " + communicationSocket); 110f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen if (communicationSocket != null) { 111f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen new ConnectionThread(communicationSocket).start(); 112f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 113f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen 114f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen synchronized (HandoverServer.this) { 115f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen threadRunning = mThreadRunning; 116f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 117f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 118f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen if (DBG) Log.d(TAG, "stop running"); 119f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } catch (LlcpException e) { 120f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen Log.e(TAG, "llcp error", e); 121f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } catch (IOException e) { 122f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen Log.e(TAG, "IO error", e); 123f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } finally { 124f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen synchronized (HandoverServer.this) { 125f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen if (mServerSocket != null) { 126f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen if (DBG) Log.d(TAG, "about to close"); 127f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen try { 128f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen mServerSocket.close(); 129f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } catch (IOException e) { 130f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen // ignore 131f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 132f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen mServerSocket = null; 133f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 134f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 135f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 136f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen 137f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen synchronized (HandoverServer.this) { 138f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen threadRunning = mThreadRunning; 139f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 140f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 141f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 142f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen 143f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen public void shutdown() { 144f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen synchronized (HandoverServer.this) { 145f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen mThreadRunning = false; 146f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen if (mServerSocket != null) { 147f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen try { 148f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen mServerSocket.close(); 149f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } catch (IOException e) { 150f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen // ignore 151f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 152f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen mServerSocket = null; 153f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 154f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 155f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 156f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 157f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen 158f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen private class ConnectionThread extends Thread { 159f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen private final LlcpSocket mSock; 160f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen 161f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen ConnectionThread(LlcpSocket socket) { 162f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen super(TAG); 163f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen mSock = socket; 164f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 165f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen 166f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen @Override 167f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen public void run() { 168f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen if (DBG) Log.d(TAG, "starting connection thread"); 169f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); 170f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen 171f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen try { 172f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen boolean running; 173f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen synchronized (HandoverServer.this) { 174f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen running = mServerRunning; 175f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 176f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen 177f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen byte[] partial = new byte[mSock.getLocalMiu()]; 178f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen 179f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen NdefMessage handoverRequestMsg = null; 180f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen while (running) { 181f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen int size = mSock.receive(partial); 182f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen if (size < 0) { 183f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen break; 184f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 185f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen byteStream.write(partial, 0, size); 186f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen // 1) Try to parse a handover request message from bytes received so far 187f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen try { 188f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen handoverRequestMsg = new NdefMessage(byteStream.toByteArray()); 189f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } catch (FormatException e) { 190f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen // Ignore, and try to fetch more bytes 191f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 192f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen 193f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen if (handoverRequestMsg != null) { 194f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen // 2) convert to handover response 195f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen NdefMessage resp = mHandoverManager.tryHandoverRequest(handoverRequestMsg); 196f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen if (resp == null) { 197f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen Log.e(TAG, "Failed to create handover response"); 198f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen break; 199f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 200f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen 201f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen // 3) send handover response 202f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen int offset = 0; 203f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen byte[] buffer = resp.toByteArray(); 204f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen int remoteMiu = mSock.getRemoteMiu(); 205f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen while (offset < buffer.length) { 206f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen int length = Math.min(buffer.length - offset, remoteMiu); 207f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen byte[] tmpBuffer = Arrays.copyOfRange(buffer, offset, offset+length); 208f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen mSock.send(tmpBuffer); 209f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen offset += length; 210f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 211f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen // We're done 212f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen mCallback.onHandoverRequestReceived(); 213be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project // We can process another handover transfer 214be1939b4b6003ac7a65fcb95a3912f5e1ce8e75fThe Android Open Source Project byteStream = new ByteArrayOutputStream(); 215f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 216f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen 217f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen synchronized (HandoverServer.this) { 218f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen running = mServerRunning; 219f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 220f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 221f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen 222f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } catch (IOException e) { 223f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen if (DBG) Log.d(TAG, "IOException"); 224f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } finally { 225f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen try { 226f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen if (DBG) Log.d(TAG, "about to close"); 227f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen mSock.close(); 228f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } catch (IOException e) { 229f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen // ignore 230f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 231f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen try { 232f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen byteStream.close(); 233f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } catch (IOException e) { 234f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen // ignore 235f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 236f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 237f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen if (DBG) Log.d(TAG, "finished connection thread"); 238f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 239f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen } 240f5a196b643c654c7ea98a5e2935e3bff6683399bMartijn Coenen} 241