Skip to content

Commit

Permalink
Merge pull request #1133 from embrace-io/move-core-module
Browse files Browse the repository at this point in the history
Modularise core module
  • Loading branch information
fractalwrench authored Jul 23, 2024
2 parents 48f2704 + a85aea6 commit da96dfe
Show file tree
Hide file tree
Showing 18 changed files with 80 additions and 73 deletions.
1 change: 1 addition & 0 deletions embrace-android-core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ dependencies {
compileOnly(libs.opentelemetry.api)
compileOnly(libs.opentelemetry.semconv)
compileOnly(libs.opentelemetry.semconv.incubating)
compileOnly(libs.lifecycle.common.java8)
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import android.content.res.Resources
* Interface for retrieving identifiers and strings from the app's [android.content.res.Resources] object. This can be used
* instead of directly accessing resources through the [Context] so we can more easily fake things during tests.
*/
internal interface AndroidResourcesService {
fun getIdentifier(name: String?, defType: String?, defPackage: String?): Int
public interface AndroidResourcesService {
public fun getIdentifier(name: String?, defType: String?, defPackage: String?): Int

@Throws(Resources.NotFoundException::class)
fun getString(id: Int): String
public fun getString(id: Int): String
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,27 @@ import android.content.res.Resources
/**
* Specifies the application ID and build ID.
*/
internal class BuildInfo internal constructor(
public class BuildInfo(
/**
* The ID of the particular build, generated at compile-time.
*/
val buildId: String?,
public val buildId: String?,

/**
* The BuildType name of the particular build, extracted at compile-time.
*/
val buildType: String?,
public val buildType: String?,

/**
* The Flavor name of the particular build, extracted at compile-time.
*/
val buildFlavor: String?
public val buildFlavor: String?
) {

internal companion object {
const val BUILD_INFO_BUILD_ID: String = "emb_build_id"
const val BUILD_INFO_BUILD_TYPE: String = "emb_build_type"
const val BUILD_INFO_BUILD_FLAVOR: String = "emb_build_flavor"
public companion object {
public const val BUILD_INFO_BUILD_ID: String = "emb_build_id"
public const val BUILD_INFO_BUILD_TYPE: String = "emb_build_type"
public const val BUILD_INFO_BUILD_FLAVOR: String = "emb_build_flavor"
private const val RES_TYPE_STRING = "string"

/**
Expand All @@ -35,7 +35,7 @@ internal class BuildInfo internal constructor(
* @return the build information
*/
@JvmStatic
fun fromResources(resources: AndroidResourcesService, packageName: String): BuildInfo {
public fun fromResources(resources: AndroidResourcesService, packageName: String): BuildInfo {
return BuildInfo(
getBuildResource(resources, packageName, BUILD_INFO_BUILD_ID),
getBuildResource(resources, packageName, BUILD_INFO_BUILD_TYPE),
Expand All @@ -46,7 +46,7 @@ internal class BuildInfo internal constructor(
/**
* Given a build property name and a build property type, retrieves the embrace build resource value.
*/
fun getBuildResource(
public fun getBuildResource(
resources: AndroidResourcesService,
packageName: String,
buildProperty: String
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import android.content.Context
/**
* Implementation used in production that just defers to the given [Context]
*/
internal class EmbraceAndroidResourcesService(private val context: Context) : AndroidResourcesService {
public class EmbraceAndroidResourcesService(private val context: Context) :

Check warning on line 9 in embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/EmbraceAndroidResourcesService.kt

View check run for this annotation

Codecov / codecov/patch

embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/EmbraceAndroidResourcesService.kt#L9

Added line #L9 was not covered by tests
AndroidResourcesService {
@SuppressLint("DiscouragedApi")
override fun getIdentifier(name: String?, defType: String?, defPackage: String?): Int =
context.resources.getIdentifier(name, defType, defPackage)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,34 +11,34 @@ import io.embrace.android.embracesdk.internal.registry.ServiceRegistry
* Contains a core set of dependencies that are required by most services/classes in the SDK.
* This includes a reference to the application context, a clock, logger, etc...
*/
internal interface CoreModule {
public interface CoreModule {

/**
* Reference to the context. This will always return the application context so won't leak.
*/
val context: Context
public val context: Context

val packageInfo: PackageInfo
public val packageInfo: PackageInfo

/**
* Reference to the current application.
*/
val application: Application
public val application: Application

/**
* Returns the service registry. This is used to register services that need to be closed
*/
val serviceRegistry: ServiceRegistry
public val serviceRegistry: ServiceRegistry

/**
* Returns an service to retrieve Android resources
*/
val resources: AndroidResourcesService
public val resources: AndroidResourcesService

/**
* Whether the application is a debug build
*/
val isDebug: Boolean
public val isDebug: Boolean

val buildInfo: BuildInfo
public val buildInfo: BuildInfo
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import io.embrace.android.embracesdk.internal.capture.metadata.AppEnvironment
import io.embrace.android.embracesdk.internal.logging.EmbLogger
import io.embrace.android.embracesdk.internal.registry.ServiceRegistry

internal class CoreModuleImpl(
public class CoreModuleImpl(
ctx: Context,
logger: EmbLogger
) : CoreModule {
Expand All @@ -26,7 +26,7 @@ internal class CoreModuleImpl(
override val packageInfo: PackageInfo
get() = context.packageManager.getPackageInfo(context.packageName, 0)

override val application by singleton { context as Application }
override val application: Application by singleton { context as Application }

override val serviceRegistry: ServiceRegistry by singleton {
ServiceRegistry(logger)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import kotlin.reflect.KProperty
/**
* How the dependency should be loaded.
*/
internal enum class LoadType {
public enum class LoadType {

/**
* The dependency should be instantiated as soon as the module is created.
Expand All @@ -27,7 +27,7 @@ internal enum class LoadType {
* Lazy dependencies are NOT thread safe. It is assumed that dependencies will always be
* initialized on the same thread.
*/
internal inline fun <reified T> singleton(
public inline fun <reified T> singleton(
loadType: LoadType = LoadType.LAZY,
noinline provider: Provider<T>
): ReadOnlyProperty<Any?, T> = SingletonDelegate(loadType, provider)
Expand All @@ -36,16 +36,16 @@ internal inline fun <reified T> singleton(
* Creates a new dependency from a factory, meaning every time this property is called a
* new object will be created.
*/
internal inline fun <reified T> factory(
public inline fun <reified T> factory(
noinline provider: Provider<T>
): ReadOnlyProperty<Any?, T> = FactoryDelegate(provider)

internal class FactoryDelegate<T>(private inline val provider: Provider<T>) : ReadOnlyProperty<Any?, T> {
public class FactoryDelegate<T>(private inline val provider: Provider<T>) : ReadOnlyProperty<Any?, T> {

override fun getValue(thisRef: Any?, property: KProperty<*>): T = provider()
}

internal class SingletonDelegate<T>(
public class SingletonDelegate<T>(
loadType: LoadType,
provider: Provider<T>
) : ReadOnlyProperty<Any?, T> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import java.util.concurrent.atomic.AtomicBoolean
* An object that holds all of the services that are registered with the SDK. This makes it simpler
* to remember to set callbacks & close resources when creating a new service.
*/
internal class ServiceRegistry(
public class ServiceRegistry(
private val logger: EmbLogger
) : Closeable {

Expand All @@ -24,17 +24,23 @@ internal class ServiceRegistry(

// lazy init avoids type checks at startup until absolutely necessary.
// once these variables are initialized, no further services should be registered.
val closeables by lazy { registry.filterIsInstance<Closeable>() }
val memoryCleanerListeners by lazy { registry.filterIsInstance<MemoryCleanerListener>() }
val processStateListeners by lazy { registry.filterIsInstance<ProcessStateListener>() }
val activityLifecycleListeners by lazy { registry.filterIsInstance<ActivityLifecycleListener>() }
val startupListener by lazy { registry.filterIsInstance<StartupListener>() }
public val closeables: List<Closeable> by lazy { registry.filterIsInstance<Closeable>() }
public val memoryCleanerListeners: List<MemoryCleanerListener> by lazy {
registry.filterIsInstance<MemoryCleanerListener>()
}
public val processStateListeners: List<ProcessStateListener> by lazy {
registry.filterIsInstance<ProcessStateListener>()
}
public val activityLifecycleListeners: List<ActivityLifecycleListener> by lazy {
registry.filterIsInstance<ActivityLifecycleListener>()
}
public val startupListener: List<StartupListener> by lazy { registry.filterIsInstance<StartupListener>() }

fun registerServices(vararg services: Any?) {
public fun registerServices(vararg services: Any?) {
services.forEach(::registerService)
}

fun registerService(service: Any?) {
public fun registerService(service: Any?) {
if (initialized.get()) {
error("Cannot register a service - already initialized.")
}
Expand All @@ -44,35 +50,35 @@ internal class ServiceRegistry(
registry.add(service)
}

fun closeRegistration() {
public fun closeRegistration() {
initialized.set(true)
}

fun registerActivityListeners(processStateService: ProcessStateService) = processStateListeners.forEachSafe(
public fun registerActivityListeners(processStateService: ProcessStateService): Unit = processStateListeners.forEachSafe(
"Failed to register activity listener",
processStateService::addListener
)

fun registerActivityLifecycleListeners(activityLifecycleTracker: ActivityTracker) = activityLifecycleListeners.forEachSafe(
public fun registerActivityLifecycleListeners(activityLifecycleTracker: ActivityTracker): Unit = activityLifecycleListeners.forEachSafe(
"Failed to register activity lifecycle listener",
activityLifecycleTracker::addListener
)

fun registerMemoryCleanerListeners(memoryCleanerService: MemoryCleanerService) =
public fun registerMemoryCleanerListeners(memoryCleanerService: MemoryCleanerService): Unit =
memoryCleanerListeners.forEachSafe(
"Failed to register memory cleaner listener",
memoryCleanerService::addListener
)

fun registerStartupListener(activityLifecycleTracker: ActivityTracker) =
public fun registerStartupListener(activityLifecycleTracker: ActivityTracker): Unit =
startupListener.forEachSafe(
"Failed to register application lifecycle listener",
activityLifecycleTracker::addStartupListener
)

// close all of the services in one go. this prevents someone creating a Closeable service
// but forgetting to close it.
override fun close() = closeables.forEachSafe("Failed to close service", Closeable::close)
override fun close(): Unit = closeables.forEachSafe("Failed to close service", Closeable::close)

private fun <T> List<T>.forEachSafe(msg: String, action: (t: T) -> Unit) {
this.forEach {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package io.embrace.android.embracesdk.internal.session

internal interface MemoryCleanerListener {
public interface MemoryCleanerListener {

/**
* Clean collections in memory when a session ends occurs.
*/
fun cleanCollections()
public fun cleanCollections()
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package io.embrace.android.embracesdk.internal.session

internal interface MemoryCleanerService {
public interface MemoryCleanerService {

/**
* Adds an observer of the end session event.
*
* @param listener the observer to register
*/
fun addListener(listener: MemoryCleanerListener)
public fun addListener(listener: MemoryCleanerListener)

/**
* Flush collections from each service which has collections in memory.
*/
fun cleanServicesCollections()
public fun cleanServicesCollections()
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,27 @@ import android.os.Bundle
/**
* Listener implemented by observers of the [ActivityLifecycleTracker].
*/
internal interface ActivityLifecycleListener {
public interface ActivityLifecycleListener {

/**
* Triggered when an activity is opened.
*
* @param activity details of the activity
*/
fun onView(activity: Activity) {}
public fun onView(activity: Activity) {}

Check warning on line 16 in embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/session/lifecycle/ActivityLifecycleListener.kt

View check run for this annotation

Codecov / codecov/patch

embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/session/lifecycle/ActivityLifecycleListener.kt#L16

Added line #L16 was not covered by tests

/**
* Triggered when an activity is closed.
*
* @param activity details of the activity
*/
fun onViewClose(activity: Activity) {}
public fun onViewClose(activity: Activity) {}

Check warning on line 23 in embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/session/lifecycle/ActivityLifecycleListener.kt

View check run for this annotation

Codecov / codecov/patch

embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/session/lifecycle/ActivityLifecycleListener.kt#L23

Added line #L23 was not covered by tests

/**
* Triggered when an activity is created.
*
* @param activity the activity
* @param bundle the bundle
*/
fun onActivityCreated(activity: Activity, bundle: Bundle?) {}
public fun onActivityCreated(activity: Activity, bundle: Bundle?) {}

Check warning on line 31 in embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/session/lifecycle/ActivityLifecycleListener.kt

View check run for this annotation

Codecov / codecov/patch

embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/session/lifecycle/ActivityLifecycleListener.kt#L31

Added line #L31 was not covered by tests
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ import java.io.Closeable
/**
* Tracks activity lifecycle events.
*/
internal interface ActivityTracker : Application.ActivityLifecycleCallbacks, Closeable {
public interface ActivityTracker : Application.ActivityLifecycleCallbacks, Closeable {

/**
* Gets the activity which is currently in the foreground.
*
* @return an optional of the activity currently in the foreground
*/
val foregroundActivity: Activity?
public val foregroundActivity: Activity?

fun addListener(listener: ActivityLifecycleListener)
public fun addListener(listener: ActivityLifecycleListener)

fun addStartupListener(listener: StartupListener)
public fun addStartupListener(listener: StartupListener)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@ package io.embrace.android.embracesdk.internal.session.lifecycle
/**
* Listener implemented by observers of the [ProcessStateService].
*/
internal interface ProcessStateListener {
public interface ProcessStateListener {

/**
* Triggered when the app enters the background.
*/
fun onBackground(timestamp: Long) {}
public fun onBackground(timestamp: Long) {}

/**
* Triggered when the application is resumed.
*
* @param coldStart whether this is a cold start
* @param timestamp the timestamp at which the application entered the foreground
*/
fun onForeground(coldStart: Boolean, timestamp: Long) {}
public fun onForeground(coldStart: Boolean, timestamp: Long) {}

Check warning on line 19 in embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/session/lifecycle/ProcessStateListener.kt

View check run for this annotation

Codecov / codecov/patch

embrace-android-core/src/main/kotlin/io/embrace/android/embracesdk/internal/session/lifecycle/ProcessStateListener.kt#L19

Added line #L19 was not covered by tests
}
Loading

0 comments on commit da96dfe

Please sign in to comment.