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.Process;
     21 import android.util.Log;
     22 
     23 import java.io.IOException;
     24 
     25 import javax.obex.ClientSession;
     26 import javax.obex.HeaderSet;
     27 import javax.obex.ObexTransport;
     28 import javax.obex.ResponseCodes;
     29 
     30 class BluetoothMasObexClientSession {
     31     private static final String TAG = "BluetoothMasObexClientSession";
     32 
     33     private static final byte[] MAS_TARGET = new byte[] {
     34             (byte) 0xbb, 0x58, 0x2b, 0x40, 0x42, 0x0c, 0x11, (byte) 0xdb, (byte) 0xb0, (byte) 0xde,
     35             0x08, 0x00, 0x20, 0x0c, (byte) 0x9a, 0x66
     36     };
     37 
     38     static final int MSG_OBEX_CONNECTED = 100;
     39     static final int MSG_OBEX_DISCONNECTED = 101;
     40     static final int MSG_REQUEST_COMPLETED = 102;
     41 
     42     private final ObexTransport mTransport;
     43 
     44     private final Handler mSessionHandler;
     45 
     46     private ClientThread mClientThread;
     47 
     48     private volatile boolean mInterrupted;
     49 
     50     private class ClientThread extends Thread {
     51         private final ObexTransport mTransport;
     52 
     53         private ClientSession mSession;
     54 
     55         private BluetoothMasRequest mRequest;
     56 
     57         private boolean mConnected;
     58 
     59         public ClientThread(ObexTransport transport) {
     60             super("MAS ClientThread");
     61 
     62             mTransport = transport;
     63             mConnected = false;
     64         }
     65 
     66         @Override
     67         public void run() {
     68             Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
     69 
     70             connect();
     71 
     72             if (mConnected) {
     73                 mSessionHandler.obtainMessage(MSG_OBEX_CONNECTED).sendToTarget();
     74             } else {
     75                 mSessionHandler.obtainMessage(MSG_OBEX_DISCONNECTED).sendToTarget();
     76                 return;
     77             }
     78 
     79             while (!mInterrupted) {
     80                 synchronized (this) {
     81                     if (mRequest == null) {
     82                         try {
     83                             this.wait();
     84                         } catch (InterruptedException e) {
     85                             mInterrupted = true;
     86                         }
     87                     }
     88                 }
     89 
     90                 if (!mInterrupted && mRequest != null) {
     91                     try {
     92                         mRequest.execute(mSession);
     93                     } catch (IOException e) {
     94                         // this will "disconnect" to cleanup
     95                         mInterrupted = true;
     96                     }
     97 
     98                     BluetoothMasRequest oldReq = mRequest;
     99                     mRequest = null;
    100 
    101                     mSessionHandler.obtainMessage(MSG_REQUEST_COMPLETED, oldReq).sendToTarget();
    102                 }
    103             }
    104 
    105             disconnect();
    106 
    107             mSessionHandler.obtainMessage(MSG_OBEX_DISCONNECTED).sendToTarget();
    108         }
    109 
    110         private void connect() {
    111             try {
    112                 mSession = new ClientSession(mTransport);
    113 
    114                 HeaderSet headerset = new HeaderSet();
    115                 headerset.setHeader(HeaderSet.TARGET, MAS_TARGET);
    116 
    117                 headerset = mSession.connect(headerset);
    118 
    119                 if (headerset.getResponseCode() == ResponseCodes.OBEX_HTTP_OK) {
    120                     mConnected = true;
    121                 } else {
    122                     disconnect();
    123                 }
    124             } catch (IOException e) {
    125             }
    126         }
    127 
    128         private void disconnect() {
    129             try {
    130                 mSession.disconnect(null);
    131             } catch (IOException e) {
    132             }
    133 
    134             try {
    135                 mSession.close();
    136             } catch (IOException e) {
    137             }
    138 
    139             mConnected = false;
    140         }
    141 
    142         public synchronized boolean schedule(BluetoothMasRequest request) {
    143             if (mRequest != null) {
    144                 return false;
    145             }
    146 
    147             mRequest = request;
    148             notify();
    149 
    150             return true;
    151         }
    152     }
    153 
    154     public BluetoothMasObexClientSession(ObexTransport transport, Handler handler) {
    155         mTransport = transport;
    156         mSessionHandler = handler;
    157     }
    158 
    159     public void start() {
    160         if (mClientThread == null) {
    161             mClientThread = new ClientThread(mTransport);
    162             mClientThread.start();
    163         }
    164 
    165     }
    166 
    167     public void stop() {
    168         if (mClientThread != null) {
    169             mClientThread.interrupt();
    170 
    171             (new Thread() {
    172                 @Override
    173                 public void run() {
    174                     try {
    175                         mClientThread.join();
    176                         mClientThread = null;
    177                     } catch (InterruptedException e) {
    178                         Log.w(TAG, "Interrupted while waiting for thread to join");
    179                     }
    180                 }
    181             }).run();
    182         }
    183     }
    184 
    185     public boolean makeRequest(BluetoothMasRequest request) {
    186         if (mClientThread == null) {
    187             return false;
    188         }
    189 
    190         return mClientThread.schedule(request);
    191     }
    192 }
    193