<commit_before>package com.openxc.interfaces.bluetooth;

import java.io.BufferedInputStream;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.util.Log;

import com.google.common.base.Objects;
import com.openxc.R;
import com.openxc.interfaces.VehicleInterface;
import com.openxc.messages.SerializationException;
import com.openxc.messages.VehicleMessage;
import com.openxc.messages.streamers.JsonStreamer;
import com.openxc.messages.streamers.VehicleMessageStreamer;
import com.openxc.sinks.DataSinkException;
import com.openxc.sources.BytestreamDataSource;
import com.openxc.sources.DataSourceException;
import com.openxc.sources.DataSourceResourceException;
import com.openxc.sources.SourceCallback;

/**
 * A vehicle data source reading measurements from an Bluetooth-enabled
 * OpenXC device.
 *
 * This class tries to connect to a previously paired Bluetooth device with a
 * given MAC address. If found, it opens a socket to the device and streams
 * both read and write OpenXC messages.
 *
 * This class requires both the android.permission.BLUETOOTH and
 * android.permission.BLUETOOTH_ADMIN permissions.
 */
public class BluetoothVehicleInterface extends BytestreamDataSource
        implements VehicleInterface {
    private static final String TAG = "BluetoothVehicleInterface";
    public static final String DEVICE_NAME_PREFIX = "OpenXC-VI-";

    private static VehicleMessageStreamer sStreamer = new JsonStreamer();
    private DeviceManager mDeviceManager;
    private Thread mAcceptThread;
    private String mExplicitAddress;
    private String mConnectedAddress;
    private BufferedWriter mOutStream;
    private BufferedInputStream mInStream;
    private BluetoothSocket mSocket;
    private boolean mPerformAutomaticScan = true;
    private boolean mUsePolling = false;

    public BluetoothVehicleInterface(SourceCallback callback, Context context,
            String address) throws DataSourceException {
        super(callback, context);
        try {
            mDeviceManager = new DeviceManager(getContext());
        } catch(BluetoothException e) {
            throw new DataSourceException(
                    "Unable to open Bluetooth device manager", e);
        }

        IntentFilter filter = new IntentFilter(
                BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        getContext().registerReceiver(mDiscoveryReceiver, filter);
        filter = new IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED);
        getContext().registerReceiver(mDiscoveryReceiver, filter);

        SharedPreferences preferences =
                PreferenceManager.getDefaultSharedPreferences(context);
        mUsePolling = preferences.getBoolean(
                context.getString(R.string.bluetooth_polling_key), true);
        Log.d(TAG, "Bluetooth device polling is " + (mUsePolling ? "enabled" : "disabled"));

        setAddress(address);
        start();

        mAcceptThread = new Thread(new SocketAccepter());
        mAcceptThread.start();
    }

    public BluetoothVehicleInterface(Context context, String address)
            throws DataSourceException {
        this(null, context, address);
    }

    /**
     * Control whether periodic polling is used to detect a Bluetooth VI.
     *
     * This class opens a Bluetooth socket and will accept incoming connections
     * from a VI that can act as the Bluetooth master. For VIs that are only
     * able to act as slave, we have to poll for a connection occasionally to
     * see if it's within range.
     */
    public void setPollingStatus(boolean enabled) {
        mUsePolling = enabled;
    }

    @Override
    public void receive(VehicleMessage command) throws DataSinkException {
        // TODO who knows what the current serialization format is? only using
        // JSON right now
        try {
            if(!write(new String(sStreamer.serializeForStream(command)))) {
                throw new DataSinkException("Unable to write command");
            }
        } catch(SerializationException e) {
            throw new DataSinkException(
                    "Unable to serialize command for sending", e);
        }
    }

    @Override
    public boolean setResource(String otherAddress) throws DataSourceException {
        boolean reconnect = false;
        if(isConnected()) {
            if(otherAddress == null) {
                // switch to automatic but don't break the existing connection
                reconnect = false;
            } else if(!sameResource(mConnectedAddress, otherAddress) &&<commit_msg>Move a TODO to an issue.<commit_after>package com.openxc.interfaces.bluetooth;

import java.io.BufferedInputStream;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.util.Log;

import com.google.common.base.Objects;
import com.openxc.R;
import com.openxc.interfaces.VehicleInterface;
import com.openxc.messages.SerializationException;
import com.openxc.messages.VehicleMessage;
import com.openxc.messages.streamers.JsonStreamer;
import com.openxc.messages.streamers.VehicleMessageStreamer;
import com.openxc.sinks.DataSinkException;
import com.openxc.sources.BytestreamDataSource;
import com.openxc.sources.DataSourceException;
import com.openxc.sources.DataSourceResourceException;
import com.openxc.sources.SourceCallback;

/**
 * A vehicle data source reading measurements from an Bluetooth-enabled
 * OpenXC device.
 *
 * This class tries to connect to a previously paired Bluetooth device with a
 * given MAC address. If found, it opens a socket to the device and streams
 * both read and write OpenXC messages.
 *
 * This class requires both the android.permission.BLUETOOTH and
 * android.permission.BLUETOOTH_ADMIN permissions.
 */
public class BluetoothVehicleInterface extends BytestreamDataSource
        implements VehicleInterface {
    private static final String TAG = "BluetoothVehicleInterface";
    public static final String DEVICE_NAME_PREFIX = "OpenXC-VI-";

    private static VehicleMessageStreamer sStreamer = new JsonStreamer();
    private DeviceManager mDeviceManager;
    private Thread mAcceptThread;
    private String mExplicitAddress;
    private String mConnectedAddress;
    private BufferedWriter mOutStream;
    private BufferedInputStream mInStream;
    private BluetoothSocket mSocket;
    private boolean mPerformAutomaticScan = true;
    private boolean mUsePolling = false;

    public BluetoothVehicleInterface(SourceCallback callback, Context context,
            String address) throws DataSourceException {
        super(callback, context);
        try {
            mDeviceManager = new DeviceManager(getContext());
        } catch(BluetoothException e) {
            throw new DataSourceException(
                    "Unable to open Bluetooth device manager", e);
        }

        IntentFilter filter = new IntentFilter(
                BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        getContext().registerReceiver(mDiscoveryReceiver, filter);
        filter = new IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED);
        getContext().registerReceiver(mDiscoveryReceiver, filter);

        SharedPreferences preferences =
                PreferenceManager.getDefaultSharedPreferences(context);
        mUsePolling = preferences.getBoolean(
                context.getString(R.string.bluetooth_polling_key), true);
        Log.d(TAG, "Bluetooth device polling is " + (mUsePolling ? "enabled" : "disabled"));

        setAddress(address);
        start();

        mAcceptThread = new Thread(new SocketAccepter());
        mAcceptThread.start();
    }

    public BluetoothVehicleInterface(Context context, String address)
            throws DataSourceException {
        this(null, context, address);
    }

    /**
     * Control whether periodic polling is used to detect a Bluetooth VI.
     *
     * This class opens a Bluetooth socket and will accept incoming connections
     * from a VI that can act as the Bluetooth master. For VIs that are only
     * able to act as slave, we have to poll for a connection occasionally to
     * see if it's within range.
     */
    public void setPollingStatus(boolean enabled) {
        mUsePolling = enabled;
    }

    @Override
    public void receive(VehicleMessage command) throws DataSinkException {
        // See https://github.com/openxc/openxc-android/issues/181
        try {
            if(!write(new String(sStreamer.serializeForStream(command)))) {
                throw new DataSinkException("Unable to write command");
            }
        } catch(SerializationException e) {
            throw new DataSinkException(
                    "Unable to serialize command for sending", e);
        }
    }

    @Override
    public boolean setResource(String otherAddress) throws DataSourceException {
        boolean reconnect = false;
        if(isConnected()) {
            if(otherAddress == null) {
                // switch to automatic but don't break the existing connection
                reconnect = false;
            } else if(!sameResource(mConnectedAddress, otherAddress) &&
{'fraction_non_alphanumeric': 0.07183196274645794, 'fraction_numerical': 0.00029723570791637767, 'mean_word_length': 3.4271929824561402, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3635377', 'n_tokens_mistral': 2565, 'n_tokens_neox': 2514, 'n_words': 731}