Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a03579a6 authored by Sayantan Roychowdhury's avatar Sayantan Roychowdhury
Browse files

Merge branch 'release-1.9-rc'

# Conflicts:
#	app/src/main/java/foundation/e/apps/manager/workmanager/AppInstallProcessor.kt
parents 12ed556b 6b0e1cd7
Loading
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -11,7 +11,7 @@ plugins {


def versionMajor = 2
def versionMajor = 2
def versionMinor = 4
def versionMinor = 4
def versionPatch = 7
def versionPatch = 8


def getGitHash = { ->
def getGitHash = { ->
    def stdOut = new ByteArrayOutputStream()
    def stdOut = new ByteArrayOutputStream()
+17 −30
Original line number Original line Diff line number Diff line
@@ -92,10 +92,18 @@ class DownloadManager @Inject constructor(
        downloadFile: File,
        downloadFile: File,
        downloadCompleted: ((Boolean, String) -> Unit)?
        downloadCompleted: ((Boolean, String) -> Unit)?
    ): Long {
    ): Long {
        var downloadId = -1L
        try {
            val request = DownloadManager.Request(Uri.parse(url))
            val request = DownloadManager.Request(Uri.parse(url))
                .setTitle("Downloading...")
                .setTitle("Downloading...")
                .setDestinationUri(Uri.fromFile(downloadFile))
                .setDestinationUri(Uri.fromFile(downloadFile))
        val downloadId = downloadManager.enqueue(request)
            downloadId = downloadManager.enqueue(request)
        } catch (e: java.lang.NullPointerException) {
            Timber.e(e, "Url: $url; downloadFilePath: ${downloadFile.absolutePath}")
            downloadCompleted?.invoke(false, e.localizedMessage ?: "No message found!")
            return downloadId
        }

        downloadsMaps[downloadId] = true
        downloadsMaps[downloadId] = true
        tickerFlow(downloadId, .5.seconds).onEach {
        tickerFlow(downloadId, .5.seconds).onEach {
            checkDownloadProgress(downloadId, downloadFile.absolutePath, downloadCompleted)
            checkDownloadProgress(downloadId, downloadFile.absolutePath, downloadCompleted)
@@ -150,6 +158,10 @@ class DownloadManager @Inject constructor(
        return getDownloadStatus(downloadId) == DownloadManager.STATUS_SUCCESSFUL
        return getDownloadStatus(downloadId) == DownloadManager.STATUS_SUCCESSFUL
    }
    }


    fun hasDownloadFailed(downloadId: Long): Boolean {
        return getDownloadStatus(downloadId) == DownloadManager.STATUS_FAILED
    }

    private fun getDownloadStatus(downloadId: Long): Int {
    private fun getDownloadStatus(downloadId: Long): Int {
        try {
        try {
            downloadManager.query(downloadManagerQuery.setFilterById(downloadId))
            downloadManager.query(downloadManagerQuery.setFilterById(downloadId))
@@ -157,7 +169,7 @@ class DownloadManager @Inject constructor(
                    if (cursor.moveToFirst()) {
                    if (cursor.moveToFirst()) {
                        val status =
                        val status =
                            cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS))
                            cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS))
                        Timber.d("Download Failed: downloadId: $downloadId $status")
                        Timber.d("Download Status: downloadId: $downloadId $status")
                        return status
                        return status
                    }
                    }
                }
                }
@@ -166,29 +178,4 @@ class DownloadManager @Inject constructor(
        }
        }
        return DownloadManager.STATUS_FAILED
        return DownloadManager.STATUS_FAILED
    }
    }

    suspend fun checkDownloadProcess(downloadingIds: LongArray, handleFailed: suspend () -> Unit) {
        try {
            downloadManager.query(downloadManagerQuery.setFilterById(*downloadingIds))
                .use { cursor ->

                    if (!cursor.moveToFirst()) {
                        return@use
                    }

                    while (!cursor.isAfterLast) {
                        val status =
                            cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS))

                        if (status == DownloadManager.STATUS_FAILED) {
                            handleFailed()
                        }

                        cursor.moveToNext()
                    }
                }
        } catch (e: Exception) {
            Timber.e(e)
        }
    }
}
}
+21 −5
Original line number Original line Diff line number Diff line
@@ -64,15 +64,30 @@ class DownloadManagerUtils @Inject constructor(
                        fusedDownload.downloadIdMap.values.filter { it }.size
                        fusedDownload.downloadIdMap.values.filter { it }.size
                    Timber.d("===> updateDownloadStatus: ${fusedDownload.name}: $downloadId: $numberOfDownloadedItems/${fusedDownload.downloadIdMap.size}")
                    Timber.d("===> updateDownloadStatus: ${fusedDownload.name}: $downloadId: $numberOfDownloadedItems/${fusedDownload.downloadIdMap.size}")


                    if (downloadManager.hasDownloadFailed(downloadId)) {
                        handleDownloadFailed(fusedDownload)
                        return@launch
                    }

                    if (validateDownload(numberOfDownloadedItems, fusedDownload, downloadId)) {
                    if (validateDownload(numberOfDownloadedItems, fusedDownload, downloadId)) {
                        handleDownloadSuccess(fusedDownload)
                    }
                }
            }
        }
    }

    private suspend fun handleDownloadSuccess(fusedDownload: FusedDownload) {
        Timber.i("===> Download is completed for: ${fusedDownload.name}")
        Timber.i("===> Download is completed for: ${fusedDownload.name}")
        fusedManagerRepository.moveOBBFileToOBBDirectory(fusedDownload)
        fusedManagerRepository.moveOBBFileToOBBDirectory(fusedDownload)
        fusedDownload.status = Status.DOWNLOADED
        fusedDownload.status = Status.DOWNLOADED
        fusedManagerRepository.updateFusedDownload(fusedDownload)
        fusedManagerRepository.updateFusedDownload(fusedDownload)
    }
    }
                }

            }
    private suspend fun handleDownloadFailed(fusedDownload: FusedDownload) {
        }
        fusedManagerRepository.installationIssue(fusedDownload)
        fusedManagerRepository.cancelDownload(fusedDownload)
        Timber.i("===> Download failed: ${fusedDownload.name} ${fusedDownload.status}")
    }
    }


    private suspend fun validateDownload(
    private suspend fun validateDownload(
@@ -88,7 +103,8 @@ class DownloadManagerUtils @Inject constructor(
    private fun areAllFilesDownloaded(
    private fun areAllFilesDownloaded(
        numberOfDownloadedItems: Int,
        numberOfDownloadedItems: Int,
        fusedDownload: FusedDownload
        fusedDownload: FusedDownload
    ) = numberOfDownloadedItems == fusedDownload.downloadIdMap.size
    ) = numberOfDownloadedItems == fusedDownload.downloadIdMap.size &&
        numberOfDownloadedItems == fusedDownload.downloadURLList.size


    private suspend fun updateDownloadIdMap(
    private suspend fun updateDownloadIdMap(
        fusedDownload: FusedDownload,
        fusedDownload: FusedDownload,
+3 −1
Original line number Original line Diff line number Diff line
@@ -156,8 +156,10 @@ class FusedManagerImpl @Inject constructor(


            // Reset the status before deleting download
            // Reset the status before deleting download
            updateDownloadStatus(fusedDownload, fusedDownload.orgStatus)
            updateDownloadStatus(fusedDownload, fusedDownload.orgStatus)

            if (fusedDownload.status != Status.INSTALLATION_ISSUE) {
                databaseRepository.deleteDownload(fusedDownload)
                databaseRepository.deleteDownload(fusedDownload)
            }

            flushOldDownload(fusedDownload.packageName)
            flushOldDownload(fusedDownload.packageName)
        } else {
        } else {
            Timber.d("Unable to cancel download!")
            Timber.d("Unable to cancel download!")
+12 −23
Original line number Original line Diff line number Diff line
@@ -21,7 +21,6 @@ package foundation.e.apps.manager.workmanager
import android.content.Context
import android.content.Context
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.android.qualifiers.ApplicationContext
import foundation.e.apps.R
import foundation.e.apps.R
import foundation.e.apps.api.DownloadManager
import foundation.e.apps.api.fused.UpdatesDao
import foundation.e.apps.api.fused.UpdatesDao
import foundation.e.apps.manager.database.DatabaseRepository
import foundation.e.apps.manager.database.DatabaseRepository
import foundation.e.apps.manager.database.fusedDownload.FusedDownload
import foundation.e.apps.manager.database.fusedDownload.FusedDownload
@@ -29,7 +28,6 @@ import foundation.e.apps.manager.fused.FusedManagerRepository
import foundation.e.apps.updates.UpdatesNotifier
import foundation.e.apps.updates.UpdatesNotifier
import foundation.e.apps.utils.enums.ResultStatus
import foundation.e.apps.utils.enums.ResultStatus
import foundation.e.apps.utils.enums.Status
import foundation.e.apps.utils.enums.Status
import foundation.e.apps.utils.enums.Type
import foundation.e.apps.utils.modules.DataStoreManager
import foundation.e.apps.utils.modules.DataStoreManager
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Dispatchers
@@ -50,7 +48,6 @@ class AppInstallProcessor @Inject constructor(
    @ApplicationContext private val context: Context,
    @ApplicationContext private val context: Context,
    private val databaseRepository: DatabaseRepository,
    private val databaseRepository: DatabaseRepository,
    private val fusedManagerRepository: FusedManagerRepository,
    private val fusedManagerRepository: FusedManagerRepository,
    private val downloadManager: DownloadManager,
    private val dataStoreManager: DataStoreManager
    private val dataStoreManager: DataStoreManager
) {
) {


@@ -91,10 +88,7 @@ class AppInstallProcessor @Inject constructor(
                    return@let
                    return@let
                }
                }


                if (fusedDownload.areFilesDownloaded() && !fusedManagerRepository.isFusedDownloadInstalled(
                if (areFilesDownloadedButNotInstalled(fusedDownload)) {
                        fusedDownload
                    )
                ) {
                    Timber.i("===> Downloaded But not installed ${fusedDownload.name}")
                    Timber.i("===> Downloaded But not installed ${fusedDownload.name}")
                    fusedManagerRepository.updateDownloadStatus(fusedDownload, Status.INSTALLING)
                    fusedManagerRepository.updateDownloadStatus(fusedDownload, Status.INSTALLING)
                }
                }
@@ -107,7 +101,7 @@ class AppInstallProcessor @Inject constructor(
        } catch (e: Exception) {
        } catch (e: Exception) {
            Timber.e("doWork: Failed: ${e.stackTraceToString()}")
            Timber.e("doWork: Failed: ${e.stackTraceToString()}")
            fusedDownload?.let {
            fusedDownload?.let {
                fusedManagerRepository.installationIssue(it)
                fusedManagerRepository.cancelDownload(fusedDownload)
            }
            }
        }
        }


@@ -115,6 +109,13 @@ class AppInstallProcessor @Inject constructor(
        return Result.success(ResultStatus.OK)
        return Result.success(ResultStatus.OK)
    }
    }


    private fun areFilesDownloadedButNotInstalled(fusedDownload: FusedDownload) =
        fusedDownload.areFilesDownloaded() && (
            !fusedManagerRepository.isFusedDownloadInstalled(
                fusedDownload
            ) || fusedDownload.status == Status.INSTALLING
            )

    private suspend fun checkUpdateWork(
    private suspend fun checkUpdateWork(
        fusedDownload: FusedDownload?
        fusedDownload: FusedDownload?
    ) {
    ) {
@@ -181,22 +182,16 @@ class AppInstallProcessor @Inject constructor(
            .onEach {
            .onEach {
                val download = databaseRepository.getDownloadById(fusedDownload.id)
                val download = databaseRepository.getDownloadById(fusedDownload.id)
                if (download == null) {
                if (download == null) {
                    Timber.d("===> download null: finish installation")
                    finishInstallation(fusedDownload)
                    finishInstallation(fusedDownload)
                } else {
                } else {
                    handleFusedDownloadStatusCheckingException(download)
                    handleFusedDownloadStatusCheckingException(download)
                    if (isAppDownloading(download)) {
                        checkDownloadProcess(download)
                    }
                }
                }
            }.launchIn(CoroutineScope(Dispatchers.IO))
            }.launchIn(CoroutineScope(Dispatchers.IO))
        Timber.d(">>> ===> doWork: Download started " + fusedDownload.name + " " + fusedDownload.status)
        Timber.d(">>> ===> doWork: Download started " + fusedDownload.name + " " + fusedDownload.status)
        return true
        return true
    }
    }


    private fun isAppDownloading(download: FusedDownload): Boolean {
        return download.type == Type.NATIVE && download.status != Status.INSTALLED && download.status != Status.INSTALLATION_ISSUE
    }

    private suspend fun handleFusedDownloadStatusCheckingException(
    private suspend fun handleFusedDownloadStatusCheckingException(
        download: FusedDownload
        download: FusedDownload
    ) {
    ) {
@@ -222,12 +217,6 @@ class AppInstallProcessor @Inject constructor(
        }
        }
    }
    }


    private suspend fun checkDownloadProcess(fusedDownload: FusedDownload) {
        downloadManager.checkDownloadProcess(fusedDownload.downloadIdMap.keys.toLongArray()) {
            fusedManagerRepository.installationIssue(fusedDownload)
        }
    }

    private suspend fun handleFusedDownloadStatus(fusedDownload: FusedDownload) {
    private suspend fun handleFusedDownloadStatus(fusedDownload: FusedDownload) {
        when (fusedDownload.status) {
        when (fusedDownload.status) {
            Status.AWAITING, Status.DOWNLOADING -> {
            Status.AWAITING, Status.DOWNLOADING -> {
@@ -239,15 +228,15 @@ class AppInstallProcessor @Inject constructor(
                Timber.i("===> doWork: Installing ${fusedDownload.name} ${fusedDownload.status}")
                Timber.i("===> doWork: Installing ${fusedDownload.name} ${fusedDownload.status}")
            }
            }
            Status.INSTALLED, Status.INSTALLATION_ISSUE -> {
            Status.INSTALLED, Status.INSTALLATION_ISSUE -> {
                finishInstallation(fusedDownload)
                Timber.i("===> doWork: Installed/Failed: ${fusedDownload.name} ${fusedDownload.status}")
                Timber.i("===> doWork: Installed/Failed: ${fusedDownload.name} ${fusedDownload.status}")
                finishInstallation(fusedDownload)
            }
            }
            else -> {
            else -> {
                finishInstallation(fusedDownload)
                Timber.wtf(
                Timber.wtf(
                    TAG,
                    TAG,
                    "===> ${fusedDownload.name} is in wrong state ${fusedDownload.status}"
                    "===> ${fusedDownload.name} is in wrong state ${fusedDownload.status}"
                )
                )
                finishInstallation(fusedDownload)
            }
            }
        }
        }
    }
    }