Since nobody else seems to have an answer to offer I started testing on my own.
I tried making an app that creates a device from a string representation of an address and tried setting up my device with the 48 bit address alternating the public or private bit to see what the Android stack does.
private final BluetoothGattCallback leGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) {
Log.i("Fisken", "Gatt connected " + gatt.getDevice().getAddress() + " status " + status);
if (status != BluetoothGatt.GATT_SUCCESS) {
Log.w("Fisken", "Disconnect and close");
gatt.disconnect();
gatt.close();
}
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
Log.i("Fisken", "Gatt disconnected " + gatt.getDevice().getAddress() + " status " + status);
if (status != BluetoothGatt.GATT_SUCCESS) {
Log.w("Fisken", "Disconnect and close");
gatt.disconnect();
}
gatt.close();
}
}
};
BluetoothAdapter mBluetoothAdapter = ((BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE)).getAdapter();
BluetoothDevice d = mBluetoothAdapter.getRemoteDevice("FF:55:44:33:22:11");
d.connectGatt(this, false, leGattCallback);
With this code, if I start my BLE peripheral with a random address everything works as expected. However, if I try running it with the same address with the public bit set, logcat says "Gatt connected", but that's just not true. And I'm never able to disconnect.
Update: I did some more testing to figure this out. The onConnectionStateChange event I get is just the connection attempt timing out. The status is set to either 133 (if I get STATE_CONNECTED) or 257 (if I get a STATE_DISCONNECTED) and I've seen both. In either case I should (and now do in the sample code) cancel the connection attempt and close the client.
I've also found out that if I do a scan first, so that the device I'm trying to connect to have been seen recently and then do a connect based solely on the device mac address then I am able to connect to both random and public addresses without any trouble.
So this seems to be a bug/and or missing feature in the Android API. It does not allow you to connect to a public address without first having scanned for it. It does however work for random addresses.