From a01e2edacd28fccfd7428bee2c1b6e2463ec50dd Mon Sep 17 00:00:00 2001 From: Sayantan Roychowdhury Date: Thu, 25 Jul 2024 01:00:54 +0530 Subject: [PATCH 1/7] update AppLoungePackageManager to accept versionName in isUpdatable --- .../install/pkg/AppLoungePackageManager.kt | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/foundation/e/apps/install/pkg/AppLoungePackageManager.kt b/app/src/main/java/foundation/e/apps/install/pkg/AppLoungePackageManager.kt index 78da25fa5..edb939a16 100644 --- a/app/src/main/java/foundation/e/apps/install/pkg/AppLoungePackageManager.kt +++ b/app/src/main/java/foundation/e/apps/install/pkg/AppLoungePackageManager.kt @@ -32,17 +32,16 @@ import android.os.Build import androidx.core.content.pm.PackageInfoCompat import dagger.hilt.android.qualifiers.ApplicationContext import foundation.e.apps.OpenForTesting +import foundation.e.apps.data.application.search.SearchApi import foundation.e.apps.data.enums.Origin import foundation.e.apps.data.enums.Status import foundation.e.apps.data.enums.Type -import foundation.e.apps.data.application.search.SearchApi import foundation.e.apps.data.install.models.AppInstall -import kotlinx.coroutines.DelicateCoroutinesApi -import timber.log.Timber import java.io.File -import java.lang.IllegalArgumentException import javax.inject.Inject import javax.inject.Singleton +import kotlinx.coroutines.DelicateCoroutinesApi +import timber.log.Timber @Singleton @OpenForTesting @@ -72,9 +71,16 @@ class AppLoungePackageManager @Inject constructor( } } - private fun isUpdatable(packageName: String, versionCode: Int): Boolean { + private fun isUpdatable(packageName: String, versionCode: Int, versionName: String): Boolean { val packageInfo = getPackageInfo(packageName) ?: return false - return versionCode.toLong() > PackageInfoCompat.getLongVersionCode(packageInfo) + val installedVersionNumber = PackageInfoCompat.getLongVersionCode(packageInfo) + val installedVersionName = packageInfo.versionName + + val isVersionNumberHigher = versionCode.toLong() > installedVersionNumber + val isVersionNameHigher = + versionName.isNotBlank() && versionName > installedVersionName + + return isVersionNumberHigher || isVersionNameHigher } fun getLaunchIntent(packageName: String): Intent? { @@ -96,9 +102,13 @@ class AppLoungePackageManager @Inject constructor( * * Recommended to use: [SearchApi.getFusedAppInstallationStatus]. */ - fun getPackageStatus(packageName: String, versionCode: Int): Status { + fun getPackageStatus( + packageName: String, + versionCode: Int, + versionName: String = "", + ): Status { return if (isInstalled(packageName)) { - if (isUpdatable(packageName, versionCode)) { + if (isUpdatable(packageName, versionCode, versionName)) { Status.UPDATABLE } else { Status.INSTALLED -- GitLab From 4232bac283a0b57a728b7ac3454adf9b3ebefd58 Mon Sep 17 00:00:00 2001 From: Sayantan Roychowdhury Date: Thu, 25 Jul 2024 01:01:32 +0530 Subject: [PATCH 2/7] update ApplicationDataManager --- .../e/apps/data/application/ApplicationDataManager.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/foundation/e/apps/data/application/ApplicationDataManager.kt b/app/src/main/java/foundation/e/apps/data/application/ApplicationDataManager.kt index 3364511b0..2630550ac 100644 --- a/app/src/main/java/foundation/e/apps/data/application/ApplicationDataManager.kt +++ b/app/src/main/java/foundation/e/apps/data/application/ApplicationDataManager.kt @@ -114,7 +114,11 @@ class ApplicationDataManager @Inject constructor( return if (application.is_pwa) { pwaManager.getPwaStatus(application) } else { - appLoungePackageManager.getPackageStatus(application.package_name, application.latest_version_code) + appLoungePackageManager.getPackageStatus( + application.package_name, + application.latest_version_code, + application.latest_version_number, + ) } } } -- GitLab From 4165e1acc7c54f24a1257a6c5d569737e0ad2755 Mon Sep 17 00:00:00 2001 From: Sayantan Roychowdhury Date: Thu, 25 Jul 2024 01:01:53 +0530 Subject: [PATCH 3/7] add test for AppLoungePackageManager --- .../pkg/AppLoungePackageManagerTest.kt | 198 ++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 app/src/test/java/foundation/e/apps/install/pkg/AppLoungePackageManagerTest.kt diff --git a/app/src/test/java/foundation/e/apps/install/pkg/AppLoungePackageManagerTest.kt b/app/src/test/java/foundation/e/apps/install/pkg/AppLoungePackageManagerTest.kt new file mode 100644 index 000000000..f39603d5e --- /dev/null +++ b/app/src/test/java/foundation/e/apps/install/pkg/AppLoungePackageManagerTest.kt @@ -0,0 +1,198 @@ +package foundation.e.apps.install.pkg + +import android.content.Context +import android.content.pm.PackageInfo +import android.content.pm.PackageManager +import androidx.core.content.pm.PackageInfoCompat +import foundation.e.apps.data.enums.Status +import kotlin.test.assertEquals +import kotlin.test.assertFalse +import org.junit.Before +import org.junit.Test +import org.mockito.Mock +import org.mockito.Mockito +import org.mockito.Mockito.mock +import org.mockito.MockitoAnnotations + +class AppLoungePackageManagerTest { + + private lateinit var appLoungePackageManager: AppLoungePackageManager + + @Mock + private lateinit var context: Context + + @Mock + private lateinit var packageManager: PackageManager + + private val testPackageName = "foundation.e.test" + + @Before + fun setup() { + MockitoAnnotations.openMocks(this) + Mockito.`when`(context.packageManager).thenReturn(packageManager) + appLoungePackageManager = AppLoungePackageManager(context) + } + + private fun mockPackagePresence( + expectedPackageName: String, + expectedVersionCode: Int, + expectedVersionName: String, + optionalFlag: Int = 0, + ) { + val expectedPackageInfo = mock(PackageInfo::class.java).apply { + packageName = expectedPackageName + versionName = expectedVersionName + versionCode = expectedVersionCode + } + Mockito.`when`( + packageManager.getPackageInfo(expectedPackageName, optionalFlag) + ).thenReturn(expectedPackageInfo) + } + + private fun mockPackagePresence() { + mockPackagePresence(testPackageName, 0, "") + } + + private fun mockPackageAbsence() { + Mockito.`when`(packageManager.getPackageInfo(testPackageName, PackageManager.GET_META_DATA)) + .thenThrow(PackageManager.NameNotFoundException::class.java) + } + + @Test + fun givenPackageInfoIsPresent_whenCheckIsInstalled_thenReturnTrue() { + mockPackagePresence() + assert(appLoungePackageManager.isInstalled(testPackageName)) + } + + @Test + fun givenPackageInfoIsAbsent_whenCheckIsInstalled_thenReturnFalse() { + mockPackageAbsence() + assertFalse(appLoungePackageManager.isInstalled(testPackageName)) + } + + @Test + fun givenPackageInfoIsPresent_thenReturnProperVersionCode() { + val installedVersionCode = 40903000 + val installedVersionName = "4.9.3" + + mockPackagePresence( + expectedPackageName = testPackageName, + expectedVersionCode = installedVersionCode, + expectedVersionName = installedVersionName, + ) + + assertEquals( + installedVersionCode.toLong(), + PackageInfoCompat.getLongVersionCode(packageManager.getPackageInfo(testPackageName, 0)) + ) + } + + @Test + fun givenPackageInfoIsAbsent_whenCheckIsUpdatable_thenReturnStatusUNAVAILABLE() { + mockPackageAbsence() + + val newVersionCode = 40903000 + val newVersionName = "4.9.3+eOS-1.0" + + assertEquals( + Status.UNAVAILABLE, appLoungePackageManager.getPackageStatus( + packageName = testPackageName, + versionCode = newVersionCode, + versionName = newVersionName, + ) + ) + } + + @Test + fun givenNewVersionCode_andSameVersionName_whenCheckIsUpdatable_thenReturnStatusUPDATABLE() { + val installedVersionCode = 40903000 + val installedVersionName = "4.9.3" + + mockPackagePresence( + expectedPackageName = testPackageName, + expectedVersionCode = installedVersionCode, + expectedVersionName = installedVersionName, + ) + + val newVersionCode = 40903001 + val newVersionName = "4.9.3" + + assertEquals( + Status.UPDATABLE, appLoungePackageManager.getPackageStatus( + packageName = testPackageName, + versionCode = newVersionCode, + versionName = newVersionName, + ) + ) + } + + @Test + fun givenNewVersionCode_andNewVersionNameBlank_whenCheckIsUpdatable_thenReturnStatusUPDATABLE() { + val installedVersionCode = 40903000 + val installedVersionName = "4.9.3" + + mockPackagePresence( + expectedPackageName = testPackageName, + expectedVersionCode = installedVersionCode, + expectedVersionName = installedVersionName, + ) + + val newVersionCode = 40903001 + val newVersionName = "" + + assertEquals( + Status.UPDATABLE, appLoungePackageManager.getPackageStatus( + packageName = testPackageName, + versionCode = newVersionCode, + versionName = newVersionName, + ) + ) + } + + @Test + fun givenNewVersionName_andSameVersionCode_whenCheckIsUpdatable_thenReturnStatusUPDATABLE() { + val installedVersionCode = 40903000 + val installedVersionName = "4.9.3" + + mockPackagePresence( + expectedPackageName = testPackageName, + expectedVersionCode = installedVersionCode, + expectedVersionName = installedVersionName, + ) + + val newVersionCode = 40903000 + val newVersionName = "4.9.3+eOS-1.0" + + assertEquals( + Status.UPDATABLE, appLoungePackageManager.getPackageStatus( + packageName = testPackageName, + versionCode = newVersionCode, + versionName = newVersionName, + ) + ) + } + + @Test + fun givenSameVersionCode_andSameVersionName_whenCheckIsUpdatable_thenReturnStatusINSTALLED() { + val installedVersionCode = 40903000 + val installedVersionName = "4.9.3+eOS-1.0" + + mockPackagePresence( + expectedPackageName = testPackageName, + expectedVersionCode = installedVersionCode, + expectedVersionName = installedVersionName, + ) + + val newVersionCode = 40903000 + val newVersionName = "4.9.3+eOS-1.0" + + assertEquals( + Status.INSTALLED, appLoungePackageManager.getPackageStatus( + packageName = testPackageName, + versionCode = newVersionCode, + versionName = newVersionName, + ) + ) + } + +} \ No newline at end of file -- GitLab From a619ebab5848208fd0a28f30b6c3985ecaa71188 Mon Sep 17 00:00:00 2001 From: Sayantan Roychowdhury Date: Thu, 25 Jul 2024 06:21:48 +0530 Subject: [PATCH 4/7] license --- .../pkg/AppLoungePackageManagerTest.kt | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/app/src/test/java/foundation/e/apps/install/pkg/AppLoungePackageManagerTest.kt b/app/src/test/java/foundation/e/apps/install/pkg/AppLoungePackageManagerTest.kt index f39603d5e..3ba9414d3 100644 --- a/app/src/test/java/foundation/e/apps/install/pkg/AppLoungePackageManagerTest.kt +++ b/app/src/test/java/foundation/e/apps/install/pkg/AppLoungePackageManagerTest.kt @@ -1,3 +1,21 @@ +/* + * Copyright MURENA SAS 2024 + * Apps Quickly and easily install Android apps onto your device! + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package foundation.e.apps.install.pkg import android.content.Context @@ -195,4 +213,4 @@ class AppLoungePackageManagerTest { ) } -} \ No newline at end of file +} -- GitLab From 33f26828949628d322c0cdf2d7aca3ea37ad8fde Mon Sep 17 00:00:00 2001 From: Sayantan Roychowdhury Date: Thu, 25 Jul 2024 06:48:51 +0530 Subject: [PATCH 5/7] fix broken tests --- .../foundation/e/apps/apps/AppsApiTest.kt | 27 ++++++++++++------- .../e/apps/fused/SearchApiImplTest.kt | 2 +- .../foundation/e/apps/home/HomeApiTest.kt | 2 +- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/app/src/test/java/foundation/e/apps/apps/AppsApiTest.kt b/app/src/test/java/foundation/e/apps/apps/AppsApiTest.kt index f86f01f6f..861cacf8e 100644 --- a/app/src/test/java/foundation/e/apps/apps/AppsApiTest.kt +++ b/app/src/test/java/foundation/e/apps/apps/AppsApiTest.kt @@ -229,7 +229,8 @@ class AppsApiTest { Mockito.`when`( appLoungePackageManager.getPackageStatus( eq("foundation.e.demoone"), - eq(123) + eq(123), + eq(""), ) ) .thenReturn( @@ -238,7 +239,8 @@ class AppsApiTest { Mockito.`when`( appLoungePackageManager.getPackageStatus( eq("foundation.e.demotwo"), - eq(123) + eq(123), + eq(""), ) ) .thenReturn( @@ -247,7 +249,8 @@ class AppsApiTest { Mockito.`when`( appLoungePackageManager.getPackageStatus( eq("foundation.e.demothree"), - eq(123) + eq(123), + eq(""), ) ) .thenReturn( @@ -287,7 +290,8 @@ class AppsApiTest { Mockito.`when`( appLoungePackageManager.getPackageStatus( eq("foundation.e.demoone"), - eq(123) + eq(123), + eq(""), ) ) .thenReturn( @@ -296,7 +300,8 @@ class AppsApiTest { Mockito.`when`( appLoungePackageManager.getPackageStatus( eq("foundation.e.demotwo"), - eq(123) + eq(123), + eq(""), ) ) .thenReturn( @@ -305,7 +310,8 @@ class AppsApiTest { Mockito.`when`( appLoungePackageManager.getPackageStatus( eq("foundation.e.demothree"), - eq(123) + eq(123), + eq(""), ) ) .thenReturn( @@ -345,7 +351,8 @@ class AppsApiTest { Mockito.`when`( appLoungePackageManager.getPackageStatus( eq("foundation.e.demoone"), - eq(123) + eq(123), + eq(""), ) ) .thenReturn( @@ -354,7 +361,8 @@ class AppsApiTest { Mockito.`when`( appLoungePackageManager.getPackageStatus( eq("foundation.e.demotwo"), - eq(123) + eq(123), + eq(""), ) ) .thenReturn( @@ -363,7 +371,8 @@ class AppsApiTest { Mockito.`when`( appLoungePackageManager.getPackageStatus( eq("foundation.e.demothree"), - eq(123) + eq(123), + eq(""), ) ) .thenReturn( diff --git a/app/src/test/java/foundation/e/apps/fused/SearchApiImplTest.kt b/app/src/test/java/foundation/e/apps/fused/SearchApiImplTest.kt index ffceefecc..117b5cc9f 100644 --- a/app/src/test/java/foundation/e/apps/fused/SearchApiImplTest.kt +++ b/app/src/test/java/foundation/e/apps/fused/SearchApiImplTest.kt @@ -201,7 +201,7 @@ class SearchApiImplTest { willThrowException: Boolean = false ) { Mockito.`when`(pwaManager.getPwaStatus(any())).thenReturn(Status.UNAVAILABLE) - Mockito.`when`(appLoungePackageManager.getPackageStatus(any(), any())) + Mockito.`when`(appLoungePackageManager.getPackageStatus(any(), any(), any())) .thenReturn(Status.UNAVAILABLE) Mockito.`when`( cleanApkAppsRepository.getSearchResult( diff --git a/app/src/test/java/foundation/e/apps/home/HomeApiTest.kt b/app/src/test/java/foundation/e/apps/home/HomeApiTest.kt index 82e5595bf..34ad19888 100644 --- a/app/src/test/java/foundation/e/apps/home/HomeApiTest.kt +++ b/app/src/test/java/foundation/e/apps/home/HomeApiTest.kt @@ -132,7 +132,7 @@ class HomeApiTest { any() ) ).thenReturn(listOf()) - Mockito.`when`(appLoungePackageManager.getPackageStatus(any(), any())) + Mockito.`when`(appLoungePackageManager.getPackageStatus(any(), any(), any())) .thenReturn(Status.UNAVAILABLE) var hasLimitedDataFound = false -- GitLab From d175e29d7946cb054af53bf4762b40faa801d13f Mon Sep 17 00:00:00 2001 From: Sayantan Roychowdhury Date: Thu, 25 Jul 2024 17:46:20 +0530 Subject: [PATCH 6/7] parse apk size for system app updates --- .../e/apps/data/gitlab/SystemAppsUpdatesRepository.kt | 2 +- .../foundation/e/apps/data/gitlab/models/SystemAppInfo.kt | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) 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 25d9487da..da2ecfd2b 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 @@ -98,7 +98,7 @@ class SystemAppsUpdatesRepository @Inject constructor( Timber.e("Blocked system app: $packageName, details: $systemAppInfo") null } else { - systemAppInfo.toApplication() + systemAppInfo.toApplication(context) } } diff --git a/app/src/main/java/foundation/e/apps/data/gitlab/models/SystemAppInfo.kt b/app/src/main/java/foundation/e/apps/data/gitlab/models/SystemAppInfo.kt index 5ccb2239a..7361cfb64 100644 --- a/app/src/main/java/foundation/e/apps/data/gitlab/models/SystemAppInfo.kt +++ b/app/src/main/java/foundation/e/apps/data/gitlab/models/SystemAppInfo.kt @@ -17,6 +17,8 @@ package foundation.e.apps.data.gitlab.models +import android.content.Context +import android.text.format.Formatter import com.fasterxml.jackson.annotation.JsonIgnoreProperties import com.squareup.moshi.Json import foundation.e.apps.data.application.data.Application @@ -41,7 +43,8 @@ data class SystemAppInfo( private const val RANDOM_SIZE = 1L -fun SystemAppInfo.toApplication(): Application { +fun SystemAppInfo.toApplication(context: Context): Application { + val apkSize = size ?: RANDOM_SIZE return Application( _id = UUID.randomUUID().toString(), author = authorName ?: "eFoundation", @@ -51,7 +54,8 @@ fun SystemAppInfo.toApplication(): Application { name = name, package_name = packageName, origin = Origin.GITLAB_RELEASES, - originalSize = size ?: RANDOM_SIZE, + originalSize = apkSize, + appSize = Formatter.formatFileSize(context, apkSize), url = downloadUrl, isSystemApp = true, filterLevel = FilterLevel.NONE, -- GitLab From 165e877bfe189e48891f1d3b051089b01447ce41 Mon Sep 17 00:00:00 2001 From: Sayantan Roychowdhury Date: Thu, 25 Jul 2024 17:53:15 +0530 Subject: [PATCH 7/7] update tests --- .../pkg/AppLoungePackageManagerTest.kt | 53 +++++++++++++++++-- 1 file changed, 49 insertions(+), 4 deletions(-) diff --git a/app/src/test/java/foundation/e/apps/install/pkg/AppLoungePackageManagerTest.kt b/app/src/test/java/foundation/e/apps/install/pkg/AppLoungePackageManagerTest.kt index 3ba9414d3..f87f2adeb 100644 --- a/app/src/test/java/foundation/e/apps/install/pkg/AppLoungePackageManagerTest.kt +++ b/app/src/test/java/foundation/e/apps/install/pkg/AppLoungePackageManagerTest.kt @@ -110,7 +110,7 @@ class AppLoungePackageManagerTest { mockPackageAbsence() val newVersionCode = 40903000 - val newVersionName = "4.9.3+eOS-1.0" + val newVersionName = "4.9.3+20240725" assertEquals( Status.UNAVAILABLE, appLoungePackageManager.getPackageStatus( @@ -179,7 +179,7 @@ class AppLoungePackageManagerTest { ) val newVersionCode = 40903000 - val newVersionName = "4.9.3+eOS-1.0" + val newVersionName = "4.9.3+20240725" assertEquals( Status.UPDATABLE, appLoungePackageManager.getPackageStatus( @@ -193,7 +193,7 @@ class AppLoungePackageManagerTest { @Test fun givenSameVersionCode_andSameVersionName_whenCheckIsUpdatable_thenReturnStatusINSTALLED() { val installedVersionCode = 40903000 - val installedVersionName = "4.9.3+eOS-1.0" + val installedVersionName = "4.9.3+20240725" mockPackagePresence( expectedPackageName = testPackageName, @@ -202,7 +202,7 @@ class AppLoungePackageManagerTest { ) val newVersionCode = 40903000 - val newVersionName = "4.9.3+eOS-1.0" + val newVersionName = "4.9.3+20240725" assertEquals( Status.INSTALLED, appLoungePackageManager.getPackageStatus( @@ -213,4 +213,49 @@ class AppLoungePackageManagerTest { ) } + @Test + fun givenNewVersionName_whenCheckIsUpdatable_thenReturnStatusUPDATABLE() { + val installedVersionCode = 40903000 + val installedVersionName = "4.9.3+20240725" + + mockPackagePresence( + expectedPackageName = testPackageName, + expectedVersionCode = installedVersionCode, + expectedVersionName = installedVersionName, + ) + + var newVersionCode = 40903000 + var newVersionName = "4.9.3+20240726" + + assertEquals( + Status.UPDATABLE, appLoungePackageManager.getPackageStatus( + packageName = testPackageName, + versionCode = newVersionCode, + versionName = newVersionName, + ) + ) + + newVersionCode = 40903000 + newVersionName = "4.9.3+20240825" + + assertEquals( + Status.UPDATABLE, appLoungePackageManager.getPackageStatus( + packageName = testPackageName, + versionCode = newVersionCode, + versionName = newVersionName, + ) + ) + + newVersionCode = 40903000 + newVersionName = "4.9.3+20250725" + + assertEquals( + Status.UPDATABLE, appLoungePackageManager.getPackageStatus( + packageName = testPackageName, + versionCode = newVersionCode, + versionName = newVersionName, + ) + ) + } + } -- GitLab