Skip to content

Commit 8f0dacb

Browse files
committed
Inject encoded Base64 shared object files map with ASM
1 parent 0762099 commit 8f0dacb

10 files changed

Lines changed: 127 additions & 52 deletions

File tree

embrace-android-payload/src/main/kotlin/io/embrace/android/embracesdk/internal/config/instrumented/InstrumentedConfigImpl.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.embrace.android.embracesdk.internal.config.instrumented
22

3+
import io.embrace.android.embracesdk.internal.config.instrumented.schema.Base64SharedObjectFilesMap
34
import io.embrace.android.embracesdk.internal.config.instrumented.schema.BaseUrlConfig
45
import io.embrace.android.embracesdk.internal.config.instrumented.schema.EnabledFeatureConfig
56
import io.embrace.android.embracesdk.internal.config.instrumented.schema.InstrumentedConfig
@@ -28,6 +29,7 @@ object InstrumentedConfigImpl : InstrumentedConfig {
2829
override val project: ProjectConfig = ProjectConfigImpl
2930
override val redaction: RedactionConfig = RedactionConfigImpl
3031
override val session: SessionConfig = SessionConfigImpl
32+
override val symbols: Base64SharedObjectFilesMap = Base64SharedObjectFilesMapImpl
3133
}
3234

3335
@EmbraceInstrumented
@@ -50,3 +52,6 @@ object RedactionConfigImpl : RedactionConfig
5052

5153
@EmbraceInstrumented
5254
object SessionConfigImpl : SessionConfig
55+
56+
@EmbraceInstrumented
57+
object Base64SharedObjectFilesMapImpl : Base64SharedObjectFilesMap
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package io.embrace.android.embracesdk.internal.config.instrumented.schema
2+
3+
/**
4+
* A Base64 encoded string of the shared object files that are used to symbolicate crashes.
5+
*/
6+
interface Base64SharedObjectFilesMap {
7+
8+
/**
9+
* A Base64 encoded string of the shared object files that are used to symbolicate crashes.
10+
*
11+
* Once decoded, this string should be a JSON object with the following structure:
12+
* {
13+
* "symbols": {
14+
* "arm64-v8a": {
15+
* "libemb-donuts.so":"11e1c3cc39fc506d06fcdb75bb4d005345aba95e",
16+
* "libemb-crisps.so":"ace3755e21c6961e9c3e329216eeb7333840074b"
17+
* }
18+
* ...
19+
* }
20+
*/
21+
fun getBase64SharedObjectFilesMap(): String? = null
22+
}

embrace-android-payload/src/main/kotlin/io/embrace/android/embracesdk/internal/config/instrumented/schema/InstrumentedConfig.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,5 @@ interface InstrumentedConfig {
1212
val project: ProjectConfig
1313
val redaction: RedactionConfig
1414
val session: SessionConfig
15+
val symbols: Base64SharedObjectFilesMap
1516
}

embrace-gradle-plugin/src/main/java/io/embrace/android/gradle/plugin/instrumentation/EmbraceClassVisitorFactoryDelegate.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,16 @@ internal fun createClassVisitorImpl(
1616
nextClassVisitor: ClassVisitor,
1717
instrumentationContext: InstrumentationContext,
1818
parameters: Property<BytecodeInstrumentationParams>,
19-
logger: (() -> String) -> Unit
19+
logger: (() -> String) -> Unit,
2020
): ClassVisitor {
2121
val api = instrumentationContext.apiVersion.get()
2222
var visitor = nextClassVisitor
2323
val className = classContext.currentClassData.className
2424

2525
// Add a visitor if this is a config class provided by the SDK
2626
val cfg = parameters.get().config.get()
27-
ConfigClassVisitorFactory.createClassVisitor(className, cfg, api, visitor)?.let {
27+
val encodedSharedObjectFilesMap = parameters.get().encodedSharedObjectFilesMap.orNull
28+
ConfigClassVisitorFactory.createClassVisitor(className, cfg, encodedSharedObjectFilesMap, api, visitor)?.let {
2829
visitor = it
2930
}
3031

embrace-gradle-plugin/src/main/java/io/embrace/android/gradle/plugin/instrumentation/config/ConfigClassVisitorFactory.kt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import io.embrace.android.gradle.plugin.instrumentation.config.arch.sdk.createNe
66
import io.embrace.android.gradle.plugin.instrumentation.config.arch.sdk.createProjectConfigInstrumentation
77
import io.embrace.android.gradle.plugin.instrumentation.config.arch.sdk.createRedactionConfigInstrumentation
88
import io.embrace.android.gradle.plugin.instrumentation.config.arch.sdk.createSessionConfigInstrumentation
9+
import io.embrace.android.gradle.plugin.instrumentation.config.arch.sdk.createSharedObjectFilesMapInstrumentation
910
import io.embrace.android.gradle.plugin.instrumentation.config.model.VariantConfig
1011
import io.embrace.android.gradle.plugin.instrumentation.config.visitor.ConfigInstrumentationClassVisitor
1112
import org.objectweb.asm.ClassVisitor
@@ -17,12 +18,14 @@ object ConfigClassVisitorFactory {
1718
NetworkCaptureConfig,
1819
ProjectConfig,
1920
RedactionConfig,
20-
SessionConfig;
21+
SessionConfig,
22+
Base64SharedObjectFilesMap;
2123

2224
val className = "io.embrace.android.embracesdk.internal.config.instrumented.${name}Impl"
2325

2426
fun createClassVisitor(
2527
cfg: VariantConfig,
28+
encodedSharedObjectFilesMap: String?,
2629
api: Int,
2730
cv: ClassVisitor?
2831
): ClassVisitor {
@@ -33,6 +36,7 @@ object ConfigClassVisitorFactory {
3336
ProjectConfig -> createProjectConfigInstrumentation(cfg)
3437
RedactionConfig -> createRedactionConfigInstrumentation(cfg)
3538
SessionConfig -> createSessionConfigInstrumentation(cfg)
39+
Base64SharedObjectFilesMap -> createSharedObjectFilesMapInstrumentation(encodedSharedObjectFilesMap)
3640
}
3741
return ConfigInstrumentationClassVisitor(instrumentation, api, cv)
3842
}
@@ -45,10 +49,11 @@ object ConfigClassVisitorFactory {
4549
fun createClassVisitor(
4650
className: String,
4751
cfg: VariantConfig,
52+
encodedSharedObjectFilesMap: String?,
4853
api: Int,
4954
cv: ClassVisitor?
5055
): ClassVisitor? {
5156
val type = ConfigClassType.values().singleOrNull { it.className == className }
52-
return type?.createClassVisitor(cfg, api, cv)
57+
return type?.createClassVisitor(cfg, encodedSharedObjectFilesMap, api, cv)
5358
}
5459
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package io.embrace.android.gradle.plugin.instrumentation.config.arch.sdk
2+
3+
import io.embrace.android.gradle.plugin.instrumentation.config.arch.modelSdkConfigClass
4+
import io.embrace.android.gradle.plugin.instrumentation.config.arch.stringMethod
5+
6+
fun createSharedObjectFilesMapInstrumentation(encodedSharedObjectFilesMap: String?) = modelSdkConfigClass {
7+
stringMethod("getBase64SharedObjectFilesMap") { encodedSharedObjectFilesMap }
8+
}

embrace-gradle-plugin/src/main/java/io/embrace/android/gradle/plugin/tasks/registration/TaskRegistrar.kt

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -48,25 +48,27 @@ class TaskRegistrar(
4848

4949
setupVariantConfigurationListProperty(variant, variantConfigurationsListProperty)
5050

51+
val params = RegistrationParams(
52+
project,
53+
ref,
54+
variant,
55+
variantConfigurationsListProperty,
56+
behavior,
57+
)
58+
59+
AsmTaskRegistration().register(params)
60+
5161
if (behavior.isPluginDisabledForVariant(variant.name) || !shouldRegisterUploadTasks(variant, variantConfigurationsListProperty)) {
5262
return
5363
} else {
54-
val params = RegistrationParams(
55-
project,
56-
ref,
57-
variant,
58-
variantConfigurationsListProperty,
59-
behavior,
60-
)
61-
registerTasks(params, variant)
64+
registerUploadTasks(params, variant)
6265
}
6366
}
6467

65-
private fun registerTasks(params: RegistrationParams, variant: AndroidCompactedVariantData) {
68+
private fun registerUploadTasks(params: RegistrationParams, variant: AndroidCompactedVariantData) {
6669
JvmMappingUploadTaskRegistration().register(params)
6770
if (behavior.isReactNativeProject) {
68-
val taskRegistration = EmbraceRnSourcemapGeneratorTaskRegistration()
69-
taskRegistration.register(params)
71+
EmbraceRnSourcemapGeneratorTaskRegistration().register(params)
7072
}
7173
val variantConfig = variantConfigurationsListProperty.get().first { it.variantName == variant.name }
7274
val unitySymbolsDirProvider = getUnitySymbolsDirProvider(variantConfig)
@@ -75,7 +77,6 @@ class TaskRegistrar(
7577
if (behavior.isIl2CppMappingFilesUploadEnabled) {
7678
Il2CppUploadTaskRegistration().register(params)
7779
}
78-
AsmTaskRegistration().register(params)
7980
}
8081

8182
private fun shouldRegisterUploadTasks(

embrace-gradle-plugin/src/test/java/io/embrace/android/gradle/plugin/instrumentation/config/InstrumentedConfigClassVisitorFactoryTest.kt

Lines changed: 61 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -9,42 +9,67 @@ import org.junit.Test
99

1010
class InstrumentedConfigClassVisitorFactoryTest {
1111

12+
private val config = VariantConfig("", null, null, null, null, null)
13+
private val api = ASM_API_VERSION
14+
private val embracePackage = "io.embrace.android.embracesdk.internal.config.instrumented"
15+
16+
@Test
17+
fun `should return null for empty class name`() {
18+
assertNull(createVisitor(""))
19+
}
20+
1221
@Test
13-
fun createClassVisitor() {
14-
val factory = ConfigClassVisitorFactory
15-
val api = ASM_API_VERSION
16-
val pkg = "io.embrace.android.embracesdk.internal.config.instrumented"
17-
val cfg = VariantConfig("", null, null, null, null, null)
18-
19-
assertNull(factory.createClassVisitor("", cfg, api, null))
20-
assertNull(factory.createClassVisitor("java.lang.Boolean", cfg, api, null))
21-
assertTrue(
22-
factory.createClassVisitor("$pkg.BaseUrlConfigImpl", cfg, api, null) is ConfigInstrumentationClassVisitor
23-
)
24-
assertTrue(
25-
factory.createClassVisitor(
26-
"$pkg.EnabledFeatureConfigImpl",
27-
cfg,
28-
api,
29-
null
30-
) is ConfigInstrumentationClassVisitor
31-
)
32-
assertTrue(
33-
factory.createClassVisitor(
34-
"$pkg.NetworkCaptureConfigImpl",
35-
cfg,
36-
api,
37-
null
38-
) is ConfigInstrumentationClassVisitor
39-
)
40-
assertTrue(
41-
factory.createClassVisitor("$pkg.ProjectConfigImpl", cfg, api, null) is ConfigInstrumentationClassVisitor
42-
)
43-
assertTrue(
44-
factory.createClassVisitor("$pkg.RedactionConfigImpl", cfg, api, null) is ConfigInstrumentationClassVisitor
45-
)
46-
assertTrue(
47-
factory.createClassVisitor("$pkg.SessionConfigImpl", cfg, api, null) is ConfigInstrumentationClassVisitor
48-
)
22+
fun `should return null for non-config class`() {
23+
assertNull(createVisitor("java.lang.Boolean"))
4924
}
25+
26+
@Test
27+
fun `should create visitor for BaseUrlConfigImpl`() {
28+
val visitor = createVisitor("$embracePackage.BaseUrlConfigImpl")
29+
assertTrue(visitor is ConfigInstrumentationClassVisitor)
30+
}
31+
32+
@Test
33+
fun `should create visitor for EnabledFeatureConfigImpl`() {
34+
val visitor = createVisitor("$embracePackage.EnabledFeatureConfigImpl")
35+
assertTrue(visitor is ConfigInstrumentationClassVisitor)
36+
}
37+
38+
@Test
39+
fun `should create visitor for NetworkCaptureConfigImpl`() {
40+
val visitor = createVisitor("$embracePackage.NetworkCaptureConfigImpl")
41+
assertTrue(visitor is ConfigInstrumentationClassVisitor)
42+
}
43+
44+
@Test
45+
fun `should create visitor for ProjectConfigImpl`() {
46+
val visitor = createVisitor("$embracePackage.ProjectConfigImpl")
47+
assertTrue(visitor is ConfigInstrumentationClassVisitor)
48+
}
49+
50+
@Test
51+
fun `should create visitor for RedactionConfigImpl`() {
52+
val visitor = createVisitor("$embracePackage.RedactionConfigImpl")
53+
assertTrue(visitor is ConfigInstrumentationClassVisitor)
54+
}
55+
56+
@Test
57+
fun `should create visitor for SessionConfigImpl`() {
58+
val visitor = createVisitor("$embracePackage.SessionConfigImpl")
59+
assertTrue(visitor is ConfigInstrumentationClassVisitor)
60+
}
61+
62+
@Test
63+
fun `should create visitor for Base64SharedObjectFilesMap`() {
64+
val visitor = createVisitor("$embracePackage.Base64SharedObjectFilesMapImpl")
65+
assertTrue(visitor is ConfigInstrumentationClassVisitor)
66+
}
67+
68+
@Test
69+
fun `should return null for invalid package name`() {
70+
assertNull(createVisitor("invalid.package.ClassName"))
71+
}
72+
73+
private fun createVisitor(className: String) =
74+
ConfigClassVisitorFactory.createClassVisitor(className, config, null, api, null)
5075
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package io.embrace.android.embracesdk.fakes.config
2+
3+
import io.embrace.android.embracesdk.internal.config.instrumented.schema.Base64SharedObjectFilesMap
4+
5+
class FakeBase64SharedObjectFilesMap : Base64SharedObjectFilesMap

embrace-test-fakes/src/main/kotlin/io/embrace/android/embracesdk/fakes/config/FakeInstrumentedConfig.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.embrace.android.embracesdk.fakes.config
22

33
import io.embrace.android.embracesdk.internal.config.instrumented.InstrumentedConfigImpl
4+
import io.embrace.android.embracesdk.internal.config.instrumented.schema.Base64SharedObjectFilesMap
45
import io.embrace.android.embracesdk.internal.config.instrumented.schema.InstrumentedConfig
56
import io.embrace.android.embracesdk.internal.config.instrumented.schema.NetworkCaptureConfig
67
import io.embrace.android.embracesdk.internal.config.instrumented.schema.OtelLimitsConfig
@@ -20,4 +21,5 @@ data class FakeInstrumentedConfig(
2021
override val project: ProjectConfig = FakeProjectConfig(base.project, appId = "abcde"),
2122
override val redaction: RedactionConfig = FakeRedactionConfig(base.redaction),
2223
override val session: SessionConfig = FakeSessionConfig(base.session),
24+
override val symbols: Base64SharedObjectFilesMap = FakeBase64SharedObjectFilesMap(),
2325
) : InstrumentedConfig

0 commit comments

Comments
 (0)