Skip to content

Commit

Permalink
Merge pull request #440 from this-Aditya/mac_hash
Browse files Browse the repository at this point in the history
Added Hash of MAC address for nearby bluetooth devices
  • Loading branch information
yatharthranjan authored Mar 28, 2024
2 parents 8c6c6b7 + 7104f59 commit 9678845
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 4 deletions.
1 change: 1 addition & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ org.gradle.jvmargs=-Xmx3072m -XX:MaxMetaspaceSize=1536m -Dfile.encoding=UTF-8 -X
org.gradle.parallel=true
org.gradle.vfs.watch=true
kotlin.code.style=official
android.jetifier.ignorelist=jackson-core-2.16.1.jar

android.defaults.buildfeatures.buildconfig=true

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@
package org.radarbase.passive.phone

import android.Manifest
import android.annotation.SuppressLint
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.SharedPreferences
import android.content.pm.PackageManager
import android.os.Build
import androidx.core.app.ActivityCompat
Expand All @@ -32,16 +34,28 @@ import org.radarbase.android.source.BaseSourceState
import org.radarbase.android.source.SourceStatusListener
import org.radarbase.android.util.BluetoothStateReceiver.Companion.bluetoothAdapter
import org.radarbase.android.util.BluetoothStateReceiver.Companion.hasBluetoothPermission
import org.radarbase.android.util.HashGenerator
import org.radarbase.android.util.OfflineProcessor
import org.radarcns.kafka.ObservationKey
import org.radarcns.passive.phone.PairedState
import org.radarcns.passive.phone.PhoneBluetoothDeviceScanned
import org.radarcns.passive.phone.PhoneBluetoothDevices
import org.slf4j.LoggerFactory
import java.nio.ByteBuffer
import java.util.concurrent.ThreadLocalRandom
import java.util.concurrent.TimeUnit

class PhoneBluetoothManager(service: PhoneBluetoothService) : AbstractSourceManager<PhoneBluetoothService, BaseSourceState>(service) {
private val processor: OfflineProcessor
private val bluetoothDevicesTopic: DataCache<ObservationKey, PhoneBluetoothDevices> = createCache("android_phone_bluetooth_devices", PhoneBluetoothDevices())
private val bluetoothScannedTopic: DataCache<ObservationKey, PhoneBluetoothDeviceScanned> = createCache("android_phone_bluetooth_device_scanned", PhoneBluetoothDeviceScanned())

private var bluetoothBroadcastReceiver: BroadcastReceiver? = null
private val hashGenerator: HashGenerator = HashGenerator(service, "bluetooth_devices")
private val preferences: SharedPreferences
get() = service.getSharedPreferences(PhoneBluetoothManager::class.java.name, Context.MODE_PRIVATE)

private var hashSaltReference: Int = 0

init {
name = service.getString(R.string.bluetooth_devices)
Expand All @@ -51,6 +65,17 @@ class PhoneBluetoothManager(service: PhoneBluetoothService) : AbstractSourceMana
requestName = ACTION_SCAN_DEVICES
wake = true
}
preferences.apply {
if (contains(HASH_SALT_REFERENCE)) {
hashSaltReference = getInt(HASH_SALT_REFERENCE, -1)
} else {
val random = ThreadLocalRandom.current()
while (hashSaltReference == 0) {
hashSaltReference = random.nextInt()
}
edit().putInt(HASH_SALT_REFERENCE, hashSaltReference).apply()
}
}
}

override fun start(acceptableIds: Set<String>) {
Expand Down Expand Up @@ -79,20 +104,56 @@ class PhoneBluetoothManager(service: PhoneBluetoothService) : AbstractSourceMana
bluetoothBroadcastReceiver = object : BroadcastReceiver() {
private var numberOfDevices: Int = 0

val hasConnectPermission = Build.VERSION.SDK_INT < Build.VERSION_CODES.S
|| ActivityCompat.checkSelfPermission(service, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED

@SuppressLint("MissingPermission")
override fun onReceive(context: Context, intent: Intent) {
val action = intent.action ?: return
when (action) {
BluetoothDevice.ACTION_FOUND -> {
numberOfDevices++

val device: BluetoothDevice = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE, BluetoothDevice::class.java)
} else {
@Suppress("DEPRECATION")
intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)
} ?: return

val macAddress = device.address
val macAddressHash: ByteBuffer = hashGenerator.createHashByteBuffer(macAddress + "$hashSaltReference")

val scannedTopicBuilder = PhoneBluetoothDeviceScanned.newBuilder().apply {
time = currentTime
timeReceived = currentTime
}

val pairedDevices: Set<BluetoothDevice> = if (hasConnectPermission) bluetoothAdapter.bondedDevices else emptySet()

pairedDevices.forEach { bd ->
val mac = bd.address
val hash = hashGenerator.createHashByteBuffer(mac + "$hashSaltReference")

send(bluetoothScannedTopic, scannedTopicBuilder.apply {
this.macAddressHash = hash
this.pairedState = bd.bondState.toPairedState()
this.hashSaltReference = hashSaltReference
}.build())
}

send(bluetoothScannedTopic, scannedTopicBuilder.apply {
this.macAddressHash = macAddressHash
this.pairedState = device.bondState.toPairedState()
this.hashSaltReference = hashSaltReference
}.build())

}

BluetoothAdapter.ACTION_DISCOVERY_FINISHED -> {
service.unregisterReceiver(this)
bluetoothBroadcastReceiver = null

val hasConnectPermission = Build.VERSION.SDK_INT < Build.VERSION_CODES.S
|| ActivityCompat.checkSelfPermission(service, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED

val bondedDevices = if (hasConnectPermission) bluetoothAdapter.bondedDevices.size else -1

if (!isClosed) {
Expand Down Expand Up @@ -135,5 +196,13 @@ class PhoneBluetoothManager(service: PhoneBluetoothService) : AbstractSourceMana

private const val SCAN_DEVICES_REQUEST_CODE = 3248902
private const val ACTION_SCAN_DEVICES = "org.radarbase.passive.phone.PhoneBluetoothManager.ACTION_SCAN_DEVICES"
private const val HASH_SALT_REFERENCE = "hash_salt_reference"

private fun Int.toPairedState(): PairedState = when(this) {
10 -> PairedState.NOT_PAIRED
11 -> PairedState.PAIRING
12 -> PairedState.PAIRED
else -> PairedState.UNKNOWN
}
}
}
2 changes: 1 addition & 1 deletion radar-commons-android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ dependencies {
exclude group: 'org.json', module: 'json'
exclude group: 'org.apache.avro', module: 'avro'
}
api ('org.radarbase:radar-schemas-commons:0.8.5') {
api ('org.radarbase:radar-schemas-commons:0.8.7') {
exclude group: 'org.apache.avro', module: 'avro'
}
api(project(':avro-android'))
Expand Down

0 comments on commit 9678845

Please sign in to comment.