Skip to content

Commit

Permalink
CollectorController finalized
Browse files Browse the repository at this point in the history
  • Loading branch information
highjun committed Nov 7, 2024
1 parent 40a56e6 commit fd2c304
Show file tree
Hide file tree
Showing 10 changed files with 97 additions and 94 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,21 @@ import kaist.iclab.tracker.notf.NotfManagerInterface
import kaist.iclab.tracker.permission.PermissionManagerInterface
import org.koin.android.ext.koin.androidContext
import org.koin.core.module.dsl.singleOf
import org.koin.core.module.dsl.viewModel
import org.koin.core.module.dsl.viewModelOf
import org.koin.dsl.module

val appModule = module {
single<CollectorControllerInterface> {
Tracker.getCollectorController()
}
single<NotfManagerInterface> {
Tracker.getNotfManager()
}
single<PermissionManagerInterface> {
Tracker.getPermissionManager()
}

// singleOf(::ActivityTransitionCollector)
singleOf(::AmbientLightCollector)
// singleOf(::AppUsageLogCollector)
Expand All @@ -28,38 +40,17 @@ val appModule = module {
// singleOf(::WiFiScanCollector)

single<Map<String, CollectorInterface>> {
mapOf(
// "ActivityTransitionCollector" to get<ActivityTransitionCollector>(),
"AmbientLight" to get<AmbientLightCollector>(),
// "AppUsageLogCollector" to get<AppUsageLogCollector>(),
// "BatteryCollector" to get<BatteryCollector>(),
// "CallLogCollector" to get<CallLogCollector>(),
// "DataTrafficStatCollector" to get<DataTrafficStatCollector>(),
// "LocationCollector" to get<LocationCollector>(),
// "MessageLogCollector" to get<MessageLogCollector>(),
// "NotificationCollector" to get<NotificationCollector>(),
// "ScreenCollector" to get<ScreenCollector>(),
// "UserInteractionCollector" to get<UserInteractionCollector>(),
// "WiFiScanCollector" to get<WiFiScanCollector>()
)
}

single<CollectorControllerInterface> {
Tracker.getCollectorController()
}
single<NotfManagerInterface> {
Tracker.getNotfManager()
}
single<PermissionManagerInterface> {
Tracker.getPermissionManager()
listOf(
get<AmbientLightCollector>()
).map({ it.NAME to it }).toMap()
}


single<TrackerUtil> {
TrackerUtil(androidContext())
}

single<AbstractMainViewModel>{
viewModel<AbstractMainViewModel>{
MainViewModelImpl(get(), get(), get<Map<String, CollectorInterface>>().keys.toTypedArray())
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package kaist.iclab.field_tracker

import android.app.Application
import android.content.Context
import android.hardware.SensorManager
import android.util.Log
import kaist.iclab.tracker.Tracker
import kaist.iclab.tracker.controller.AbstractCollector
import kaist.iclab.tracker.controller.CollectorControllerInterface
import kaist.iclab.tracker.controller.CollectorInterface
import kaist.iclab.tracker.notf.NotfManagerInterface
import org.koin.android.ext.android.get
Expand All @@ -20,21 +23,24 @@ class MainApplication: Application(){
androidContext(this@MainApplication)
modules(appModule)
}
// Tracker.initialize(this@MainApplication, get(), get(), get())
// initConfiguration()

initConfiguration()
}

// fun initConfiguration() {
// val collectorMap = get<Map<String, CollectorInterface>>()
// collectorMap.forEach { (name, collector) ->
// collector.listener = { data ->
// Log.d(collector.NAME, "Data: $data")
// }
// }
//
// val notfManager = get<NotfManagerInterface>()
// notfManager.setServiceNotfDescription(
// icon = R.drawable.ic_notf
// )
// }
fun initConfiguration() {
val collectorController = get<CollectorControllerInterface>()
collectorController.initializeCollectors(get())

val collectorMap = get<Map<String, CollectorInterface>>()
collectorMap.forEach { (name, collector) ->
collector.listener = { data ->
Log.d(collector.NAME, "Data: $data")
}
}

val notfManager = get<NotfManagerInterface>()
notfManager.setServiceNotfDescription(
icon = R.drawable.ic_notf
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ import kaist.iclab.tracker.controller.CollectorState
import org.koin.androidx.compose.koinViewModel

@Composable
fun MainScreen(viewModel: AbstractMainViewModel = koinViewModel()) {
fun MainScreen(viewModel: AbstractMainViewModel = koinViewModel<AbstractMainViewModel>()) {
val isRunning = viewModel.controllerStateFlow.collectAsStateWithLifecycle()
val collectorStates = viewModel.collectorStateFlow.collectAsStateWithLifecycle(
viewModel.collectors.map{ it to CollectorState(CollectorState.FLAG.UNAVAILABLE, "Not initialized") }.toMap()
Expand Down Expand Up @@ -92,12 +92,14 @@ fun MainScreen(viewModel: AbstractMainViewModel = koinViewModel()) {
Section(
contents = viewModel.collectors.map{ name ->
{
val isToggled = collectorStates.value[name]?.flag == CollectorState.FLAG.ENABLED
|| collectorStates.value[name]?.flag == CollectorState.FLAG.RUNNING
SettingRow(
title = name,
displayStatus = false,
displayToggle = true,
toggleStatus = collectorStates.value[name]?.flag == CollectorState.FLAG.ENABLED,
onClick = {if(collectorStates.value[name]?.flag == CollectorState.FLAG.ENABLED)
toggleStatus = isToggled,
onClick = {if(isToggled)
viewModel.disableCollector(name) else viewModel.enableCollector(name)}
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ class MainViewModelImpl(
}

override val controllerStateFlow = collectorController.stateFlow
override val collectorStateFlow = collectorController.collectorStateFlow
override val configFlow = collectorController.configFlow
override val collectorStateFlow = collectorController.collectorStateFlow()
override val configFlow = collectorController.configFlow()

override fun start() {
collectorController.start()
Expand Down
22 changes: 6 additions & 16 deletions tracker-library/src/main/java/kaist/iclab/tracker/Tracker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ object Tracker {
private var permissionManager: WeakReference<PermissionManagerInterface>? = null

@Volatile
private var notfManagerInterface: NotfManagerInterface? = null
private var notfManager: NotfManagerInterface? = null

@Synchronized
fun initialize(context: Context,
Expand All @@ -33,28 +33,18 @@ object Tracker {
if (collectorController?.get() == null) {
collectorController = WeakReference(collectorController_)
}
if(notfManagerInterface == null){
notfManagerInterface = notfManager_
notfManagerInterface?.createServiceNotfChannel(context)
if(notfManager== null){
notfManager= notfManager_
notfManager?.createServiceNotfChannel(context)
}

}
// if (collectorController?.get() == null) {
// permissionManager = WeakReference(permissionManager_)
// val collectorController_ = CollectorControllerImpl(context.applicationContext)
// collectorController = WeakReference(collectorController_)
// }
// if(notfManagerInterface == null){
// notfManagerInterface = NotfManagerImpl()
// notfManagerInterface?.createServiceNotfChannel(context)
// }
// }

@Synchronized
fun initialize(context: Context){
val notfManager_ = NotfManagerImpl()
notfManager_.createServiceNotfChannel(context)
initialize(context,PermissionManagerImpl(context),notfManager_, CollectorControllerImpl(context, emptyMap()))
initialize(context,PermissionManagerImpl(context),notfManager_, CollectorControllerImpl(context))

}

Expand All @@ -67,6 +57,6 @@ object Tracker {
}

fun getNotfManager(): NotfManagerInterface {
return notfManagerInterface ?: throw IllegalStateException("TrackerService not initialized")
return notfManager ?: throw IllegalStateException("TrackerService not initialized")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,7 @@ class AmbientLightCollector(
val value: Float
) : DataEntity(received)

private val sensorManager: SensorManager by lazy{
context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
}

private val sensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager

private val sensorEventListener = object:SensorEventListener {
override fun onAccuracyChanged(sensor: Sensor?, p1: Int) {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,6 @@ abstract class AbstractCollector<
K: DataEntity>(
val permissionManager: PermissionManagerInterface
): CollectorInterface {
init {
initState()
initConfig()
}

protected val TAG: String = this::class.simpleName ?: "UnnamedClass"
override val NAME: String = extractName(this::class.simpleName ?: "UnknownCollector")

Expand Down Expand Up @@ -54,7 +49,11 @@ abstract class AbstractCollector<
if(!availability.status) _stateFlow.tryEmit(CollectorState(CollectorState.FLAG.UNAVAILABLE, availability.reason))
else if(!permissionManager.isPermissionsGranted(permissions)) _stateFlow.tryEmit(
CollectorState(CollectorState.FLAG.PERMISSION_REQUIRED))
else _stateFlow.tryEmit(CollectorState(CollectorState.FLAG.ENABLED))
else _stateFlow.tryEmit(CollectorState(CollectorState.FLAG.DISABLED))
}
override fun initialize() {
initState()
initConfig()
}

/* Check whether the system allow to collect data
Expand All @@ -66,7 +65,7 @@ abstract class AbstractCollector<
permissionManager.request(permissions) {
val granted = permissions.all { permission -> it[permission] == true }
Log.d(TAG, "Permission granted: $granted")
if(granted) _stateFlow.tryEmit(CollectorState(CollectorState.FLAG.ENABLED))
if(granted) _stateFlow.tryEmit(CollectorState(CollectorState.FLAG.DISABLED))
else _stateFlow.tryEmit(CollectorState(CollectorState.FLAG.PERMISSION_REQUIRED, "Permission denied"))
onResult(granted)
}
Expand All @@ -77,11 +76,11 @@ abstract class AbstractCollector<
// Replace "Collector" with an empty string
val tmp = className.replace("Collector", "")

// Split the name into parts based on camel case and underscores
// Split the name into parts based on camel case
val parts =
tmp.split("(?=\\p{Upper})|_|(?<=\\p{Lower})(?=\\p{Upper})".toRegex())

// Join the parts and convert to uppercase
return parts.joinToString("_").uppercase()
// Join the parts using whitespace and convert
return parts.joinToString(" ")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,38 +21,53 @@ import kotlinx.coroutines.flow.merge

class CollectorControllerImpl(
private val context: Context,
override val collectorMap: Map<String, CollectorInterface>
) : CollectorControllerInterface {
private val _stateFlow = MutableStateFlow<Boolean>(false)
override val stateFlow: StateFlow<Boolean>
get() = _stateFlow.asStateFlow()

override val collectorStateFlow = combine(collectorMap.map { (key, collector) ->
collector.stateFlow.map { state ->
key to state
override fun collectorStateFlow(): Flow<Map<String, CollectorState>> {
return combine(_collectorMap.map { (key, collector) ->
collector.stateFlow.map { state ->
key to state
}
}) { pairs -> pairs.toMap() }
}

private var _collectorMap: Map<String, CollectorInterface> = emptyMap()
override fun initializeCollectors(collectorMap: Map<String, CollectorInterface>) {
_collectorMap = collectorMap
_collectorMap.forEach { (_, collector) ->
collector.initialize()
}
}) { pairs -> pairs.toMap() }
}

override fun enableCollector(name: String) {
collectorMap[name]?.let { collector->
Log.d("CollectorControllerImpl", "enableCollector: $name")
_collectorMap[name]?.let { collector ->
Log.d("CollectorControllerImpl", "Collector found")
collector.requestPermissions() {
if (it) { collector.enable() }
if (it) {
collector.enable()
}
}
}
}

override fun disableCollector(name: String) {
collectorMap[name]?.disable()
_collectorMap[name]?.disable()
}

override val configFlow = combine(collectorMap.map { (key, collector) ->
collector.configFlow.map { config ->
key to config
}
}) { pairs -> pairs.toMap() }
override fun configFlow(): Flow<Map<String, CollectorConfig>> {
return combine(_collectorMap.map { (key, collector) ->
collector.configFlow.map { config ->
key to config
}
}) { pairs -> pairs.toMap() }
}

override fun updateConfig(config: Map<String, CollectorConfig>) {
collectorMap.forEach { (name, collector) ->
_collectorMap.forEach { (name, collector) ->
config[name]?.let {
collector.updateConfig(it)
}
Expand All @@ -76,7 +91,7 @@ class CollectorControllerImpl(
class CollectorService : Service() {
val controller = Tracker.getCollectorController() as CollectorControllerImpl
val notfManager = Tracker.getNotfManager()
val collectorMap = controller.collectorMap
val collectorMap = controller._collectorMap
override fun onBind(intent: Intent?): IBinder? = null
override fun onDestroy() {
stop()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,19 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow

interface CollectorControllerInterface {
val collectorMap: Map<String, CollectorInterface>

val stateFlow: StateFlow<Boolean>
fun start()
fun stop()

val collectorStateFlow: Flow<Map<String, CollectorState>>

fun collectorStateFlow(): Flow<Map<String, CollectorState>>
fun initializeCollectors(
collectorMap: Map<String, CollectorInterface>
)
fun enableCollector(name: String)
fun disableCollector(name: String)


val configFlow : Flow<Map<String, CollectorConfig>>
fun configFlow() : Flow<Map<String, CollectorConfig>>
fun updateConfig(config: Map<String, CollectorConfig>)
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ interface CollectorInterface {

val stateFlow: StateFlow<CollectorState>

/* UNAVAILABLE => Check*/
fun initialize()
/* DISABLED => READY */
fun enable()
/* READY => DISABLED */
Expand Down

0 comments on commit fd2c304

Please sign in to comment.