|
|
Identifying the cause of a non-deterministic build is a challenge on every platform, but on Android this has additional complexity due to Fenix's layered architecture - each layer undergoing active development.
|
|
|
|
|
|
We will use tor-browser-build#40485 while describing how to investigate and resolve this problem.
|
|
|
|
|
|
Needed Tools:
|
|
|
- `unzip`, provided by the `unzip` package on Debian
|
|
|
- `apktool`, provided by the `apktool` package on Debian
|
|
|
- command for creating a collision-resistant hash of files
|
|
|
- this guide will use `sha256sum` and `sha256deep`
|
|
|
- On Debian-based systems, these are available in `coreutils` and `hashdeep`, respectively
|
|
|
- (optionally) `find`, provided by `findutils` on Debian
|
|
|
- (optionally) `diffoscope`, provided by `diffoscope` on Debian
|
|
|
|
|
|
Note, `diffoscope` is a powerful all-in-one solution for diffing two archives, but this guide prefers following a more manual process at each stage for finer grain control over the investigation. Feel free to use `diffoscope` if you feel comfortable skipping some of the more manual steps and want a tool that tells you exactly how two archives are different.
|
|
|
|
|
|
### Step 0: Obtain two differing build packages
|
|
|
|
|
|
The initial step is obtaining two packages that were built from the same source code, but resulted in two packages that differ in some way. Often at least one of these packages is built by another person, but you may create both packages yourself, if building the same code at different times results in differing packages.
|
|
|
|
|
|
```
|
|
|
$ sha256sum 11.5a10-build2/{1,2}/tor-browser-11.5a10-android-x86_64-multi-qa.apk
|
|
|
89adbfb3a09d2db1990a98c406dd60e568a182a5b323d766650cc4e2c8afee1e 11.5a10-build2/1/tor-browser-11.5a10-android-x86_64-multi-qa.apk
|
|
|
f9a89bc3a761d2adf1d3d0c35f874f531a53c6ae8a58f46f9ce16d91f6bba17e 11.5a10-build2/2/tor-browser-11.5a10-android-x86_64-multi-qa.apk
|
|
|
```
|
|
|
|
|
|
### Step 1: Identify which files differ within the package, or if the archives themselves are a problem
|
|
|
|
|
|
We have seen [situations](https://gitlab.torproject.org/tpo/applications/tor-browser-build/-/issues/32360) where ZIP archives are created non-deterministically. Please amend this guide with additional steps regarding solving this issue.
|
|
|
|
|
|
Identifying non-matching elements within the apk is as simple as extracting the files within the apks (or aars) and comparing them.
|
|
|
|
|
|
```
|
|
|
$ cd 11.5a10-build2/1/
|
|
|
$ unzip -d unzipped/ tor-browser-11.5a10-android-x86_64-multi-qa.apk
|
|
|
$ sha256deep -r unzipped/ | sort -k2 | sed 's,'$PWD',,' > shadeep_1
|
|
|
$ cd ../2/
|
|
|
$ unzip -d unzipped/ tor-browser-11.5a10-android-x86_64-multi-qa.apk
|
|
|
$ sha256deep -r unzipped/ | sort -k2 | sed 's,'$PWD',,' > shadeep_2
|
|
|
$ cd ../
|
|
|
$ diff -u {1,2}/shadeep_*
|
|
|
```
|
|
|
|
|
|
The use of `$PWD` is important because `sha256deep` includes the absolute file path, therefore comparing two outputs of `sha256deep` will always differ. Replace `$PWD` with something different, if you prefer.
|
|
|
|
|
|
The output may look something like:
|
|
|
|
|
|
```diff
|
|
|
--- 1/shadeep_1 2022-05-02 15:15:18.442075338 +0000
|
|
|
+++ 2/shadeep_2 2022-05-02 15:14:51.673966668 +0000
|
|
|
@@ -4,7 +4,7 @@
|
|
|
e0e54836058309521d64bf23420109a79b30d26db7806301d47e384e3261d5d6 unzipped/assets/common/geoip
|
|
|
2b996bf4219f5d2e135646f9e7ee52744881bf0a86cb6b3c5716bab0ca777243 unzipped/assets/common/geoip6
|
|
|
caa24da47c90ed4a260ee260ecd1dab3f8937688e82ae0a3705703b38da43278 unzipped/assets/common/torrc
|
|
|
-21044ce99cecaf85f14df6e1ca1b417545dd6c6de132d850e136730b2486e2bb unzipped/assets/dexopt/baseline.prof
|
|
|
+d276b3cd973d1d8f4a4e8820e1fc2318617cf252b0398360a4a5cf872e0f966a unzipped/assets/dexopt/baseline.prof
|
|
|
7ff0eb4f2c678d574cc98f6a092f31997c122412586156a1ff4aebc9b76f7627 unzipped/assets/domains/br
|
|
|
aaf76feadadb0f30cb79dd6824a3ed107ebdac75ac629f0916d38887651ace0a unzipped/assets/domains/ca
|
|
|
3c271c89be6f722235e4a069460471c0bee3e118fc403e24a67525289837a1cc unzipped/assets/domains/de
|
|
|
@@ -498,8 +498,8 @@
|
|
|
79ebab7fe148390fc324f539a2a7c94b2ade9ba33fd1cf4914ff80fcc4c3dcd7 unzipped/assets/searchplugins/yandex.xml
|
|
|
7d8df6264700eae16233122cfcb7ccc83177ae986b9fa2fb522e5135875facda unzipped/assets/searchplugins/youtube.xml
|
|
|
8ca7bd3bd2ca30c8e65150ea52e1c00ef418021569ac73c7fb48ac2079ee1299 unzipped/assets/shared_error_style.css
|
|
|
-9482307b0493f1d23cdefc12ef95407009783e01da2cdb38830eef473a2ca0c0 unzipped/classes2.dex
|
|
|
-c5ac8bb4c65b16457edfcf419ebe1cdd5b0827a5de76d6601051157c4106c39e unzipped/classes.dex
|
|
|
+2f75bcb8f17bb3dca947bd31d915af14853463c52e2295b127f56b6c57db3c67 unzipped/classes2.dex
|
|
|
+dd015154d63458e9dd4c33e08527afb2c71e9fb187c3d96a6b8e54eb3216a55a unzipped/classes.dex
|
|
|
2607dd7a7379d775a8b8c011f0336576f57320617e9d6a5e152b52dbcdc9ddae unzipped/DebugProbesKt.bin
|
|
|
de8a46a4947a140783a4d714364f18ccf02c4759d6ab5ace9da0b1c058efa6c3 unzipped/fetch_msg_types.proto
|
|
|
cb93b54f651ad6fa439d8fc33c8e0be1a9b2085df88edc2f267c83f4cffd2f76 unzipped/firebase-common.properties
|
|
|
@@ -546,8 +546,8 @@
|
|
|
7235eb0271fce4f9ed5a0ba292ffd96d8f39544e04252506eb7bce942b455025 unzipped/lib/x86_64/libTor.so
|
|
|
3a3679477e6387ce4697f060b418abd7a75651536298cc4739e3f6b67cdf4c92 unzipped/lib/x86_64/libtun2socks.so
|
|
|
9275c113d024e228c64c1f76c77859dccc95e6ef2e27284281b102445dfe1af4 unzipped/lib/x86_64/libxul.so
|
|
|
-de1362710cfa78e494ba9c44e20189853c40772bb7bb46b1d47c653808706300 unzipped/META-INF/ANDROIDQ.RSA
|
|
|
-c6835103e1d43487024c6a91f8b6c08a5c00a3610d0446e529138a66497a6204 unzipped/META-INF/ANDROIDQ.SF
|
|
|
+f66a7d79c29372e31377167ab80fff478f073d81450ab02d4995a4e4db4538bf unzipped/META-INF/ANDROIDQ.RSA
|
|
|
+bf33447c243a91b8894c5f21dc726ddf6ebd405071b1e75455be06bbbb70a711 unzipped/META-INF/ANDROIDQ.SF
|
|
|
10e2e117b01523891ca271a615ae36e9d5e52348fd7d642f66727602c1b8dcbe unzipped/META-INF/androidx.activity_activity-compose.version
|
|
|
10e2e117b01523891ca271a615ae36e9d5e52348fd7d642f66727602c1b8dcbe unzipped/META-INF/androidx.activity_activity-ktx.version
|
|
|
10e2e117b01523891ca271a615ae36e9d5e52348fd7d642f66727602c1b8dcbe unzipped/META-INF/androidx.activity_activity.version
|
|
|
@@ -644,7 +644,7 @@
|
|
|
9927e4392d0216300aa135317885771db7cb72706f05e6a3c1e9ff63194b8cae unzipped/META-INF/androidx.work_work-runtime.version
|
|
|
dc7746e42e0df8aa5a24dd015e29f1f83917269955f6ece2b5fc214f42665e80 unzipped/META-INF/com/android/build/gradle/app-metadata.properties
|
|
|
6cf4e084b47f33c9b02ef79279d157833868f8f70514169a768be353ee328fea unzipped/META-INF/com.google.android.material_material.version
|
|
|
-b545636615c13c6054b96be0e20e8aba06993bf93c40fafc55bea7e379e375e7 unzipped/META-INF/MANIFEST.MF
|
|
|
+ffdd81b711c5612d22680d06327b3f49a209336b437459b2bf2a648dccc69fe3 unzipped/META-INF/MANIFEST.MF
|
|
|
3129b8edf6db07de6f8ff47695e2177c8bba4eed2962d3085c719e5acbb58a33 unzipped/META-INF/services/kotlinx.coroutines.CoroutineExceptionHandler
|
|
|
a1ea77ea8f93f419256b6e66f29713f950d8d6e90442b608d880a48003b5eb72 unzipped/META-INF/services/kotlinx.coroutines.internal.MainDispatcherFactory
|
|
|
9fedeef899f0315931e347f7e31db46e79a7b6dbc54d11e8eb51fe1b4607737e unzipped/META-INF/web-fragment.xml
|
|
|
```
|
|
|
|
|
|
We can initially ignore these files:
|
|
|
- `unzipped/assets/dexopt/baseline.prof`
|
|
|
- `unzipped/META-INF/ANDROIDQ.RSA`
|
|
|
- `unzipped/META-INF/ANDROIDQ.SF`
|
|
|
- `unzipped/META-INF/MANIFEST.MF`
|
|
|
|
|
|
We can ignore them because they are the result of other files - if all of the input files are identical, then these files should be identical. However, we can see that the following two files differ:
|
|
|
- `unzipped/classes2.dex`
|
|
|
- `unzipped/classes.dex`
|
|
|
|
|
|
Therefore, we start our investigation with those. If none of the other files differ, then begin looking closer at the content and file formats of the differing files - possibly using `xxd` or `hexdump`.
|
|
|
|
|
|
`.dex` files are Android's byte code object files. `apktool` provides a way to "decompile" these into a more readable format.
|
|
|
|
|
|
```
|
|
|
$ cd 11.5a10-build2/1/
|
|
|
$ mkdir decompiled
|
|
|
$ cd decompiled
|
|
|
$ apktool d ../tor-browser-11.5a10-android-x86_64-multi-qa.apk
|
|
|
$ cd ..
|
|
|
$ sha256deep -r decompiled | sort -k2 | sed 's,'${PWD}',,' > shadeep_decompiled_1
|
|
|
$ cd ../2/
|
|
|
$ mkdir decompiled
|
|
|
$ cd decompiled
|
|
|
$ apktool d ../tor-browser-11.5a10-android-x86_64-multi-qa.apk
|
|
|
$ cd ..
|
|
|
$ sha256deep -r decompiled | sort -k2 | sed 's,'${PWD}',,' > shadeep_decompiled_2
|
|
|
$ cd ../
|
|
|
$ diff -u {1,2}/shadeep_decompiled_* | less
|
|
|
```
|
|
|
|
|
|
|
|
|
The output may look something like:
|
|
|
|
|
|
```diff
|
|
|
--- 1/shadeep_decompiled_1 2022-05-02 15:36:24.675602448 +0000
|
|
|
+++ 2/shadeep_decompiled_2 2022-05-02 15:36:38.955664737 +0000
|
|
|
@@ -5,7 +5,7 @@
|
|
|
e0e54836058309521d64bf23420109a79b30d26db7806301d47e384e3261d5d6 decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/assets/common/geoip
|
|
|
2b996bf4219f5d2e135646f9e7ee52744881bf0a86cb6b3c5716bab0ca777243 decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/assets/common/geoip6
|
|
|
caa24da47c90ed4a260ee260ecd1dab3f8937688e82ae0a3705703b38da43278 decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/assets/common/torrc
|
|
|
-21044ce99cecaf85f14df6e1ca1b417545dd6c6de132d850e136730b2486e2bb decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/assets/dexopt/baseline.prof
|
|
|
+d276b3cd973d1d8f4a4e8820e1fc2318617cf252b0398360a4a5cf872e0f966a decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/assets/dexopt/baseline.prof
|
|
|
7ff0eb4f2c678d574cc98f6a092f31997c122412586156a1ff4aebc9b76f7627 decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/assets/domains/br
|
|
|
aaf76feadadb0f30cb79dd6824a3ed107ebdac75ac629f0916d38887651ace0a decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/assets/domains/ca
|
|
|
3c271c89be6f722235e4a069460471c0bee3e118fc403e24a67525289837a1cc decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/assets/domains/de
|
|
|
@@ -525,8 +525,8 @@
|
|
|
3a3679477e6387ce4697f060b418abd7a75651536298cc4739e3f6b67cdf4c92 decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/lib/x86_64/libtun2socks.so
|
|
|
9275c113d024e228c64c1f76c77859dccc95e6ef2e27284281b102445dfe1af4 decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/lib/x86_64/libxul.so
|
|
|
66e3a31f9a4eaf59bc3f47361ce68075a317032cbd81d9b38ee73849073572cc decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/original/AndroidManifest.xml
|
|
|
-de1362710cfa78e494ba9c44e20189853c40772bb7bb46b1d47c653808706300 decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/original/META-INF/ANDROIDQ.RSA
|
|
|
-c6835103e1d43487024c6a91f8b6c08a5c00a3610d0446e529138a66497a6204 decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/original/META-INF/ANDROIDQ.SF
|
|
|
+f66a7d79c29372e31377167ab80fff478f073d81450ab02d4995a4e4db4538bf decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/original/META-INF/ANDROIDQ.RSA
|
|
|
+bf33447c243a91b8894c5f21dc726ddf6ebd405071b1e75455be06bbbb70a711 decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/original/META-INF/ANDROIDQ.SF
|
|
|
10e2e117b01523891ca271a615ae36e9d5e52348fd7d642f66727602c1b8dcbe decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/original/META-INF/androidx.activity_activity-compose.version
|
|
|
10e2e117b01523891ca271a615ae36e9d5e52348fd7d642f66727602c1b8dcbe decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/original/META-INF/androidx.activity_activity-ktx.version
|
|
|
10e2e117b01523891ca271a615ae36e9d5e52348fd7d642f66727602c1b8dcbe decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/original/META-INF/androidx.activity_activity.version
|
|
|
@@ -623,7 +623,7 @@
|
|
|
9927e4392d0216300aa135317885771db7cb72706f05e6a3c1e9ff63194b8cae decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/original/META-INF/androidx.work_work-runtime.version
|
|
|
dc7746e42e0df8aa5a24dd015e29f1f83917269955f6ece2b5fc214f42665e80 decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/original/META-INF/com/android/build/gradle/app-metadata.properties
|
|
|
6cf4e084b47f33c9b02ef79279d157833868f8f70514169a768be353ee328fea decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/original/META-INF/com.google.android.material_material.version
|
|
|
-b545636615c13c6054b96be0e20e8aba06993bf93c40fafc55bea7e379e375e7 decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/original/META-INF/MANIFEST.MF
|
|
|
+ffdd81b711c5612d22680d06327b3f49a209336b437459b2bf2a648dccc69fe3 decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/original/META-INF/MANIFEST.MF
|
|
|
3129b8edf6db07de6f8ff47695e2177c8bba4eed2962d3085c719e5acbb58a33 decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/original/META-INF/services/kotlinx.coroutines.CoroutineExceptionHandler
|
|
|
a1ea77ea8f93f419256b6e66f29713f950d8d6e90442b608d880a48003b5eb72 decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/original/META-INF/services/kotlinx.coroutines.internal.MainDispatcherFactory
|
|
|
9fedeef899f0315931e347f7e31db46e79a7b6dbc54d11e8eb51fe1b4607737e decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/original/META-INF/web-fragment.xml
|
|
|
@@ -8672,7 +8672,7 @@
|
|
|
203929ab67ac3826f354854164d827c8c0c816e621f52108b33dcd1f0e62f102 decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/GleanMetrics/FirstSession$network$2.smali
|
|
|
a955bdc6100533a707e9a55823295604f716cceccf48a41d4cb0336dbb7a7ba1 decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/GleanMetrics/FirstSession$timestamp$2.smali
|
|
|
802f11e155681762f90992b04275417c7057a7be57227ffeb6ccd0129b653ddc decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/GleanMetrics/FirstSession.smali
|
|
|
-9b00af95629a64bf398501db0b3146ebd5191496eb55cf32c1e86b0b8cfaabcf decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/GleanMetrics/GleanBuildInfo$buildInfo$2.smali
|
|
|
+3cd3fc68eec2a6bf90fb090c77a06f7aa5e5a8bbf2a274de4ae74007d0a772be decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/GleanMetrics/GleanBuildInfo$buildInfo$2.smali
|
|
|
bad700b1d7c12097706c7a8c649d1a719418e8db978e6b31de23d4da5593b789 decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/GleanMetrics/GleanBuildInfo.smali
|
|
|
5a974cfddef6769d65754ae065658e8bea8df4090cd53896f0cb037f1758b873 decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/GleanMetrics/History$opened$2.smali
|
|
|
06ddd723c7804b32c50c8dc6e85036d3b06ca0e9662305e6282099b9cbe0b06b decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/GleanMetrics/History$openedItem$2.smali
|
|
|
@@ -9890,18 +9890,18 @@
|
|
|
9015d873e250597b9e968842a9abbca3a63d6bcd95cd5b05df9d46d1641be659 decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/nimbus/FxNimbus$Features$searchTermGroups$2$1.smali
|
|
|
8ff8e168e640033614d9aaf194b15bc3e3ff6c113892efbe17974acb685873e7 decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/nimbus/FxNimbus$Features$searchTermGroups$2$2.smali
|
|
|
c78b1619d900927fbf2acb0bc5dcd48ae54e5b9dc2226f40cab442a34a3508a0 decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/nimbus/FxNimbus$Features$searchTermGroups$2.smali
|
|
|
-e2660c15fe12e7d1124c1e48fd02226e967576a54a48b13efc284b4def887ccc decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/nimbus/FxNimbus$Features.smali
|
|
|
+5e3c91e1cb18eca37718a614a177176473ff5e3fe5cc5da1a068fcee1ba18410 decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/nimbus/FxNimbus$Features.smali
|
|
|
065197da383561647a4345efb3325bd4953a00749b349977236f027faab654b2 decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/nimbus/FxNimbus.smali
|
|
|
9df0da9779e0cdb2e9d73bd80a7fb5dbb5983b4e0a3402b917a973a0ee085275 decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/nimbus/Homescreen$Defaults.smali
|
|
|
8ed74647e36a0098a7dd6e901d21708a7fcc65708e3acdf7caf0eb2fd9201467 decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/nimbus/Homescreen$sectionsEnabled$2$1.smali
|
|
|
f16deaa4bddff504a6a34462dc750aa699f311deff32fca349758813a9c2c7da decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/nimbus/Homescreen$sectionsEnabled$2.smali
|
|
|
-af75f79c47fb91a5400d80230e9147a0cd19b4db7ca039bcfc53870b81936b1c decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/nimbus/HomeScreenSection$Companion$enumMap$2.smali
|
|
|
+dbd9c0b9c19d907f995913d284bc37e621fd9e6e7cf2175a01d27f6ac6f491e3 decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/nimbus/HomeScreenSection$Companion$enumMap$2.smali
|
|
|
eb8e5786291e833787c5dc8f2fa719dcd6536fe8d87c45e59c1691fc82c38c11 decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/nimbus/HomeScreenSection$Companion.smali
|
|
|
-a2458e02be1cbcd50b9de769b9942438bbf4094cc05c4a70b389684633535064 decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/nimbus/HomeScreenSection.smali
|
|
|
+3d657873f7c8006d363ab34a793e1ae1e3fc9f2c4a3a38a2a3d2755480541acb decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/nimbus/HomeScreenSection.smali
|
|
|
a5996da3f93ad541d3f760e5fe7f2986347bae3fd64d6bf8bea99395f5b6e54f decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/nimbus/Homescreen.smali
|
|
|
-35fce72715d6da6e0f22b2f1093e50a4a82020b394248bbd99f95be29a307392 decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/nimbus/MessageSurfaceId$Companion$enumMap$2.smali
|
|
|
+91fe9d69e11d4970b17036043ca4155a311bdeeee4b7b9cfa416c3abbdf9b334 decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/nimbus/MessageSurfaceId$Companion$enumMap$2.smali
|
|
|
062b51cc6872a74a59be72df185cafe66a91e80b61cb64009508e2236ebbfe08 decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/nimbus/MessageSurfaceId$Companion.smali
|
|
|
-3624caf105bff17a901ec5060f78dc93327a1a8239530773fdb37d9de6370d4e decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/nimbus/MessageSurfaceId.smali
|
|
|
+c617067b3fea0e03e2175b469d73eb23f254abd0012152fc42f5478cabe2f92a decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/nimbus/MessageSurfaceId.smali
|
|
|
c39b8396a6c86af64728f8f4aff2e36a3a7085f86859288a32b716e6d9d4fde8 decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/nimbus/NimbusBranchesAction$UpdateBranches.smali
|
|
|
9a20dd1e2188264af2788249129f7cd5a4fc122c4e97889180329a4e1af4057c decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/nimbus/NimbusBranchesAction$UpdateSelectedBranch.smali
|
|
|
6f0808ef47a13fa97628978a28a5d664678f79ea7faccc0cabbf1ac6b9aca8eb decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/nimbus/NimbusBranchesAction$UpdateUnselectBranch.smali
|
|
|
```
|
|
|
|
|
|
Again, we can ignore `baseline.prof`, `ANDROIDQ*`, and `MANIFEST.MF`. Now we see specific source code files that differ:
|
|
|
- `decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/GleanMetrics/GleanBuildInfo$buildInfo$2.smali`
|
|
|
- `decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/nimbus/FxNimbus$Features.smali`
|
|
|
- `decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/nimbus/HomeScreenSection$Companion$enumMap$2.smali`
|
|
|
- `decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/nimbus/HomeScreenSection$Companion.smali`
|
|
|
- `decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/nimbus/MessageSurfaceId.smali`
|
|
|
|
|
|
Note, `smali` is the decompiled format.
|
|
|
|
|
|
### Step 2: Identify how the files differ
|
|
|
|
|
|
This is the easiest part, when dealing with decompiled Kotlin/Java Smali files: We simply diff the files.
|
|
|
|
|
|
```diff
|
|
|
--- 1/decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/nimbus/MessageSurfaceId.smali 2022-05-02 15:30:08.077958257 +0000
|
|
|
+++ 2/decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/nimbus/MessageSurfaceId.smali 2022-05-02 15:30:33.050067369 +0000
|
|
|
@@ -50,13 +50,13 @@
|
|
|
.line 1
|
|
|
new-instance v0, Lorg/mozilla/fenix/nimbus/MessageSurfaceId;
|
|
|
|
|
|
- const-string v1, "HOMESCREEN_BANNER"
|
|
|
+ const-string v1, "APP_MENU_ITEM"
|
|
|
|
|
|
const/4 v2, 0x0
|
|
|
|
|
|
invoke-direct {v0, v1, v2}, Lorg/mozilla/fenix/nimbus/MessageSurfaceId;-><init>(Ljava/lang/String;I)V
|
|
|
|
|
|
- sput-object v0, Lorg/mozilla/fenix/nimbus/MessageSurfaceId;->HOMESCREEN_BANNER:Lorg/mozilla/fenix/nimbus/MessageSurfaceId;
|
|
|
+ sput-object v0, Lorg/mozilla/fenix/nimbus/MessageSurfaceId;->APP_MENU_ITEM:Lorg/mozilla/fenix/nimbus/MessageSurfaceId;
|
|
|
|
|
|
.line 2
|
|
|
new-instance v1, Lorg/mozilla/fenix/nimbus/MessageSurfaceId;
|
|
|
@@ -72,13 +72,13 @@
|
|
|
.line 3
|
|
|
new-instance v3, Lorg/mozilla/fenix/nimbus/MessageSurfaceId;
|
|
|
|
|
|
- const-string v5, "APP_MENU_ITEM"
|
|
|
+ const-string v5, "HOMESCREEN_BANNER"
|
|
|
|
|
|
const/4 v6, 0x2
|
|
|
|
|
|
invoke-direct {v3, v5, v6}, Lorg/mozilla/fenix/nimbus/MessageSurfaceId;-><init>(Ljava/lang/String;I)V
|
|
|
|
|
|
- sput-object v3, Lorg/mozilla/fenix/nimbus/MessageSurfaceId;->APP_MENU_ITEM:Lorg/mozilla/fenix/nimbus/MessageSurfaceId;
|
|
|
+ sput-object v3, Lorg/mozilla/fenix/nimbus/MessageSurfaceId;->HOMESCREEN_BANNER:Lorg/mozilla/fenix/nimbus/MessageSurfaceId;
|
|
|
|
|
|
const/4 v5, 0x3
|
|
|
```
|
|
|
|
|
|
While not immediately obvious, looking at this diff we see that the content is identical, but the location within the files of the content is different. For example, `HOMESCREEN_BANNER` is on line 53 in one file, but on line 75 in another file.
|
|
|
|
|
|
### Step 3: Identify why the files differ
|
|
|
The two most common reasons for differences are:
|
|
|
- embedded timestamps
|
|
|
- non-deterministic code generation
|
|
|
|
|
|
#34015, #21960, tor-browser-build#40084, tor-browser-build#40085
|
|
|
|
|
|
`11.5a10-build2` was non-deterministic due to *both* of these issues in two different components. Looking at the smali files that don't match, we see two groupings: Nimbus and Glean. Nimbus is part of [applications-services](https://github.com/mozilla/application-services.git) and [Glean](https://github.com/mozilla/glean.git) is a standalone project. However, the situation is even more complicated than it seems.
|
|
|
|
|
|
|
|
|
#### Nimbus Investigation
|
|
|
|
|
|
Let's start with Nimbus. As above, we have these four files:
|
|
|
|
|
|
- `decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/nimbus/FxNimbus$Features.smali`
|
|
|
- `decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/nimbus/HomeScreenSection$Companion$enumMap$2.smali`
|
|
|
- `decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/nimbus/HomeScreenSection$Companion.smali`
|
|
|
- `decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/nimbus/MessageSurfaceId.smali`
|
|
|
|
|
|
There are two key observations here:
|
|
|
1. If you diff each of these files, you see that they all have the same content, but they are in a different order. This likely means the code is generated somehow.
|
|
|
2. That these files are in the `org.mozilla.fenix.nimbus` namespace, this means that we need to look in Fenix for more information about them - they are not in the Numbus repository. If you don't where you can find these files, then `git grep` is your friend, but you must keep in mind that if these files are actually generated code then you may not find any files in the fenix repository matching these class names. Therefore, you may need to be creative when searching for the source of these files: try different name mangling techniques. For example, if we look for `HomeScreenSection`, try searching for:
|
|
|
- `HomeScreenSection`
|
|
|
- `homeScreenSection`
|
|
|
- `Home-Screen-Section`
|
|
|
- `Home-screen-section`
|
|
|
- `Home_Screen_Section`
|
|
|
- `home_screen_section`
|
|
|
|
|
|
Using case insensitive search (`git grep -i`) helps, too. In this case, the class name was not mangled:
|
|
|
|
|
|
```
|
|
|
$ git grep -in HomeScreenSection
|
|
|
app/src/main/java/org/mozilla/fenix/utils/Settings.kt:44:import org.mozilla.fenix.nimbus.HomeScreenSection
|
|
|
app/src/main/java/org/mozilla/fenix/utils/Settings.kt:135: // default = { homescreenSections[HomeScreenSection.TOP_SITES] == true },
|
|
|
app/src/main/java/org/mozilla/fenix/utils/Settings.kt:1277: // private val homescreenSections: Map<HomeScreenSection, Boolean> by lazy {
|
|
|
app/src/main/java/org/mozilla/fenix/utils/Settings.kt:1284: // default = { homescreenSections[HomeScreenSection.RECENT_EXPLORATIONS] == true },
|
|
|
app/src/main/java/org/mozilla/fenix/utils/Settings.kt:1296: // default = { homescreenSections[HomeScreenSection.JUMP_BACK_IN] == true },
|
|
|
app/src/main/java/org/mozilla/fenix/utils/Settings.kt:1306: // default = { homescreenSections[HomeScreenSection.RECENTLY_SAVED] == true },
|
|
|
app/src/main/java/org/mozilla/fenix/utils/Settings.kt:1339: // default = { homescreenSections[HomeScreenSection.POCKET] == true },
|
|
|
app/src/main/java/org/mozilla/fenix/utils/Settings.kt:1348: // default = { homescreenSections[HomeScreenSection.CONTILE_TOP_SITES] == true },
|
|
|
nimbus.fml.yaml:14: type: Map<HomeScreenSection, Boolean>
|
|
|
nimbus.fml.yaml:76: HomeScreenSection:
|
|
|
```
|
|
|
|
|
|
`nimbus.fml.yaml` seems like it is the important file here. Indeed, that is the file that declares the `HomeScreenSection` type. Next, find how this file is consumed:
|
|
|
|
|
|
```
|
|
|
$ git grep -n nimbus.fml.yaml
|
|
|
app/build.gradle:423: manifestFile = "nimbus.fml.yaml"
|
|
|
```
|
|
|
|
|
|
We see it is consumed within `app/build.gradle` and there appears to be a gradle plugin for this: `org.mozilla.components.nimbus-gradle-plugin`
|
|
|
|
|
|
Find the source code for this is not always trivial and may require some searching on your favorite search engine and asking Mozilla folks. In this case, we can find the source code in the `application-services` repo under [components/support/nimbus-fml/](https://github.com/mozilla/application-services/tree/main/components/support/nimbus-fml). The most important observation that you should remember while you look through this code, is that you are looking at code-generating code. In particular, this means that you must look for how data is input into this code/program, and how the result is output from it. From past experience, we know that choice of data structure plays a significant role in deterministic results, therefore look for code that parses data and store it in non-deterministic data structures, such as rust's `HashMap`. For example, in `nimbus-fml` we see the use of `HashMap` in its [parser.rs](https://github.com/mozilla/application-services/blob/bf2bce239ab13e9216e6f5190d2bb2c3771f6049/components/support/nimbus-fml/src/parser.rs#L27).
|
|
|
|
|
|
In #40420 we found that `BTreeMap` is a reasonable deterministic replacement for `HashMap`. Next, walk through the parsing and code generation logic and replace instances of `HashMap` with `BTreeMap` where iterating over the data structure may cause different ordering between the input file and output file. Create a patch and test it in tor-browser-build:
|
|
|
|
|
|
1. Copy the patch into the correct project (e.g., `fenix`), let's call it `bugXXXXX.patch`
|
|
|
1. Add the patch file as an input file of the project
|
|
|
1. `- filename: bugXXXXX.patch`
|
|
|
1. Apply the patch in `build`, likely close to where the compile/build command is executed
|
|
|
1. `patch -p1 < $rootdir/bugXXXXX.patch`
|
|
|
|
|
|
If it compiles, then backup the results and run the build again: compare the resulting packages and investigate further if differences remain.
|
|
|
|
|
|
#### Glean Investigation
|
|
|
|
|
|
Glean is a little trickier because it is a dependency at multiple layers of the architecture and because we don't build it ourselves.
|
|
|
|
|
|
- `decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/GleanMetrics/GleanBuildInfo$buildInfo$2.smali`
|
|
|
|
|
|
Again, we see that this file lives in the `org.mozilla.fenix` namespace, but the diff is not in the line ordering.
|
|
|
|
|
|
```diff
|
|
|
$ diff -u {1,2}/'decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/GleanMetrics/GleanBuildInfo$buildInfo$2.smali'
|
|
|
--- 1/decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/GleanMetrics/GleanBuildInfo$buildInfo$2.smali 2022-05-05 20:34:36.846589039 +0000
|
|
|
+++ 2/decompiled/tor-browser-11.5a10-android-x86_64-multi-qa/smali_classes2/org/mozilla/fenix/GleanMetrics/GleanBuildInfo$buildInfo$2.smali 2022-05-05 20:34:19.698514703 +0000
|
|
|
@@ -88,13 +88,13 @@
|
|
|
|
|
|
const/4 v3, 0x4
|
|
|
|
|
|
- const/4 v4, 0x2
|
|
|
+ const/4 v4, 0x3
|
|
|
|
|
|
- const/16 v5, 0x15
|
|
|
+ const/16 v5, 0x10
|
|
|
|
|
|
- const/16 v6, 0x20
|
|
|
+ const/16 v6, 0x2f
|
|
|
|
|
|
- const/16 v7, 0x14
|
|
|
+ const/16 v7, 0x9
|
|
|
|
|
|
move-object v1, v0
|
|
|
```
|
|
|
|
|
|
These look like numbers - they could be a checksum or a date or something else. If we look closer at the smali, for context, we see:
|
|
|
|
|
|
```
|
|
|
.method public final invoke()Lmozilla/telemetry/glean/BuildInfo;
|
|
|
.locals 8
|
|
|
|
|
|
const-string v0, "GMT+0"
|
|
|
|
|
|
.line 2
|
|
|
invoke-static {v0}, Ljava/util/TimeZone;->getTimeZone(Ljava/lang/String;)Ljava/util/TimeZone;
|
|
|
|
|
|
move-result-object v0
|
|
|
|
|
|
invoke-static {v0}, Ljava/util/Calendar;->getInstance(Ljava/util/TimeZone;)Ljava/util/Calendar;
|
|
|
|
|
|
move-result-object v0
|
|
|
|
|
|
const/16 v2, 0x7e6
|
|
|
|
|
|
const/4 v3, 0x4
|
|
|
|
|
|
const/4 v4, 0x3
|
|
|
|
|
|
const/16 v5, 0x10
|
|
|
|
|
|
const/16 v6, 0x2f
|
|
|
|
|
|
const/16 v7, 0x9
|
|
|
|
|
|
move-object v1, v0
|
|
|
```
|
|
|
|
|
|
This looks like a timestamp issue created a build time. Next, knowing Glean, as we do, we know that the code generation portion of Glean is contained in a separate repository: [glean_parser](https://github.com/mozilla/glean_parser). Searching that repo for `BuildInfo` reveals:
|
|
|
|
|
|
```
|
|
|
$ git grep -n BuildInfo
|
|
|
CHANGELOG.md:74:- For Kotlin skip generating `GleanBuildInfo.kt` when requested (with `with_buildinfo=false`) ([#341](https://github.com/mozilla/glean_parser/pull/341))
|
|
|
glean_parser/kotlin.py:272: - `with_buildinfo`: If "true" a `GleanBuildInfo.kt` file is generated.
|
|
|
glean_parser/kotlin.py:299: with (output_dir / "GleanBuildInfo.kt").open("w", encoding="utf-8") as fd:
|
|
|
glean_parser/swift.py:137:class BuildInfo:
|
|
|
glean_parser/swift.py:187: - with_buildinfo: If "true" the `GleanBuildInfo` is generated.
|
|
|
glean_parser/swift.py:217: build_info = BuildInfo(build_date=build_date)
|
|
|
glean_parser/templates/kotlin.buildinfo.jinja2:19:import {{ glean_namespace }}.BuildInfo
|
|
|
glean_parser/templates/kotlin.buildinfo.jinja2:23:internal object GleanBuildInfo {
|
|
|
glean_parser/templates/kotlin.buildinfo.jinja2:24: val buildInfo: BuildInfo by lazy {
|
|
|
glean_parser/templates/kotlin.buildinfo.jinja2:25: BuildInfo(
|
|
|
glean_parser/templates/swift.jinja2:69: public static let info = BuildInfo(buildDate: {{ build_info.build_date }})
|
|
|
tests/test_cli.py:53: "GleanBuildInfo.kt",
|
|
|
tests/test_cli.py:120: path = Path(str(tmpdir)) / "GleanBuildInfo.kt"
|
|
|
tests/test_cli.py:148: path = Path(str(tmpdir)) / "GleanBuildInfo.kt"
|
|
|
tests/test_kotlin.py:72: "GleanBuildInfo.kt",
|
|
|
tests/test_kotlin.py:91: with (tmpdir / "GleanBuildInfo.kt").open("r", encoding="utf-8") as fd:
|
|
|
tests/test_kotlin.py:128: ["Pings.kt", "GleanBuildInfo.kt"]
|
|
|
tests/test_kotlin.py:225: ["Category.kt", "GleanBuildInfo.kt"]
|
|
|
tests/test_kotlin.py:252: ["Category.kt", "GleanBuildInfo.kt"]
|
|
|
tests/test_kotlin.py:277: "GleanBuildInfo.kt",
|
|
|
tests/test_kotlin.py:374: ["Event.kt", "GleanBuildInfo.kt"]
|
|
|
tests/test_kotlin.py:401: ["Event.kt", "GleanBuildInfo.kt"]
|
|
|
tests/test_kotlin.py:426: ["Core.kt", "GleanBuildInfo.kt"]
|
|
|
tests/test_swift.py:53: assert "BuildInfo(buildDate:" in content
|
|
|
tests/test_swift.py:100: assert "BuildInfo(buildDate:" in content
|
|
|
```
|
|
|
|
|
|
`glean_parser/templates/kotlin.buildinfo.jinja2` seems to be the definition (e.g., `internal object GleanBuildInfo {`). Indeed, we can see [buildDate = {{ build_date }}](https://github.com/mozilla/glean_parser/blob/main/glean_parser/templates/kotlin.buildinfo.jinja2#L28), next we find where that is created. We can take at least two routes:
|
|
|
|
|
|
1. search for it and try walking the code paths leading here
|
|
|
1. find the patch(set) that introduced this line and work forward from there
|
|
|
|
|
|
We already discussed the first option earlier, so let's try the second option. We can try using `git blame` to identify the commit that introduced this line, but that won't always be successful because there may have been subsequent modifications of that line - but feel free to follow that path if you feel comfortable with it.
|
|
|
|
|
|
Here, we'll start with `git log -G`:
|
|
|
|
|
|
```
|
|
|
$ git log -Gbuild_date glean_parser/templates/kotlin.buildinfo.jinja2
|
|
|
commit 9dd0bdde691d0550973515fb1765f65714fbbcbb
|
|
|
Author: Jan-Erik Rediger <jrediger@mozilla.com>
|
|
|
Date: Mon Jan 3 15:17:54 2022 +0100
|
|
|
|
|
|
Generate build date at invocation time
|
|
|
```
|
|
|
|
|
|
This shows us all of the commits that contained `build_date` in the template file. In this case, there was only one commit - so `git blame` would've worked just as well.
|
|
|
|
|
|
At this point, read through the commit and understand how the timestamp is generated and investigate paths to providing or injecting your own timestamp. In this specific case Mozilla explicitly gives us a solution to this problem:
|
|
|
|
|
|
```diff
|
|
|
--- a/CHANGELOG.md
|
|
|
+++ b/CHANGELOG.md
|
|
|
@@ -4,6 +4,16 @@
|
|
|
|
|
|
- Support global file-level tags in metrics.yaml ([bug 1745283](https://bugzilla.mozilla.org/show_bug.cgi?id=1745283))
|
|
|
- Glinter: Reject metric files if they use `unit` by mistake. It should be `time_unit` ([#432](https://github.com/mozilla/glean_parser/pull/432)).
|
|
|
+- Automatically generate a build date when generating build info ([#431](https://github.com/mozilla/glean_parser/pull/431)).
|
|
|
+ Enabled for Kotlin and Swift.
|
|
|
+ This can be changed with the `build_date` command line option.
|
|
|
+ `build_date=0` will use a static unix epoch time.
|
|
|
+ `build_date=2022-01-03T17:30:00` will parse the ISO8601 string to use (as a UTC timestamp).
|
|
|
+ Other values will throw an error.
|
|
|
+
|
|
|
+ Example:
|
|
|
+
|
|
|
+ glean_parser translate --format kotlin --option build_date=2021-11-01T01:00:00 path/to/metrics.yaml
|
|
|
```
|
|
|
|
|
|
Next, we must find how we can use this information. This may take some bruteforce searching: search for `build_date` in all of the projects that consume/use/depend on `glean_parser`. Here we see that `glean` uses `build_date` in some way:
|
|
|
|
|
|
```
|
|
|
$ git grep -n build_date
|
|
|
docs/user/user/pings/index.md:140:#### `build_date` _(optional)_
|
|
|
glean-core/ios/sdk_generator.sh:98: BUILD_DATE="--option build_date=$2"
|
|
|
glean-core/metrics.yaml:202: build_date:
|
|
|
glean.1.schema.json:36: "build_date": {
|
|
|
gradle-plugin/src/main/groovy/mozilla/telemetry/glean-gradle-plugin/GleanGradlePlugin.groovy:222: args "build_date=${project.ext.get("gleanBuildDate")}"
|
|
|
samples/android/app/src/androidTest/java/org/mozilla/samples/gleancore/pings/BaselinePingTest.kt:51: var buildDate = clientInfo.getString("build_date")
|
|
|
samples/android/app/src/androidTest/java/org/mozilla/samples/gleancore/pings/BaselinePingTest.kt:67: buildDate = clientInfo.getString("build_date")
|
|
|
samples/ios/app/glean-sample-appUITests/BaselinePingTest.swift:70: var buildDate = clientInfo["build_date"] as! String
|
|
|
samples/ios/app/glean-sample-appUITests/BaselinePingTest.swift:91: buildDate = clientInfo["build_date"] as! String
|
|
|
samples/ios/app/glean-sample-appUITests/BaselinePingTest.swift:127: buildDate = clientInfo["build_date"] as! String
|
|
|
```
|
|
|
|
|
|
`gradle-plugin` seems interesting and relevant because that is the package that `fenix` depends on (in `app/build.gradle`: `apply plugin: "org.mozilla.telemetry.glean-gradle-plugin"`). Looking at [gradle-plugin/src/main/groovy/mozilla/telemetry/glean-gradle-plugin/GleanGradlePlugin.groovy](https://github.com/mozilla/glean/blob/b213cdd168b6d7b559eaf7a65fc573062482e239/gradle-plugin/src/main/groovy/mozilla/telemetry/glean-gradle-plugin/GleanGradlePlugin.groovy#L219) :
|
|
|
|
|
|
```
|
|
|
// For applications check if they overwrote the build date.
|
|
|
if (project.ext.has("gleanBuildDate")) {
|
|
|
args "-s"
|
|
|
args "build_date=${project.ext.get("gleanBuildDate")}"
|
|
|
}
|
|
|
}
|
|
|
```
|
|
|
|
|
|
A new hint: `gleanBuildDate`!
|
|
|
|
|
|
```
|
|
|
$ git grep -n gleanBuildDate
|
|
|
docs/user/language-bindings/android/android-build-configuration-options.md:8:## `gleanBuildDate`
|
|
|
docs/user/language-bindings/android/android-build-configuration-options.md:18:ext.gleanBuildDate = "2022-01-03T17:30:00"
|
|
|
gradle-plugin/src/main/groovy/mozilla/telemetry/glean-gradle-plugin/GleanGradlePlugin.groovy:220: if (project.ext.has("gleanBuildDate")) {
|
|
|
gradle-plugin/src/main/groovy/mozilla/telemetry/glean-gradle-plugin/GleanGradlePlugin.groovy:222: args "build_date=${project.ext.get("gleanBuildDate")}"
|
|
|
samples/android/app/build.gradle:61:ext.gleanBuildDate = "2020-11-06T11:30:50+00:00"
|
|
|
```
|
|
|
|
|
|
Finally, in `glean`'s [sample app](https://github.com/mozilla/glean/blob/b213cdd168b6d7b559eaf7a65fc573062482e239/samples/android/app/build.gradle#L61) we see how they inject this in a `build.gradle`:
|
|
|
|
|
|
```
|
|
|
// Fixed build date so we can test for it
|
|
|
ext.gleanBuildDate = "2020-11-06T11:30:50+00:00"
|
|
|
```
|
|
|
|
|
|
Now, we can add something like this in `fenix`'s `build.gradle` and try resolving the issue. |
|
|
\ No newline at end of file |