BluetoothOppObexServerSession.java revision 03f25a2055e51bcc5e8870642763b502956b6830
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     */
13109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    public void start(Handler handler) {
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;
2898099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen        }
2908099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen
29109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        Uri contentUri = mContext.getContentResolver().insert(BluetoothShare.CONTENT_URI, values);
29209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        mLocalShareInfoId = Integer.parseInt(contentUri.getPathSegments().get(1));
29309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
29409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (needConfirm) {
29509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Intent in = new Intent(BluetoothShare.INCOMING_FILE_CONFIRMATION_REQUEST_ACTION);
29609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            in.setClassName(Constants.THIS_PACKAGE_NAME, BluetoothOppReceiver.class.getName());
29709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            mContext.sendBroadcast(in);
29809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
29909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
300ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly        if (V) Log.v(TAG, "insert contentUri: " + contentUri);
3019d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun        if (V) Log.v(TAG, "mLocalShareInfoId = " + mLocalShareInfoId);
30209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
303ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly        if (V) Log.v(TAG, "acquire partial WakeLock");
3041ac5507790a87810061a19dadec36eb328a222eaTao Liejun
3051ac5507790a87810061a19dadec36eb328a222eaTao Liejun
30609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        synchronized (this) {
3074492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh            if (mWakeLock.isHeld()) {
3084492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh                mPartialWakeLock.acquire();
3094492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh                mWakeLock.release();
3104492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh            }
3114492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh            mServerBlocking = true;
31209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            try {
313df7415da0e510ab8e4b73831a5ade38306982fe1Tao Liejun
31409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                while (mServerBlocking) {
31509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    wait(1000);
3161ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    if (mCallback != null && !mTimeoutMsgSent) {
31709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        mCallback.sendMessageDelayed(mCallback
31809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                .obtainMessage(BluetoothOppObexSession.MSG_CONNECT_TIMEOUT),
31909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                BluetoothOppObexSession.SESSION_TIMEOUT);
3201ac5507790a87810061a19dadec36eb328a222eaTao Liejun                        mTimeoutMsgSent = true;
321ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                        if (V) Log.v(TAG, "MSG_CONNECT_TIMEOUT sent");
32209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    }
32309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                }
32409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            } catch (InterruptedException e) {
325ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                if (V) Log.v(TAG, "Interrupted in onPut blocking");
32609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
32709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
328ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly        if (D) Log.d(TAG, "Server unblocked ");
3299d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun        synchronized (this) {
3309d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun            if (mCallback != null && mTimeoutMsgSent) {
3319d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun                mCallback.removeMessages(BluetoothOppObexSession.MSG_CONNECT_TIMEOUT);
3329d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun            }
3336769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun        }
33409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
33509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        /* we should have mInfo now */
33609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
33709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        /*
33809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly         * TODO check if this mInfo match the one that we insert before server
33909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly         * blocking? just to make sure no error happens
34009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly         */
34109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (mInfo.mId != mLocalShareInfoId) {
34209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Log.e(TAG, "Unexpected error!");
34309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
34409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        mAccepted = mInfo.mConfirm;
34509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
346ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly        if (V) Log.v(TAG, "after confirm: userAccepted=" + mAccepted);
34709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        int status = BluetoothShare.STATUS_SUCCESS;
34809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
34909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (mAccepted == BluetoothShare.USER_CONFIRMATION_CONFIRMED
3508099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen                || mAccepted == BluetoothShare.USER_CONFIRMATION_AUTO_CONFIRMED
3518099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen                || mAccepted == BluetoothShare.USER_CONFIRMATION_HANDOVER_CONFIRMED) {
35209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            /* Confirm or auto-confirm */
35309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
35409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            if (mFileInfo.mFileName == null) {
35509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                status = mFileInfo.mStatus;
35609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                /* TODO need to check if this line is correct */
35709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                mInfo.mStatus = mFileInfo.mStatus;
35809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                Constants.updateShareStatus(mContext, mInfo.mId, status);
35909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                obexResponse = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
36009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
36109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
36209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
36309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            if (mFileInfo.mFileName != null) {
36409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
36509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                ContentValues updateValues = new ContentValues();
36609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                contentUri = Uri.parse(BluetoothShare.CONTENT_URI + "/" + mInfo.mId);
36709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                updateValues.put(BluetoothShare._DATA, mFileInfo.mFileName);
36809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                updateValues.put(BluetoothShare.STATUS, BluetoothShare.STATUS_RUNNING);
36909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                mContext.getContentResolver().update(contentUri, updateValues, null, null);
37009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
37109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                status = receiveFile(mFileInfo, op);
37209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                /*
37309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                 * TODO map status to obex response code
37409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                 */
37509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                if (status != BluetoothShare.STATUS_SUCCESS) {
37609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    obexResponse = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
37709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                }
37809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                Constants.updateShareStatus(mContext, mInfo.mId, status);
37909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
38009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
38109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            if (status == BluetoothShare.STATUS_SUCCESS) {
38209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                Message msg = Message.obtain(mCallback, BluetoothOppObexSession.MSG_SHARE_COMPLETE);
38309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                msg.obj = mInfo;
38409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                msg.sendToTarget();
38509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            } else {
3861ac5507790a87810061a19dadec36eb328a222eaTao Liejun                if (mCallback != null) {
3871ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    Message msg = Message.obtain(mCallback,
3881ac5507790a87810061a19dadec36eb328a222eaTao Liejun                            BluetoothOppObexSession.MSG_SESSION_ERROR);
3891ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    mInfo.mStatus = status;
3901ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    msg.obj = mInfo;
3911ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    msg.sendToTarget();
3921ac5507790a87810061a19dadec36eb328a222eaTao Liejun                }
39309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
39409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        } else if (mAccepted == BluetoothShare.USER_CONFIRMATION_DENIED
39509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                || mAccepted == BluetoothShare.USER_CONFIRMATION_TIMEOUT) {
39609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            /* user actively deny the inbound transfer */
39709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            /*
39809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly             * Note There is a question: what's next if user deny the first obj?
39909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly             * Option 1 :continue prompt for next objects
40009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly             * Option 2 :reject next objects and finish the session
40109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly             * Now we take option 2:
40209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly             */
40352236de777c23788df8147de15912a57e8bc36ddTao Liejun
40452236de777c23788df8147de15912a57e8bc36ddTao Liejun            Log.i(TAG, "Rejected incoming request");
4051ac5507790a87810061a19dadec36eb328a222eaTao Liejun            if (mFileInfo.mFileName != null) {
4061ac5507790a87810061a19dadec36eb328a222eaTao Liejun                try {
4071ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    mFileInfo.mOutputStream.close();
4081ac5507790a87810061a19dadec36eb328a222eaTao Liejun                } catch (IOException e) {
4091ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    Log.e(TAG, "error close file stream");
4101ac5507790a87810061a19dadec36eb328a222eaTao Liejun                }
4111ac5507790a87810061a19dadec36eb328a222eaTao Liejun                new File(mFileInfo.mFileName).delete();
4121ac5507790a87810061a19dadec36eb328a222eaTao Liejun            }
4131ac5507790a87810061a19dadec36eb328a222eaTao Liejun            // set status as local cancel
4141ac5507790a87810061a19dadec36eb328a222eaTao Liejun            status = BluetoothShare.STATUS_CANCELED;
41509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Constants.updateShareStatus(mContext, mInfo.mId, status);
41609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            obexResponse = ResponseCodes.OBEX_HTTP_FORBIDDEN;
4171ac5507790a87810061a19dadec36eb328a222eaTao Liejun
41809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Message msg = Message.obtain(mCallback);
41909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            msg.what = BluetoothOppObexSession.MSG_SHARE_INTERRUPTED;
4201ac5507790a87810061a19dadec36eb328a222eaTao Liejun            mInfo.mStatus = status;
42109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            msg.obj = mInfo;
42209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            msg.sendToTarget();
42309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
42409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        return obexResponse;
42509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
42609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
42709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private int receiveFile(BluetoothOppReceiveFileInfo fileInfo, Operation op) {
42809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        /*
42909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly         * implement receive file
43009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly         */
43109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        int status = -1;
43209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        BufferedOutputStream bos = null;
43309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
43409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        InputStream is = null;
43509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        boolean error = false;
43609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        try {
43709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            is = op.openInputStream();
43809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        } catch (IOException e1) {
43909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Log.e(TAG, "Error when openInputStream");
44009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            status = BluetoothShare.STATUS_OBEX_DATA_ERROR;
44109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            error = true;
44209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
44309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
44409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        Uri contentUri = Uri.parse(BluetoothShare.CONTENT_URI + "/" + mInfo.mId);
44509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
44609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (!error) {
44709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            ContentValues updateValues = new ContentValues();
44809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            updateValues.put(BluetoothShare._DATA, fileInfo.mFileName);
44909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            mContext.getContentResolver().update(contentUri, updateValues, null, null);
45009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
45109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
45209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        int position = 0;
45309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (!error) {
4541ac5507790a87810061a19dadec36eb328a222eaTao Liejun            bos = new BufferedOutputStream(fileInfo.mOutputStream, 0x10000);
45509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
45609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
45709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (!error) {
45809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            int outputBufferSize = op.getMaxPacketSize();
45909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            byte[] b = new byte[outputBufferSize];
46009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            int readLength = 0;
46152236de777c23788df8147de15912a57e8bc36ddTao Liejun            long timestamp = 0;
46209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            try {
46309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                while ((!mInterrupted) && (position != fileInfo.mLength)) {
46409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
465ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                    if (V) timestamp = System.currentTimeMillis();
46609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
46709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    readLength = is.read(b);
46809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
46909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    if (readLength == -1) {
470ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                        if (D) Log.d(TAG, "Receive file reached stream end at position" + position);
47109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        break;
47209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    }
47309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
47409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    bos.write(b, 0, readLength);
47509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    position += readLength;
47609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
477ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                    if (V) {
47809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        Log.v(TAG, "Receive file position = " + position + " readLength "
47909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                + readLength + " bytes took "
48009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                + (System.currentTimeMillis() - timestamp) + " ms");
48109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    }
48209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
48309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    ContentValues updateValues = new ContentValues();
48409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    updateValues.put(BluetoothShare.CURRENT_BYTES, position);
48509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    mContext.getContentResolver().update(contentUri, updateValues, null, null);
48609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                }
48709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            } catch (IOException e1) {
48809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                Log.e(TAG, "Error when receiving file");
4899abe9c9e1ccad600b1069490293d78dfd984017bAndreas Areskoug                /* OBEX Abort packet received from remote device */
4909abe9c9e1ccad600b1069490293d78dfd984017bAndreas Areskoug                if ("Abort Received".equals(e1.getMessage())) {
4919abe9c9e1ccad600b1069490293d78dfd984017bAndreas Areskoug                    status = BluetoothShare.STATUS_CANCELED;
4929abe9c9e1ccad600b1069490293d78dfd984017bAndreas Areskoug                } else {
4939abe9c9e1ccad600b1069490293d78dfd984017bAndreas Areskoug                    status = BluetoothShare.STATUS_OBEX_DATA_ERROR;
4949abe9c9e1ccad600b1069490293d78dfd984017bAndreas Areskoug                }
49509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                error = true;
49609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
49709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
49809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
49909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (mInterrupted) {
500ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly            if (D) Log.d(TAG, "receiving file interrupted by user.");
50109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            status = BluetoothShare.STATUS_CANCELED;
50209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        } else {
50309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            if (position == fileInfo.mLength) {
504ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                if (D) Log.d(TAG, "Receiving file completed for " + fileInfo.mFileName);
50509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                status = BluetoothShare.STATUS_SUCCESS;
50609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            } else {
507ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                if (D) Log.d(TAG, "Reading file failed at " + position + " of " + fileInfo.mLength);
50809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                if (status == -1) {
50909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    status = BluetoothShare.STATUS_UNKNOWN_ERROR;
51009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                }
51109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
51209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
51309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
51409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (bos != null) {
51509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            try {
51609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                bos.close();
51709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            } catch (IOException e) {
51809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                Log.e(TAG, "Error when closing stream after send");
51909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
52009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
52109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        return status;
52209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
52309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
52409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private BluetoothOppReceiveFileInfo processShareInfo() {
525ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly        if (D) Log.d(TAG, "processShareInfo() " + mInfo.mId);
52609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        BluetoothOppReceiveFileInfo fileInfo = BluetoothOppReceiveFileInfo.generateFileInfo(
52709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                mContext, mInfo.mId);
528ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly        if (V) {
52909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Log.v(TAG, "Generate BluetoothOppReceiveFileInfo:");
53009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Log.v(TAG, "filename  :" + fileInfo.mFileName);
53109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Log.v(TAG, "length    :" + fileInfo.mLength);
53209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Log.v(TAG, "status    :" + fileInfo.mStatus);
53309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
53409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        return fileInfo;
53509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
53609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
53709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    @Override
53809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    public int onConnect(HeaderSet request, HeaderSet reply) {
53909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
540ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly        if (D) Log.d(TAG, "onConnect");
541ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly        if (V) Constants.logHeader(request);
5429d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun        try {
5439d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun            byte[] uuid = (byte[])request.getHeader(HeaderSet.TARGET);
5449d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun            if (V) Log.v(TAG, "onConnect(): uuid =" + Arrays.toString(uuid));
5459d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun            if(uuid != null) {
546eb1192b4208d4bf77c92011822e6d171b9f09980Jaikumar Ganesh                 return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
5479d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun            }
5489d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun        } catch (IOException e) {
5499d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun            Log.e(TAG, e.toString());
5509d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun            return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
5519d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun        }
55209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        mTimestamp = System.currentTimeMillis();
55309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        return ResponseCodes.OBEX_HTTP_OK;
55409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
55509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
55609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    @Override
55709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    public void onDisconnect(HeaderSet req, HeaderSet resp) {
558ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly        if (D) Log.d(TAG, "onDisconnect");
55909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        resp.responseCode = ResponseCodes.OBEX_HTTP_OK;
56009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
56109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
5624492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh    private synchronized void releaseWakeLocks() {
56332e47df203390052c1ef771d78b22fc4aa5f9e72Tao Liejun        if (mWakeLock.isHeld()) {
56432e47df203390052c1ef771d78b22fc4aa5f9e72Tao Liejun            mWakeLock.release();
56532e47df203390052c1ef771d78b22fc4aa5f9e72Tao Liejun        }
56632e47df203390052c1ef771d78b22fc4aa5f9e72Tao Liejun        if (mPartialWakeLock.isHeld()) {
56732e47df203390052c1ef771d78b22fc4aa5f9e72Tao Liejun            mPartialWakeLock.release();
56832e47df203390052c1ef771d78b22fc4aa5f9e72Tao Liejun        }
5694492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh    }
5704492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh
5714492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh    @Override
5724492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh    public void onClose() {
5734492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh        if (V) Log.v(TAG, "release WakeLock");
5744492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh        releaseWakeLocks();
5754492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh
5769d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun        /* onClose could happen even before start() where mCallback is set */
5779d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun        if (mCallback != null) {
5789d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun            Message msg = Message.obtain(mCallback);
5799d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun            msg.what = BluetoothOppObexSession.MSG_SESSION_COMPLETE;
5809d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun            msg.obj = mInfo;
5819d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun            msg.sendToTarget();
5829d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun        }
58309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
58409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly}
585