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 16 package com.android.bluetooth; 17 18 import android.bluetooth.BluetoothSocket; 19 import android.os.Handler; 20 import android.os.HandlerThread; 21 import android.os.Looper; 22 import android.os.Message; 23 import android.util.Log; 24 25 import com.android.obex.HeaderSet; 26 import com.android.obex.ServerRequestHandler; 27 28 import java.io.IOException; 29 30 /** 31 * A simple ObexServer used to handle connection rejection in two cases: - A profile cannot handle a 32 * new connection, as it is already connected to another device. - The user rejected access to the 33 * resources needed by the profile. 34 * 35 * <p>Will reject the OBEX connection, start a timer, and at timeout close the socket. 36 */ 37 public class ObexRejectServer extends ServerRequestHandler implements Handler.Callback { 38 39 private static final String TAG = "ObexRejectServer"; 40 private final int mResult; 41 private final HandlerThread mHandlerThread; 42 private final Handler mMessageHandler; 43 private static final int MSG_ID_TIMEOUT = 0x01; 44 private static final int TIMEOUT_VALUE = 5 * 1000; // ms 45 private final BluetoothSocket mSocket; 46 47 /** 48 * @param result the ResponseCodes.OBEX_HTTP_ code to respond to an incoming connect request. 49 */ ObexRejectServer(int result, BluetoothSocket socket)50 public ObexRejectServer(int result, BluetoothSocket socket) { 51 super(); 52 mResult = result; 53 mSocket = socket; 54 mHandlerThread = 55 new HandlerThread( 56 "TestTimeoutHandler", android.os.Process.THREAD_PRIORITY_BACKGROUND); 57 mHandlerThread.start(); 58 Looper timeoutLooper = mHandlerThread.getLooper(); 59 mMessageHandler = new Handler(timeoutLooper, this); 60 // Initiate self destruction. 61 mMessageHandler.sendEmptyMessageDelayed(MSG_ID_TIMEOUT, TIMEOUT_VALUE); 62 } 63 64 // OBEX operation handlers 65 @Override onConnect(HeaderSet request, HeaderSet reply)66 public int onConnect(HeaderSet request, HeaderSet reply) { 67 Log.i(TAG, "onConnect() returning error"); 68 return mResult; 69 } 70 shutdown()71 public void shutdown() { 72 mMessageHandler.removeCallbacksAndMessages(null); 73 mHandlerThread.quit(); 74 try { 75 // This will cause an exception in the ServerSession, causing it to shut down 76 mSocket.close(); 77 } catch (IOException e) { 78 Log.w(TAG, "Unable to close socket - ignoring", e); 79 } 80 } 81 82 @Override handleMessage(Message msg)83 public boolean handleMessage(Message msg) { 84 Log.i(TAG, "Handling message ID: " + msg.what); 85 switch (msg.what) { 86 case MSG_ID_TIMEOUT: 87 shutdown(); 88 break; 89 default: 90 // Message not handled 91 return false; 92 } 93 return true; // Message handled 94 } 95 } 96