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

Commit 72ed83d4 authored by vnori's avatar vnori Committed by android-build-merger
Browse files

Merge "Allow multiple connections on MAP profile."

am: 816621a4

Change-Id: I4d87e668a78ec94808aedea15d324d64e515bb23
parents 54fb21c1 816621a4
Loading
Loading
Loading
Loading
+253 −36
Original line number Diff line number Diff line
@@ -21,9 +21,17 @@ import android.app.PendingIntent;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothUuid;
import android.bluetooth.IBluetoothMapClient;
import android.bluetooth.SdpMasRecord;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.ParcelUuid;
import android.provider.Settings;
import android.support.annotation.VisibleForTesting;
import android.util.Log;

import com.android.bluetooth.Utils;
@@ -31,8 +39,11 @@ import com.android.bluetooth.btservice.ProfileService;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

public class MapClientService extends ProfileService {
    private static final String TAG = "MapClientService";
@@ -40,15 +51,15 @@ public class MapClientService extends ProfileService {
    static final boolean DBG = false;
    static final boolean VDBG = false;

    private static final int MAXIMUM_CONNECTED_DEVICES = 1;
    static final int MAXIMUM_CONNECTED_DEVICES = 4;

    private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;

    MceStateMachine mMceStateMachine;
    private Map<BluetoothDevice, MceStateMachine> mMapInstanceMap = new ConcurrentHashMap<>(1);
    private MnsService mMnsServer;
    private BluetoothAdapter mAdapter;
    private static MapClientService sMapClientService;

    private MapBroadcastReceiver mMapReceiver = new MapBroadcastReceiver();

    public static synchronized MapClientService getMapClientService() {
        if (sMapClientService != null && sMapClientService.isAvailable()) {
@@ -76,28 +87,126 @@ public class MapClientService extends ProfileService {
        } else {
            if (DBG) {
                if (sMapClientService == null) {
                    Log.d(TAG, "setA2dpService(): service not available");
                    Log.d(TAG, "MapClientService service not available");
                } else if (!sMapClientService.isAvailable()) {
                    Log.d(TAG, "setA2dpService(): service is cleaning up");
                    Log.d(TAG, "MapClientService service is cleaning up");
                }
            }
        }
    }

    private static synchronized void clearMapClientService() {
        sMapClientService = null;
    }

    @VisibleForTesting
    Map<BluetoothDevice, MceStateMachine> getInstanceMap() {
        return mMapInstanceMap;
    }

    /**
     * Connect the given Bluetooth device.
     *
     * @param device
     * @return true if connection is successful, false otherwise.
     */
    public synchronized boolean connect(BluetoothDevice device) {
        Log.d(TAG, "MAP Mce connect " + device.toString());
        return mMceStateMachine.connect(device);
        if (device == null) {
            throw new IllegalArgumentException("Null device");
        }
        if (DBG) {
            StringBuilder sb = new StringBuilder();
            dump(sb);
            Log.d(TAG, "MAP connect device: " + device
                    + ", InstanceMap start state: " + sb.toString());
        }
        MceStateMachine mapStateMachine = mMapInstanceMap.get(device);
        if (mapStateMachine == null) {
            // a map state machine instance doesn't exist yet, create a new one if we can.
            if (mMapInstanceMap.size() < MAXIMUM_CONNECTED_DEVICES) {
                addDeviceToMapAndConnect(device);
                return true;
            } else {
                // Maxed out on the number of allowed connections.
                // see if some of the current connections can be cleaned-up, to make room.
                removeUncleanAccounts();
                if (mMapInstanceMap.size() < MAXIMUM_CONNECTED_DEVICES) {
                    addDeviceToMapAndConnect(device);
                    return true;
                } else {
                    Log.e(TAG, "Maxed out on the number of allowed MAP connections. "
                            + "Connect request rejected on " + device);
                    return false;
                }
            }
        }

        // statemachine already exists in the map.
        int state = getConnectionState(device);
        if (state == BluetoothProfile.STATE_CONNECTED
                || state == BluetoothProfile.STATE_CONNECTING) {
            Log.w(TAG, "Received connect request while already connecting/connected.");
            return false;
        }

        // Statemachine exists but not in connecting or connected state! it should
        // have been removed form the map. lets get rid of it and add a new one.
        if (DBG) {
            Log.d(TAG, "Statemachine exists for a device in unexpected state: " + state);
        }
        mMapInstanceMap.remove(mapStateMachine);
        addDeviceToMapAndConnect(device);
        if (DBG) {
            StringBuilder sb = new StringBuilder();
            dump(sb);
            Log.d(TAG, "MAP connect device: " + device
                    + ", InstanceMap end state: " + sb.toString());
        }
        return true;
    }

    private synchronized void addDeviceToMapAndConnect(BluetoothDevice device) {
        // When creating a new statemachine, its state is set to CONNECTING - which will trigger
        // connect.
        MceStateMachine mapStateMachine = new MceStateMachine(this, device);
        mMapInstanceMap.put(device, mapStateMachine);
    }

    public synchronized boolean disconnect(BluetoothDevice device) {
        Log.d(TAG, "MAP Mce disconnect " + device.toString());
        return mMceStateMachine.disconnect(device);
        if (DBG) {
            StringBuilder sb = new StringBuilder();
            dump(sb);
            Log.d(TAG, "MAP disconnect device: " + device
                    + ", InstanceMap start state: " + sb.toString());
        }
        MceStateMachine mapStateMachine = mMapInstanceMap.get(device);
        // a map state machine instance doesn't exist. maybe it is already gone?
        if (mapStateMachine == null) {
            return false;
        }
        int connectionState = mapStateMachine.getState();
        if (connectionState != BluetoothProfile.STATE_CONNECTED
                && connectionState != BluetoothProfile.STATE_CONNECTING) {
            return false;
        }
        mapStateMachine.disconnect();
        if (DBG) {
            StringBuilder sb = new StringBuilder();
            dump(sb);
            Log.d(TAG, "MAP disconnect device: " + device
                    + ", InstanceMap start state: " + sb.toString());
        }
        return true;
    }

    public List<BluetoothDevice> getConnectedDevices() {
        return getDevicesMatchingConnectionStates(new int[]{BluetoothAdapter.STATE_CONNECTED});
    }

    MceStateMachine getMceStateMachineForDevice(BluetoothDevice device) {
        return mMapInstanceMap.get(device);
    }

    public synchronized List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
        Log.d(TAG, "getDevicesMatchingConnectionStates" + Arrays.toString(states));
        List<BluetoothDevice> deviceList = new ArrayList<>();
@@ -117,11 +226,10 @@ public class MapClientService extends ProfileService {
    }

    public synchronized int getConnectionState(BluetoothDevice device) {
        if (mMceStateMachine != null && device.equals(mMceStateMachine.getDevice())) {
            return mMceStateMachine.getState();
        } else {
            return BluetoothProfile.STATE_DISCONNECTED;
        }
        MceStateMachine mapStateMachine = mMapInstanceMap.get(device);
        // a map state machine instance doesn't exist yet, create a new one if we can.
        return (mapStateMachine == null) ? BluetoothProfile.STATE_DISCONNECTED
                : mapStateMachine.getState();
    }

    public boolean setPriority(BluetoothDevice device, int priority) {
@@ -142,12 +250,9 @@ public class MapClientService extends ProfileService {

    public synchronized boolean sendMessage(BluetoothDevice device, Uri[] contacts, String message,
            PendingIntent sentIntent, PendingIntent deliveredIntent) {
        if (mMceStateMachine != null && device.equals(mMceStateMachine.getDevice())) {
            return mMceStateMachine.sendMapMessage(contacts, message, sentIntent, deliveredIntent);
        } else {
            return false;
        }

        MceStateMachine mapStateMachine = mMapInstanceMap.get(device);
        return mapStateMachine != null
                && mapStateMachine.sendMapMessage(contacts, message, sentIntent, deliveredIntent);
    }

    @Override
@@ -157,20 +262,21 @@ public class MapClientService extends ProfileService {

    @Override
    protected boolean start() {
        if (DBG) {
            Log.d(TAG, "start()");
        }
        Log.e(TAG, "start()");
        setService(this);

        if (mMnsServer == null) {
            mMnsServer = new MnsService(this);
        }
        if (mMceStateMachine == null) {
            mMceStateMachine = new MceStateMachine(this);
            mMnsServer = MapUtils.newMnsServiceInstance(this);
        }

        mAdapter = BluetoothAdapter.getDefaultAdapter();
        mStartError = false;

        IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothDevice.ACTION_SDP_RECORD);
        filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
        registerReceiver(mMapReceiver, filter);
        removeUncleanAccounts();
        return !mStartError;
    }

@@ -179,35 +285,88 @@ public class MapClientService extends ProfileService {
        if (DBG) {
            Log.d(TAG, "stop()");
        }
        unregisterReceiver(mMapReceiver);
        if (mMnsServer != null) {
            mMnsServer.stop();
        }
        if (mMceStateMachine.getState() == BluetoothAdapter.STATE_CONNECTED) {
            mMceStateMachine.disconnect(mMceStateMachine.getDevice());
        for (MceStateMachine stateMachine : mMapInstanceMap.values()) {
            if (stateMachine.getState() == BluetoothAdapter.STATE_CONNECTED) {
                stateMachine.disconnect();
            }
            stateMachine.doQuit();
        }
        mMceStateMachine.doQuit();
        return true;
    }

    @Override
    protected void cleanup() {
        if (DBG) {
            Log.d(TAG, "cleanup()");
            Log.d(TAG, "in Cleanup");
        }
        removeUncleanAccounts();
        clearMapClientService();
    }

    void cleanupDevice(BluetoothDevice device) {
        if (DBG) {
            StringBuilder sb = new StringBuilder();
            dump(sb);
            Log.d(TAG, "Cleanup device: " + device + ", InstanceMap start state: "
                    + sb.toString());
        }
        synchronized (mMapInstanceMap) {
            MceStateMachine stateMachine = mMapInstanceMap.get(device);
            if (stateMachine != null) {
                mMapInstanceMap.remove(device);
            }
        }
        if (DBG) {
            StringBuilder sb = new StringBuilder();
            dump(sb);
            Log.d(TAG, "Cleanup device: " + device + ", InstanceMap end state: "
                    + sb.toString());
        }
    }

    @VisibleForTesting
    void removeUncleanAccounts() {
        if (DBG) {
            StringBuilder sb = new StringBuilder();
            dump(sb);
            Log.d(TAG, "removeUncleanAccounts:InstanceMap end state: "
                    + sb.toString());
        }
        Iterator iterator = mMapInstanceMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<BluetoothDevice, MceStateMachine> profileConnection =
                    (Map.Entry) iterator.next();
            if (profileConnection.getValue().getState() == BluetoothProfile.STATE_DISCONNECTED) {
                iterator.remove();
            }
        }
        if (DBG) {
            StringBuilder sb = new StringBuilder();
            dump(sb);
            Log.d(TAG, "removeUncleanAccounts:InstanceMap end state: "
                    + sb.toString());
        }
    }

    public synchronized boolean getUnreadMessages(BluetoothDevice device) {
        if (mMceStateMachine != null && device.equals(mMceStateMachine.getDevice())) {
            return mMceStateMachine.getUnreadMessages();
        } else {
        MceStateMachine mapStateMachine = mMapInstanceMap.get(device);
        if (mapStateMachine == null) {
            return false;
        }
        return mapStateMachine.getUnreadMessages();
    }

    @Override
    public synchronized void dump(StringBuilder sb) {
    public void dump(StringBuilder sb) {
        super.dump(sb);
        println(sb, "StateMachine: " + mMceStateMachine.toString());
        ProfileService.println(sb, "# Services Connected: " + mMapInstanceMap.size());
        for (MceStateMachine stateMachine : mMapInstanceMap.values()) {
            stateMachine.dump(sb);
        }
    }

    //Binder object: Must be static class or memory leak may occur
@@ -360,4 +519,62 @@ public class MapClientService extends ProfileService {
            return service.getUnreadMessages(device);
        }
    }

    private class MapBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (DBG) {
                Log.d(TAG, "onReceive: " + action);
            }
            if (!action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)
                    && !action.equals(BluetoothDevice.ACTION_SDP_RECORD)) {
                // we don't care about this intent
                return;
            }
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            if (device == null) {
                Log.e(TAG, "broadcast has NO device param!");
                return;
            }
            if (DBG) {
                Log.d(TAG, "broadcast has device: (" + device.getAddress() + ", "
                        + device.getName() + ")");
            }
            MceStateMachine stateMachine = MapClientService.this.mMapInstanceMap.get(device);
            if (stateMachine == null) {
                Log.e(TAG, "No Statemachine found for the device from broadcast");
                return;
            }

            if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
                if (stateMachine.getState() == BluetoothProfile.STATE_CONNECTED) {
                    stateMachine.disconnect();
                }
            }

            if (action.equals(BluetoothDevice.ACTION_SDP_RECORD)) {
                ParcelUuid uuid = intent.getParcelableExtra(BluetoothDevice.EXTRA_UUID);
                if (DBG) {
                    Log.d(TAG, "UUID of SDP: " + uuid);
                }

                if (uuid.equals(BluetoothUuid.MAS)) {
                    // Check if we have a valid SDP record.
                    SdpMasRecord masRecord =
                            intent.getParcelableExtra(BluetoothDevice.EXTRA_SDP_RECORD);
                    if (DBG) {
                        Log.d(TAG, "SDP = " + masRecord);
                    }
                    int status = intent.getIntExtra(BluetoothDevice.EXTRA_SDP_SEARCH_STATUS, -1);
                    if (masRecord == null) {
                        Log.w(TAG, "SDP search ended with no MAS record. Status: " + status);
                        return;
                    }
                    stateMachine.obtainMessage(MceStateMachine.MSG_MAS_SDP_DONE,
                            masRecord).sendToTarget();
                }
            }
        }
    }
}
+31 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.bluetooth.mapclient;

import android.support.annotation.VisibleForTesting;

class MapUtils {
    private static MnsService sMnsService = null;

    @VisibleForTesting
    static void setMnsService(MnsService service) {
        sMnsService = service;
    }

    static MnsService newMnsServiceInstance(MapClientService mapClientService) {
        return (sMnsService != null) ? new MnsService(mapClientService) : sMnsService;
    }
}
+28 −88
Original line number Diff line number Diff line
@@ -47,13 +47,9 @@ import android.bluetooth.BluetoothMapClient;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothUuid;
import android.bluetooth.SdpMasRecord;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Message;
import android.os.ParcelUuid;
import android.telecom.PhoneAccount;
import android.util.Log;

@@ -66,6 +62,7 @@ import com.android.vcard.VCardEntry;
import com.android.vcard.VCardProperty;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;

@@ -111,7 +108,7 @@ final class MceStateMachine extends StateMachine {
    private State mConnected;
    private State mDisconnecting;

    private BluetoothDevice mDevice;
    private final BluetoothDevice mDevice;
    private MapClientService mService;
    private MasClient mMasClient;
    private HashMap<String, Bmessage> mSentMessageLog = new HashMap<>(MAX_MESSAGES);
@@ -119,14 +116,14 @@ final class MceStateMachine extends StateMachine {
    private HashMap<Bmessage, PendingIntent> mDeliveryReceiptRequested =
            new HashMap<>(MAX_MESSAGES);
    private Bmessage.Type mDefaultMessageType = Bmessage.Type.SMS_CDMA;
    private MapBroadcastReceiver mMapReceiver = new MapBroadcastReceiver();

    MceStateMachine(MapClientService service) {
    MceStateMachine(MapClientService service, BluetoothDevice device) {
        super(TAG);
        mService = service;

        mPreviousState = BluetoothProfile.STATE_DISCONNECTED;

        mDevice = device;
        mDisconnected = new Disconnected();
        mConnecting = new Connecting();
        mDisconnecting = new Disconnecting();
@@ -136,7 +133,7 @@ final class MceStateMachine extends StateMachine {
        addState(mConnecting);
        addState(mDisconnecting);
        addState(mConnected);
        setInitialState(mDisconnected);
        setInitialState(mConnecting);
        start();
    }

@@ -144,6 +141,13 @@ final class MceStateMachine extends StateMachine {
        quitNow();
    }

    @Override
    protected void onQuitting() {
        if (mService != null) {
            mService.cleanupDevice(mDevice);
        }
    }

    synchronized BluetoothDevice getDevice() {
        return mDevice;
    }
@@ -181,19 +185,11 @@ final class MceStateMachine extends StateMachine {
        return BluetoothProfile.STATE_DISCONNECTED;
    }

    public boolean connect(BluetoothDevice device) {
        if (DBG) {
            Log.d(TAG, "Connect Request " + device.getAddress());
        }
        sendMessage(MSG_CONNECT, device);
        return true;
    }

    public boolean disconnect(BluetoothDevice device) {
    public boolean disconnect() {
        if (DBG) {
            Log.d(TAG, "Disconnect Request " + device.getAddress());
            Log.d(TAG, "Disconnect Request " + mDevice.getAddress());
        }
        sendMessage(MSG_DISCONNECT, device);
        sendMessage(MSG_DISCONNECT, mDevice);
        return true;
    }

@@ -291,6 +287,11 @@ final class MceStateMachine extends StateMachine {
        }
    }

    public void dump(StringBuilder sb) {
        ProfileService.println(sb, "mCurrentDevice: " + mDevice.getAddress() + " (name = "
                + mDevice.getName() + "), StateMachine: " + this.toString());
    }

    class Disconnected extends State {
        @Override
        public void enter() {
@@ -299,24 +300,7 @@ final class MceStateMachine extends StateMachine {
            }
            onConnectionStateChanged(mPreviousState, BluetoothProfile.STATE_DISCONNECTED);
            mPreviousState = BluetoothProfile.STATE_DISCONNECTED;
        }

        @Override
        public boolean processMessage(Message message) {
            switch (message.what) {
                case MSG_CONNECT:
                    synchronized (MceStateMachine.this) {
                        mDevice = (BluetoothDevice) message.obj;
                    }
                    transitionTo(mConnecting);
                    break;

                default:
                    Log.w(TAG, "Unexpected message: " + message.what + " from state:"
                            + this.getName());
                    return NOT_HANDLED;
            }
            return HANDLED;
            quit();
        }

        @Override
@@ -333,12 +317,6 @@ final class MceStateMachine extends StateMachine {
            }
            onConnectionStateChanged(mPreviousState, BluetoothProfile.STATE_CONNECTING);

            IntentFilter filter = new IntentFilter();
            filter.addAction(BluetoothDevice.ACTION_SDP_RECORD);
            filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
            // unregisterReceiver in Disconnecting
            mService.registerReceiver(mMapReceiver, filter);

            BluetoothAdapter.getDefaultAdapter().cancelDiscovery();
            // When commanded to connect begin SDP to find the MAS server.
            mDevice.sdpSearch(BluetoothUuid.MAS);
@@ -437,11 +415,15 @@ final class MceStateMachine extends StateMachine {
                    break;

                case MSG_GET_MESSAGE_LISTING:
                    // Get latest 50 Unread messages in the last week
                    MessagesFilter filter = new MessagesFilter();
                    filter.setMessageType((byte) 0);
                    mMasClient.makeRequest(
                            new RequestGetMessagesListing((String) message.obj, 0, filter, 0, 1,
                                    0));
                    filter.setReadStatus(MessagesFilter.READ_STATUS_UNREAD);
                    Calendar calendar = Calendar.getInstance();
                    calendar.add(Calendar.DATE, -7);
                    filter.setPeriod(calendar.getTime(), null);
                    mMasClient.makeRequest(new RequestGetMessagesListing(
                            (String) message.obj, 0, filter, 0, 50, 0));
                    break;

                case MSG_MAS_REQUEST_COMPLETED:
@@ -633,7 +615,6 @@ final class MceStateMachine extends StateMachine {
                Log.d(TAG, "Enter Disconnecting: " + getCurrentMessage().what);
            }
            onConnectionStateChanged(mPreviousState, BluetoothProfile.STATE_DISCONNECTING);
            mService.unregisterReceiver(mMapReceiver);

            if (mMasClient != null) {
                mMasClient.makeRequest(new RequestSetNotificationRegistration(false));
@@ -683,45 +664,4 @@ final class MceStateMachine extends StateMachine {
        }
        sendMessage(MSG_NOTIFICATION, ev);
    }

    private class MapBroadcastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (DBG) {
                Log.d(TAG, "onReceive");
            }
            String action = intent.getAction();
            if (DBG) {
                Log.d(TAG, "onReceive: " + action);
            }
            if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                if (getDevice().equals(device) && getState() == BluetoothProfile.STATE_CONNECTED) {
                    disconnect(device);
                }
            }

            if (BluetoothDevice.ACTION_SDP_RECORD.equals(intent.getAction())) {
                ParcelUuid uuid = intent.getParcelableExtra(BluetoothDevice.EXTRA_UUID);
                if (DBG) {
                    Log.d(TAG, "UUID of SDP: " + uuid);
                }

                if (uuid.equals(BluetoothUuid.MAS)) {
                    // Check if we have a valid SDP record.
                    SdpMasRecord masRecord =
                            intent.getParcelableExtra(BluetoothDevice.EXTRA_SDP_RECORD);
                    if (DBG) {
                        Log.d(TAG, "SDP = " + masRecord);
                    }
                    int status = intent.getIntExtra(BluetoothDevice.EXTRA_SDP_SEARCH_STATUS, -1);
                    if (masRecord == null) {
                        Log.w(TAG, "SDP search ended with no MAS record. Status: " + status);
                        return;
                    }
                    obtainMessage(MceStateMachine.MSG_MAS_SDP_DONE, masRecord).sendToTarget();
                }
            }
        }
    }
}
+7 −1
Original line number Diff line number Diff line
@@ -122,7 +122,13 @@ class MnsService {
                Log.d(TAG, "onConnect" + device + " SOCKET: " + socket);
            }
            /* Signal to the service that we have received an incoming connection.*/
            MnsObexServer srv = new MnsObexServer(sContext.mMceStateMachine, sServerSockets);
            MceStateMachine stateMachine = sContext.getMceStateMachineForDevice(device);
            if (stateMachine == null) {
                Log.e(TAG, "Error: NO statemachine for device: " + device.getAddress()
                        + " (name: " + device.getName());
                return false;
            }
            MnsObexServer srv = new MnsObexServer(stateMachine, sServerSockets);
            BluetoothObexTransport transport = new BluetoothObexTransport(socket);
            try {
                new ServerSession(transport, srv, null);
+152 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading