BluetoothOppObexServerSession.java revision df7415da0e510ab8e4b73831a5ade38306982fe1
109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly/* 209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Copyright (c) 2008-2009, Motorola, Inc. 309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * 409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * All rights reserved. 509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * 609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Redistribution and use in source and binary forms, with or without 709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * modification, are permitted provided that the following conditions are met: 809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * 909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * - Redistributions of source code must retain the above copyright notice, 1009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * this list of conditions and the following disclaimer. 1109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * 1209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * - Redistributions in binary form must reproduce the above copyright notice, 1309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * this list of conditions and the following disclaimer in the documentation 1409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * and/or other materials provided with the distribution. 1509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * 1609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * - Neither the name of the Motorola, Inc. nor the names of its contributors 1709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * may be used to endorse or promote products derived from this software 1809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * without specific prior written permission. 1909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * 2009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 2409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 2509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 2609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 2809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 2909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * POSSIBILITY OF SUCH DAMAGE. 3109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 3209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 3309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellypackage com.android.bluetooth.opp; 3409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 3509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport java.io.BufferedOutputStream; 3609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport java.io.File; 3709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport java.io.FileNotFoundException; 3809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport java.io.FileOutputStream; 3909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport java.io.IOException; 4009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport java.io.InputStream; 4109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 4209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.content.ContentValues; 4309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.content.Context; 4409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.content.Intent; 4509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.net.Uri; 4609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.os.Handler; 4709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.os.Message; 4809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.util.Log; 4909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.webkit.MimeTypeMap; 5009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 5109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport javax.obex.HeaderSet; 5209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport javax.obex.ObexTransport; 5309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport javax.obex.Operation; 5409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport javax.obex.ResponseCodes; 5509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport javax.obex.ServerRequestHandler; 5609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport javax.obex.ServerSession; 5709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 5809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly/** 5909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * This class runs as an OBEX server 6009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 6109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellypublic class BluetoothOppObexServerSession extends ServerRequestHandler implements 6209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly BluetoothOppObexSession { 6309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 6409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private static final String TAG = "BtOpp Server"; 6509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 6609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private ObexTransport mTransport; 6709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 6809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private Context mContext; 6909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 7009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private Handler mCallback = null; 7109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 7209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* status when server is blocking for user/auto confirmation */ 7309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private boolean mServerBlocking = true; 7409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 7509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* the current transfer info */ 7609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private BluetoothOppShareInfo mInfo; 7709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 7809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* info id when we insert the record */ 7909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private int mLocalShareInfoId; 8009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 8109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private int mAccepted = BluetoothShare.USER_CONFIRMATION_PENDING; 8209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 8309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private boolean mInterrupted = false; 8409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 8509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private ServerSession mSession; 8609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 8709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private long mTimestamp; 8809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 8909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private BluetoothOppReceiveFileInfo mFileInfo; 9009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 9109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public BluetoothOppObexServerSession(Context context, ObexTransport transport) { 9209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mContext = context; 9309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mTransport = transport; 9409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 9509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 9609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void unblock() { 9709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mServerBlocking = false; 9809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 9909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 10009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /** 10109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Called when connection is accepted from remote, to retrieve the first 10209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Header then wait for user confirmation 10309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 10409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void preStart() { 10509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly try { 10609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGV) { 10709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Create ServerSession with transport " + mTransport.toString()); 10809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 10909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mSession = new ServerSession(mTransport, this, null); 11009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } catch (IOException e) { 11109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.e(TAG, "Create server session error" + e); 11209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 11309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 11409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 11509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /** 11609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Called from BluetoothOppTransfer to start the "Transfer" 11709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 11809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void start(Handler handler) { 11909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGV) { 12009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Start!"); 12109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 12209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mCallback = handler; 12309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 12409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 12509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 12609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /** 1276769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun * Called from BluetoothOppTransfer to cancel the "Transfer" Otherwise, 1286769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun * server should end by itself. 12909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 13009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void stop() { 13109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* 13209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * TODO now we implement in a tough way, just close the socket. 13309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * maybe need nice way 13409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 13509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGV) { 13609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Stop!"); 13709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 13809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mInterrupted = true; 13909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mSession != null) { 14009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly try { 14109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mSession.close(); 14209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mTransport.close(); 14309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } catch (IOException e) { 14409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.e(TAG, "close mTransport error" + e); 14509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 14609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 14709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 14809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 14909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void addShare(BluetoothOppShareInfo info) { 15009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGV) { 15109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "addShare for id " + info.mId); 15209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 15309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mInfo = info; 15409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mFileInfo = processShareInfo(); 15509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 15609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 15709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly @Override 15809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public int onPut(Operation op) { 15909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGV) { 16009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "onPut " + op.toString()); 16109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 16209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly HeaderSet request; 16309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly String name, mimeType; 16409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Long length; 16509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 16609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int obexResponse = ResponseCodes.OBEX_HTTP_OK; 16709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 16809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /** 16909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * For multiple objects, reject further objects after user deny the 17009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * first one 17109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 17209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mAccepted == BluetoothShare.USER_CONFIRMATION_DENIED) { 17309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return ResponseCodes.OBEX_HTTP_FORBIDDEN; 17409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 17509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 17609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly try { 17709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly boolean pre_reject = false; 1786769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun request = op.getReceivedHeader(); 17909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 18009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly logHeader(request); 18109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 18209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly name = (String)request.getHeader(HeaderSet.NAME); 18309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly length = (Long)request.getHeader(HeaderSet.LENGTH); 18409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mimeType = (String)request.getHeader(HeaderSet.TYPE); 18509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 18609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (length == 0) { 18709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGV) { 18809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.w(TAG, "length is 0, reject the transfer"); 18909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 19009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly pre_reject = true; 19109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly obexResponse = ResponseCodes.OBEX_HTTP_LENGTH_REQUIRED; 19209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 19309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 19409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (name == null || name.equals("")) { 19509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGV) { 19609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.w(TAG, "name is null or empty, reject the transfer"); 19709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 19809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly pre_reject = true; 19909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly obexResponse = ResponseCodes.OBEX_HTTP_BAD_REQUEST; 20009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 20109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 20209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (!pre_reject) { 20309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* first we look for Mimetype in Android map */ 20409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly String extension, type; 20509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int dotIndex = name.indexOf('.'); 20609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (dotIndex < 0) { 20709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGV) { 20809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.w(TAG, "There is no file extension, reject the transfer"); 20909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 21009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly pre_reject = true; 21109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly obexResponse = ResponseCodes.OBEX_HTTP_BAD_REQUEST; 21209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 21309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly extension = name.substring(dotIndex + 1); 21409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly MimeTypeMap map = MimeTypeMap.getSingleton(); 21509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly type = map.getMimeTypeFromExtension(extension); 21609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 21709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Mimetype guessed from extension " + extension + " is " 21809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + mimeType); 21909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 22009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (type != null) { 22109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mimeType = type; 22209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 22309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 22409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mimeType == null) { 22509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGV) { 22609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.w(TAG, "Can't get mimetype, reject the transfer"); 22709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 22809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly pre_reject = true; 22909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly obexResponse = ResponseCodes.OBEX_HTTP_BAD_REQUEST; 23009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 23109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 23209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mimeType != null) { 23309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mimeType = mimeType.toLowerCase(); 23409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 23509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 23609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 23709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 23809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (!pre_reject 23909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly && (mimeType == null || Constants.mimeTypeMatches(mimeType, 24009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Constants.UNACCEPTABLE_SHARE_INBOUND_TYPES))) { 24109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGV) { 24209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.w(TAG, "mimeType is null or in unacceptable list, reject the transfer"); 24309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 24409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly pre_reject = true; 24509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly obexResponse = ResponseCodes.OBEX_HTTP_UNSUPPORTED_TYPE; 24609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 24709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 24809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (pre_reject && obexResponse != ResponseCodes.OBEX_HTTP_OK) { 24909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return obexResponse; 25009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 25109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 25209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } catch (IOException e) { 25309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.e(TAG, "get getReceivedHeaders error " + e); 25409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return ResponseCodes.OBEX_HTTP_BAD_REQUEST; 25509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 25609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 25709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly ContentValues values = new ContentValues(); 25809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 25909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly values.put(BluetoothShare.FILENAME_HINT, name); 26009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly values.put(BluetoothShare.TOTAL_BYTES, length.intValue()); 26109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly values.put(BluetoothShare.MIMETYPE, mimeType); 26209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 26309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mTransport instanceof BluetoothOppRfcommTransport) { 26409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly String a = ((BluetoothOppRfcommTransport)mTransport).getRemoteAddress(); 26509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly values.put(BluetoothShare.DESTINATION, a); 26609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 26709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly values.put(BluetoothShare.DESTINATION, "FF:FF:FF:00:00:00"); 26809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 26909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 27009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly values.put(BluetoothShare.DIRECTION, BluetoothShare.DIRECTION_INBOUND); 27109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly values.put(BluetoothShare.TIMESTAMP, mTimestamp); 27209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 27309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly boolean needConfirm = true; 27409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /** It's not first put if !serverBlocking, so we auto accept it */ 27509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (!mServerBlocking) { 27609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly values.put(BluetoothShare.USER_CONFIRMATION, 27709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly BluetoothShare.USER_CONFIRMATION_AUTO_CONFIRMED); 27809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly needConfirm = false; 27909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 28009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 28109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Uri contentUri = mContext.getContentResolver().insert(BluetoothShare.CONTENT_URI, values); 28209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mLocalShareInfoId = Integer.parseInt(contentUri.getPathSegments().get(1)); 28309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 28409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (needConfirm) { 28509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Intent in = new Intent(BluetoothShare.INCOMING_FILE_CONFIRMATION_REQUEST_ACTION); 28609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly in.setClassName(Constants.THIS_PACKAGE_NAME, BluetoothOppReceiver.class.getName()); 28709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mContext.sendBroadcast(in); 28809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 28909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 29009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 29109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "insert contentUri: " + contentUri); 29209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "mLocalShareInfoId = " + mLocalShareInfoId); 29309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 29409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 29509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly // TODO add server wait timeout 29609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mServerBlocking = true; 297df7415da0e510ab8e4b73831a5ade38306982fe1Tao Liejun boolean msgSent = false; 29809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly synchronized (this) { 29909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly try { 300df7415da0e510ab8e4b73831a5ade38306982fe1Tao Liejun 30109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly while (mServerBlocking) { 30209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly wait(1000); 30309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mCallback != null && !msgSent) { 30409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mCallback.sendMessageDelayed(mCallback 30509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly .obtainMessage(BluetoothOppObexSession.MSG_CONNECT_TIMEOUT), 30609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly BluetoothOppObexSession.SESSION_TIMEOUT); 30709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msgSent = true; 30809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 30909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "MSG_CONNECT_TIMEOUT sent"); 31009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 31109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 31209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 31309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } catch (InterruptedException e) { 31409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 31509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Interrupted in onPut blocking"); 31609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 31709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 31809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 31909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGV) { 32009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Server unblocked "); 32109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 322df7415da0e510ab8e4b73831a5ade38306982fe1Tao Liejun if (mCallback != null && msgSent) { 3236769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun mCallback.removeMessages(BluetoothOppObexSession.MSG_CONNECT_TIMEOUT); 3246769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun } 32509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 32609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* we should have mInfo now */ 32709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 32809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* 32909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * TODO check if this mInfo match the one that we insert before server 33009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * blocking? just to make sure no error happens 33109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 33209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mInfo.mId != mLocalShareInfoId) { 33309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.e(TAG, "Unexpected error!"); 33409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 33509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mAccepted = mInfo.mConfirm; 33609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 33709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 33809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "after confirm: userAccepted=" + mAccepted); 33909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 34009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int status = BluetoothShare.STATUS_SUCCESS; 34109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 34209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mAccepted == BluetoothShare.USER_CONFIRMATION_CONFIRMED 343df7415da0e510ab8e4b73831a5ade38306982fe1Tao Liejun || mAccepted == BluetoothShare.USER_CONFIRMATION_AUTO_CONFIRMED) { 34409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* Confirm or auto-confirm */ 34509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 34609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mFileInfo.mFileName == null) { 34709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly status = mFileInfo.mStatus; 34809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* TODO need to check if this line is correct */ 34909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mInfo.mStatus = mFileInfo.mStatus; 35009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Constants.updateShareStatus(mContext, mInfo.mId, status); 35109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly obexResponse = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; 35209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 35309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 35409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 35509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mFileInfo.mFileName != null) { 35609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 35709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly ContentValues updateValues = new ContentValues(); 35809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly contentUri = Uri.parse(BluetoothShare.CONTENT_URI + "/" + mInfo.mId); 35909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly updateValues.put(BluetoothShare._DATA, mFileInfo.mFileName); 36009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly updateValues.put(BluetoothShare.STATUS, BluetoothShare.STATUS_RUNNING); 36109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mContext.getContentResolver().update(contentUri, updateValues, null, null); 36209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 36309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly status = receiveFile(mFileInfo, op); 36409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* 36509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * TODO map status to obex response code 36609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 36709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (status != BluetoothShare.STATUS_SUCCESS) { 36809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly obexResponse = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; 36909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 37009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Constants.updateShareStatus(mContext, mInfo.mId, status); 37109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 37209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 37309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (status == BluetoothShare.STATUS_SUCCESS) { 37409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Message msg = Message.obtain(mCallback, BluetoothOppObexSession.MSG_SHARE_COMPLETE); 37509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.obj = mInfo; 37609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.sendToTarget(); 37709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 37809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Message msg = Message.obtain(mCallback, BluetoothOppObexSession.MSG_SESSION_ERROR); 37909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.obj = mInfo; 38009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.sendToTarget(); 38109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 38209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else if (mAccepted == BluetoothShare.USER_CONFIRMATION_DENIED 38309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly || mAccepted == BluetoothShare.USER_CONFIRMATION_TIMEOUT) { 38409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* user actively deny the inbound transfer */ 38509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* 38609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Note There is a question: what's next if user deny the first obj? 38709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Option 1 :continue prompt for next objects 38809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Option 2 :reject next objects and finish the session 38909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Now we take option 2: 39009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 39109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 39209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "request forbidden, indicate interrupted"); 39309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 39409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly status = BluetoothShare.STATUS_FORBIDDEN; 39509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Constants.updateShareStatus(mContext, mInfo.mId, status); 39609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly obexResponse = ResponseCodes.OBEX_HTTP_FORBIDDEN; 39709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Message msg = Message.obtain(mCallback); 39809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* TODO check which message should be sent */ 39909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.what = BluetoothOppObexSession.MSG_SHARE_INTERRUPTED; 40009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.obj = mInfo; 40109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.sendToTarget(); 40209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 40309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return obexResponse; 40409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 40509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 40609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private int receiveFile(BluetoothOppReceiveFileInfo fileInfo, Operation op) { 40709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* 40809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * implement receive file 40909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 41009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int status = -1; 41109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly BufferedOutputStream bos = null; 41209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 41309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly InputStream is = null; 41409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly boolean error = false; 41509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly try { 41609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly is = op.openInputStream(); 41709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } catch (IOException e1) { 41809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.e(TAG, "Error when openInputStream"); 41909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly status = BluetoothShare.STATUS_OBEX_DATA_ERROR; 42009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly error = true; 42109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 42209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 42309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Uri contentUri = Uri.parse(BluetoothShare.CONTENT_URI + "/" + mInfo.mId); 42409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 42509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (!error) { 42609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly ContentValues updateValues = new ContentValues(); 42709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly updateValues.put(BluetoothShare._DATA, fileInfo.mFileName); 42809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mContext.getContentResolver().update(contentUri, updateValues, null, null); 42909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 43009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 43109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int position = 0; 43209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (!error) { 43309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly File f = new File(fileInfo.mFileName); 43409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly try { 43509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly bos = new BufferedOutputStream(new FileOutputStream(f), 0x10000); 43609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } catch (FileNotFoundException e1) { 43709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.e(TAG, "Error when open file " + f.toString()); 43809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly status = BluetoothShare.STATUS_FILE_ERROR; 43909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly error = true; 44009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 44109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 44209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 44309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (!error) { 44409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int outputBufferSize = op.getMaxPacketSize(); 44509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly byte[] b = new byte[outputBufferSize]; 44609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int readLength = 0; 44709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly long timestamp; 44809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly try { 44909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly while ((!mInterrupted) && (position != fileInfo.mLength)) { 45009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 45109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 45209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly timestamp = System.currentTimeMillis(); 45309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 45409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 45509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly readLength = is.read(b); 45609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 45709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (readLength == -1) { 45809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGV) { 45909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Receive file reached stream end at position" + position); 46009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 46109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly break; 46209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 46309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 46409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly bos.write(b, 0, readLength); 46509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly position += readLength; 46609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 46709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.USE_EMULATOR_DEBUG) { 46809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly synchronized (this) { 46909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly try { 47009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly wait(300); 47109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } catch (InterruptedException e) { 47209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly status = BluetoothShare.STATUS_CANCELED; 47309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mInterrupted = true; 47409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 47509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "ReceiveFile interrupted when receive file " 47609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + fileInfo.mFileName + " at " + position + " of " 47709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + position); 47809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 47909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Constants.updateShareStatus(mContext, mInfo.mId, status); 48009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 48109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 48209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 48309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 48409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 48509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Receive file position = " + position + " readLength " 48609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + readLength + " bytes took " 48709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + (System.currentTimeMillis() - timestamp) + " ms"); 48809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 48909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 49009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly ContentValues updateValues = new ContentValues(); 49109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly updateValues.put(BluetoothShare.CURRENT_BYTES, position); 49209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mContext.getContentResolver().update(contentUri, updateValues, null, null); 49309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 49409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } catch (IOException e1) { 49509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.e(TAG, "Error when receiving file"); 49609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly status = BluetoothShare.STATUS_OBEX_DATA_ERROR; 49709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly error = true; 49809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 49909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 50009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 50109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mInterrupted) { 50209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGV) { 50309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "receiving file interrupted by user."); 50409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 50509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly status = BluetoothShare.STATUS_CANCELED; 50609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 50709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (position == fileInfo.mLength) { 50809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGV) { 50909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Receiving file completed for " + fileInfo.mFileName); 51009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 51109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly status = BluetoothShare.STATUS_SUCCESS; 51209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 51309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGV) { 51409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Reading file failed at " + position + " of " + fileInfo.mLength); 51509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 51609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (status == -1) { 51709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly status = BluetoothShare.STATUS_UNKNOWN_ERROR; 51809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 51909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 52009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 52109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 52209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Constants.updateShareStatus(mContext, mInfo.mId, status); 52309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (bos != null) { 52409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly try { 52509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly bos.close(); 52609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } catch (IOException e) { 52709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.e(TAG, "Error when closing stream after send"); 52809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 52909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 53009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return status; 53109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 53209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 53309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private BluetoothOppReceiveFileInfo processShareInfo() { 53409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGV) { 53509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "processShareInfo() " + mInfo.mId); 53609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 53709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly BluetoothOppReceiveFileInfo fileInfo = BluetoothOppReceiveFileInfo.generateFileInfo( 53809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mContext, mInfo.mId); 53909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 54009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Generate BluetoothOppReceiveFileInfo:"); 54109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "filename :" + fileInfo.mFileName); 54209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "length :" + fileInfo.mLength); 54309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "status :" + fileInfo.mStatus); 54409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 54509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return fileInfo; 54609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 54709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 54809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly @Override 54909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public int onConnect(HeaderSet request, HeaderSet reply) { 55009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 55109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGV) { 55209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "onConnect"); 55309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 55409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGVV) { 55509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly logHeader(request); 55609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 55709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 55809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mTimestamp = System.currentTimeMillis(); 55909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return ResponseCodes.OBEX_HTTP_OK; 56009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 56109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 56209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly @Override 56309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void onDisconnect(HeaderSet req, HeaderSet resp) { 56409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 56509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (Constants.LOGV) { 56609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "onDisconnect"); 56709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 56809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly resp.responseCode = ResponseCodes.OBEX_HTTP_OK; 56909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* onDisconnect could happen even before start() where mCallback is set */ 57009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mCallback != null) { 57109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Message msg = Message.obtain(mCallback); 57209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.what = BluetoothOppObexSession.MSG_SESSION_COMPLETE; 57309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.obj = mInfo; 57409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.sendToTarget(); 57509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 57609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 57709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 57809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly @Override 57909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void onClose() { 58009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 58109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 58209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private void logHeader(HeaderSet hs) { 58309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Dumping HeaderSet " + hs.toString()); 58409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly try { 58509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 58609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "COUNT : " + hs.getHeader(HeaderSet.COUNT)); 58709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "NAME : " + hs.getHeader(HeaderSet.NAME)); 58809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "TYPE : " + hs.getHeader(HeaderSet.TYPE)); 58909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "LENGTH : " + hs.getHeader(HeaderSet.LENGTH)); 59009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "TIME_ISO_8601 : " + hs.getHeader(HeaderSet.TIME_ISO_8601)); 59109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "TIME_4_BYTE : " + hs.getHeader(HeaderSet.TIME_4_BYTE)); 59209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "DESCRIPTION : " + hs.getHeader(HeaderSet.DESCRIPTION)); 59309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "TARGET : " + hs.getHeader(HeaderSet.TARGET)); 59409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "HTTP : " + hs.getHeader(HeaderSet.HTTP)); 59509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "WHO : " + hs.getHeader(HeaderSet.WHO)); 59609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "OBJECT_CLASS : " + hs.getHeader(HeaderSet.OBJECT_CLASS)); 59709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "APPLICATION_PARAMETER : " + hs.getHeader(HeaderSet.APPLICATION_PARAMETER)); 59809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } catch (IOException e) { 59909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.e(TAG, "dump HeaderSet error " + e); 60009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 60109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 60209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 60309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly} 604