Commit c1645087 authored by stopcovid@lunabee.com's avatar stopcovid@lunabee.com

Update to 2.0.0

parent e6e62524
......@@ -49,9 +49,6 @@ captures/
.externalNativeBuild
.cxx/
# Google Services (e.g. APIs or Firebase)
# google-services.json
# Freeline
freeline.py
freeline/
......
......@@ -12,13 +12,14 @@ apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 29
buildToolsVersion "29.0.3"
compileSdkVersion 30
buildToolsVersion '30.0.2'
defaultConfig {
minSdkVersion 21
targetSdkVersion 29
versionCode 13
versionName "1.4.0"
targetSdkVersion 30
buildConfigField 'String', 'BLE_VERSION', '"1.4.0"'
}
compileOptions {
......@@ -49,22 +50,22 @@ dependencies {
testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0"
testImplementation "org.robolectric:robolectric:4.3.1"
def mockitoVersion = '3.3.3'
def mockitoVersion = '3.5.11'
testImplementation "org.mockito:mockito-core:${mockitoVersion}"
testImplementation "org.mockito:mockito-inline:${mockitoVersion}"
def androidXTestVersion = '1.3.0-rc01'
def androidXTestVersion = '1.3.0'
testImplementation "androidx.test:core-ktx:${androidXTestVersion}"
testImplementation "androidx.test:monitor:${androidXTestVersion}"
testImplementation "androidx.test:runner:${androidXTestVersion}"
testImplementation "androidx.test:rules:${androidXTestVersion}"
testImplementation "androidx.test.ext:truth:${androidXTestVersion}"
def androidXTestJUnitVersion = '1.1.2-rc01'
def androidXTestJUnitVersion = '1.1.2'
testImplementation "androidx.test.ext:junit:${androidXTestJUnitVersion}"
def coroutines_version = "1.3.8"
def coroutines_version = "1.3.9"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version"
......
......@@ -8,8 +8,7 @@
~ Created by Orange / Date - 2020/04/27 - for the STOP-COVID project
-->
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.orange.proximitynotification">
......@@ -30,4 +29,5 @@
</application>
</manifest>
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* Authors
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Created by Orange / Date - 2020/09/14 - for the STOP-COVID project
*/
package com.orange.proximitynotification
sealed class ProximityNotificationEvent {
abstract val id: ProximityNotificationEventId
data class Debug(
override val id: ProximityNotificationEventId,
val message: String
) : ProximityNotificationEvent()
data class Info(
override val id: ProximityNotificationEventId,
val message: String
) : ProximityNotificationEvent()
data class Error(
override val id: ProximityNotificationEventId,
val message: String,
val cause: Throwable? = null
) : ProximityNotificationEvent()
}
\ No newline at end of file
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* Authors
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Created by Orange / Date - 2020/09/14 - for the STOP-COVID project
*/
package com.orange.proximitynotification
import com.orange.proximitynotification.ProximityNotificationEventId.Category.*
enum class ProximityNotificationEventId(val category: Category) {
BLE_ADVERTISER_START(BLE_ADVERTISER),
BLE_ADVERTISER_START_ERROR(BLE_ADVERTISER),
BLE_ADVERTISER_START_SUCCESS(BLE_ADVERTISER),
BLE_ADVERTISER_STOP(BLE_ADVERTISER),
BLE_ADVERTISER_STOP_ERROR(BLE_ADVERTISER),
BLE_ADVERTISER_STOP_SUCCESS(BLE_ADVERTISER),
BLE_GATT_START(BLE_GATT),
BLE_GATT_START_ERROR(BLE_GATT),
BLE_GATT_START_SUCCESS(BLE_GATT),
BLE_GATT_STOP(BLE_GATT),
BLE_GATT_STOP_ERROR(BLE_GATT),
BLE_GATT_STOP_SUCCESS(BLE_GATT),
BLE_GATT_REQUEST_REMOTE_RSSI(BLE_GATT),
BLE_GATT_REQUEST_REMOTE_RSSI_TIMEOUT(BLE_GATT),
BLE_GATT_REQUEST_REMOTE_RSSI_ERROR(BLE_GATT),
BLE_GATT_REQUEST_REMOTE_RSSI_SUCCESS(BLE_GATT),
BLE_GATT_ON_CHARACTERISTIC_WRITE_REQUEST(BLE_GATT),
BLE_GATT_ON_CHARACTERISTIC_WRITE_REQUEST_ERROR(BLE_GATT),
BLE_GATT_ON_CHARACTERISTIC_WRITE_REQUEST_SUCCESS(BLE_GATT),
BLE_SCANNER_START(BLE_SCANNER),
BLE_SCANNER_START_ERROR(BLE_SCANNER),
BLE_SCANNER_START_SUCCESS(BLE_SCANNER),
BLE_SCANNER_STOP(BLE_SCANNER),
BLE_SCANNER_STOP_ERROR(BLE_SCANNER),
BLE_SCANNER_STOP_SUCCESS(BLE_SCANNER),
BLE_SCANNER_ON_BATCH_SCAN_RESULT(BLE_SCANNER),
BLE_SCANNER_ON_SCAN_RESULT(BLE_SCANNER),
PROXIMITY_NOTIFICATION_START(PROXIMITY_NOTIFICATION),
PROXIMITY_NOTIFICATION_START_BLE(PROXIMITY_NOTIFICATION),
PROXIMITY_NOTIFICATION_STOP(PROXIMITY_NOTIFICATION),
PROXIMITY_NOTIFICATION_STOP_BLE(PROXIMITY_NOTIFICATION),
PROXIMITY_NOTIFICATION_PAYLOAD_UPDATED(PROXIMITY_NOTIFICATION),
PROXIMITY_NOTIFICATION_BLE_SETTINGS_UPDATED(PROXIMITY_NOTIFICATION),
PROXIMITY_NOTIFICATION_BLUETOOTH_DISABLED(PROXIMITY_NOTIFICATION),
PROXIMITY_NOTIFICATION_BLUETOOTH_ENABLED(PROXIMITY_NOTIFICATION),
BLE_PROXIMITY_NOTIFICATION_FACTORY(PROXIMITY_NOTIFICATION);
enum class Category {
/**
* BLE advertising error
*/
BLE_ADVERTISER,
/**
* BLE scanner error
*/
BLE_SCANNER,
/**
* BLE gatt error
*/
BLE_GATT,
/**
* Proximity notification component error
*/
PROXIMITY_NOTIFICATION
}
}
\ No newline at end of file
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*
* Authors
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Created by Orange / Date - 2020/09/14 - for the STOP-COVID project
*/
package com.orange.proximitynotification
object ProximityNotificationLogger {
interface Listener {
fun onEvent(event: ProximityNotificationEvent)
}
private var listener: Listener? = null
@Synchronized
fun registerListener(listener: Listener) {
this.listener = listener
}
@Synchronized
fun unregisterListener() {
this.listener = null
}
@Synchronized
fun log(event: ProximityNotificationEvent) = listener?.onEvent(event)
fun debug(eventId: ProximityNotificationEventId, message: String) = log(
ProximityNotificationEvent.Debug(eventId, message)
)
fun info(eventId: ProximityNotificationEventId, message: String) = log(
ProximityNotificationEvent.Info(eventId, message)
)
fun error(eventId: ProximityNotificationEventId, message: String, cause: Throwable? = null) =
log(ProximityNotificationEvent.Error(eventId, message, cause))
}
\ No newline at end of file
......@@ -31,7 +31,8 @@ import kotlin.coroutines.CoroutineContext
* ProximityNotification foreground service.
*/
abstract class ProximityNotificationService : Service(),
ProximityNotificationCallback, ProximityPayloadProvider, CoroutineScope {
ProximityNotificationCallback, ProximityPayloadProvider, ProximityNotificationLogger.Listener,
CoroutineScope {
private var bleProximityNotification: BleProximityNotification? = null
private var bluetoothStateBroadcastReceiver: BluetoothStateBroadcastReceiver? = null
......@@ -42,8 +43,14 @@ abstract class ProximityNotificationService : Service(),
abstract val foregroundNotificationId: Int
abstract val bleSettings: BleSettings
override fun onCreate() {
super.onCreate()
ProximityNotificationLogger.registerListener(this)
}
override fun onDestroy() {
stop()
ProximityNotificationLogger.unregisterListener()
super.onDestroy()
cancel()
......@@ -60,6 +67,11 @@ abstract class ProximityNotificationService : Service(),
* @see BluetoothStateBroadcastReceiver
*/
fun start() {
ProximityNotificationLogger.info(
ProximityNotificationEventId.PROXIMITY_NOTIFICATION_START,
"Start Proximity Notification"
)
registerBluetoothBroadcastReceiver()
doStart()
}
......@@ -71,6 +83,11 @@ abstract class ProximityNotificationService : Service(),
* @see BluetoothStateBroadcastReceiver
*/
fun stop() {
ProximityNotificationLogger.info(
ProximityNotificationEventId.PROXIMITY_NOTIFICATION_STOP,
"Stop Proximity Notification"
)
doStop()
unregisterBluetoothBroadcastReceiver()
}
......@@ -81,6 +98,11 @@ abstract class ProximityNotificationService : Service(),
* @see ProximityPayloadProvider
*/
fun notifyProximityPayloadUpdated() {
ProximityNotificationLogger.info(
ProximityNotificationEventId.PROXIMITY_NOTIFICATION_PAYLOAD_UPDATED,
"Proximity payload updated"
)
bleProximityNotification?.notifyPayloadUpdated()
}
......@@ -89,6 +111,11 @@ abstract class ProximityNotificationService : Service(),
* It will restart [BleProximityNotification]
*/
fun notifyBleSettingsUpdate() {
ProximityNotificationLogger.info(
ProximityNotificationEventId.PROXIMITY_NOTIFICATION_BLE_SETTINGS_UPDATED,
"BLE settings updated"
)
if (isRunning()) {
stopBleProximityNotification()
startBleProximityNotification()
......@@ -134,12 +161,15 @@ abstract class ProximityNotificationService : Service(),
stopBleProximityNotification()
}
BleProximityNotificationFactory.build(this, bleSettings, this)?.run {
bleProximityNotification = this
setUp(
this@ProximityNotificationService,
this@ProximityNotificationService
)
ProximityNotificationLogger.info(
ProximityNotificationEventId.PROXIMITY_NOTIFICATION_START_BLE,
"Start BLE Proximity Notification"
)
BleProximityNotificationFactory.build(this, bleSettings, this)?.let {
bleProximityNotification = it
it.setUp(this, this)
it.start()
} ?: run {
onError(
ProximityNotificationError(
......@@ -148,11 +178,14 @@ abstract class ProximityNotificationService : Service(),
)
)
}
bleProximityNotification?.start()
}
private fun stopBleProximityNotification() {
ProximityNotificationLogger.info(
ProximityNotificationEventId.PROXIMITY_NOTIFICATION_STOP_BLE,
"Stop BLE Proximity Notification"
)
bleProximityNotification?.stop()
bleProximityNotification = null
}
......@@ -164,7 +197,10 @@ abstract class ProximityNotificationService : Service(),
* @see ProximityNotification#stop
*/
protected open fun onBluetoothDisabled() {
Timber.d("Bluetooth disabled")
ProximityNotificationLogger.info(
ProximityNotificationEventId.PROXIMITY_NOTIFICATION_BLUETOOTH_DISABLED,
"Bluetooth disabled"
)
doStop()
}
......@@ -176,11 +212,18 @@ abstract class ProximityNotificationService : Service(),
* @see ProximityNotification#start
*/
protected open fun onBluetoothEnabled() {
Timber.d("Bluetooth enabled")
ProximityNotificationLogger.info(
ProximityNotificationEventId.PROXIMITY_NOTIFICATION_BLUETOOTH_ENABLED,
"Bluetooth enabled"
)
doStart()
}
override fun onEvent(event: ProximityNotificationEvent) {
Timber.d("onEvent event = $event")
}
/**
* Create the Notification to display once this foreground service is running
*
......
......@@ -12,6 +12,8 @@ package com.orange.proximitynotification.ble
import android.bluetooth.BluetoothManager
import android.content.Context
import com.orange.proximitynotification.ProximityNotificationEventId
import com.orange.proximitynotification.ProximityNotificationLogger
import com.orange.proximitynotification.ble.advertiser.BleAdvertiserImpl
import com.orange.proximitynotification.ble.gatt.BleGattClientProviderImpl
import com.orange.proximitynotification.ble.gatt.BleGattManagerImpl
......@@ -32,13 +34,19 @@ object BleProximityNotificationFactory {
val bluetoothAdapter = bluetoothManager.adapter
if (bluetoothAdapter.bluetoothLeAdvertiser == null) {
ProximityNotificationLogger.error(
ProximityNotificationEventId.BLE_PROXIMITY_NOTIFICATION_FACTORY,
"bluetoothAdapter.bluetoothLeAdvertiser is null"
)
return null
}
val bleGattClientProvider = BleGattClientProviderImpl(context)
val bleAdvertiser = BleAdvertiserImpl(settings, bluetoothAdapter.bluetoothLeAdvertiser)
val bleScanner = BleScannerImpl(settings, BluetoothLeScannerCompat.getScanner())
val bleGattManager = BleGattManagerImpl(settings, context, bluetoothManager, bleGattClientProvider)
val bleGattManager =
BleGattManagerImpl(settings, context, bluetoothManager, bleGattClientProvider)
return BleProximityNotification(
bleScanner,
......
......@@ -15,8 +15,9 @@ import android.bluetooth.le.AdvertiseData
import android.bluetooth.le.AdvertiseSettings
import android.bluetooth.le.BluetoothLeAdvertiser
import android.os.ParcelUuid
import com.orange.proximitynotification.ProximityNotificationEventId
import com.orange.proximitynotification.ProximityNotificationLogger
import com.orange.proximitynotification.ble.BleSettings
import timber.log.Timber
class BleAdvertiserImpl(
override val settings: BleSettings,
......@@ -26,14 +27,21 @@ class BleAdvertiserImpl(
private var advertiseCallback: InnerAdvertiseCallback? = null
override fun start(data: ByteArray, callback: BleAdvertiser.Callback): Boolean {
Timber.d("Starting Advertising")
ProximityNotificationLogger.info(
ProximityNotificationEventId.BLE_ADVERTISER_START,
"Starting advertising"
)
doStop()
return doStart(data, callback)
}
override fun stop() {
Timber.d("Stopping Advertising")
ProximityNotificationLogger.info(
ProximityNotificationEventId.BLE_ADVERTISER_STOP,
"Stopping advertising"
)
doStop()
}
......@@ -46,14 +54,29 @@ class BleAdvertiserImpl(
buildAdvertiseData(data),
advertiseCallback
)
}.onFailure {
ProximityNotificationLogger.error(
eventId = ProximityNotificationEventId.BLE_ADVERTISER_START_ERROR,
message = "Failed to start advertising",
cause = it
)
}.isSuccess
}
private fun doStop() {
advertiseCallback?.let {
runCatching {
bluetoothAdvertiser.stopAdvertising(advertiseCallback)
}
advertiseCallback?.runCatching {
bluetoothAdvertiser.stopAdvertising(advertiseCallback)
}?.onFailure {
ProximityNotificationLogger.error(
eventId = ProximityNotificationEventId.BLE_ADVERTISER_STOP_ERROR,
message = "Failed to stop advertising",
cause = it
)
}?.onSuccess {
ProximityNotificationLogger.info(
eventId = ProximityNotificationEventId.BLE_ADVERTISER_STOP_SUCCESS,
message = "Succeed to stop advertising"
)
}
advertiseCallback = null
}
......@@ -80,13 +103,22 @@ class BleAdvertiserImpl(
AdvertiseCallback() {
override fun onStartFailure(errorCode: Int) {
super.onStartFailure(errorCode)
Timber.w("Advertising failed errorCode=$errorCode")
ProximityNotificationLogger.error(
ProximityNotificationEventId.BLE_ADVERTISER_START_ERROR,
"Failed to start advertising (errorCode=$errorCode)"
)
callback.onError(errorCode)
}
override fun onStartSuccess(settingsInEffect: AdvertiseSettings) {
super.onStartSuccess(settingsInEffect)
Timber.d("Advertising successfully started")
ProximityNotificationLogger.info(
ProximityNotificationEventId.BLE_ADVERTISER_START_SUCCESS,
"Succeed to start advertising"
)
}
}
......
......@@ -18,6 +18,8 @@ import android.bluetooth.BluetoothGattServerCallback
import android.bluetooth.BluetoothGattService
import android.bluetooth.BluetoothManager
import android.content.Context
import com.orange.proximitynotification.ProximityNotificationEventId
import com.orange.proximitynotification.ProximityNotificationLogger
import com.orange.proximitynotification.ble.BleSettings
import com.orange.proximitynotification.tools.CoroutineContextProvider
import kotlinx.coroutines.CoroutineExceptionHandler
......@@ -30,7 +32,6 @@ import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeout
import timber.log.Timber
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
......@@ -58,10 +59,26 @@ internal class BleGattManagerImpl(
)