1/* 2* Copyright (C) 2015 Samsung System LSI 3* Licensed under the Apache License, Version 2.0 (the "License"); 4* you may not use this file except in compliance with the License. 5* You may obtain a copy of the License at 6* 7* http://www.apache.org/licenses/LICENSE-2.0 8* 9* Unless required by applicable law or agreed to in writing, software 10* distributed under the License is distributed on an "AS IS" BASIS, 11* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12* See the License for the specific language governing permissions and 13* limitations under the License. 14*/ 15 16package com.android.bluetooth; 17 18import android.bluetooth.BluetoothSocket; 19import android.os.Handler; 20import android.os.Handler.Callback; 21import android.os.HandlerThread; 22import android.os.Looper; 23import android.os.Message; 24import android.util.Log; 25 26import java.io.IOException; 27 28import javax.obex.HeaderSet; 29import javax.obex.ServerRequestHandler; 30 31/** 32 * A simple ObexServer used to handle connection rejection in two cases: 33 * - A profile cannot handle a new connection, as it is already connected to another device. 34 * - The user rejected access to the resources needed by the profile. 35 * 36 * Will reject the OBEX connection, start a timer, and at timeout close the socket. 37 */ 38public class ObexRejectServer extends ServerRequestHandler implements Callback { 39 40 private static final String TAG = "ObexRejectServer"; 41 private static final boolean V = true; 42 private final int mResult; 43 private final HandlerThread mHandlerThread; 44 private final Handler mMessageHandler; 45 private static final int MSG_ID_TIMEOUT = 0x01; 46 private static final int TIMEOUT_VALUE = 5 * 1000; // ms 47 private final BluetoothSocket mSocket; 48 49 /** 50 * @param result the ResponseCodes.OBEX_HTTP_ code to respond to an incoming connect request. 51 */ 52 public ObexRejectServer(int result, BluetoothSocket socket) { 53 super(); 54 mResult = result; 55 mSocket = socket; 56 mHandlerThread = new HandlerThread("TestTimeoutHandler", 57 android.os.Process.THREAD_PRIORITY_BACKGROUND); 58 mHandlerThread.start(); 59 Looper timeoutLooper = mHandlerThread.getLooper(); 60 mMessageHandler = new Handler(timeoutLooper, this); 61 // Initiate self destruction. 62 mMessageHandler.sendEmptyMessageDelayed(MSG_ID_TIMEOUT, TIMEOUT_VALUE); 63 } 64 65 // OBEX operation handlers 66 @Override 67 public int onConnect(HeaderSet request, HeaderSet reply) { 68 if (V) { 69 Log.i(TAG, "onConnect() returning error"); 70 } 71 return mResult; 72 } 73 74 public void shutdown() { 75 mMessageHandler.removeCallbacksAndMessages(null); 76 mHandlerThread.quit(); 77 try { 78 // This will cause an exception in the ServerSession, causing it to shut down 79 mSocket.close(); 80 } catch (IOException e) { 81 Log.w(TAG, "Unable to close socket - ignoring", e); 82 } 83 } 84 85 @Override 86 public boolean handleMessage(Message msg) { 87 if (V) { 88 Log.i(TAG, "Handling message ID: " + msg.what); 89 } 90 switch (msg.what) { 91 case MSG_ID_TIMEOUT: 92 shutdown(); 93 break; 94 default: 95 // Message not handled 96 return false; 97 } 98 return true; // Message handled 99 } 100} 101