BluetoothOppObexServerSession.java revision 8eb70f8bdf4e8c970810b3400aba8d08d14ce222
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.IOException; 3809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport java.io.InputStream; 399d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejunimport java.util.Arrays; 4009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 4109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.content.ContentValues; 4209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.content.Context; 4309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.content.Intent; 4409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.net.Uri; 4509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.os.Handler; 4609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.os.Message; 4752236de777c23788df8147de15912a57e8bc36ddTao Liejunimport android.os.PowerManager; 4852236de777c23788df8147de15912a57e8bc36ddTao Liejunimport android.os.PowerManager.WakeLock; 4909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.util.Log; 5009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.webkit.MimeTypeMap; 5109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 5209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport javax.obex.HeaderSet; 5309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport javax.obex.ObexTransport; 5409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport javax.obex.Operation; 5509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport javax.obex.ResponseCodes; 5609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport javax.obex.ServerRequestHandler; 5709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport javax.obex.ServerSession; 5809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 5909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly/** 6009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * This class runs as an OBEX server 6109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 6209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellypublic class BluetoothOppObexServerSession extends ServerRequestHandler implements 6309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly BluetoothOppObexSession { 6409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 65ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly private static final String TAG = "BtOppObexServer"; 66ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly private static final boolean D = Constants.DEBUG; 67ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly private static final boolean V = Constants.VERBOSE; 6809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 6909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private ObexTransport mTransport; 7009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 7109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private Context mContext; 7209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 7309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private Handler mCallback = null; 7409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 7509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* status when server is blocking for user/auto confirmation */ 7609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private boolean mServerBlocking = true; 7709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 7809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* the current transfer info */ 7909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private BluetoothOppShareInfo mInfo; 8009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 8109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* info id when we insert the record */ 8209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private int mLocalShareInfoId; 8309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 8409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private int mAccepted = BluetoothShare.USER_CONFIRMATION_PENDING; 8509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 8609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private boolean mInterrupted = false; 8709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 8809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private ServerSession mSession; 8909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 9009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private long mTimestamp; 9109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 9209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private BluetoothOppReceiveFileInfo mFileInfo; 9309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 9452236de777c23788df8147de15912a57e8bc36ddTao Liejun private WakeLock mWakeLock; 9552236de777c23788df8147de15912a57e8bc36ddTao Liejun 9652236de777c23788df8147de15912a57e8bc36ddTao Liejun private WakeLock mPartialWakeLock; 9752236de777c23788df8147de15912a57e8bc36ddTao Liejun 981ac5507790a87810061a19dadec36eb328a222eaTao Liejun boolean mTimeoutMsgSent = false; 991ac5507790a87810061a19dadec36eb328a222eaTao Liejun 10009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public BluetoothOppObexServerSession(Context context, ObexTransport transport) { 10109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mContext = context; 10209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mTransport = transport; 10352236de777c23788df8147de15912a57e8bc36ddTao Liejun PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE); 10452236de777c23788df8147de15912a57e8bc36ddTao Liejun mWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP 10552236de777c23788df8147de15912a57e8bc36ddTao Liejun | PowerManager.ON_AFTER_RELEASE, TAG); 10652236de777c23788df8147de15912a57e8bc36ddTao Liejun mPartialWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); 10709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 10809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 10909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void unblock() { 11009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mServerBlocking = false; 11109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 11209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 11309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /** 11409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Called when connection is accepted from remote, to retrieve the first 11509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Header then wait for user confirmation 11609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 11709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void preStart() { 118ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (D) Log.d(TAG, "acquire full WakeLock"); 11952236de777c23788df8147de15912a57e8bc36ddTao Liejun mWakeLock.acquire(); 12009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly try { 121ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (D) Log.d(TAG, "Create ServerSession with transport " + mTransport.toString()); 12209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mSession = new ServerSession(mTransport, this, null); 12309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } catch (IOException e) { 12409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.e(TAG, "Create server session error" + e); 12509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 12609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 12709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 12809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /** 12909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Called from BluetoothOppTransfer to start the "Transfer" 13009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 1318eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen public void start(Handler handler, int numShares) { 132ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (D) Log.d(TAG, "Start!"); 13309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mCallback = handler; 13409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 13509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 13609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 13709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /** 1386769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun * Called from BluetoothOppTransfer to cancel the "Transfer" Otherwise, 1396769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun * server should end by itself. 14009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 14109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void stop() { 14209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* 14309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * TODO now we implement in a tough way, just close the socket. 14409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * maybe need nice way 14509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 146ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (D) Log.d(TAG, "Stop!"); 14709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mInterrupted = true; 14809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mSession != null) { 14909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly try { 15009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mSession.close(); 15109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mTransport.close(); 15209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } catch (IOException e) { 15309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.e(TAG, "close mTransport error" + e); 15409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 15509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 1561ac5507790a87810061a19dadec36eb328a222eaTao Liejun mCallback = null; 1571ac5507790a87810061a19dadec36eb328a222eaTao Liejun mSession = null; 15809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 15909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 16009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void addShare(BluetoothOppShareInfo info) { 161ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (D) Log.d(TAG, "addShare for id " + info.mId); 16209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mInfo = info; 16309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mFileInfo = processShareInfo(); 16409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 16509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 16609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly @Override 16709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public int onPut(Operation op) { 168ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (D) Log.d(TAG, "onPut " + op.toString()); 16909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly HeaderSet request; 17009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly String name, mimeType; 17109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Long length; 17209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 17309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int obexResponse = ResponseCodes.OBEX_HTTP_OK; 17409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 17509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /** 17609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * For multiple objects, reject further objects after user deny the 17709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * first one 17809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 17909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mAccepted == BluetoothShare.USER_CONFIRMATION_DENIED) { 18009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return ResponseCodes.OBEX_HTTP_FORBIDDEN; 18109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 18209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 18303f25a2055e51bcc5e8870642763b502956b6830Martijn Coenen String destination; 18403f25a2055e51bcc5e8870642763b502956b6830Martijn Coenen if (mTransport instanceof BluetoothOppRfcommTransport) { 18503f25a2055e51bcc5e8870642763b502956b6830Martijn Coenen destination = ((BluetoothOppRfcommTransport)mTransport).getRemoteAddress(); 18603f25a2055e51bcc5e8870642763b502956b6830Martijn Coenen } else { 18703f25a2055e51bcc5e8870642763b502956b6830Martijn Coenen destination = "FF:FF:FF:00:00:00"; 18803f25a2055e51bcc5e8870642763b502956b6830Martijn Coenen } 18903f25a2055e51bcc5e8870642763b502956b6830Martijn Coenen boolean isWhitelisted = BluetoothOppManager.getInstance(mContext). 19003f25a2055e51bcc5e8870642763b502956b6830Martijn Coenen isWhitelisted(destination); 19103f25a2055e51bcc5e8870642763b502956b6830Martijn Coenen 19209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly try { 19309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly boolean pre_reject = false; 19403f25a2055e51bcc5e8870642763b502956b6830Martijn Coenen 1956769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun request = op.getReceivedHeader(); 196ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Constants.logHeader(request); 19709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly name = (String)request.getHeader(HeaderSet.NAME); 19809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly length = (Long)request.getHeader(HeaderSet.LENGTH); 19909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mimeType = (String)request.getHeader(HeaderSet.TYPE); 20009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 20109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (length == 0) { 202ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (D) Log.w(TAG, "length is 0, reject the transfer"); 20309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly pre_reject = true; 20409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly obexResponse = ResponseCodes.OBEX_HTTP_LENGTH_REQUIRED; 20509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 20609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 20709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (name == null || name.equals("")) { 208ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (D) Log.w(TAG, "name is null or empty, reject the transfer"); 20909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly pre_reject = true; 21009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly obexResponse = ResponseCodes.OBEX_HTTP_BAD_REQUEST; 21109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 21209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 21309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (!pre_reject) { 21409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* first we look for Mimetype in Android map */ 21509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly String extension, type; 21659256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh int dotIndex = name.lastIndexOf("."); 21703f25a2055e51bcc5e8870642763b502956b6830Martijn Coenen if (dotIndex < 0 && mimeType == null) { 21803f25a2055e51bcc5e8870642763b502956b6830Martijn Coenen if (D) Log.w(TAG, "There is no file extension or mime type," + 21903f25a2055e51bcc5e8870642763b502956b6830Martijn Coenen "reject the transfer"); 22009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly pre_reject = true; 22109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly obexResponse = ResponseCodes.OBEX_HTTP_BAD_REQUEST; 22209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 2231ac5507790a87810061a19dadec36eb328a222eaTao Liejun extension = name.substring(dotIndex + 1).toLowerCase(); 22409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly MimeTypeMap map = MimeTypeMap.getSingleton(); 22509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly type = map.getMimeTypeFromExtension(extension); 226ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Mimetype guessed from extension " + extension + " is " + type); 22709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (type != null) { 22809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mimeType = type; 22909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 23009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 23109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mimeType == null) { 232ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (D) Log.w(TAG, "Can't get mimetype, reject the transfer"); 23309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly pre_reject = true; 234239bc526513429995c61c4148c105725c395b1a9Jackson Fan obexResponse = ResponseCodes.OBEX_HTTP_UNSUPPORTED_TYPE; 23509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 23609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 23709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mimeType != null) { 23809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mimeType = mimeType.toLowerCase(); 23909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 24009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 24109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 24209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 243fb946935fe50d957e835ac00a592bd3d222edef3Oscar Montemayor // Reject policy: anything outside the "white list" plus unspecified 24476d17f9aff4a4aaad0f5af91eee1028473c10b16Olsson // MIME Types. Also reject everything in the "black list". 24509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (!pre_reject 24676d17f9aff4a4aaad0f5af91eee1028473c10b16Olsson && (mimeType == null 24703f25a2055e51bcc5e8870642763b502956b6830Martijn Coenen || (!isWhitelisted && !Constants.mimeTypeMatches(mimeType, 24803f25a2055e51bcc5e8870642763b502956b6830Martijn Coenen Constants.ACCEPTABLE_SHARE_INBOUND_TYPES)) 24976d17f9aff4a4aaad0f5af91eee1028473c10b16Olsson || Constants.mimeTypeMatches(mimeType, 25076d17f9aff4a4aaad0f5af91eee1028473c10b16Olsson Constants.UNACCEPTABLE_SHARE_INBOUND_TYPES))) { 251ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (D) Log.w(TAG, "mimeType is null or in unacceptable list, reject the transfer"); 25209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly pre_reject = true; 25309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly obexResponse = ResponseCodes.OBEX_HTTP_UNSUPPORTED_TYPE; 25409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 25509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 25609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (pre_reject && obexResponse != ResponseCodes.OBEX_HTTP_OK) { 2571ac5507790a87810061a19dadec36eb328a222eaTao Liejun // some bad implemented client won't send disconnect 25809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return obexResponse; 25909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 26009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 26109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } catch (IOException e) { 26209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.e(TAG, "get getReceivedHeaders error " + e); 26309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return ResponseCodes.OBEX_HTTP_BAD_REQUEST; 26409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 26509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 26609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly ContentValues values = new ContentValues(); 26709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 26809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly values.put(BluetoothShare.FILENAME_HINT, name); 26909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly values.put(BluetoothShare.TOTAL_BYTES, length.intValue()); 27009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly values.put(BluetoothShare.MIMETYPE, mimeType); 27109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 2728099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen values.put(BluetoothShare.DESTINATION, destination); 27309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 27409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly values.put(BluetoothShare.DIRECTION, BluetoothShare.DIRECTION_INBOUND); 27509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly values.put(BluetoothShare.TIMESTAMP, mTimestamp); 27609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 27709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly boolean needConfirm = true; 27809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /** It's not first put if !serverBlocking, so we auto accept it */ 27909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (!mServerBlocking) { 28009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly values.put(BluetoothShare.USER_CONFIRMATION, 28109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly BluetoothShare.USER_CONFIRMATION_AUTO_CONFIRMED); 28209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly needConfirm = false; 28309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 28409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 28503f25a2055e51bcc5e8870642763b502956b6830Martijn Coenen if (isWhitelisted) { 2868099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen values.put(BluetoothShare.USER_CONFIRMATION, 2878099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen BluetoothShare.USER_CONFIRMATION_HANDOVER_CONFIRMED); 2888099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen needConfirm = false; 2898eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen 2908099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen } 2918099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen 29209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Uri contentUri = mContext.getContentResolver().insert(BluetoothShare.CONTENT_URI, values); 29309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mLocalShareInfoId = Integer.parseInt(contentUri.getPathSegments().get(1)); 29409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 29509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (needConfirm) { 29609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Intent in = new Intent(BluetoothShare.INCOMING_FILE_CONFIRMATION_REQUEST_ACTION); 29709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly in.setClassName(Constants.THIS_PACKAGE_NAME, BluetoothOppReceiver.class.getName()); 29809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mContext.sendBroadcast(in); 29909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 30009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 301ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "insert contentUri: " + contentUri); 3029d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun if (V) Log.v(TAG, "mLocalShareInfoId = " + mLocalShareInfoId); 30309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 304ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "acquire partial WakeLock"); 3051ac5507790a87810061a19dadec36eb328a222eaTao Liejun 3061ac5507790a87810061a19dadec36eb328a222eaTao Liejun 30709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly synchronized (this) { 3084492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh if (mWakeLock.isHeld()) { 3094492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh mPartialWakeLock.acquire(); 3104492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh mWakeLock.release(); 3114492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh } 3124492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh mServerBlocking = true; 31309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly try { 314df7415da0e510ab8e4b73831a5ade38306982fe1Tao Liejun 31509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly while (mServerBlocking) { 31609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly wait(1000); 3171ac5507790a87810061a19dadec36eb328a222eaTao Liejun if (mCallback != null && !mTimeoutMsgSent) { 31809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mCallback.sendMessageDelayed(mCallback 31909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly .obtainMessage(BluetoothOppObexSession.MSG_CONNECT_TIMEOUT), 32009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly BluetoothOppObexSession.SESSION_TIMEOUT); 3211ac5507790a87810061a19dadec36eb328a222eaTao Liejun mTimeoutMsgSent = true; 322ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "MSG_CONNECT_TIMEOUT sent"); 32309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 32409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 32509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } catch (InterruptedException e) { 326ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "Interrupted in onPut blocking"); 32709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 32809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 329ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (D) Log.d(TAG, "Server unblocked "); 3309d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun synchronized (this) { 3319d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun if (mCallback != null && mTimeoutMsgSent) { 3329d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun mCallback.removeMessages(BluetoothOppObexSession.MSG_CONNECT_TIMEOUT); 3339d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun } 3346769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun } 33509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 33609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* we should have mInfo now */ 33709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 33809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* 33909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * TODO check if this mInfo match the one that we insert before server 34009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * blocking? just to make sure no error happens 34109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 34209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mInfo.mId != mLocalShareInfoId) { 34309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.e(TAG, "Unexpected error!"); 34409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 34509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mAccepted = mInfo.mConfirm; 34609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 347ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Log.v(TAG, "after confirm: userAccepted=" + mAccepted); 34809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int status = BluetoothShare.STATUS_SUCCESS; 34909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 35009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mAccepted == BluetoothShare.USER_CONFIRMATION_CONFIRMED 3518099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen || mAccepted == BluetoothShare.USER_CONFIRMATION_AUTO_CONFIRMED 3528099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen || mAccepted == BluetoothShare.USER_CONFIRMATION_HANDOVER_CONFIRMED) { 35309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* Confirm or auto-confirm */ 35409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 35509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mFileInfo.mFileName == null) { 35609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly status = mFileInfo.mStatus; 35709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* TODO need to check if this line is correct */ 35809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mInfo.mStatus = mFileInfo.mStatus; 35909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Constants.updateShareStatus(mContext, mInfo.mId, status); 36009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly obexResponse = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; 36109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 36209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 36309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 36409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mFileInfo.mFileName != null) { 36509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 36609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly ContentValues updateValues = new ContentValues(); 36709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly contentUri = Uri.parse(BluetoothShare.CONTENT_URI + "/" + mInfo.mId); 36809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly updateValues.put(BluetoothShare._DATA, mFileInfo.mFileName); 36909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly updateValues.put(BluetoothShare.STATUS, BluetoothShare.STATUS_RUNNING); 37009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mContext.getContentResolver().update(contentUri, updateValues, null, null); 37109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 37209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly status = receiveFile(mFileInfo, op); 37309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* 37409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * TODO map status to obex response code 37509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 37609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (status != BluetoothShare.STATUS_SUCCESS) { 37709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly obexResponse = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; 37809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 37909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Constants.updateShareStatus(mContext, mInfo.mId, status); 38009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 38109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 38209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (status == BluetoothShare.STATUS_SUCCESS) { 38309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Message msg = Message.obtain(mCallback, BluetoothOppObexSession.MSG_SHARE_COMPLETE); 38409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.obj = mInfo; 38509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.sendToTarget(); 38609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 3871ac5507790a87810061a19dadec36eb328a222eaTao Liejun if (mCallback != null) { 3881ac5507790a87810061a19dadec36eb328a222eaTao Liejun Message msg = Message.obtain(mCallback, 3891ac5507790a87810061a19dadec36eb328a222eaTao Liejun BluetoothOppObexSession.MSG_SESSION_ERROR); 3901ac5507790a87810061a19dadec36eb328a222eaTao Liejun mInfo.mStatus = status; 3911ac5507790a87810061a19dadec36eb328a222eaTao Liejun msg.obj = mInfo; 3921ac5507790a87810061a19dadec36eb328a222eaTao Liejun msg.sendToTarget(); 3931ac5507790a87810061a19dadec36eb328a222eaTao Liejun } 39409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 39509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else if (mAccepted == BluetoothShare.USER_CONFIRMATION_DENIED 39609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly || mAccepted == BluetoothShare.USER_CONFIRMATION_TIMEOUT) { 39709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* user actively deny the inbound transfer */ 39809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* 39909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Note There is a question: what's next if user deny the first obj? 40009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Option 1 :continue prompt for next objects 40109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Option 2 :reject next objects and finish the session 40209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * Now we take option 2: 40309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 40452236de777c23788df8147de15912a57e8bc36ddTao Liejun 40552236de777c23788df8147de15912a57e8bc36ddTao Liejun Log.i(TAG, "Rejected incoming request"); 4061ac5507790a87810061a19dadec36eb328a222eaTao Liejun if (mFileInfo.mFileName != null) { 4071ac5507790a87810061a19dadec36eb328a222eaTao Liejun try { 4081ac5507790a87810061a19dadec36eb328a222eaTao Liejun mFileInfo.mOutputStream.close(); 4091ac5507790a87810061a19dadec36eb328a222eaTao Liejun } catch (IOException e) { 4101ac5507790a87810061a19dadec36eb328a222eaTao Liejun Log.e(TAG, "error close file stream"); 4111ac5507790a87810061a19dadec36eb328a222eaTao Liejun } 4121ac5507790a87810061a19dadec36eb328a222eaTao Liejun new File(mFileInfo.mFileName).delete(); 4131ac5507790a87810061a19dadec36eb328a222eaTao Liejun } 4141ac5507790a87810061a19dadec36eb328a222eaTao Liejun // set status as local cancel 4151ac5507790a87810061a19dadec36eb328a222eaTao Liejun status = BluetoothShare.STATUS_CANCELED; 41609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Constants.updateShareStatus(mContext, mInfo.mId, status); 41709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly obexResponse = ResponseCodes.OBEX_HTTP_FORBIDDEN; 4181ac5507790a87810061a19dadec36eb328a222eaTao Liejun 41909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Message msg = Message.obtain(mCallback); 42009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.what = BluetoothOppObexSession.MSG_SHARE_INTERRUPTED; 4211ac5507790a87810061a19dadec36eb328a222eaTao Liejun mInfo.mStatus = status; 42209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.obj = mInfo; 42309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly msg.sendToTarget(); 42409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 42509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return obexResponse; 42609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 42709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 42809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private int receiveFile(BluetoothOppReceiveFileInfo fileInfo, Operation op) { 42909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly /* 43009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * implement receive file 43109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */ 43209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int status = -1; 43309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly BufferedOutputStream bos = null; 43409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 43509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly InputStream is = null; 43609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly boolean error = false; 43709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly try { 43809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly is = op.openInputStream(); 43909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } catch (IOException e1) { 44009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.e(TAG, "Error when openInputStream"); 44109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly status = BluetoothShare.STATUS_OBEX_DATA_ERROR; 44209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly error = true; 44309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 44409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 44509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Uri contentUri = Uri.parse(BluetoothShare.CONTENT_URI + "/" + mInfo.mId); 44609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 44709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (!error) { 44809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly ContentValues updateValues = new ContentValues(); 44909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly updateValues.put(BluetoothShare._DATA, fileInfo.mFileName); 45009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mContext.getContentResolver().update(contentUri, updateValues, null, null); 45109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 45209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 45309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int position = 0; 45409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (!error) { 4551ac5507790a87810061a19dadec36eb328a222eaTao Liejun bos = new BufferedOutputStream(fileInfo.mOutputStream, 0x10000); 45609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 45709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 45809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (!error) { 45909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int outputBufferSize = op.getMaxPacketSize(); 46009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly byte[] b = new byte[outputBufferSize]; 46109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly int readLength = 0; 46252236de777c23788df8147de15912a57e8bc36ddTao Liejun long timestamp = 0; 46309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly try { 46409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly while ((!mInterrupted) && (position != fileInfo.mLength)) { 46509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 466ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) timestamp = System.currentTimeMillis(); 46709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 46809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly readLength = is.read(b); 46909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 47009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (readLength == -1) { 471ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (D) Log.d(TAG, "Receive file reached stream end at position" + position); 47209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly break; 47309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 47409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 47509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly bos.write(b, 0, readLength); 47609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly position += readLength; 47709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 478ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) { 47909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Receive file position = " + position + " readLength " 48009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + readLength + " bytes took " 48109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly + (System.currentTimeMillis() - timestamp) + " ms"); 48209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 48309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 48409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly ContentValues updateValues = new ContentValues(); 48509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly updateValues.put(BluetoothShare.CURRENT_BYTES, position); 48609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mContext.getContentResolver().update(contentUri, updateValues, null, null); 48709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 48809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } catch (IOException e1) { 48909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.e(TAG, "Error when receiving file"); 4909abe9c9e1ccad600b1069490293d78dfd984017bAndreas Areskoug /* OBEX Abort packet received from remote device */ 4919abe9c9e1ccad600b1069490293d78dfd984017bAndreas Areskoug if ("Abort Received".equals(e1.getMessage())) { 4929abe9c9e1ccad600b1069490293d78dfd984017bAndreas Areskoug status = BluetoothShare.STATUS_CANCELED; 4939abe9c9e1ccad600b1069490293d78dfd984017bAndreas Areskoug } else { 4949abe9c9e1ccad600b1069490293d78dfd984017bAndreas Areskoug status = BluetoothShare.STATUS_OBEX_DATA_ERROR; 4959abe9c9e1ccad600b1069490293d78dfd984017bAndreas Areskoug } 49609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly error = true; 49709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 49809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 49909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 50009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (mInterrupted) { 501ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (D) Log.d(TAG, "receiving file interrupted by user."); 50209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly status = BluetoothShare.STATUS_CANCELED; 50309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 50409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (position == fileInfo.mLength) { 505ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (D) Log.d(TAG, "Receiving file completed for " + fileInfo.mFileName); 50609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly status = BluetoothShare.STATUS_SUCCESS; 50709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } else { 508ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (D) Log.d(TAG, "Reading file failed at " + position + " of " + fileInfo.mLength); 50909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (status == -1) { 51009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly status = BluetoothShare.STATUS_UNKNOWN_ERROR; 51109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 51209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 51309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 51409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 51509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly if (bos != null) { 51609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly try { 51709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly bos.close(); 51809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } catch (IOException e) { 51909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.e(TAG, "Error when closing stream after send"); 52009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 52109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 52209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return status; 52309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 52409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 52509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly private BluetoothOppReceiveFileInfo processShareInfo() { 526ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (D) Log.d(TAG, "processShareInfo() " + mInfo.mId); 52709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly BluetoothOppReceiveFileInfo fileInfo = BluetoothOppReceiveFileInfo.generateFileInfo( 52809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mContext, mInfo.mId); 529ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) { 53009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "Generate BluetoothOppReceiveFileInfo:"); 53109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "filename :" + fileInfo.mFileName); 53209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "length :" + fileInfo.mLength); 53309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly Log.v(TAG, "status :" + fileInfo.mStatus); 53409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 53509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return fileInfo; 53609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 53709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 53809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly @Override 53909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public int onConnect(HeaderSet request, HeaderSet reply) { 54009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 541ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (D) Log.d(TAG, "onConnect"); 542ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (V) Constants.logHeader(request); 5438eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen Long objectCount = null; 5449d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun try { 5459d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun byte[] uuid = (byte[])request.getHeader(HeaderSet.TARGET); 5469d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun if (V) Log.v(TAG, "onConnect(): uuid =" + Arrays.toString(uuid)); 5479d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun if(uuid != null) { 548eb1192b4208d4bf77c92011822e6d171b9f09980Jaikumar Ganesh return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE; 5499d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun } 5508eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen 5518eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen objectCount = (Long) request.getHeader(HeaderSet.COUNT); 5529d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun } catch (IOException e) { 5539d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun Log.e(TAG, e.toString()); 5549d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR; 5559d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun } 5568eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen String destination; 5578eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen if (mTransport instanceof BluetoothOppRfcommTransport) { 5588eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen destination = ((BluetoothOppRfcommTransport)mTransport).getRemoteAddress(); 5598eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen } else { 5608eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen destination = "FF:FF:FF:00:00:00"; 5618eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen } 5628eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen boolean isHandover = BluetoothOppManager.getInstance(mContext). 5638eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen isWhitelisted(destination); 5648eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen if (isHandover) { 5658eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen // Notify the handover requester file transfer has started 5668eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen Intent intent = new Intent(Constants.ACTION_HANDOVER_STARTED); 5678eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen if (objectCount != null) { 5688eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen intent.putExtra(Constants.EXTRA_BT_OPP_OBJECT_COUNT, objectCount.intValue()); 5698eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen } else { 5708eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen intent.putExtra(Constants.EXTRA_BT_OPP_OBJECT_COUNT, 5718eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen Constants.COUNT_HEADER_UNAVAILABLE); 5728eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen } 5738eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen intent.putExtra(Constants.EXTRA_BT_OPP_ADDRESS, destination); 5748eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen mContext.sendBroadcast(intent, Constants.HANDOVER_STATUS_PERMISSION); 5758eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen } 57609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly mTimestamp = System.currentTimeMillis(); 57709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly return ResponseCodes.OBEX_HTTP_OK; 57809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 57909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 58009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly @Override 58109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly public void onDisconnect(HeaderSet req, HeaderSet resp) { 582ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly if (D) Log.d(TAG, "onDisconnect"); 58309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly resp.responseCode = ResponseCodes.OBEX_HTTP_OK; 58409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 58509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly 5864492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh private synchronized void releaseWakeLocks() { 58732e47df203390052c1ef771d78b22fc4aa5f9e72Tao Liejun if (mWakeLock.isHeld()) { 58832e47df203390052c1ef771d78b22fc4aa5f9e72Tao Liejun mWakeLock.release(); 58932e47df203390052c1ef771d78b22fc4aa5f9e72Tao Liejun } 59032e47df203390052c1ef771d78b22fc4aa5f9e72Tao Liejun if (mPartialWakeLock.isHeld()) { 59132e47df203390052c1ef771d78b22fc4aa5f9e72Tao Liejun mPartialWakeLock.release(); 59232e47df203390052c1ef771d78b22fc4aa5f9e72Tao Liejun } 5934492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh } 5944492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh 5954492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh @Override 5964492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh public void onClose() { 5974492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh if (V) Log.v(TAG, "release WakeLock"); 5984492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh releaseWakeLocks(); 5994492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh 6009d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun /* onClose could happen even before start() where mCallback is set */ 6019d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun if (mCallback != null) { 6029d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun Message msg = Message.obtain(mCallback); 6039d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun msg.what = BluetoothOppObexSession.MSG_SESSION_COMPLETE; 6049d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun msg.obj = mInfo; 6059d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun msg.sendToTarget(); 6069d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun } 60709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly } 60809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly} 609