diff --git a/app/build.gradle b/app/build.gradle index 3320d6921ea6d93a67574761b1397a7a59fccec4..1303802f194b7fe32945486839641ed199c6e5fc 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,7 +11,7 @@ plugins { def versionMajor = 2 def versionMinor = 8 -def versionPatch = 1 +def versionPatch = 3 def getGitHash = { -> def stdOut = new ByteArrayOutputStream() @@ -42,7 +42,7 @@ def getSentryDsn = { -> } android { - compileSdk 33 + compileSdk 34 defaultConfig { applicationId "foundation.e.apps" diff --git a/app/src/main/java/foundation/e/apps/AppLoungeApplication.kt b/app/src/main/java/foundation/e/apps/AppLoungeApplication.kt index 12af89dcf19c12d5fecc9ec1ba3cd42cef1fffc1..262ba4879da9e0112586ebe394ebf997b549c174 100644 --- a/app/src/main/java/foundation/e/apps/AppLoungeApplication.kt +++ b/app/src/main/java/foundation/e/apps/AppLoungeApplication.kt @@ -91,13 +91,13 @@ class AppLoungeApplication : Application(), Configuration.Provider { Telemetry.init(BuildConfig.SENTRY_DSN, this) plant(object : Timber.Tree() { override fun log(priority: Int, tag: String?, message: String, t: Throwable?) { - if (priority <= Log.WARN && !listOf( + /*if (priority <= Log.WARN && !listOf( TAG_AUTHDATA_DUMP, TAG_APP_INSTALL_STATE ).contains(tag) ) { return - } + }*/ Log.println(priority, tag, message) } }) diff --git a/app/src/main/java/foundation/e/apps/data/gitlab/ReleaseInfoApi.kt b/app/src/main/java/foundation/e/apps/data/gitlab/ReleaseInfoApi.kt index 4b2a3fbf76cfc139ae6e045c1113a6b84c06fcdc..76062c758cccce0e29a05fde954975ac667d9b5c 100644 --- a/app/src/main/java/foundation/e/apps/data/gitlab/ReleaseInfoApi.kt +++ b/app/src/main/java/foundation/e/apps/data/gitlab/ReleaseInfoApi.kt @@ -17,11 +17,14 @@ package foundation.e.apps.data.gitlab -import foundation.e.apps.data.gitlab.models.ReleaseInfo +import foundation.e.apps.data.gitlab.models.GitLabReleaseInfo import retrofit2.Response import retrofit2.http.GET import retrofit2.http.Path +/* +Provides GitLab API client method (https://docs.gitlab.com/ee/api/releases/) + */ interface ReleaseInfoApi { companion object { @@ -32,6 +35,5 @@ interface ReleaseInfoApi { @GET("{projectId}/releases") suspend fun getReleases( @Path("projectId") projectId: Int, - ): Response> - + ): Response> } diff --git a/app/src/main/java/foundation/e/apps/data/gitlab/SystemAppsUpdatesRepository.kt b/app/src/main/java/foundation/e/apps/data/gitlab/SystemAppsUpdatesRepository.kt index c928cface437b5237011967bfef8b312da418e4d..7d126d4120b0e22158e180fb7cb5a4ef4a2ba393 100644 --- a/app/src/main/java/foundation/e/apps/data/gitlab/SystemAppsUpdatesRepository.kt +++ b/app/src/main/java/foundation/e/apps/data/gitlab/SystemAppsUpdatesRepository.kt @@ -43,6 +43,15 @@ class SystemAppsUpdatesRepository @Inject constructor( private val releaseInfoApi: ReleaseInfoApi, ) { + private val androidVersionCode by lazy { + try { getAndroidVersionCodeChar() } + catch (exception: UnsupportedAndroidApiException) { + Timber.w(exception.message, + "Android API isn't in supported range to update some system apps") + "UnsupportedAndroidAPI" + } + } + private val systemAppProjectList = mutableListOf() private fun getUpdatableSystemApps(): List { @@ -55,13 +64,7 @@ class SystemAppsUpdatesRepository @Inject constructor( return@handleNetworkResult } - val systemName = getFullSystemName() - val endPoint = if (isEligibleToFetchAppListFromTest(systemName)) { - UpdatableSystemAppsApi.EndPoint.ENDPOINT_TEST - } else { - UpdatableSystemAppsApi.EndPoint.ENDPOINT_RELEASE - } - + val endPoint = getUpdatableSystemAppEndPoint() val response = updatableSystemAppsApi.getUpdatableSystemApps(endPoint) if (response.isSuccessful && !response.body().isNullOrEmpty()) { @@ -77,6 +80,18 @@ class SystemAppsUpdatesRepository @Inject constructor( } } + private fun getUpdatableSystemAppEndPoint(): UpdatableSystemAppsApi.EndPoint { + val systemName = getFullSystemName() + Timber.d("getFullSystemName: $systemName") + return if (isEligibleToFetchAppListFromTest(systemName)) { + Timber.d("Use test endpoint") + UpdatableSystemAppsApi.EndPoint.ENDPOINT_TEST + } else { + Timber.d("Use release end point") + UpdatableSystemAppsApi.EndPoint.ENDPOINT_RELEASE + } + } + private fun isEligibleToFetchAppListFromTest(systemName: String) = systemName.isBlank() || systemName.contains("beta") || systemName.contains("rc") || @@ -96,23 +111,38 @@ class SystemAppsUpdatesRepository @Inject constructor( } private suspend fun getReleaseDetailsUrl( - projectId: Int, + systemAppProject: SystemAppProject, releaseType: OsReleaseType, ): String? { + val projectId = systemAppProject.projectId val releaseResponse = releaseInfoApi.getReleases(projectId) - val releases = releaseResponse.body() + var releases = releaseResponse.body() if (!releaseResponse.isSuccessful || releases == null) { Timber.e("Failed to fetch releases for project id - $projectId") return null } + Timber.d("getReleaseDetailsUrl: ${systemAppProject.packageName} is android dependent: ${systemAppProject.dependsOnAndroidVersion}") + + if (systemAppProject.dependsOnAndroidVersion) { + val versionSuffix = "-$androidVersionCode" + Timber.d("Filtering app on $versionSuffix") + Timber.d("Release list's size for $projectId before filtering is: ${releases.size}") + + + releases = releases.filter { isVersionedTag(it.tagName, versionSuffix) } + Timber.d("Release list's size for $projectId after filtering is: ${releases.size}") + } + val sortedReleases = releases.sortedByDescending { it.releasedAt } for (release in sortedReleases) { + Timber.d("releaseType: $releaseType") release.getAssetWebLink("${releaseType}.json")?.run { + Timber.d("release asset web link: $this") return this.removePrefix(SystemAppDefinitionApi.BASE_URL) } } @@ -120,25 +150,37 @@ class SystemAppsUpdatesRepository @Inject constructor( return null } - private suspend fun getSystemAppUpdateInfo( + private fun isVersionedTag(tag: String, versionSuffix: String): Boolean { + val result = tag.endsWith(suffix = versionSuffix, ignoreCase = true) + Timber.d("isVersionedTag ? $result, tag: $tag, versioNSuffix: $versionSuffix") + return result + } + + + private suspend fun getApplication( packageName: String, releaseType: OsReleaseType, sdkLevel: Int, device: String, ): Application? { - val projectId = - systemAppProjectList.find { it.packageName == packageName }?.projectId ?: return null + val systemAppProject = systemAppProjectList.find { it.packageName == packageName } ?: run { + Timber.e("Can't find $packageName in System apps") + return null + } + Timber.d("") - val detailsUrl = getReleaseDetailsUrl(projectId, releaseType) ?: return null + val detailsUrl = getReleaseDetailsUrl(systemAppProject, releaseType) ?: run { + Timber.e("Can't get url for release's detail for $packageName of $releaseType") + return null + } - val response = systemAppDefinitionApi.getSystemAppUpdateInfo(detailsUrl) - val systemAppInfo = response.body() + val systemAppInfo = getSystemAppInfo(packageName, detailsUrl) ?: run { + Timber.e("Can't get system App info for $packageName with $detailsUrl") + return null + } - return if (systemAppInfo == null) { - Timber.e("Null app info for: $packageName, response: ${response.errorBody()?.string()}") - null - } else if (isSystemAppBlocked(systemAppInfo, sdkLevel, device)) { + return if (isSystemAppBlocked(systemAppInfo, sdkLevel, device)) { Timber.e("Blocked system app: $packageName, details: $systemAppInfo") null } else { @@ -146,6 +188,20 @@ class SystemAppsUpdatesRepository @Inject constructor( } } + private suspend fun getSystemAppInfo( + packageName: String, + detailsUrl: String + ): SystemAppInfo? { + val response = systemAppDefinitionApi.getSystemAppUpdateInfo(detailsUrl) + + return if (response.isSuccessful) { + response.body() + } else { + Timber.e("Can't get AppInfo for $packageName, response: ${response.errorBody()?.string()}") + null + } + } + private fun getFullSystemName(): String { return SystemInfoProvider.getSystemProperty(SystemInfoProvider.KEY_LINEAGE_VERSION) ?: "" } @@ -164,6 +220,21 @@ class SystemAppsUpdatesRepository @Inject constructor( } } + /** + * This method must be updated when Murena or /e/ foundation support new Android version + * or stop to support an old one + */ + private fun getAndroidVersionCodeChar(): String { + Timber.d("getAndroidVersionCodeChar: currentAPI = ${Build.VERSION.SDK_INT}") + Timber.d("VERSION_CODES.S = ${Build.VERSION_CODES.S}") + return when (val currentAPI = Build.VERSION.SDK_INT) { + Build.VERSION_CODES.S, Build.VERSION_CODES.S_V2 -> "S" + Build.VERSION_CODES.TIRAMISU -> "T" + Build.VERSION_CODES.UPSIDE_DOWN_CAKE -> "U" + else -> throw UnsupportedAndroidApiException("API level $currentAPI is not supported") + } + } + suspend fun getSystemUpdates(): List { val updateList = mutableListOf() val releaseType = getSystemReleaseType() @@ -179,7 +250,7 @@ class SystemAppsUpdatesRepository @Inject constructor( } val result = handleNetworkResult { - getSystemAppUpdateInfo( + getApplication( it, releaseType, sdkLevel, @@ -187,6 +258,7 @@ class SystemAppsUpdatesRepository @Inject constructor( ) } + result.data?.run { applicationDataManager.updateStatus(this) updateList.add(this) @@ -200,5 +272,6 @@ class SystemAppsUpdatesRepository @Inject constructor( return updateList } - } + +private class UnsupportedAndroidApiException(message: String) : RuntimeException(message) \ No newline at end of file diff --git a/app/src/main/java/foundation/e/apps/data/gitlab/models/ReleaseInfo.kt b/app/src/main/java/foundation/e/apps/data/gitlab/models/ReleaseInfo.kt index 6284fe92ad511ae354ddbf62eece5432f4bd9159..cb51761d0aa0e9904214ceaa9c074974beda593f 100644 --- a/app/src/main/java/foundation/e/apps/data/gitlab/models/ReleaseInfo.kt +++ b/app/src/main/java/foundation/e/apps/data/gitlab/models/ReleaseInfo.kt @@ -19,10 +19,10 @@ package foundation.e.apps.data.gitlab.models import com.squareup.moshi.Json -data class ReleaseInfo( +data class GitLabReleaseInfo( val name: String, - @Json(name = "released_at") - val releasedAt: String, + @Json(name = "tag_name") val tagName: String, + @Json(name = "released_at") val releasedAt: String, val assets: ReleaseAssets, ) { fun getAssetWebLink(assetName: String): String? { diff --git a/app/src/main/java/foundation/e/apps/data/gitlab/models/SystemAppProject.kt b/app/src/main/java/foundation/e/apps/data/gitlab/models/SystemAppProject.kt index edc7f2bffdeaf584e4e54aaceae0412b5dd5ed9f..054a869f5d746d34c42f4bc92c1d626174e1639b 100644 --- a/app/src/main/java/foundation/e/apps/data/gitlab/models/SystemAppProject.kt +++ b/app/src/main/java/foundation/e/apps/data/gitlab/models/SystemAppProject.kt @@ -20,4 +20,5 @@ package foundation.e.apps.data.gitlab.models data class SystemAppProject( val packageName: String, val projectId: Int, + val dependsOnAndroidVersion: Boolean = false )