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 android.content.ContentValues;
3609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.content.Context;
3709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.content.Intent;
3809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.net.Uri;
3909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.os.Handler;
4009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.os.Message;
4152236de777c23788df8147de15912a57e8bc36ddTao Liejunimport android.os.PowerManager;
4252236de777c23788df8147de15912a57e8bc36ddTao Liejunimport android.os.PowerManager.WakeLock;
4371f70164a0044b0f5c26847def4eecfd0a306102Hiroki Yamamotoimport android.os.SystemClock;
4409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.util.Log;
4509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport android.webkit.MimeTypeMap;
4609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
470ad53ef457f156314595a27c63660454450d3c84Jack Heimport com.android.bluetooth.BluetoothMetricsProto;
48c4fbd756e2645147470c486ae96f2253f5e13a52Jack Heimport com.android.bluetooth.BluetoothObexTransport;
490ad53ef457f156314595a27c63660454450d3c84Jack Heimport com.android.bluetooth.btservice.MetricsLogger;
50c4fbd756e2645147470c486ae96f2253f5e13a52Jack He
51c4fbd756e2645147470c486ae96f2253f5e13a52Jack Heimport java.io.BufferedOutputStream;
52c4fbd756e2645147470c486ae96f2253f5e13a52Jack Heimport java.io.File;
53c4fbd756e2645147470c486ae96f2253f5e13a52Jack Heimport java.io.IOException;
54c4fbd756e2645147470c486ae96f2253f5e13a52Jack Heimport java.io.InputStream;
55c4fbd756e2645147470c486ae96f2253f5e13a52Jack Heimport java.util.Arrays;
56c4fbd756e2645147470c486ae96f2253f5e13a52Jack He
5709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport javax.obex.HeaderSet;
5809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport javax.obex.ObexTransport;
5909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport javax.obex.Operation;
6009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport javax.obex.ResponseCodes;
6109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport javax.obex.ServerRequestHandler;
6209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pellyimport javax.obex.ServerSession;
6309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
6409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly/**
6509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly * This class runs as an OBEX server
6609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly */
67c4fbd756e2645147470c486ae96f2253f5e13a52Jack Hepublic class BluetoothOppObexServerSession extends ServerRequestHandler
68c4fbd756e2645147470c486ae96f2253f5e13a52Jack He        implements BluetoothOppObexSession {
6909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
70ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly    private static final String TAG = "BtOppObexServer";
71ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly    private static final boolean D = Constants.DEBUG;
72ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly    private static final boolean V = Constants.VERBOSE;
7309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
7409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private ObexTransport mTransport;
7509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
7609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private Context mContext;
7709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
7809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private Handler mCallback = null;
7909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
8009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    /* status when server is blocking for user/auto confirmation */
8109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private boolean mServerBlocking = true;
8209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
8309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    /* the current transfer info */
8409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private BluetoothOppShareInfo mInfo;
8509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
8609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    /* info id when we insert the record */
8709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private int mLocalShareInfoId;
8809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
8909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private int mAccepted = BluetoothShare.USER_CONFIRMATION_PENDING;
9009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
9109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private boolean mInterrupted = false;
9209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
9309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private ServerSession mSession;
9409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
9509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private long mTimestamp;
9609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
9709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private BluetoothOppReceiveFileInfo mFileInfo;
9809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
9952236de777c23788df8147de15912a57e8bc36ddTao Liejun    private WakeLock mPartialWakeLock;
10052236de777c23788df8147de15912a57e8bc36ddTao Liejun
1011ac5507790a87810061a19dadec36eb328a222eaTao Liejun    boolean mTimeoutMsgSent = false;
1021ac5507790a87810061a19dadec36eb328a222eaTao Liejun
1037621506c7ade0a034f1cb77f5c1215db103768dbHansong Zhang    private BluetoothOppService mBluetoothOppService;
1044aa5e4e2fe52c06d97481db0bf180349053dae48Hemant Gupta
1050ad53ef457f156314595a27c63660454450d3c84Jack He    private int mNumFilesAttemptedToReceive;
1060ad53ef457f156314595a27c63660454450d3c84Jack He
107c4fbd756e2645147470c486ae96f2253f5e13a52Jack He    public BluetoothOppObexServerSession(Context context, ObexTransport transport,
1087621506c7ade0a034f1cb77f5c1215db103768dbHansong Zhang            BluetoothOppService service) {
10909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        mContext = context;
11009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        mTransport = transport;
1117621506c7ade0a034f1cb77f5c1215db103768dbHansong Zhang        mBluetoothOppService = service;
112c4fbd756e2645147470c486ae96f2253f5e13a52Jack He        PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
11352236de777c23788df8147de15912a57e8bc36ddTao Liejun        mPartialWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
114d2f6bd176055ed6c707f3e27ff130318afd231b1Ajay Panicker        mPartialWakeLock.setReferenceCounted(false);
11509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
11609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
1172fbb1d97d08d5d72fe824e543c714e56cd7be236Jack He    @Override
11809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    public void unblock() {
11909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        mServerBlocking = false;
12009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
12109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
12209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    /**
12309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly     * Called when connection is accepted from remote, to retrieve the first
12409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly     * Header then wait for user confirmation
12509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly     */
126db94389c30d5ad5555a922d28868b119e1c6f2e1Andre Eisenbach    public void preStart() {
12709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        try {
128c4fbd756e2645147470c486ae96f2253f5e13a52Jack He            if (D) {
129c4fbd756e2645147470c486ae96f2253f5e13a52Jack He                Log.d(TAG, "Create ServerSession with transport " + mTransport.toString());
130c4fbd756e2645147470c486ae96f2253f5e13a52Jack He            }
13109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            mSession = new ServerSession(mTransport, this, null);
13209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        } catch (IOException e) {
13309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Log.e(TAG, "Create server session error" + e);
13409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
13509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
13609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
13709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    /**
13809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly     * Called from BluetoothOppTransfer to start the "Transfer"
13909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly     */
1402fbb1d97d08d5d72fe824e543c714e56cd7be236Jack He    @Override
1418eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen    public void start(Handler handler, int numShares) {
142c4fbd756e2645147470c486ae96f2253f5e13a52Jack He        if (D) {
143c4fbd756e2645147470c486ae96f2253f5e13a52Jack He            Log.d(TAG, "Start!");
144c4fbd756e2645147470c486ae96f2253f5e13a52Jack He        }
14509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        mCallback = handler;
14609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
14709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
14809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
14909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    /**
1506769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun     * Called from BluetoothOppTransfer to cancel the "Transfer" Otherwise,
1516769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun     * server should end by itself.
15209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly     */
1532fbb1d97d08d5d72fe824e543c714e56cd7be236Jack He    @Override
15409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    public void stop() {
15509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        /*
15609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly         * TODO now we implement in a tough way, just close the socket.
15709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly         * maybe need nice way
15809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly         */
159c4fbd756e2645147470c486ae96f2253f5e13a52Jack He        if (D) {
160c4fbd756e2645147470c486ae96f2253f5e13a52Jack He            Log.d(TAG, "Stop!");
161c4fbd756e2645147470c486ae96f2253f5e13a52Jack He        }
16209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        mInterrupted = true;
16309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (mSession != null) {
16409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            try {
16509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                mSession.close();
16609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                mTransport.close();
16709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            } catch (IOException e) {
16809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                Log.e(TAG, "close mTransport error" + e);
16909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
17009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
1711ac5507790a87810061a19dadec36eb328a222eaTao Liejun        mCallback = null;
1721ac5507790a87810061a19dadec36eb328a222eaTao Liejun        mSession = null;
17309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
17409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
1752fbb1d97d08d5d72fe824e543c714e56cd7be236Jack He    @Override
17609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    public void addShare(BluetoothOppShareInfo info) {
177c4fbd756e2645147470c486ae96f2253f5e13a52Jack He        if (D) {
178c4fbd756e2645147470c486ae96f2253f5e13a52Jack He            Log.d(TAG, "addShare for id " + info.mId);
179c4fbd756e2645147470c486ae96f2253f5e13a52Jack He        }
18009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        mInfo = info;
18109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        mFileInfo = processShareInfo();
18209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
18309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
18409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    @Override
18509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    public int onPut(Operation op) {
186c4fbd756e2645147470c486ae96f2253f5e13a52Jack He        if (D) {
187c4fbd756e2645147470c486ae96f2253f5e13a52Jack He            Log.d(TAG, "onPut " + op.toString());
188c4fbd756e2645147470c486ae96f2253f5e13a52Jack He        }
18909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
19079cd1a86171c772516d79c640bc244bcffee2960Myles Watson        /* For multiple objects, reject further objects after the user denies the first one */
19109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (mAccepted == BluetoothShare.USER_CONFIRMATION_DENIED) {
19209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            return ResponseCodes.OBEX_HTTP_FORBIDDEN;
19309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
19409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
19503f25a2055e51bcc5e8870642763b502956b6830Martijn Coenen        String destination;
196bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        if (mTransport instanceof BluetoothObexTransport) {
197c4fbd756e2645147470c486ae96f2253f5e13a52Jack He            destination = ((BluetoothObexTransport) mTransport).getRemoteAddress();
19803f25a2055e51bcc5e8870642763b502956b6830Martijn Coenen        } else {
19903f25a2055e51bcc5e8870642763b502956b6830Martijn Coenen            destination = "FF:FF:FF:00:00:00";
20003f25a2055e51bcc5e8870642763b502956b6830Martijn Coenen        }
201e2f0e0fce32c77e0ac097b5b14dead5102959b82Jack He        boolean isWhitelisted =
202e2f0e0fce32c77e0ac097b5b14dead5102959b82Jack He                BluetoothOppManager.getInstance(mContext).isWhitelisted(destination);
20303f25a2055e51bcc5e8870642763b502956b6830Martijn Coenen
20479cd1a86171c772516d79c640bc244bcffee2960Myles Watson        HeaderSet request;
20579cd1a86171c772516d79c640bc244bcffee2960Myles Watson        String name, mimeType;
20679cd1a86171c772516d79c640bc244bcffee2960Myles Watson        Long length;
20709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        try {
2086769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun            request = op.getReceivedHeader();
209c4fbd756e2645147470c486ae96f2253f5e13a52Jack He            if (V) {
210c4fbd756e2645147470c486ae96f2253f5e13a52Jack He                Constants.logHeader(request);
211c4fbd756e2645147470c486ae96f2253f5e13a52Jack He            }
212c4fbd756e2645147470c486ae96f2253f5e13a52Jack He            name = (String) request.getHeader(HeaderSet.NAME);
213c4fbd756e2645147470c486ae96f2253f5e13a52Jack He            length = (Long) request.getHeader(HeaderSet.LENGTH);
214c4fbd756e2645147470c486ae96f2253f5e13a52Jack He            mimeType = (String) request.getHeader(HeaderSet.TYPE);
21579cd1a86171c772516d79c640bc244bcffee2960Myles Watson        } catch (IOException e) {
21679cd1a86171c772516d79c640bc244bcffee2960Myles Watson            Log.e(TAG, "onPut: getReceivedHeaders error " + e);
21779cd1a86171c772516d79c640bc244bcffee2960Myles Watson            return ResponseCodes.OBEX_HTTP_BAD_REQUEST;
21879cd1a86171c772516d79c640bc244bcffee2960Myles Watson        }
21909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
22079cd1a86171c772516d79c640bc244bcffee2960Myles Watson        if (length == 0) {
22179cd1a86171c772516d79c640bc244bcffee2960Myles Watson            if (D) {
22279cd1a86171c772516d79c640bc244bcffee2960Myles Watson                Log.w(TAG, "length is 0, reject the transfer");
22309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
22479cd1a86171c772516d79c640bc244bcffee2960Myles Watson            return ResponseCodes.OBEX_HTTP_LENGTH_REQUIRED;
22579cd1a86171c772516d79c640bc244bcffee2960Myles Watson        }
22609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
22779cd1a86171c772516d79c640bc244bcffee2960Myles Watson        if (name == null || name.isEmpty()) {
22879cd1a86171c772516d79c640bc244bcffee2960Myles Watson            if (D) {
22979cd1a86171c772516d79c640bc244bcffee2960Myles Watson                Log.w(TAG, "name is null or empty, reject the transfer");
23009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
23179cd1a86171c772516d79c640bc244bcffee2960Myles Watson            return ResponseCodes.OBEX_HTTP_BAD_REQUEST;
23279cd1a86171c772516d79c640bc244bcffee2960Myles Watson        }
23309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
23479cd1a86171c772516d79c640bc244bcffee2960Myles Watson        // First we look for the mime type in the Android map
23579cd1a86171c772516d79c640bc244bcffee2960Myles Watson        String extension, type;
23679cd1a86171c772516d79c640bc244bcffee2960Myles Watson        int dotIndex = name.lastIndexOf(".");
23779cd1a86171c772516d79c640bc244bcffee2960Myles Watson        if (dotIndex < 0 && mimeType == null) {
23879cd1a86171c772516d79c640bc244bcffee2960Myles Watson            if (D) {
23979cd1a86171c772516d79c640bc244bcffee2960Myles Watson                Log.w(TAG, "There is no file extension or mime type, reject the transfer");
24079cd1a86171c772516d79c640bc244bcffee2960Myles Watson            }
24179cd1a86171c772516d79c640bc244bcffee2960Myles Watson            return ResponseCodes.OBEX_HTTP_BAD_REQUEST;
24279cd1a86171c772516d79c640bc244bcffee2960Myles Watson        } else {
24379cd1a86171c772516d79c640bc244bcffee2960Myles Watson            extension = name.substring(dotIndex + 1).toLowerCase();
24479cd1a86171c772516d79c640bc244bcffee2960Myles Watson            MimeTypeMap map = MimeTypeMap.getSingleton();
24579cd1a86171c772516d79c640bc244bcffee2960Myles Watson            type = map.getMimeTypeFromExtension(extension);
24679cd1a86171c772516d79c640bc244bcffee2960Myles Watson            if (V) {
24779cd1a86171c772516d79c640bc244bcffee2960Myles Watson                Log.v(TAG, "Mimetype guessed from extension " + extension + " is " + type);
24879cd1a86171c772516d79c640bc244bcffee2960Myles Watson            }
24979cd1a86171c772516d79c640bc244bcffee2960Myles Watson            if (type != null) {
25079cd1a86171c772516d79c640bc244bcffee2960Myles Watson                mimeType = type;
25179cd1a86171c772516d79c640bc244bcffee2960Myles Watson            } else {
25279cd1a86171c772516d79c640bc244bcffee2960Myles Watson                if (mimeType == null) {
253c4fbd756e2645147470c486ae96f2253f5e13a52Jack He                    if (D) {
25479cd1a86171c772516d79c640bc244bcffee2960Myles Watson                        Log.w(TAG, "Can't get mimetype, reject the transfer");
25509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    }
25679cd1a86171c772516d79c640bc244bcffee2960Myles Watson                    return ResponseCodes.OBEX_HTTP_UNSUPPORTED_TYPE;
25709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                }
25809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
25979cd1a86171c772516d79c640bc244bcffee2960Myles Watson            mimeType = mimeType.toLowerCase();
26079cd1a86171c772516d79c640bc244bcffee2960Myles Watson        }
26109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
26279cd1a86171c772516d79c640bc244bcffee2960Myles Watson        // Reject anything outside the "whitelist" plus unspecified MIME Types.
26379cd1a86171c772516d79c640bc244bcffee2960Myles Watson        if (mimeType == null || (!isWhitelisted && !Constants.mimeTypeMatches(mimeType,
26479cd1a86171c772516d79c640bc244bcffee2960Myles Watson                Constants.ACCEPTABLE_SHARE_INBOUND_TYPES))) {
26579cd1a86171c772516d79c640bc244bcffee2960Myles Watson            if (D) {
26679cd1a86171c772516d79c640bc244bcffee2960Myles Watson                Log.w(TAG, "mimeType is null or in unacceptable list, reject the transfer");
26709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
26879cd1a86171c772516d79c640bc244bcffee2960Myles Watson            return ResponseCodes.OBEX_HTTP_UNSUPPORTED_TYPE;
26909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
27009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
27109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        ContentValues values = new ContentValues();
27209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        values.put(BluetoothShare.FILENAME_HINT, name);
2733aecf54308d60eea10fe10a5c18e4dff455aef66Pradeep Panigrahi        values.put(BluetoothShare.TOTAL_BYTES, length);
27409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        values.put(BluetoothShare.MIMETYPE, mimeType);
2758099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen        values.put(BluetoothShare.DESTINATION, destination);
27609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        values.put(BluetoothShare.DIRECTION, BluetoothShare.DIRECTION_INBOUND);
27709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        values.put(BluetoothShare.TIMESTAMP, mTimestamp);
27809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
27979cd1a86171c772516d79c640bc244bcffee2960Myles Watson        // It's not first put if !serverBlocking, so we auto accept it
280c4fbd756e2645147470c486ae96f2253f5e13a52Jack He        if (!mServerBlocking && (mAccepted == BluetoothShare.USER_CONFIRMATION_CONFIRMED
281c4fbd756e2645147470c486ae96f2253f5e13a52Jack He                || mAccepted == BluetoothShare.USER_CONFIRMATION_AUTO_CONFIRMED)) {
28209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            values.put(BluetoothShare.USER_CONFIRMATION,
28309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    BluetoothShare.USER_CONFIRMATION_AUTO_CONFIRMED);
28409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
28509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
28603f25a2055e51bcc5e8870642763b502956b6830Martijn Coenen        if (isWhitelisted) {
2878099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen            values.put(BluetoothShare.USER_CONFIRMATION,
2888099f5e7bfa7227ba674b5f0076f331e737bafd7Martijn Coenen                    BluetoothShare.USER_CONFIRMATION_HANDOVER_CONFIRMED);
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
294c4fbd756e2645147470c486ae96f2253f5e13a52Jack He        if (V) {
295c4fbd756e2645147470c486ae96f2253f5e13a52Jack He            Log.v(TAG, "insert contentUri: " + contentUri);
296c4fbd756e2645147470c486ae96f2253f5e13a52Jack He            Log.v(TAG, "mLocalShareInfoId = " + mLocalShareInfoId);
297c4fbd756e2645147470c486ae96f2253f5e13a52Jack He        }
29809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
29909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        synchronized (this) {
300f6ae67403c20cec20bc8f906411fce4c9ea769f0Sunny Goyal            mPartialWakeLock.acquire();
3014492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh            mServerBlocking = true;
30209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            try {
303df7415da0e510ab8e4b73831a5ade38306982fe1Tao Liejun
30409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                while (mServerBlocking) {
30509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    wait(1000);
3061ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    if (mCallback != null && !mTimeoutMsgSent) {
307c4fbd756e2645147470c486ae96f2253f5e13a52Jack He                        mCallback.sendMessageDelayed(mCallback.obtainMessage(
308c4fbd756e2645147470c486ae96f2253f5e13a52Jack He                                BluetoothOppObexSession.MSG_CONNECT_TIMEOUT),
30909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                                BluetoothOppObexSession.SESSION_TIMEOUT);
3101ac5507790a87810061a19dadec36eb328a222eaTao Liejun                        mTimeoutMsgSent = true;
311c4fbd756e2645147470c486ae96f2253f5e13a52Jack He                        if (V) {
312c4fbd756e2645147470c486ae96f2253f5e13a52Jack He                            Log.v(TAG, "MSG_CONNECT_TIMEOUT sent");
313c4fbd756e2645147470c486ae96f2253f5e13a52Jack He                        }
31409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    }
31509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                }
31609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            } catch (InterruptedException e) {
317c4fbd756e2645147470c486ae96f2253f5e13a52Jack He                if (V) {
318c4fbd756e2645147470c486ae96f2253f5e13a52Jack He                    Log.v(TAG, "Interrupted in onPut blocking");
319c4fbd756e2645147470c486ae96f2253f5e13a52Jack He                }
32009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
32109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
322c4fbd756e2645147470c486ae96f2253f5e13a52Jack He        if (D) {
323c4fbd756e2645147470c486ae96f2253f5e13a52Jack He            Log.d(TAG, "Server unblocked ");
324c4fbd756e2645147470c486ae96f2253f5e13a52Jack He        }
3259d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun        synchronized (this) {
3269d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun            if (mCallback != null && mTimeoutMsgSent) {
3279d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun                mCallback.removeMessages(BluetoothOppObexSession.MSG_CONNECT_TIMEOUT);
3289d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun            }
3296769b59d715ea98bd72eafcfea9acd2714a887daTao Liejun        }
33009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
33109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        /* we should have mInfo now */
33209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
33309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        /*
33409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly         * TODO check if this mInfo match the one that we insert before server
33509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly         * blocking? just to make sure no error happens
33609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly         */
33709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (mInfo.mId != mLocalShareInfoId) {
33809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Log.e(TAG, "Unexpected error!");
33909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
34009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        mAccepted = mInfo.mConfirm;
34109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
342c4fbd756e2645147470c486ae96f2253f5e13a52Jack He        if (V) {
343c4fbd756e2645147470c486ae96f2253f5e13a52Jack He            Log.v(TAG, "after confirm: userAccepted=" + mAccepted);
344c4fbd756e2645147470c486ae96f2253f5e13a52Jack He        }
34509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        int status = BluetoothShare.STATUS_SUCCESS;
34609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
34779cd1a86171c772516d79c640bc244bcffee2960Myles Watson        int obexResponse = ResponseCodes.OBEX_HTTP_OK;
34879cd1a86171c772516d79c640bc244bcffee2960Myles Watson
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 */
3530ad53ef457f156314595a27c63660454450d3c84Jack He            mNumFilesAttemptedToReceive++;
35409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
35509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            if (mFileInfo.mFileName == null) {
35609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                status = mFileInfo.mStatus;
35709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                /* TODO need to check if this line is correct */
35809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                mInfo.mStatus = mFileInfo.mStatus;
35909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                Constants.updateShareStatus(mContext, mInfo.mId, status);
36009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                obexResponse = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
36109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
36209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
36309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
36409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            if (mFileInfo.mFileName != null) {
36509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
36609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                ContentValues updateValues = new ContentValues();
36709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                contentUri = Uri.parse(BluetoothShare.CONTENT_URI + "/" + mInfo.mId);
36809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                updateValues.put(BluetoothShare._DATA, mFileInfo.mFileName);
36909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                updateValues.put(BluetoothShare.STATUS, BluetoothShare.STATUS_RUNNING);
37009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                mContext.getContentResolver().update(contentUri, updateValues, null, null);
37109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
37209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                status = receiveFile(mFileInfo, op);
37309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                /*
37409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                 * TODO map status to obex response code
37509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                 */
37609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                if (status != BluetoothShare.STATUS_SUCCESS) {
37709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    obexResponse = ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
37809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                }
37909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                Constants.updateShareStatus(mContext, mInfo.mId, status);
38009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
38109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
38209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            if (status == BluetoothShare.STATUS_SUCCESS) {
38309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                Message msg = Message.obtain(mCallback, BluetoothOppObexSession.MSG_SHARE_COMPLETE);
38409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                msg.obj = mInfo;
38509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                msg.sendToTarget();
38609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            } else {
3871ac5507790a87810061a19dadec36eb328a222eaTao Liejun                if (mCallback != null) {
388c4fbd756e2645147470c486ae96f2253f5e13a52Jack He                    Message msg =
389c4fbd756e2645147470c486ae96f2253f5e13a52Jack He                            Message.obtain(mCallback, BluetoothOppObexSession.MSG_SESSION_ERROR);
3901ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    mInfo.mStatus = status;
3911ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    msg.obj = mInfo;
3921ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    msg.sendToTarget();
3931ac5507790a87810061a19dadec36eb328a222eaTao Liejun                }
39409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
39509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        } else if (mAccepted == BluetoothShare.USER_CONFIRMATION_DENIED
39609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                || mAccepted == BluetoothShare.USER_CONFIRMATION_TIMEOUT) {
39709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            /* user actively deny the inbound transfer */
39809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            /*
39909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly             * Note There is a question: what's next if user deny the first obj?
40009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly             * Option 1 :continue prompt for next objects
40109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly             * Option 2 :reject next objects and finish the session
40209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly             * Now we take option 2:
40309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly             */
40452236de777c23788df8147de15912a57e8bc36ddTao Liejun
40552236de777c23788df8147de15912a57e8bc36ddTao Liejun            Log.i(TAG, "Rejected incoming request");
4061ac5507790a87810061a19dadec36eb328a222eaTao Liejun            if (mFileInfo.mFileName != null) {
4071ac5507790a87810061a19dadec36eb328a222eaTao Liejun                try {
4081ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    mFileInfo.mOutputStream.close();
4091ac5507790a87810061a19dadec36eb328a222eaTao Liejun                } catch (IOException e) {
4101ac5507790a87810061a19dadec36eb328a222eaTao Liejun                    Log.e(TAG, "error close file stream");
4111ac5507790a87810061a19dadec36eb328a222eaTao Liejun                }
4121ac5507790a87810061a19dadec36eb328a222eaTao Liejun                new File(mFileInfo.mFileName).delete();
4131ac5507790a87810061a19dadec36eb328a222eaTao Liejun            }
4141ac5507790a87810061a19dadec36eb328a222eaTao Liejun            // set status as local cancel
4151ac5507790a87810061a19dadec36eb328a222eaTao Liejun            status = BluetoothShare.STATUS_CANCELED;
41609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Constants.updateShareStatus(mContext, mInfo.mId, status);
41709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            obexResponse = ResponseCodes.OBEX_HTTP_FORBIDDEN;
4181ac5507790a87810061a19dadec36eb328a222eaTao Liejun
41909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Message msg = Message.obtain(mCallback);
42009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            msg.what = BluetoothOppObexSession.MSG_SHARE_INTERRUPTED;
4211ac5507790a87810061a19dadec36eb328a222eaTao Liejun            mInfo.mStatus = status;
42209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            msg.obj = mInfo;
42309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            msg.sendToTarget();
42409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
42509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        return obexResponse;
42609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
42709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
42809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private int receiveFile(BluetoothOppReceiveFileInfo fileInfo, Operation op) {
42909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        /*
43009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly         * implement receive file
43109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly         */
43209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        int status = -1;
43309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        BufferedOutputStream bos = null;
43409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
43509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        InputStream is = null;
43609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        boolean error = false;
43709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        try {
43809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            is = op.openInputStream();
43909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        } catch (IOException e1) {
44009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Log.e(TAG, "Error when openInputStream");
44109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            status = BluetoothShare.STATUS_OBEX_DATA_ERROR;
44209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            error = true;
44309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
44409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
44509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        Uri contentUri = Uri.parse(BluetoothShare.CONTENT_URI + "/" + mInfo.mId);
44609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
44709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (!error) {
44809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            ContentValues updateValues = new ContentValues();
44909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            updateValues.put(BluetoothShare._DATA, fileInfo.mFileName);
45009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            mContext.getContentResolver().update(contentUri, updateValues, null, null);
45109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
45209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
453944be107f513c90a7a8319f19bbe132b236ef1e7Deepak A Metri        long position = 0;
45479cd1a86171c772516d79c640bc244bcffee2960Myles Watson        long percent;
455944be107f513c90a7a8319f19bbe132b236ef1e7Deepak A Metri        long prevPercent = 0;
456944be107f513c90a7a8319f19bbe132b236ef1e7Deepak A Metri
45709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (!error) {
4581ac5507790a87810061a19dadec36eb328a222eaTao Liejun            bos = new BufferedOutputStream(fileInfo.mOutputStream, 0x10000);
45909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
46009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
46109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (!error) {
46209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            int outputBufferSize = op.getMaxPacketSize();
46309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            byte[] b = new byte[outputBufferSize];
46479cd1a86171c772516d79c640bc244bcffee2960Myles Watson            int readLength;
46552236de777c23788df8147de15912a57e8bc36ddTao Liejun            long timestamp = 0;
46679cd1a86171c772516d79c640bc244bcffee2960Myles Watson            long currentTime;
46771f70164a0044b0f5c26847def4eecfd0a306102Hiroki Yamamoto            long prevTimestamp = SystemClock.elapsedRealtime();
46809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            try {
46909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                while ((!mInterrupted) && (position != fileInfo.mLength)) {
47009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
471c4fbd756e2645147470c486ae96f2253f5e13a52Jack He                    if (V) {
47271f70164a0044b0f5c26847def4eecfd0a306102Hiroki Yamamoto                        timestamp = SystemClock.elapsedRealtime();
473c4fbd756e2645147470c486ae96f2253f5e13a52Jack He                    }
47409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
47509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    readLength = is.read(b);
47609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
47709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    if (readLength == -1) {
478c4fbd756e2645147470c486ae96f2253f5e13a52Jack He                        if (D) {
479c4fbd756e2645147470c486ae96f2253f5e13a52Jack He                            Log.d(TAG, "Receive file reached stream end at position" + position);
480c4fbd756e2645147470c486ae96f2253f5e13a52Jack He                        }
48109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                        break;
48209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    }
48309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
48409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    bos.write(b, 0, readLength);
48509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    position += readLength;
486944be107f513c90a7a8319f19bbe132b236ef1e7Deepak A Metri                    percent = position * 100 / fileInfo.mLength;
48771f70164a0044b0f5c26847def4eecfd0a306102Hiroki Yamamoto                    currentTime = SystemClock.elapsedRealtime();
48809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
489ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly                    if (V) {
490c4fbd756e2645147470c486ae96f2253f5e13a52Jack He                        Log.v(TAG,
491c4fbd756e2645147470c486ae96f2253f5e13a52Jack He                                "Receive file position = " + position + " readLength " + readLength
49271f70164a0044b0f5c26847def4eecfd0a306102Hiroki Yamamoto                                        + " bytes took " + (currentTime - timestamp) + " ms");
49309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    }
49409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
495944be107f513c90a7a8319f19bbe132b236ef1e7Deepak A Metri                    // Update the Progress Bar only if there is change in percentage
49671f70164a0044b0f5c26847def4eecfd0a306102Hiroki Yamamoto                    // or once per a period to notify NFC of this transfer is still alive
49771f70164a0044b0f5c26847def4eecfd0a306102Hiroki Yamamoto                    if (percent > prevPercent
49871f70164a0044b0f5c26847def4eecfd0a306102Hiroki Yamamoto                            || currentTime - prevTimestamp > Constants.NFC_ALIVE_CHECK_MS) {
499944be107f513c90a7a8319f19bbe132b236ef1e7Deepak A Metri                        ContentValues updateValues = new ContentValues();
500944be107f513c90a7a8319f19bbe132b236ef1e7Deepak A Metri                        updateValues.put(BluetoothShare.CURRENT_BYTES, position);
501944be107f513c90a7a8319f19bbe132b236ef1e7Deepak A Metri                        mContext.getContentResolver().update(contentUri, updateValues, null, null);
502944be107f513c90a7a8319f19bbe132b236ef1e7Deepak A Metri                        prevPercent = percent;
50371f70164a0044b0f5c26847def4eecfd0a306102Hiroki Yamamoto                        prevTimestamp = currentTime;
504944be107f513c90a7a8319f19bbe132b236ef1e7Deepak A Metri                    }
50509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                }
50609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            } catch (IOException e1) {
507cc284c80ef076eb33b99521cbb1cf3d6982fa341Ajay Panicker                Log.e(TAG, "Error when receiving file: " + e1);
5089abe9c9e1ccad600b1069490293d78dfd984017bAndreas Areskoug                /* OBEX Abort packet received from remote device */
5099abe9c9e1ccad600b1069490293d78dfd984017bAndreas Areskoug                if ("Abort Received".equals(e1.getMessage())) {
5109abe9c9e1ccad600b1069490293d78dfd984017bAndreas Areskoug                    status = BluetoothShare.STATUS_CANCELED;
5119abe9c9e1ccad600b1069490293d78dfd984017bAndreas Areskoug                } else {
5129abe9c9e1ccad600b1069490293d78dfd984017bAndreas Areskoug                    status = BluetoothShare.STATUS_OBEX_DATA_ERROR;
5139abe9c9e1ccad600b1069490293d78dfd984017bAndreas Areskoug                }
51409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                error = true;
51509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
51609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
51709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
51809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (mInterrupted) {
519c4fbd756e2645147470c486ae96f2253f5e13a52Jack He            if (D) {
520c4fbd756e2645147470c486ae96f2253f5e13a52Jack He                Log.d(TAG, "receiving file interrupted by user.");
521c4fbd756e2645147470c486ae96f2253f5e13a52Jack He            }
52209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            status = BluetoothShare.STATUS_CANCELED;
52309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        } else {
52409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            if (position == fileInfo.mLength) {
525c4fbd756e2645147470c486ae96f2253f5e13a52Jack He                if (D) {
526c4fbd756e2645147470c486ae96f2253f5e13a52Jack He                    Log.d(TAG, "Receiving file completed for " + fileInfo.mFileName);
527c4fbd756e2645147470c486ae96f2253f5e13a52Jack He                }
52809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                status = BluetoothShare.STATUS_SUCCESS;
52909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            } else {
530c4fbd756e2645147470c486ae96f2253f5e13a52Jack He                if (D) {
531c4fbd756e2645147470c486ae96f2253f5e13a52Jack He                    Log.d(TAG, "Reading file failed at " + position + " of " + fileInfo.mLength);
532c4fbd756e2645147470c486ae96f2253f5e13a52Jack He                }
53309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                if (status == -1) {
53409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                    status = BluetoothShare.STATUS_UNKNOWN_ERROR;
53509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                }
53609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
53709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
53809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
53909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        if (bos != null) {
54009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            try {
54109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                bos.close();
54209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            } catch (IOException e) {
54309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly                Log.e(TAG, "Error when closing stream after send");
54409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            }
54509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
5460eab1c87e9a0b26e3f61dcc46681a0a20f9cb745Hemant Gupta        BluetoothOppUtility.cancelNotification(mContext);
54709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        return status;
54809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
54909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
55009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    private BluetoothOppReceiveFileInfo processShareInfo() {
551c4fbd756e2645147470c486ae96f2253f5e13a52Jack He        if (D) {
552c4fbd756e2645147470c486ae96f2253f5e13a52Jack He            Log.d(TAG, "processShareInfo() " + mInfo.mId);
553c4fbd756e2645147470c486ae96f2253f5e13a52Jack He        }
554c4fbd756e2645147470c486ae96f2253f5e13a52Jack He        BluetoothOppReceiveFileInfo fileInfo =
555c4fbd756e2645147470c486ae96f2253f5e13a52Jack He                BluetoothOppReceiveFileInfo.generateFileInfo(mContext, mInfo.mId);
556ce4d93666275df294cb073fe41de5b85932570a8Nick Pelly        if (V) {
55709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Log.v(TAG, "Generate BluetoothOppReceiveFileInfo:");
55809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Log.v(TAG, "filename  :" + fileInfo.mFileName);
55909e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Log.v(TAG, "length    :" + fileInfo.mLength);
56009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly            Log.v(TAG, "status    :" + fileInfo.mStatus);
56109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        }
56209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        return fileInfo;
56309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
56409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
56509e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    @Override
56609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    public int onConnect(HeaderSet request, HeaderSet reply) {
56709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
568c4fbd756e2645147470c486ae96f2253f5e13a52Jack He        if (D) {
569c4fbd756e2645147470c486ae96f2253f5e13a52Jack He            Log.d(TAG, "onConnect");
570c4fbd756e2645147470c486ae96f2253f5e13a52Jack He        }
571c4fbd756e2645147470c486ae96f2253f5e13a52Jack He        if (V) {
572c4fbd756e2645147470c486ae96f2253f5e13a52Jack He            Constants.logHeader(request);
573c4fbd756e2645147470c486ae96f2253f5e13a52Jack He        }
5748eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen        Long objectCount = null;
5759d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun        try {
576c4fbd756e2645147470c486ae96f2253f5e13a52Jack He            byte[] uuid = (byte[]) request.getHeader(HeaderSet.TARGET);
577c4fbd756e2645147470c486ae96f2253f5e13a52Jack He            if (V) {
578c4fbd756e2645147470c486ae96f2253f5e13a52Jack He                Log.v(TAG, "onConnect(): uuid =" + Arrays.toString(uuid));
579c4fbd756e2645147470c486ae96f2253f5e13a52Jack He            }
580c4fbd756e2645147470c486ae96f2253f5e13a52Jack He            if (uuid != null) {
581c4fbd756e2645147470c486ae96f2253f5e13a52Jack He                return ResponseCodes.OBEX_HTTP_NOT_ACCEPTABLE;
5829d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun            }
5838eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen
5848eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen            objectCount = (Long) request.getHeader(HeaderSet.COUNT);
5859d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun        } catch (IOException e) {
5869d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun            Log.e(TAG, e.toString());
5879d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun            return ResponseCodes.OBEX_HTTP_INTERNAL_ERROR;
5889d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun        }
5898eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen        String destination;
590bbb4110b455b3aa29106d5b4f0a37e1be8e09475Casper Bonde        if (mTransport instanceof BluetoothObexTransport) {
591c4fbd756e2645147470c486ae96f2253f5e13a52Jack He            destination = ((BluetoothObexTransport) mTransport).getRemoteAddress();
5928eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen        } else {
5938eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen            destination = "FF:FF:FF:00:00:00";
5948eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen        }
59579cd1a86171c772516d79c640bc244bcffee2960Myles Watson        boolean isHandover = BluetoothOppManager.getInstance(mContext).isWhitelisted(destination);
5968eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen        if (isHandover) {
5978eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen            // Notify the handover requester file transfer has started
5988eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen            Intent intent = new Intent(Constants.ACTION_HANDOVER_STARTED);
5998eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen            if (objectCount != null) {
6008eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen                intent.putExtra(Constants.EXTRA_BT_OPP_OBJECT_COUNT, objectCount.intValue());
6018eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen            } else {
6028eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen                intent.putExtra(Constants.EXTRA_BT_OPP_OBJECT_COUNT,
6038eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen                        Constants.COUNT_HEADER_UNAVAILABLE);
6048eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen            }
6058eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen            intent.putExtra(Constants.EXTRA_BT_OPP_ADDRESS, destination);
6068eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen            mContext.sendBroadcast(intent, Constants.HANDOVER_STATUS_PERMISSION);
6078eb70f8bdf4e8c970810b3400aba8d08d14ce222Martijn Coenen        }
60809e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        mTimestamp = System.currentTimeMillis();
6090ad53ef457f156314595a27c63660454450d3c84Jack He        mNumFilesAttemptedToReceive = 0;
61009e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        return ResponseCodes.OBEX_HTTP_OK;
61109e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
61209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
61309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    @Override
61409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    public void onDisconnect(HeaderSet req, HeaderSet resp) {
615c4fbd756e2645147470c486ae96f2253f5e13a52Jack He        if (D) {
616c4fbd756e2645147470c486ae96f2253f5e13a52Jack He            Log.d(TAG, "onDisconnect");
617c4fbd756e2645147470c486ae96f2253f5e13a52Jack He        }
6180ad53ef457f156314595a27c63660454450d3c84Jack He        if (mNumFilesAttemptedToReceive > 0) {
6190ad53ef457f156314595a27c63660454450d3c84Jack He            // Log incoming OPP transfer if more than one file is accepted by user
6200ad53ef457f156314595a27c63660454450d3c84Jack He            MetricsLogger.logProfileConnectionEvent(BluetoothMetricsProto.ProfileId.OPP);
6210ad53ef457f156314595a27c63660454450d3c84Jack He        }
62209e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly        resp.responseCode = ResponseCodes.OBEX_HTTP_OK;
62309e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
62409e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly
6254492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh    private synchronized void releaseWakeLocks() {
62632e47df203390052c1ef771d78b22fc4aa5f9e72Tao Liejun        if (mPartialWakeLock.isHeld()) {
62732e47df203390052c1ef771d78b22fc4aa5f9e72Tao Liejun            mPartialWakeLock.release();
62832e47df203390052c1ef771d78b22fc4aa5f9e72Tao Liejun        }
6294492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh    }
6304492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh
6314492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh    @Override
6324492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh    public void onClose() {
633c4fbd756e2645147470c486ae96f2253f5e13a52Jack He        if (D) {
634c4fbd756e2645147470c486ae96f2253f5e13a52Jack He            Log.d(TAG, "onClose");
635c4fbd756e2645147470c486ae96f2253f5e13a52Jack He        }
6364492b2c66cf3b26fd988f3b7f1f5df6cc9ed49f2Jaikumar Ganesh        releaseWakeLocks();
6377621506c7ade0a034f1cb77f5c1215db103768dbHansong Zhang        mBluetoothOppService.acceptNewConnections();
6380eab1c87e9a0b26e3f61dcc46681a0a20f9cb745Hemant Gupta        BluetoothOppUtility.cancelNotification(mContext);
6399d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun        /* onClose could happen even before start() where mCallback is set */
6409d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun        if (mCallback != null) {
6419d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun            Message msg = Message.obtain(mCallback);
6429d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun            msg.what = BluetoothOppObexSession.MSG_SESSION_COMPLETE;
6439d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun            msg.obj = mInfo;
6449d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun            msg.sendToTarget();
6459d9e511fe7425fb3105ece227ecedb43d6333333Tao Liejun        }
64609e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly    }
64709e9cba205af60b3f42e7a4d891a7d1392e1f2a5Nick Pelly}
648