Home | History | Annotate | Download | only in map
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.bluetooth.client.map;
     18 
     19 import android.os.Handler;
     20 import android.os.HandlerThread;
     21 import android.os.Looper;
     22 import android.os.Message;
     23 import android.os.Process;
     24 import android.util.Log;
     25 
     26 import java.io.IOException;
     27 import java.lang.ref.WeakReference;
     28 
     29 import javax.obex.ClientSession;
     30 import javax.obex.HeaderSet;
     31 import javax.obex.ObexTransport;
     32 import javax.obex.ResponseCodes;
     33 
     34 class BluetoothMasObexClientSession {
     35     private static final String TAG = "BluetoothMasObexClientSession";
     36 
     37     private static final byte[] MAS_TARGET = new byte[] {
     38             (byte) 0xbb, 0x58, 0x2b, 0x40, 0x42, 0x0c, 0x11, (byte) 0xdb, (byte) 0xb0, (byte) 0xde,
     39             0x08, 0x00, 0x20, 0x0c, (byte) 0x9a, 0x66
     40     };
     41 
     42     private boolean DBG = true;
     43 
     44     static final int MSG_OBEX_CONNECTED = 100;
     45     static final int MSG_OBEX_DISCONNECTED = 101;
     46     static final int MSG_REQUEST_COMPLETED = 102;
     47 
     48     private static final int CONNECT = 0;
     49     private static final int DISCONNECT = 1;
     50     private static final int REQUEST = 2;
     51 
     52     private final ObexTransport mTransport;
     53 
     54     private final Handler mSessionHandler;
     55 
     56     private ClientSession mSession;
     57 
     58     private HandlerThread mThread;
     59     private Handler mHandler;
     60 
     61     private boolean mConnected;
     62 
     63     private static class ObexClientHandler extends Handler {
     64        WeakReference<BluetoothMasObexClientSession> mInst;
     65 
     66        ObexClientHandler(Looper looper, BluetoothMasObexClientSession inst) {
     67           super(looper);
     68           mInst = new WeakReference<BluetoothMasObexClientSession>(inst);
     69        }
     70 
     71        @Override
     72        public void handleMessage(Message msg) {
     73           BluetoothMasObexClientSession inst = mInst.get();
     74           if (!inst.connected() && msg.what != CONNECT) {
     75               Log.w(TAG, "Cannot execute " + msg + " when not CONNECTED.");
     76               return;
     77           }
     78 
     79           switch (msg.what) {
     80               case CONNECT:
     81                   inst.connect();
     82                   break;
     83 
     84               case DISCONNECT:
     85                   inst.disconnect();
     86                   break;
     87 
     88               case REQUEST:
     89                   inst.executeRequest((BluetoothMasRequest) msg.obj);
     90                   break;
     91           }
     92        }
     93     }
     94 
     95     public BluetoothMasObexClientSession(ObexTransport transport, Handler handler) {
     96         mTransport = transport;
     97         mSessionHandler = handler;
     98     }
     99 
    100     public void start() {
    101         if (DBG) Log.d(TAG, "start called.");
    102         if (mConnected) {
    103             if (DBG) Log.d(TAG, "Already connected, nothing to do.");
    104             return;
    105         }
    106 
    107         // Start a thread to handle messages here.
    108         mThread = new HandlerThread("BluetoothMasObexClientSessionThread");
    109         mThread.start();
    110         mHandler = new ObexClientHandler(mThread.getLooper(), this);
    111 
    112         // Connect it to the target device via OBEX.
    113         mHandler.obtainMessage(CONNECT).sendToTarget();
    114     }
    115 
    116     public boolean makeRequest(BluetoothMasRequest request) {
    117         if (DBG) Log.d(TAG, "makeRequest called with: " + request);
    118 
    119         boolean status = mHandler.sendMessage(mHandler.obtainMessage(REQUEST, request));
    120         if (!status) {
    121             Log.e(TAG, "Adding messages failed, state: " + mConnected);
    122             return false;
    123         }
    124         return true;
    125     }
    126 
    127     public void stop() {
    128         if (DBG) Log.d(TAG, "stop called...");
    129 
    130         mThread.quit();
    131         disconnect();
    132     }
    133 
    134     private void connect() {
    135         try {
    136             mSession = new ClientSession(mTransport);
    137 
    138             HeaderSet headerset = new HeaderSet();
    139             headerset.setHeader(HeaderSet.TARGET, MAS_TARGET);
    140 
    141             headerset = mSession.connect(headerset);
    142 
    143             if (headerset.getResponseCode() == ResponseCodes.OBEX_HTTP_OK) {
    144                 mConnected = true;
    145                 mSessionHandler.obtainMessage(MSG_OBEX_CONNECTED).sendToTarget();
    146             } else {
    147                 disconnect();
    148             }
    149         } catch (IOException e) {
    150             disconnect();
    151         }
    152     }
    153 
    154     private void disconnect() {
    155         if (mSession != null) {
    156             try {
    157                 mSession.disconnect(null);
    158             } catch (IOException e) {
    159             }
    160 
    161             try {
    162                 mSession.close();
    163             } catch (IOException e) {
    164             }
    165         }
    166 
    167         mConnected = false;
    168         mSessionHandler.obtainMessage(MSG_OBEX_DISCONNECTED).sendToTarget();
    169     }
    170 
    171     private void executeRequest(BluetoothMasRequest request) {
    172         try {
    173             request.execute(mSession);
    174             mSessionHandler.obtainMessage(MSG_REQUEST_COMPLETED, request).sendToTarget();
    175         } catch (IOException e) {
    176             if (DBG) Log.d(TAG, "Request failed: " + request);
    177 
    178             // Disconnect to cleanup.
    179             disconnect();
    180         }
    181     }
    182 
    183 
    184     private boolean connected() {
    185         return mConnected;
    186     }
    187 }
    188