Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ee0dfb6b authored by Hemant Gupta's avatar Hemant Gupta Committed by android-build-merger
Browse files

Merge "OPP: Add OPP 1.2 feature." am: e278de21 am: 828afd46

am: 14fb99ba

Change-Id: I33a72bf2526a869f90fd213d52622fa4373859ae
parents 959379d7 14fb99ba
Loading
Loading
Loading
Loading
+27 −6
Original line number Diff line number Diff line
@@ -80,7 +80,20 @@ public class ObexServerSockets {
     */
    public static ObexServerSockets create(IObexConnectionHandler validator) {
        return create(validator, BluetoothAdapter.SOCKET_CHANNEL_AUTO_STATIC_NO_SDP,
                BluetoothAdapter.SOCKET_CHANNEL_AUTO_STATIC_NO_SDP);
                BluetoothAdapter.SOCKET_CHANNEL_AUTO_STATIC_NO_SDP, true);
    }

    /**
     * Creates an Insecure RFCOMM {@link BluetoothServerSocket} and a L2CAP
         *                  {@link BluetoothServerSocket}
     * @param validator a reference to the {@link IObexConnectionHandler} object to call
     *                  to validate an incoming connection.
     * @return a reference to a {@link ObexServerSockets} object instance.
     * @throws IOException if it occurs while creating the {@link BluetoothServerSocket}s.
     */
    public static ObexServerSockets createInsecure(IObexConnectionHandler validator) {
        return create(validator, BluetoothAdapter.SOCKET_CHANNEL_AUTO_STATIC_NO_SDP,
                BluetoothAdapter.SOCKET_CHANNEL_AUTO_STATIC_NO_SDP, false);
    }

    /**
@@ -90,14 +103,15 @@ public class ObexServerSockets {
     * {@link #getRfcommChannel()} in {@link ObexServerSockets}.
     * @param validator a reference to the {@link IObexConnectionHandler} object to call
     *                  to validate an incoming connection.
     * @param isSecure boolean flag to determine whther socket would be secured or inseucure.
     * @return a reference to a {@link ObexServerSockets} object instance.
     * @throws IOException if it occurs while creating the {@link BluetoothServerSocket}s.
     *
     * TODO: Make public when it becomes possible to determine that the listen-call
     *       failed due to channel-in-use.
     */
    private static ObexServerSockets create(IObexConnectionHandler validator,
            int rfcommChannel, int l2capPsm) {
    private static ObexServerSockets create(
            IObexConnectionHandler validator, int rfcommChannel, int l2capPsm, boolean isSecure) {
        if(D) Log.d(STAG,"create(rfcomm = " +rfcommChannel + ", l2capPsm = " + l2capPsm +")");
        BluetoothAdapter bt = BluetoothAdapter.getDefaultAdapter();
        if(bt == null) {
@@ -113,10 +127,18 @@ public class ObexServerSockets {
            initSocketOK = true;
            try {
                if(rfcommSocket == null) {
                    if (isSecure) {
                        rfcommSocket = bt.listenUsingRfcommOn(rfcommChannel);
                    } else {
                        rfcommSocket = bt.listenUsingInsecureRfcommOn(rfcommChannel);
                    }
                }
                if(l2capSocket == null) {
                    if (isSecure) {
                        l2capSocket = bt.listenUsingL2capOn(l2capPsm);
                    } else {
                        l2capSocket = bt.listenUsingInsecureL2capOn(l2capPsm);
                    }
                }
            } catch (IOException e) {
                Log.e(STAG, "Error create ServerSockets ",e);
@@ -380,5 +402,4 @@ public class ObexServerSockets {
            }
        }
    }

}
+12 −2
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@ import javax.obex.ServerRequestHandler;
import javax.obex.ServerSession;

import com.android.bluetooth.BluetoothObexTransport;
import com.android.bluetooth.ObexServerSockets;

/**
 * This class runs as an OBEX server
@@ -97,9 +98,13 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler implemen

    boolean mTimeoutMsgSent = false;

    public BluetoothOppObexServerSession(Context context, ObexTransport transport) {
    private ObexServerSockets mServerSocket;

    public BluetoothOppObexServerSession(
            Context context, ObexTransport transport, ObexServerSockets serverSocket) {
        mContext = context;
        mTransport = transport;
        mServerSocket = serverSocket;
        PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
        mPartialWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
    }
@@ -583,9 +588,14 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler implemen

    @Override
    public void onClose() {
        if (V) Log.v(TAG, "release WakeLock");
        if (D) Log.d(TAG, "onClose");
        releaseWakeLocks();

        if (mServerSocket != null) {
            if (D) Log.d(TAG, "prepareForNewConnect");
            mServerSocket.prepareForNewConnect();
        }

        /* onClose could happen even before start() where mCallback is set */
        if (mCallback != null) {
            Message msg = Message.obtain(mCallback);
+0 −230
Original line number Diff line number Diff line
/*
 * Copyright (c) 2008-2009, Motorola, Inc.
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * - Neither the name of the Motorola, Inc. nor the names of its contributors
 * may be used to endorse or promote products derived from this software
 * without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

package com.android.bluetooth.opp;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

import com.android.bluetooth.BluetoothObexTransport;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.bluetooth.BluetoothUuid;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

/**
 * This class listens on OPUSH channel for incoming connection
 */
public class BluetoothOppRfcommListener {
    private static final String TAG = "BtOppRfcommListener";

    private static final boolean V = Constants.VERBOSE;

    public static final int MSG_INCOMING_BTOPP_CONNECTION = 100;

    private volatile boolean mInterrupted;

    private Thread mSocketAcceptThread;

    private Handler mCallback;

    private static final int CREATE_RETRY_TIME = 10;

    private final BluetoothAdapter mAdapter;

    private BluetoothServerSocket mBtServerSocket = null;

    private ServerSocket mTcpServerSocket = null;

    public BluetoothOppRfcommListener(BluetoothAdapter adapter) {
        mAdapter = adapter;
    }


    public synchronized boolean start(Handler callback) {
        if (mSocketAcceptThread == null) {
            mCallback = callback;

            mSocketAcceptThread = new Thread(TAG) {

                public void run() {
                    if (Constants.USE_TCP_DEBUG) {
                        try {
                            if (V) Log.v(TAG, "Create TCP ServerSocket");
                            mTcpServerSocket = new ServerSocket(Constants.TCP_DEBUG_PORT, 1);
                        } catch (IOException e) {
                            Log.e(TAG, "Error listing on port" + Constants.TCP_DEBUG_PORT);
                            mInterrupted = true;
                        }
                        while (!mInterrupted) {
                            try {
                                Socket clientSocket = mTcpServerSocket.accept();

                                if (V) Log.v(TAG, "Socket connected!");
                                TestTcpTransport transport = new TestTcpTransport(clientSocket);
                                Message msg = Message.obtain();
                                msg.setTarget(mCallback);
                                msg.what = MSG_INCOMING_BTOPP_CONNECTION;
                                msg.obj = transport;
                                msg.sendToTarget();

                            } catch (IOException e) {
                                Log.e(TAG, "Error accept connection " + e);
                            }
                        }
                        if (V) Log.v(TAG, "TCP listen thread finished");
                    } else {
                        boolean serverOK = true;

                        /*
                         * it's possible that create will fail in some cases.
                         * retry for 10 times
                         */
                        for (int i = 0; i < CREATE_RETRY_TIME && !mInterrupted; i++) {
                            try {
                                if (V) Log.v(TAG, "Starting RFCOMM listener....");
                                mBtServerSocket = mAdapter.listenUsingInsecureRfcommWithServiceRecord("OBEX Object Push", BluetoothUuid.ObexObjectPush.getUuid());
                                if (V) Log.v(TAG, "Started RFCOMM listener....");
                            } catch (IOException e1) {
                                Log.e(TAG, "Error create RfcommServerSocket " + e1);
                                serverOK = false;
                            }

                            if (!serverOK) {
                                synchronized (this) {
                                    try {
                                        if (V) Log.v(TAG, "Wait 300 ms");
                                        Thread.sleep(300);
                                    } catch (InterruptedException e) {
                                        Log.e(TAG, "socketAcceptThread thread was interrupted (3)");
                                        mInterrupted = true;
                                    }
                                }
                            } else {
                                break;
                            }
                        }
                        if (!serverOK) {
                            Log.e(TAG, "Error start listening after " + CREATE_RETRY_TIME + " try");
                            mInterrupted = true;
                        }
                        if (!mInterrupted) {
                            Log.i(TAG, "Accept thread started.");
                        }
                        BluetoothSocket clientSocket;
                        while (!mInterrupted) {
                            try {
                                if (V) Log.v(TAG, "Accepting connection...");
                                if (mBtServerSocket == null) {

                                }
                                BluetoothServerSocket sSocket = mBtServerSocket;
                                if (sSocket ==null) {
                                    mInterrupted = true;

                                } else {
                                    clientSocket = sSocket.accept();
                                    if (V) Log.v(TAG, "Accepted connection from "
                                        + clientSocket.getRemoteDevice());
                                    BluetoothObexTransport transport = new BluetoothObexTransport(
                                        clientSocket);
                                    Message msg = Message.obtain();
                                    msg.setTarget(mCallback);
                                    msg.what = MSG_INCOMING_BTOPP_CONNECTION;
                                    msg.obj = transport;
                                    msg.sendToTarget();
                                }
                            } catch (IOException e) {
                                Log.e(TAG, "Error accept connection " + e);
                                try {
                                    Thread.sleep(500);
                                } catch (InterruptedException ie) {}
                            }
                        }
                        Log.i(TAG, "BluetoothSocket listen thread finished");
                    }
                }
            };
            mInterrupted = false;
            if(!Constants.USE_TCP_SIMPLE_SERVER) {
                mSocketAcceptThread.start();
            }
        }
        return true;
    }

    public synchronized void stop() {
        if (mSocketAcceptThread != null) {
            Log.i(TAG, "stopping Accept Thread");

            mInterrupted = true;
             if (Constants.USE_TCP_DEBUG) {
                if (V) Log.v(TAG, "close mTcpServerSocket");
                if (mTcpServerSocket != null) {
                    try {
                        mTcpServerSocket.close();
                        mTcpServerSocket = null;
                    } catch (IOException e) {
                        Log.e(TAG, "Error close mTcpServerSocket");
                    }
                }
            } else {
                if (V) Log.v(TAG, "close mBtServerSocket");

                if (mBtServerSocket != null) {
                    try {
                        mBtServerSocket.close();
                        mBtServerSocket = null;
                    } catch (IOException e) {
                        Log.e(TAG, "Error close mBtServerSocket");
                    }
                }
            }
            try {
                mSocketAcceptThread.interrupt();
                if (V) Log.v(TAG, "waiting for thread to terminate");
                //mSocketAcceptThread.join(JOIN_TIMEOUT_MS);
                mSocketAcceptThread.join();
                if (V) Log.v(TAG, "done waiting for thread to terminate");
                mSocketAcceptThread = null;
                mCallback = null;
            } catch (InterruptedException e) {
                if (V) Log.v(TAG, "Interrupted waiting for Accept Thread to join");
            }
        }
    }
}
+104 −13
Original line number Diff line number Diff line
@@ -37,7 +37,10 @@ import javax.obex.ObexTransport;

import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothDevicePicker;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.ContentValues;
@@ -55,20 +58,25 @@ import android.os.IBinder;
import android.os.Message;
import android.os.PowerManager;
import android.util.Log;
import android.widget.Toast;
import android.os.Process;

import com.android.bluetooth.BluetoothObexTransport;
import com.android.bluetooth.IObexConnectionHandler;
import com.android.bluetooth.ObexServerSockets;
import com.android.bluetooth.btservice.ProfileService;
import com.android.bluetooth.btservice.ProfileService.IProfileServiceBinder;

import java.io.IOException;
import java.util.ArrayList;
import com.android.bluetooth.sdp.SdpManager;

/**
 * Performs the background Bluetooth OPP transfer. It also starts thread to
 * accept incoming OPP connection.
 */

public class BluetoothOppService extends ProfileService {
public class BluetoothOppService extends ProfileService implements IObexConnectionHandler {
    private static final boolean D = Constants.DEBUG;
    private static final boolean V = Constants.VERBOSE;

@@ -120,8 +128,6 @@ public class BluetoothOppService extends ProfileService {

    private PowerManager mPowerManager;

    private BluetoothOppRfcommListener mSocketListener;

    private boolean mListenStarted = false;

    private boolean mMediaScanInProgress;
@@ -130,6 +136,8 @@ public class BluetoothOppService extends ProfileService {

    private ObexTransport mPendingConnection = null;

    private int mOppSdpHandle = -1;

    /*
     * TODO No support for queue incoming from multiple devices.
     * Make an array list of server session to support receiving queue from
@@ -145,7 +153,6 @@ public class BluetoothOppService extends ProfileService {
    @Override
    protected void create() {
        if (V) Log.v(TAG, "onCreate");
        mSocketListener = new BluetoothOppRfcommListener(mAdapter);
        mShares = Lists.newArrayList();
        mBatchs = Lists.newArrayList();
        mObserver = new BluetoothShareContentObserver();
@@ -205,6 +212,8 @@ public class BluetoothOppService extends ProfileService {

    private static final int MSG_INCOMING_CONNECTION_RETRY = 4;

    private static final int MSG_INCOMING_BTOPP_CONNECTION = 100;

    private static final int STOP_LISTENER = 200;

    private Handler mHandler = new Handler() {
@@ -212,9 +221,15 @@ public class BluetoothOppService extends ProfileService {
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case STOP_LISTENER:
                    if(mSocketListener != null){
                        mSocketListener.stop();
                    }
                    if (mAdapter != null && mOppSdpHandle >= 0
                            && SdpManager.getDefaultManager() != null) {
                        if (D) Log.d(TAG, "Removing SDP record mOppSdpHandle :" + mOppSdpHandle);
                        boolean status =
                                SdpManager.getDefaultManager().removeSdpRecord(mOppSdpHandle);
                        Log.d(TAG, "RemoveSDPrecord returns " + status);
                        mOppSdpHandle = -1;
                    }
                    stopListeners();
                    mListenStarted = false;
                    //Stop Active INBOUND Transfer
                    if(mServerTransfer != null){
@@ -268,9 +283,10 @@ public class BluetoothOppService extends ProfileService {
                        mMediaScanInProgress = false;
                    }
                    break;
                case BluetoothOppRfcommListener.MSG_INCOMING_BTOPP_CONNECTION:
                case MSG_INCOMING_BTOPP_CONNECTION:
                    if (D) Log.d(TAG, "Get incoming connection");
                    ObexTransport transport = (ObexTransport)msg.obj;

                    /*
                     * Strategy for incoming connections:
                     * 1. If there is no ongoing transfer, no on-hold connection, start it
@@ -330,10 +346,19 @@ public class BluetoothOppService extends ProfileService {
        }
    };

    private ObexServerSockets mServerSocket;
    private void startSocketListener() {
        if (V) Log.v(TAG, "start RfcommListener");
        mSocketListener.start(mHandler);
        if (V) Log.v(TAG, "RfcommListener started");
        if (D) Log.d(TAG, "start Socket Listeners");
        stopListeners();
        mServerSocket = ObexServerSockets.createInsecure(this);
        SdpManager sdpManager = SdpManager.getDefaultManager();
        if (sdpManager == null || mServerSocket == null) {
            Log.e(TAG, "ERROR:serversocket object is NULL  sdp manager :" + sdpManager
                            + " mServerSocket:" + mServerSocket);
            return;
        }
        sdpManager.createOppOpsRecord("OBEX Object Push", mServerSocket.getRfcommChannel(),
                mServerSocket.getL2capPsm(), 0x0102, SdpManager.OPP_FORMAT_ALL);
    }

    @Override
@@ -341,8 +366,7 @@ public class BluetoothOppService extends ProfileService {
        if (V) Log.v(TAG, "onDestroy");
        getContentResolver().unregisterContentObserver(mObserver);
        unregisterReceiver(mBluetoothReceiver);
        mSocketListener.stop();

        stopListeners();
        if (mBatchs != null) {
            mBatchs.clear();
        }
@@ -357,7 +381,7 @@ public class BluetoothOppService extends ProfileService {

    /* suppose we auto accept an incoming OPUSH connection */
    private void createServerSession(ObexTransport transport) {
        mServerSession = new BluetoothOppObexServerSession(this, transport);
        mServerSession = new BluetoothOppObexServerSession(this, transport, mServerSocket);
        mServerSession.preStart();
        if (D) Log.d(TAG, "Get ServerSession " + mServerSession.toString()
                    + " for incoming connection" + transport.toString());
@@ -1029,4 +1053,71 @@ public class BluetoothOppService extends ProfileService {
            }
        }
    }

    private void stopListeners() {
        if (mServerSocket != null) {
            mServerSocket.shutdown(false);
            mServerSocket = null;
        }
        if (D) Log.d(TAG, "stopListeners   mServerSocket :" + mServerSocket);
    }

    private BluetoothServerSocket getConnectionSocket(boolean isL2cap) {
        BluetoothServerSocket socket = null;
        boolean socketCreate = false;
        final int CREATE_RETRY_TIME = 10;
        // It's possible that create will fail in some cases. retry for 10 times
        for (int i = 0; i < CREATE_RETRY_TIME; i++) {
            if (D) Log.d(TAG, " CREATE_RETRY_TIME " + i);
            socketCreate = true;
            try {
                socket = (isL2cap)
                        ? mAdapter.listenUsingInsecureL2capOn(
                                  BluetoothAdapter.SOCKET_CHANNEL_AUTO_STATIC_NO_SDP)
                        : mAdapter.listenUsingInsecureRfcommOn(
                                  BluetoothAdapter.SOCKET_CHANNEL_AUTO_STATIC_NO_SDP);
            } catch (IOException e) {
                Log.e(TAG, "Error create ServerSockets ", e);
                socketCreate = false;
            }
            if (!socketCreate) {
                // Need to break out of this loop if BT is being turned off.
                int state = mAdapter.getState();
                if ((state != BluetoothAdapter.STATE_TURNING_ON)
                        && (state != BluetoothAdapter.STATE_ON)) {
                    Log.e(TAG, "initServerSockets failed as Bt State :" + state);
                    break;
                }
                try {
                    if (V) Log.d(TAG, "waiting 300 ms...");
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    Log.e(TAG, "create() was interrupted");
                }
            } else {
                break;
            }
        }
        if (D) Log.d(TAG, " socketCreate :" + socketCreate + " isL2cap :" + isL2cap);
        return socket;
    }

    @Override
    public boolean onConnect(BluetoothDevice device, BluetoothSocket socket) {
        if (D) Log.d(TAG, " onConnect BluetoothSocket :" + socket + " \n :device :" + device);
        BluetoothObexTransport transport = new BluetoothObexTransport(socket);
        Message msg = Message.obtain();
        msg.setTarget(mHandler);
        msg.what = MSG_INCOMING_BTOPP_CONNECTION;
        msg.obj = transport;
        msg.sendToTarget();
        return true;
    }

    @Override
    public void onAcceptFailed() {
        // TODO Auto-generated method stub
        Log.d(TAG, " onAcceptFailed:");
        mHandler.sendMessage(mHandler.obtainMessage(START_LISTENER));
    }
}
+248 −135

File changed.File mode changed from 100755 to 100644.

Preview size limit exceeded, changes collapsed.

Loading