Skip to content

Commit

Permalink
feat: support for devices running the new ColorOS-based OxygenOS
Browse files Browse the repository at this point in the history
Resolves #183. Fingerprint used to be parsed from the `getprop` output, but it's now being read from `Build.FINGERPRINT` directly (because it calls `deriveFingerprint` ensuring it exists).

Also removed unused "localDebug" buildType
  • Loading branch information
adhirajsinghchauhan committed Jan 30, 2022
1 parent 90b394c commit 99e6702
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 69 deletions.
67 changes: 34 additions & 33 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ fun loadProperties(
}
}

fun arrayForBuildConfig(vararg array: String) = array.joinToString(prefix = "{", postfix = "}") {
"\"$it\""
}

android {
compileSdkVersion(AndroidSdk.COMPILE)
buildToolsVersion = AndroidSdk.BUILD_TOOLS
Expand Down Expand Up @@ -106,13 +110,29 @@ android {
buildConfigField("String", "SERVER_DOMAIN", "\"https://oxygenupdater.com/\"")
buildConfigField("String", "SERVER_API_BASE", "\"api/v2.6/\"")
buildConfigField("String", "NOTIFICATIONS_PREFIX", "\"\"")
buildConfigField("String", "DEVICE_NAME_LOOKUP_KEY", "\"ro.display.series,ro.build.product\"")
buildConfigField("String", "OS_VERSION_NUMBER_LOOKUP_KEY", "\"ro.rom.version,ro.oxygen.version,ro.build.ota.versionname,ro.vendor.oplus.exp.version\"")
buildConfigField(
"String[]",
"DEVICE_NAME_LOOKUP_KEYS",
arrayForBuildConfig(
"ro.display.series",
"ro.build.product",
)
)
buildConfigField(
"String[]",
"OS_VERSION_NUMBER_LOOKUP_KEYS",
arrayForBuildConfig(
"ro.rom.version",
"ro.oxygen.version",
"ro.build.ota.versionname",
"ro.vendor.oplus.exp.version",
"ro.build.display.ota",
"ro.build.display.id",
)
)
buildConfigField("String", "OS_OTA_VERSION_NUMBER_LOOKUP_KEY", "\"ro.build.version.ota\"")
buildConfigField("String", "BUILD_FINGERPRINT_LOOKUP_KEY", "\"ro.build.oemfingerprint,ro.build.fingerprint\"")
// Latter one is only used on very old OOS versions
buildConfigField("String", "AB_UPDATE_LOOKUP_KEY", "\"ro.build.ab_update\"")
buildConfigField("String", "SUPPORTED_BUILD_FINGERPRINT_KEYS", "\"release-keys\"")

signingConfig = signingConfigs.getByName("release")

Expand All @@ -126,37 +146,18 @@ android {
buildConfigField("String", "SERVER_DOMAIN", "\"https://test.oxygenupdater.com/\"")
buildConfigField("String", "SERVER_API_BASE", "\"api/v2.6/\"")
buildConfigField("String", "NOTIFICATIONS_PREFIX", "\"test_\"")
buildConfigField("String", "DEVICE_NAME_LOOKUP_KEY", "\"ro.product.name\"")
buildConfigField("String", "OS_VERSION_NUMBER_LOOKUP_KEY", "\"ro.build.version.release\"")
buildConfigField("String", "OS_OTA_VERSION_NUMBER_LOOKUP_KEY", "\"ro.build.version.incremental\"")
buildConfigField("String", "BUILD_FINGERPRINT_LOOKUP_KEY", "\"ro.build.fingerprint\"")
buildConfigField("String", "AB_UPDATE_LOOKUP_KEY", "\"ro.build.ab_update\"")
buildConfigField("String", "SUPPORTED_BUILD_FINGERPRINT_KEYS", "\"\"")

isMinifyEnabled = true
isShrinkResources = true
isDebuggable = true

// Should be this: https://github.com/firebase/firebase-android-sdk/issues/2665#issuecomment-849897741,
// but that doesn't work for some reason.
withGroovyBuilder {
"firebaseCrashlytics" {
"mappingFileUploadEnabled"(false)
}
}
}
// Config for use during debugging locally on an emulator
// Uses localhost at port 8000, and reads system properties using the default build.prop values present on any Android device/emulator
create("localDebug") {
buildConfigField("String", "SERVER_DOMAIN", "\"http://10.0.2.2:8000/\"")
buildConfigField("String", "SERVER_API_BASE", "\"api/v2.6/\"")
buildConfigField("String", "NOTIFICATIONS_PREFIX", "\"test_\"")
buildConfigField("String", "DEVICE_NAME_LOOKUP_KEY", "\"ro.product.name\"")
buildConfigField("String", "OS_VERSION_NUMBER_LOOKUP_KEY", "\"ro.build.version.release\"")
buildConfigField(
"String[]",
"DEVICE_NAME_LOOKUP_KEYS",
arrayForBuildConfig("ro.product.name")
)
buildConfigField(
"String[]",
"OS_VERSION_NUMBER_LOOKUP_KEYS",
arrayForBuildConfig("ro.build.version.release")
)
buildConfigField("String", "OS_OTA_VERSION_NUMBER_LOOKUP_KEY", "\"ro.build.version.incremental\"")
buildConfigField("String", "BUILD_FINGERPRINT_LOOKUP_KEY", "\"ro.build.fingerprint\"")
buildConfigField("String", "AB_UPDATE_LOOKUP_KEY", "\"ro.build.ab_update\"")
buildConfigField("String", "SUPPORTED_BUILD_FINGERPRINT_KEYS", "\"\"")

isMinifyEnabled = true
isShrinkResources = true
Expand Down
1 change: 1 addition & 0 deletions app/src/main/java/com/oxygenupdater/apis/ServerApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ interface ServerApi {
@Path("incrementalSystemVersion") incrementalSystemVersion: String,
@Query("osVersion") osVersion: String,
@Query("osType") osType: String,
@Query("fingerprint") fingerprint: String,
@Query("isEuBuild") isEuBuild: Boolean,
@Query("appVersion") appVersion: String
): Response<UpdateData>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import com.oxygenupdater.utils.Logger.logVerbose
import java.io.BufferedReader
import java.io.IOException
import java.io.StringReader
import java.lang.Boolean.parseBoolean
import java.util.*

/**
Expand Down Expand Up @@ -43,7 +42,9 @@ class SystemVersionProperties {
/**
* Fingerprint of the build. Used to check if the device uses an official build of OxygenOS
*/
val oemFingerprint: String
val fingerprint: String = Build.FINGERPRINT.trim().also {
logVerbose(TAG, "Detected build fingerprint: $it")
}

/**
* This prop is present only on 7-series and above. Possible values:
Expand All @@ -65,7 +66,6 @@ class SystemVersionProperties {
var oxygenOSVersion = NO_OXYGEN_OS
var oxygenOSOTAVersion = NO_OXYGEN_OS
var securityPatchDate = NO_OXYGEN_OS
var oemFingerprint = NO_OXYGEN_OS
var osType = NO_OXYGEN_OS
var abPartitionLayout = false

Expand All @@ -79,18 +79,17 @@ class SystemVersionProperties {

getBuildPropProcess.destroy()

oxygenDeviceName = readBuildPropItem(BuildConfig.DEVICE_NAME_LOOKUP_KEY, properties, "Detected device: %s")
oxygenOSVersion = readBuildPropItem(BuildConfig.OS_VERSION_NUMBER_LOOKUP_KEY, properties, "Detected OxygenOS ROM with version: %s")
oxygenDeviceName = readBuildPropItem(BuildConfig.DEVICE_NAME_LOOKUP_KEYS, properties, "Detected device: %s")
oxygenOSVersion = readBuildPropItem(BuildConfig.OS_VERSION_NUMBER_LOOKUP_KEYS, properties, "Detected OxygenOS ROM with version: %s")
oxygenOSOTAVersion = readBuildPropItem(BuildConfig.OS_OTA_VERSION_NUMBER_LOOKUP_KEY, properties, "Detected OxygenOS ROM with OTA version: %s")
oemFingerprint = readBuildPropItem(BuildConfig.BUILD_FINGERPRINT_LOOKUP_KEY, properties, "Detected build fingerprint: %s")
osType = readBuildPropItem(RO_BUILD_OS_TYPE_LOOKUP_KEY, properties, "Detected OS Type: %s")
abPartitionLayout = readBuildPropItem(BuildConfig.AB_UPDATE_LOOKUP_KEY, properties, "Device has A/B partition layout: %s").toBoolean()

abPartitionLayout = parseBoolean(readBuildPropItem(BuildConfig.AB_UPDATE_LOOKUP_KEY, properties, "Device has A/B partition layout: %s"))
val euBooleanStr = readBuildPropItem(RO_BUILD_EU_LOOKUP_KEYS, properties, "isEuBuild: %s")
val isEuBuild = if (euBooleanStr == NO_OXYGEN_OS) {
readBuildPropItem(RO_VENDOR_OPLUS_REGIONMARK_LOOKUP_KEY, properties, "isEuBuild: %s").startsWith("EU")
} else {
parseBoolean(euBooleanStr)
euBooleanStr.toBoolean()
}

// This prop is present only on 7-series and above
Expand Down Expand Up @@ -118,7 +117,6 @@ class SystemVersionProperties {
this.oxygenOSVersion = oxygenOSVersion
this.oxygenOSOTAVersion = oxygenOSOTAVersion
this.securityPatchDate = securityPatchDate
this.oemFingerprint = oemFingerprint
this.osType = osType
this.isABPartitionLayout = abPartitionLayout
}
Expand All @@ -131,7 +129,6 @@ class SystemVersionProperties {
oxygenOSVersion: String?,
oxygenOSOTAVersion: String?,
securityPatchDate: String?,
oemFingerprint: String?,
osType: String?,
ABPartitionLayout: Boolean
) {
Expand All @@ -141,28 +138,31 @@ class SystemVersionProperties {
this.oxygenOSVersion = oxygenOSVersion ?: ""
this.oxygenOSOTAVersion = oxygenOSOTAVersion ?: ""
this.securityPatchDate = securityPatchDate ?: ""
this.oemFingerprint = oemFingerprint ?: ""
this.osType = osType ?: ""
this.isABPartitionLayout = ABPartitionLayout
}

@Throws(IOException::class)
private fun readBuildPropItem(itemKeys: String, buildProperties: String?, logText: String?): String {
private fun readBuildPropItem(
itemKey: String,
buildProperties: String?,
logText: String?,
) = readBuildPropItem(arrayOf(itemKey), buildProperties, logText)

@Throws(IOException::class)
private fun readBuildPropItem(
itemKeys: Array<String>,
buildProperties: String?,
logText: String?,
): String {
if (buildProperties.isNullOrEmpty()) {
return NO_OXYGEN_OS
}

var result = NO_OXYGEN_OS

// Some keys are not present on all devices. Therefore, we'll need support for multiple keys in a single string.
// If the first key is not present on this device, try the next key. We split the key string by ", "
val items = itemKeys
// see https://stackoverflow.com/a/45652573/6319730
.trim { it <= ' ' }
.replace(" ", "")
.split(",").toTypedArray()

items.forEach { item ->
// Some keys are not present on all devices, so check multiple in-order
itemKeys.forEach { item ->
val reader = BufferedReader(StringReader(buildProperties))
var inputLine: String?

Expand Down Expand Up @@ -261,7 +261,7 @@ class SystemVersionProperties {
* so that it's easy for contributors on Discord to figure out which build is for which region
* (backend will take this into account while firing the webhook).
*/
private const val RO_BUILD_EU_LOOKUP_KEYS = "ro.build.eu,ro.vendor.build.eu"
private val RO_BUILD_EU_LOOKUP_KEYS = arrayOf("ro.build.eu", "ro.vendor.build.eu")

/**
* This is a hack for Nord 2 (maybe future devices too), since it doesn't have any of the above EU keys.
Expand All @@ -286,7 +286,7 @@ class SystemVersionProperties {
*
* Note for GitHub contributors: add to the list if newer devices need to be excluded.
*/
private val RO_PRODUCT_NAME_LOOKUP_DEVICES_IGNORE = listOf(
private val RO_PRODUCT_NAME_LOOKUP_DEVICES_IGNORE = setOf(
"OnePlus",
"OnePlus 2",
"OnePlus X",
Expand All @@ -304,7 +304,7 @@ class SystemVersionProperties {
* distinction between ro.product.name in Indian and international variants.
* Only workaround is to read `ro.build.soft.version`.
*/
private val RO_BUILD_SOFT_VERSION_LOOKUP_DEVICES = listOf(
private val RO_BUILD_SOFT_VERSION_LOOKUP_DEVICES = setOf(
"OnePlus7T",
"OnePlus7TPro"
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class ServerRepository constructor(
incrementalSystemVersion,
systemVersionProperties.oxygenOSVersion,
systemVersionProperties.osType,
systemVersionProperties.fingerprint,
SettingsManager.getPreference(SettingsManager.PROPERTY_IS_EU_BUILD, false),
BuildConfig.VERSION_NAME
)
Expand Down
22 changes: 11 additions & 11 deletions app/src/main/java/com/oxygenupdater/utils/Utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@ import android.util.TypedValue
import androidx.annotation.Dimension
import com.google.android.gms.common.ConnectionResult
import com.google.android.gms.common.GoogleApiAvailability
import com.oxygenupdater.BuildConfig
import com.oxygenupdater.OxygenUpdater
import com.oxygenupdater.OxygenUpdater.Companion.isNetworkAvailable
import com.oxygenupdater.R
import com.oxygenupdater.internal.settings.SettingsManager
Expand Down Expand Up @@ -99,14 +97,14 @@ object Utils {
fun checkNetworkConnection() = isNetworkAvailable.value == true

fun checkDeviceOsSpec(devices: List<Device>?): DeviceOsSpec {
val oemFingerPrint = systemVersionProperties.oemFingerprint
val oxygenOsVersion = systemVersionProperties.oxygenOSVersion

val firmwareIsSupported = oemFingerPrint.isNotEmpty()
&& oemFingerPrint != OxygenUpdater.NO_OXYGEN_OS
&& oemFingerPrint.contains(BuildConfig.SUPPORTED_BUILD_FINGERPRINT_KEYS)
&& oxygenOsVersion.isNotEmpty()
&& oxygenOsVersion != OxygenUpdater.NO_OXYGEN_OS
// <brand>/<product>/<device>:<version.release>/<id>/<version.incremental>:<type>/<tags>
val fingerprintParts = systemVersionProperties.fingerprint.split("/").map {
it.trim()
}
val firmwareIsSupported = fingerprintParts.size == 6
&& fingerprintParts[0].lowercase() == "oneplus"
// must be `contains` and not a direct equality check
&& fingerprintParts[5].lowercase().contains("release-keys")

if (devices.isNullOrEmpty()) {
// To prevent incorrect results on empty server response. This still checks if official ROM is used and if an OxygenOS version is found on the device.
Expand All @@ -121,7 +119,9 @@ object Utils {
// user's device is definitely running OxygenOS, now onto other checks...
devices.forEach {
// find the user's device in the list of devices retrieved from the server
if (it.productNames.contains(systemVersionProperties.oxygenDeviceName)) {
if ((fingerprintParts.size > 2 && it.productNames.contains(fingerprintParts[1]))
|| it.productNames.contains(systemVersionProperties.oxygenDeviceName)
) {
return if (it.enabled) {
// device found, and is enabled, which means it is supported
SUPPORTED_OXYGEN_OS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ abstract class SystemVersionPropertiesTest {
null,
null,
null,
null,
false
)

Expand Down

0 comments on commit 99e6702

Please sign in to comment.