package org.fdroid.fdroid.localrepo.type;
import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import org.fdroid.fdroid.Utils;
import org.fdroid.fdroid.localrepo.SwapService;
import org.fdroid.fdroid.net.bluetooth.BluetoothServer;
public final class BluetoothSwap extends SwapType {
private static final String TAG = "BluetoothSwap";
public static final String BLUETOOTH_NAME_TAG = "FDroid:";
private static BluetoothSwap mInstance;
@NonNull
private final BluetoothAdapter adapter;
private boolean isDiscoverable;
@Nullable
private BluetoothServer server;
private String deviceBluetoothName;
public static SwapType create(@NonNull Context context) {
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if (adapter == null) {
return new NoBluetoothType(context);
}
if (mInstance == null) {
mInstance = new BluetoothSwap(context, adapter);
}
return mInstance;
}
private BluetoothSwap(@NonNull Context context, @NonNull BluetoothAdapter adapter) {
super(context);
this.adapter = adapter;
}
@Override
public boolean isDiscoverable() {
return isDiscoverable;
}
@Override
public boolean isConnected() {
return server != null && server.isRunning() && super.isConnected();
}
@Override
public synchronized void start() {
if (isConnected()) {
return;
}
BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
switch (intent.getIntExtra(BluetoothAdapter.EXTRA_SCAN_MODE, -1)) {
case BluetoothAdapter.SCAN_MODE_NONE:
setConnected(false);
break;
case BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE:
isDiscoverable = true;
if (server != null && server.isRunning()) {
setConnected(true);
}
break;
// Only other is BluetoothAdapter.SCAN_MODE_CONNECTABLE. For now don't handle that.
}
}
};
context.registerReceiver(receiver, new IntentFilter(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED));
/*
if (server != null) {
Utils.debugLog(TAG, "Attempting to start Bluetooth swap, but it appears to be running already. Will cancel it so it can be restarted.");
server.close();
server = null;
}*/
if (server == null) {
server = new BluetoothServer(this, context.getFilesDir());
}
sendBroadcast(SwapService.EXTRA_STARTING);
//store the original bluetoothname, and update this one to be unique
deviceBluetoothName = adapter.getName();
/*
Utils.debugLog(TAG, "Prefixing Bluetooth adapter name with " + BLUETOOTH_NAME_TAG + " to make it identifiable as a swap device.");
if (!deviceBluetoothName.startsWith(BLUETOOTH_NAME_TAG)) {
adapter.setName(BLUETOOTH_NAME_TAG + deviceBluetoothName);
}
if (!adapter.getName().startsWith(BLUETOOTH_NAME_TAG)) {
Log.e(TAG, "Couldn't change the name of the Bluetooth adapter, it will not get recognized by other swap clients.");
// TODO: Should we bail here?
}*/
if (!adapter.isEnabled()) {
Utils.debugLog(TAG, "Bluetooth adapter is disabled, attempting to enable.");
if (!adapter.enable()) {
Utils.debugLog(TAG, "Could not enable Bluetooth adapter, so bailing out of Bluetooth swap.");
setConnected(false);
return;
}
}
if (adapter.isEnabled()) {
setConnected(true);
} else {
Log.i(TAG, "Didn't start Bluetooth swapping server, because Bluetooth is disabled and couldn't be enabled.");
setConnected(false);
}
}
/**
* Don't try to start BT in the background. you can only start/stop a BT server once, else new connections don't work.
*/
@Override
public void stopInBackground() {
stop();
}
@Override
public void stop() {
if (server != null && server.isAlive()) {
server.close();
setConnected(false);
/*
if (receiver != null) {
context.unregisterReceiver(receiver);
receiver = null;
}
*/
} else {
Log.i(TAG, "Attempting to stop Bluetooth swap, but it is not currently running.");
}
}
protected void onStopped() {
Utils.debugLog(TAG, "Resetting bluetooth device name to " + deviceBluetoothName + " after swapping.");
adapter.setName(deviceBluetoothName);
}
@Override
public String getBroadcastAction() {
return SwapService.BLUETOOTH_STATE_CHANGE;
}
private static class NoBluetoothType extends SwapType {
NoBluetoothType(@NonNull Context context) {
super(context);
}
@Override
public void start() { }
@Override
public void stop() { }
@Override
protected String getBroadcastAction() {
return null;
}
}
}