BluetoothOppObexServerSession.java revision eb1192b4208d4bf77c92011822e6d171b9f09980
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
18309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        try {
18409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            boolean pre_reject = false;
1856769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun            request = op.getReceivedHeader();
186ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly            if (V) Constants.logHeader(request);
18709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            name = (String)request.getHeader(HeaderSet.NAME);
18809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            length = (Long)request.getHeader(HeaderSet.LENGTH);
18909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            mimeType = (String)request.getHeader(HeaderSet.TYPE);
19009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
19109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            if (length == 0) {
192ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                if (D) Log.w(TAG, "length is 0, reject the transfer");
19309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                pre_reject = true;
19409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                obexResponse = ResponseCodes.OBEX_HTTP_LENGTH_REQUIRED;
19509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
19609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
19709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            if (name == null || name.equals("")) {
198ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                if (D) Log.w(TAG, "name is null or empty, reject the transfer");
19909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                pre_reject = true;
20009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                obexResponse = ResponseCodes.OBEX_HTTP_BAD_REQUEST;
20109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
20209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
20309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            if (!pre_reject) {
20409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                /* first we look for Mimetype in Android map */
20509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                String extension, type;
20659256dee3f9787fd660c346d61e0271ecd4bfe9aJaikumar Ganesh                int dotIndex = name.lastIndexOf(".");
20709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                if (dotIndex < 0) {
208ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                    if (D) Log.w(TAG, "There is no file extension, reject the transfer");
20909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    pre_reject = true;
21009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    obexResponse = ResponseCodes.OBEX_HTTP_BAD_REQUEST;
21109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                } else {
2121ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    extension = name.substring(dotIndex + 1).toLowerCase();
21309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    MimeTypeMap map = MimeTypeMap.getSingleton();
21409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    type = map.getMimeTypeFromExtension(extension);
215ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                    if (V) Log.v(TAG, "Mimetype guessed from extension " + extension + " is " + type);
21609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    if (type != null) {
21709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        mimeType = type;
21809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
21909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    } else {
22009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        if (mimeType == null) {
221ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                            if (D) Log.w(TAG, "Can't get mimetype, reject the transfer");
22209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                            pre_reject = true;
223239bc526513429995c61c4148c105725c395b1a9Jackson Fan                            obexResponse = ResponseCodes.OBEX_HTTP_UNSUPPORTED_TYPE;
22409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        }
22509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    }
22609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    if (mimeType != null) {
22709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        mimeType = mimeType.toLowerCase();
22809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    }
22909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                }
23009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
23109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
232fb946935fe50d957e835ac00a592bd3d222edef3Oscar Montemayor            // Reject policy: anything outside the "white list" plus unspecified
23376d17f9aff4a4aaad0f5af91eee1028473c10b16Olsson            // MIME Types. Also reject everything in the "black list".
23409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            if (!pre_reject
23576d17f9aff4a4aaad0f5af91eee1028473c10b16Olsson                    && (mimeType == null
23676d17f9aff4a4aaad0f5af91eee1028473c10b16Olsson                            || !Constants.mimeTypeMatches(mimeType,
23776d17f9aff4a4aaad0f5af91eee1028473c10b16Olsson                                    Constants.ACCEPTABLE_SHARE_INBOUND_TYPES)
23876d17f9aff4a4aaad0f5af91eee1028473c10b16Olsson                            || Constants.mimeTypeMatches(mimeType,
23976d17f9aff4a4aaad0f5af91eee1028473c10b16Olsson                                    Constants.UNACCEPTABLE_SHARE_INBOUND_TYPES))) {
240ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                if (D) Log.w(TAG, "mimeType is null or in unacceptable list, reject the transfer");
24109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                pre_reject = true;
24209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                obexResponse = ResponseCodes.OBEX_HTTP_UNSUPPORTED_TYPE;
24309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
24409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
24509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            if (pre_reject && obexResponse != ResponseCodes.OBEX_HTTP_OK) {
2461ac5507790a87810061a19dadec36eb328a222eaTao Liejun                // some bad implemented client won't send disconnect
24709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                return obexResponse;
24809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
24909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
25009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        } catch (IOException e) {
25109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Log.e(TAG, "get getReceivedHeaders error " + e);
25209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            return ResponseCodes.OBEX_HTTP_BAD_REQUEST;
25309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
25409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
25509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        ContentValues values = new ContentValues();
25609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
25709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        values.put(BluetoothShare.FILENAME_HINT, name);
25809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        values.put(BluetoothShare.TOTAL_BYTES, length.intValue());
25909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        values.put(BluetoothShare.MIMETYPE, mimeType);
26009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
26109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (mTransport instanceof BluetoothOppRfcommTransport) {
26209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            String a = ((BluetoothOppRfcommTransport)mTransport).getRemoteAddress();
26309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            values.put(BluetoothShare.DESTINATION, a);
26409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        } else {
26509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            values.put(BluetoothShare.DESTINATION, "FF:FF:FF:00:00:00");
26609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
26709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
26809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        values.put(BluetoothShare.DIRECTION, BluetoothShare.DIRECTION_INBOUND);
26909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        values.put(BluetoothShare.TIMESTAMP, mTimestamp);
27009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
27109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        boolean needConfirm = true;
27209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        /** It's not first put if !serverBlocking, so we auto accept it */
27309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (!mServerBlocking) {
27409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            values.put(BluetoothShare.USER_CONFIRMATION,
27509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    BluetoothShare.USER_CONFIRMATION_AUTO_CONFIRMED);
27609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            needConfirm = false;
27709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
27809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
27909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        Uri contentUri = mContext.getContentResolver().insert(BluetoothShare.CONTENT_URI, values);
28009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        mLocalShareInfoId = Integer.parseInt(contentUri.getPathSegments().get(1));
28109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
28209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (needConfirm) {
28309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Intent in = new Intent(BluetoothShare.INCOMING_FILE_CONFIRMATION_REQUEST_ACTION);
28409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            in.setClassName(Constants.THIS_PACKAGE_NAME, BluetoothOppReceiver.class.getName());
28509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            mContext.sendBroadcast(in);
28609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
28709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
288ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly        if (V) Log.v(TAG, "insert contentUri: " + contentUri);
2899d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun        if (V) Log.v(TAG, "mLocalShareInfoId = " + mLocalShareInfoId);
29009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
291ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly        if (V) Log.v(TAG, "acquire partial WakeLock");
2921ac5507790a87810061a19dadec36eb328a222eaTao Liejun
2931ac5507790a87810061a19dadec36eb328a222eaTao Liejun
29409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        synchronized (this) {
2954492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh            if (mWakeLock.isHeld()) {
2964492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh                mPartialWakeLock.acquire();
2974492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh                mWakeLock.release();
2984492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh            }
2994492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh            mServerBlocking = true;
30009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            try {
301df7415da0e510ab8e4b73831a5ade38306982fe1Tao Liejun
30209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                while (mServerBlocking) {
30309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    wait(1000);
3041ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    if (mCallback != null && !mTimeoutMsgSent) {
30509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        mCallback.sendMessageDelayed(mCallback
30609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                .obtainMessage(BluetoothOppObexSession.MSG_CONNECT_TIMEOUT),
30709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                BluetoothOppObexSession.SESSION_TIMEOUT);
3081ac5507790a87810061a19dadec36eb328a222eaTao Liejun                        mTimeoutMsgSent = true;
309ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                        if (V) Log.v(TAG, "MSG_CONNECT_TIMEOUT sent");
31009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    }
31109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                }
31209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            } catch (InterruptedException e) {
313ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                if (V) Log.v(TAG, "Interrupted in onPut blocking");
31409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
31509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
316ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly        if (D) Log.d(TAG, "Server unblocked ");
3179d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun        synchronized (this) {
3189d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun            if (mCallback != null && mTimeoutMsgSent) {
3199d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun                mCallback.removeMessages(BluetoothOppObexSession.MSG_CONNECT_TIMEOUT);
3209d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun            }
3216769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun        }
32209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
32309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        /* we should have mInfo now */
32409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
32509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        /*
32609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly         * TODO check if this mInfo match the one that we insert before server
32709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly         * blocking? just to make sure no error happens
32809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly         */
32909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (mInfo.mId != mLocalShareInfoId) {
33009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Log.e(TAG, "Unexpected error!");
33109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
33209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        mAccepted = mInfo.mConfirm;
33309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
334ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly        if (V) Log.v(TAG, "after confirm: userAccepted=" + mAccepted);
33509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        int status = BluetoothShare.STATUS_SUCCESS;
33609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
33709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (mAccepted == BluetoothShare.USER_CONFIRMATION_CONFIRMED
338df7415da0e510ab8e4b73831a5ade38306982fe1Tao Liejun                || mAccepted == BluetoothShare.USER_CONFIRMATION_AUTO_CONFIRMED) {
33909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            /* Confirm or auto-confirm */
34009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
34109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            if (mFileInfo.mFileName == null) {
34209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                status = mFileInfo.mStatus;
34309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                /* TODO need to check if this line is correct */
34409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                mInfo.mStatus = mFileInfo.mStatus;
34509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                Constants.updateShareStatus(mContext, mInfo.mId, status);
34609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                obexResponse = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
34709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
34809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
34909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
35009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            if (mFileInfo.mFileName != null) {
35109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
35209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                ContentValues updateValues = new ContentValues();
35309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                contentUri = Uri.parse(BluetoothShare.CONTENT_URI + "/" + mInfo.mId);
35409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                updateValues.put(BluetoothShare._DATA, mFileInfo.mFileName);
35509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                updateValues.put(BluetoothShare.STATUS, BluetoothShare.STATUS_RUNNING);
35609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                mContext.getContentResolver().update(contentUri, updateValues, null, null);
35709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
35809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                status = receiveFile(mFileInfo, op);
35909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                /*
36009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                 * TODO map status to obex response code
36109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                 */
36209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                if (status != BluetoothShare.STATUS_SUCCESS) {
36309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    obexResponse = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
36409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                }
36509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                Constants.updateShareStatus(mContext, mInfo.mId, status);
36609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
36709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
36809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            if (status == BluetoothShare.STATUS_SUCCESS) {
36909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                Message msg = Message.obtain(mCallback, BluetoothOppObexSession.MSG_SHARE_COMPLETE);
37009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                msg.obj = mInfo;
37109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                msg.sendToTarget();
37209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            } else {
3731ac5507790a87810061a19dadec36eb328a222eaTao Liejun                if (mCallback != null) {
3741ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    Message msg = Message.obtain(mCallback,
3751ac5507790a87810061a19dadec36eb328a222eaTao Liejun                            BluetoothOppObexSession.MSG_SESSION_ERROR);
3761ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    mInfo.mStatus = status;
3771ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    msg.obj = mInfo;
3781ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    msg.sendToTarget();
3791ac5507790a87810061a19dadec36eb328a222eaTao Liejun                }
38009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
38109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        } else if (mAccepted == BluetoothShare.USER_CONFIRMATION_DENIED
38209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                || mAccepted == BluetoothShare.USER_CONFIRMATION_TIMEOUT) {
38309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            /* user actively deny the inbound transfer */
38409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            /*
38509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly             * Note There is a question: what's next if user deny the first obj?
38609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly             * Option 1 :continue prompt for next objects
38709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly             * Option 2 :reject next objects and finish the session
38809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly             * Now we take option 2:
38909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly             */
39052236de777c23788df8147de15912a57e8bc36ddTao Liejun
39152236de777c23788df8147de15912a57e8bc36ddTao Liejun            Log.i(TAG, "Rejected incoming request");
3921ac5507790a87810061a19dadec36eb328a222eaTao Liejun            if (mFileInfo.mFileName != null) {
3931ac5507790a87810061a19dadec36eb328a222eaTao Liejun                try {
3941ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    mFileInfo.mOutputStream.close();
3951ac5507790a87810061a19dadec36eb328a222eaTao Liejun                } catch (IOException e) {
3961ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    Log.e(TAG, "error close file stream");
3971ac5507790a87810061a19dadec36eb328a222eaTao Liejun                }
3981ac5507790a87810061a19dadec36eb328a222eaTao Liejun                new File(mFileInfo.mFileName).delete();
3991ac5507790a87810061a19dadec36eb328a222eaTao Liejun            }
4001ac5507790a87810061a19dadec36eb328a222eaTao Liejun            // set status as local cancel
4011ac5507790a87810061a19dadec36eb328a222eaTao Liejun            status = BluetoothShare.STATUS_CANCELED;
40209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Constants.updateShareStatus(mContext, mInfo.mId, status);
40309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            obexResponse = ResponseCodes.OBEX_HTTP_FORBIDDEN;
4041ac5507790a87810061a19dadec36eb328a222eaTao Liejun
40509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Message msg = Message.obtain(mCallback);
40609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            msg.what = BluetoothOppObexSession.MSG_SHARE_INTERRUPTED;
4071ac5507790a87810061a19dadec36eb328a222eaTao Liejun            mInfo.mStatus = status;
40809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            msg.obj = mInfo;
40909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            msg.sendToTarget();
41009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
41109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        return obexResponse;
41209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
41309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
41409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private int receiveFile(BluetoothOppReceiveFileInfo fileInfo, Operation op) {
41509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        /*
41609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly         * implement receive file
41709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly         */
41809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        int status = -1;
41909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        BufferedOutputStream bos = null;
42009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
42109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        InputStream is = null;
42209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        boolean error = false;
42309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        try {
42409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            is = op.openInputStream();
42509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        } catch (IOException e1) {
42609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Log.e(TAG, "Error when openInputStream");
42709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            status = BluetoothShare.STATUS_OBEX_DATA_ERROR;
42809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            error = true;
42909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
43009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
43109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        Uri contentUri = Uri.parse(BluetoothShare.CONTENT_URI + "/" + mInfo.mId);
43209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
43309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (!error) {
43409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            ContentValues updateValues = new ContentValues();
43509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            updateValues.put(BluetoothShare._DATA, fileInfo.mFileName);
43609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            mContext.getContentResolver().update(contentUri, updateValues, null, null);
43709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
43809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
43909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        int position = 0;
44009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (!error) {
4411ac5507790a87810061a19dadec36eb328a222eaTao Liejun            bos = new BufferedOutputStream(fileInfo.mOutputStream, 0x10000);
44209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
44309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
44409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (!error) {
44509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            int outputBufferSize = op.getMaxPacketSize();
44609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            byte[] b = new byte[outputBufferSize];
44709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            int readLength = 0;
44852236de777c23788df8147de15912a57e8bc36ddTao Liejun            long timestamp = 0;
44909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            try {
45009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                while ((!mInterrupted) && (position != fileInfo.mLength)) {
45109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
452ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                    if (V) timestamp = System.currentTimeMillis();
45309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
45409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    readLength = is.read(b);
45509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
45609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    if (readLength == -1) {
457ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                        if (D) Log.d(TAG, "Receive file reached stream end at position" + position);
45809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        break;
45909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    }
46009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
46109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    bos.write(b, 0, readLength);
46209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    position += readLength;
46309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
464ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                    if (V) {
46509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        Log.v(TAG, "Receive file position = " + position + " readLength "
46609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                + readLength + " bytes took "
46709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                + (System.currentTimeMillis() - timestamp) + " ms");
46809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    }
46909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
47009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    ContentValues updateValues = new ContentValues();
47109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    updateValues.put(BluetoothShare.CURRENT_BYTES, position);
47209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    mContext.getContentResolver().update(contentUri, updateValues, null, null);
47309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                }
47409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            } catch (IOException e1) {
47509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                Log.e(TAG, "Error when receiving file");
4769abe9c9e1ccad600b1069490293d78dfd984017bAndreas Areskoug                /* OBEX Abort packet received from remote device */
4779abe9c9e1ccad600b1069490293d78dfd984017bAndreas Areskoug                if ("Abort Received".equals(e1.getMessage())) {
4789abe9c9e1ccad600b1069490293d78dfd984017bAndreas Areskoug                    status = BluetoothShare.STATUS_CANCELED;
4799abe9c9e1ccad600b1069490293d78dfd984017bAndreas Areskoug                } else {
4809abe9c9e1ccad600b1069490293d78dfd984017bAndreas Areskoug                    status = BluetoothShare.STATUS_OBEX_DATA_ERROR;
4819abe9c9e1ccad600b1069490293d78dfd984017bAndreas Areskoug                }
48209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                error = true;
48309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
48409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
48509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
48609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (mInterrupted) {
487ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly            if (D) Log.d(TAG, "receiving file interrupted by user.");
48809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            status = BluetoothShare.STATUS_CANCELED;
48909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        } else {
49009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            if (position == fileInfo.mLength) {
491ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                if (D) Log.d(TAG, "Receiving file completed for " + fileInfo.mFileName);
49209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                status = BluetoothShare.STATUS_SUCCESS;
49309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            } else {
494ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                if (D) Log.d(TAG, "Reading file failed at " + position + " of " + fileInfo.mLength);
49509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                if (status == -1) {
49609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    status = BluetoothShare.STATUS_UNKNOWN_ERROR;
49709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                }
49809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
49909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
50009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
50109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (bos != null) {
50209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            try {
50309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                bos.close();
50409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            } catch (IOException e) {
50509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                Log.e(TAG, "Error when closing stream after send");
50609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
50709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
50809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        return status;
50909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
51009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
51109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private BluetoothOppReceiveFileInfo processShareInfo() {
512ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly        if (D) Log.d(TAG, "processShareInfo() " + mInfo.mId);
51309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        BluetoothOppReceiveFileInfo fileInfo = BluetoothOppReceiveFileInfo.generateFileInfo(
51409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                mContext, mInfo.mId);
515ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly        if (V) {
51609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Log.v(TAG, "Generate BluetoothOppReceiveFileInfo:");
51709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Log.v(TAG, "filename  :" + fileInfo.mFileName);
51809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Log.v(TAG, "length    :" + fileInfo.mLength);
51909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Log.v(TAG, "status    :" + fileInfo.mStatus);
52009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
52109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        return fileInfo;
52209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
52309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
52409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    @Override
52509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    public int onConnect(HeaderSet request, HeaderSet reply) {
52609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
527ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly        if (D) Log.d(TAG, "onConnect");
528ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly        if (V) Constants.logHeader(request);
5299d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun        try {
5309d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun            byte[] uuid = (byte[])request.getHeader(HeaderSet.TARGET);
5319d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun            if (V) Log.v(TAG, "onConnect(): uuid =" + Arrays.toString(uuid));
5329d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun            if(uuid != null) {
533eb1192b4208d4bf77c92011822e6d171b9f09980Jaikumar Ganesh                 return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
5349d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun            }
5359d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun        } catch (IOException e) {
5369d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun            Log.e(TAG, e.toString());
5379d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun            return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
5389d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun        }
53909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        mTimestamp = System.currentTimeMillis();
54009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        return ResponseCodes.OBEX_HTTP_OK;
54109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
54209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
54309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    @Override
54409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    public void onDisconnect(HeaderSet req, HeaderSet resp) {
545ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly        if (D) Log.d(TAG, "onDisconnect");
54609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        resp.responseCode = ResponseCodes.OBEX_HTTP_OK;
54709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
54809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
5494492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh    private synchronized void releaseWakeLocks() {
55032e47df203390052c1ef771d78b22fc4aa5f9e72Tao Liejun        if (mWakeLock.isHeld()) {
55132e47df203390052c1ef771d78b22fc4aa5f9e72Tao Liejun            mWakeLock.release();
55232e47df203390052c1ef771d78b22fc4aa5f9e72Tao Liejun        }
55332e47df203390052c1ef771d78b22fc4aa5f9e72Tao Liejun        if (mPartialWakeLock.isHeld()) {
55432e47df203390052c1ef771d78b22fc4aa5f9e72Tao Liejun            mPartialWakeLock.release();
55532e47df203390052c1ef771d78b22fc4aa5f9e72Tao Liejun        }
5564492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh    }
5574492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh
5584492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh    @Override
5594492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh    public void onClose() {
5604492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh        if (V) Log.v(TAG, "release WakeLock");
5614492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh        releaseWakeLocks();
5624492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh
5639d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun        /* onClose could happen even before start() where mCallback is set */
5649d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun        if (mCallback != null) {
5659d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun            Message msg = Message.obtain(mCallback);
5669d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun            msg.what = BluetoothOppObexSession.MSG_SESSION_COMPLETE;
5679d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun            msg.obj = mInfo;
5689d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun            msg.sendToTarget();
5699d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun        }
57009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
57109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly}
572