Config.kt 7.29 KB
Newer Older
1
import org.gradle.api.Project
2
import java.lang.RuntimeException
3

4
import java.text.SimpleDateFormat
Jeff Boek's avatar
Jeff Boek committed
5
6
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
7
8
9
10
11
12
13
14
15
import java.util.Date
import java.util.Locale

/* 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 http://mozilla.org/MPL/2.0/. */

object Config {
    // Synchronized build configuration for all modules
16
    const val compileSdkVersion = 29
17
    const val minSdkVersion = 21
18
    const val targetSdkVersion = 29
19
20

    @JvmStatic
21
    private fun generateDebugVersionName(): String {
22
23
24
25
26
        val today = Date()
        // Append the year (2 digits) and week in year (2 digits). This will make it easier to distinguish versions and
        // identify ancient versions when debugging issues. However this will still keep the same version number during
        // the week so that we do not end up with a lot of versions in tools like Sentry. As an extra this matches the
        // sections we use in the changelog (weeks).
27
28
29
30
31
        return SimpleDateFormat("1.0.yyww", Locale.US).format(today)
    }

    @JvmStatic
    fun releaseVersionName(project: Project): String {
32
33
34
35
        // Note: release builds must have the `versionName` set. However, the gradle ecosystem makes this hard to
        // ergonomically validate (sometimes IDEs default to a release variant and mysteriously fail due to the
        // validation, sometimes devs just need a release build and specifying project properties is annoying in IDEs),
        // so instead we'll allow the `versionName` to silently default to an empty string.
36
        return if (project.hasProperty("versionName")) project.property("versionName") as String else ""
37
    }
Jeff Boek's avatar
Jeff Boek committed
38
39
40

    @JvmStatic
    fun generateBuildDate(): String {
Georg Koppen's avatar
Georg Koppen committed
41
42
43
44
45
46
47
48
        val dateTime = if (System.getenv("MOZ_BUILD_DATE") != null) {
          // Converting our MOZ_BUILD_DATE to LocalDateTime
          val format = SimpleDateFormat("yyyyMMddHHmmss", Locale.US)
          val date = format.parse(System.getenv("MOZ_BUILD_DATE"))
          java.sql.Timestamp(date.getTime()).toLocalDateTime()
        } else {
          LocalDateTime.now()
        }
Jeff Boek's avatar
Jeff Boek committed
49
50
51
52
        val timeFormatter = DateTimeFormatter.ofPattern("h:mm a")

        return "${dateTime.dayOfWeek.toString().toLowerCase().capitalize()} ${dateTime.monthValue}/${dateTime.dayOfMonth} @ ${timeFormatter.format(dateTime)}"
    }
53
54

    private val fennecBaseVersionCode by lazy {
55
56
        val format = SimpleDateFormat("yyyyMMddHHmmss", Locale.US)
        val cutoff = format.parse("20141228000000")
Georg Koppen's avatar
Georg Koppen committed
57
        val build = if (System.getenv("MOZ_BUILD_DATE") != null) format.parse(System.getenv("MOZ_BUILD_DATE")) else Date()
58
59
60
61
62
63

        Math.floor((build.time - cutoff.time) / (1000.0 * 60.0 * 60.0)).toInt()
    }

    /**
     * Generates a versionCode that follows the same rules like legacy Fennec builds.
64
65
     * Adapted from:
     * https://searchfox.org/mozilla-central/rev/34cb8d0a2a324043bcfc2c56f37b31abe7fb23a8/python/mozbuild/mozbuild/android_version_code.py
66
67
68
69
70
71
     *
     * There is a discrepancy between the epoch date used here (20141228)
     * and the epoch used in Fennec (20150801) for historical reasons. We keep
     * this discrepancy to avoid having Fenix version codes decrease.
     * Note that the original Fennec implementation also had an inconsistency in
     * the documented epoch date (20150901) and the effective epoch date (20150801).
72
73
74
75
76
77
78
79
80
81
82
83
84
     */
    @JvmStatic
    fun generateFennecVersionCode(abi: String): Int {
        // The important consideration is that version codes be monotonically
        // increasing (per Android package name) for all published builds.  The input
        // build IDs are based on timestamps and hence are always monotonically
        // increasing.
        //
        //         The generated v1 version codes look like (in binary):
        //
        // 0111 1000 0010 tttt tttt tttt tttt txpg
        //
        // The 17 bits labelled 't' represent the number of hours since midnight on
85
        // December 28, 2014.  (2014122800 in yyyyMMddHH format.)  This yields a
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
        // little under 15 years worth of hourly build identifiers, since 2**17 / (366
        //         * 24) =~ 14.92.
        //
        //         The bits labelled 'x', 'p', and 'g' are feature flags.
        //
        // The bit labelled 'x' is 1 if the build is for an x86 or x86-64 architecture,
        // and 0 otherwise, which means the build is for an ARM or ARM64 architecture.
        // (Fennec no longer supports ARMv6, so ARM is equivalent to ARMv7.
        //
        //         ARM64 is also known as AArch64; it is logically ARMv8.)
        //
        // For the same release, x86 and x86_64 builds have higher version codes and
        // take precedence over ARM builds, so that they are preferred over ARM on
        // devices that have ARM emulation.
        //
        // The bit labelled 'p' is 1 if the build is for a 64-bit architecture (x86-64
        //         or ARM64), and 0 otherwise, which means the build is for a 32-bit
        // architecture (x86 or ARM). 64-bit builds have higher version codes so
        // they take precedence over 32-bit builds on devices that support 64-bit.
        //
106
107
        //         The bit labelled 'g' is 1 was used for APK splits and is
        //         nowadays always set to 1 until it serves a new purpose.
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
        //
        // We throw an explanatory exception when we are within one calendar year of
        // running out of build events.  This gives lots of time to update the version
        // scheme.  The responsible individual should then bump the range (to allow
        //         builds to continue) and use the time remaining to update the version scheme
        // via the reserved high order bits.
        //
        //         N.B.: the reserved 0 bit to the left of the highest order 't' bit can,
        //         sometimes, be used to bump the version scheme.  In addition, by reducing the
        // granularity of the build identifiers (for example, moving to identifying
        // builds every 2 or 4 hours), the version scheme may be adjusted further still
        // without losing a (valuable) high order bit.

        val base = fennecBaseVersionCode

        when {
            base < 0 -> throw RuntimeException("Cannot calculate versionCode. Hours underflow.")
125
126
            base > 0x20000 /* 2^17 */ -> throw RuntimeException("Cannot calculate versionCode. Hours overflow.")
            base > 0x20000 - (366 * 24) ->
127
128
129
130
131
132
133
                // You have one year to update the version scheme...
                throw RuntimeException("Running out of low order bits calculating versionCode.")
        }

        var version = 0x78200000 // 1111000001000000000000000000000
        // We reserve 1 "middle" high order bit for the future, and 3 low order bits
        // for architecture and APK splits.
134
        version = version or (base shl 3)
135
136
137
138
139
140
141
142
143
144
145

        // 'x' bit is 1 for x86/x86-64 architectures
        if (abi == "x86_64" || abi == "x86") {
            version = version or (1 shl 2)
        }

        // 'p' bit is 1 for 64-bit architectures.
        if (abi == "arm64-v8a" || abi == "x86_64") {
            version = version or (1 shl 1)
        }

146
        // 'g' bit is currently always 1 (see comment above)
147
148
149
150
        version = version or (1 shl 0)

        return version
    }
151
}