SessionInstaller: Enqueue sessions using SessionInfo class

Cleaner as well as avoid scenarios where download object gets overwritten by next
enqueued install resulting in wrong information

Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
This commit is contained in:
Aayush Gupta
2024-06-11 17:18:01 +05:30
parent c92c4220d7
commit 590e325753
2 changed files with 42 additions and 31 deletions

View File

@@ -42,6 +42,7 @@ import com.aurora.store.data.installer.AppInstaller.Companion.EXTRA_DISPLAY_NAME
import com.aurora.store.data.installer.AppInstaller.Companion.EXTRA_PACKAGE_NAME import com.aurora.store.data.installer.AppInstaller.Companion.EXTRA_PACKAGE_NAME
import com.aurora.store.data.installer.AppInstaller.Companion.EXTRA_VERSION_CODE import com.aurora.store.data.installer.AppInstaller.Companion.EXTRA_VERSION_CODE
import com.aurora.store.data.model.InstallerInfo import com.aurora.store.data.model.InstallerInfo
import com.aurora.store.data.model.SessionInfo
import com.aurora.store.data.receiver.InstallerStatusReceiver import com.aurora.store.data.receiver.InstallerStatusReceiver
import com.aurora.store.data.room.download.Download import com.aurora.store.data.room.download.Download
import com.aurora.store.util.Log import com.aurora.store.util.Log
@@ -56,10 +57,10 @@ class SessionInstaller @Inject constructor(
) : InstallerBase(context) { ) : InstallerBase(context) {
val currentSessionId: Int? val currentSessionId: Int?
get() = enqueuedSessions.firstOrNull()?.keys?.last() get() = enqueuedSessions.firstOrNull()?.last()?.sessionId
private val packageInstaller = context.packageManager.packageInstaller private val packageInstaller = context.packageManager.packageInstaller
private val enqueuedSessions = mutableListOf<MutableMap<Int, String>>() private val enqueuedSessions = mutableListOf<MutableSet<SessionInfo>>()
val callback = object : PackageInstaller.SessionCallback() { val callback = object : PackageInstaller.SessionCallback() {
override fun onCreated(sessionId: Int) {} override fun onCreated(sessionId: Int) {}
@@ -71,22 +72,20 @@ class SessionInstaller @Inject constructor(
override fun onProgressChanged(sessionId: Int, progress: Float) {} override fun onProgressChanged(sessionId: Int, progress: Float) {}
override fun onFinished(sessionId: Int, success: Boolean) { override fun onFinished(sessionId: Int, success: Boolean) {
enqueuedSessions.find { it.containsKey(sessionId) }?.let { sessionMap -> enqueuedSessions.find { set -> set.any { it.sessionId == sessionId } }?.let { sessionSet ->
sessionMap.remove(sessionId) sessionSet.remove(sessionSet.first { it.sessionId == sessionId })
// If this was a shared lib, proceed installing other libs or actual package // If this was a shared lib, proceed installing other libs or actual package
if (sessionMap.isNotEmpty() && success) { if (sessionSet.isNotEmpty() && success) {
val nextSession = sessionMap.keys.first() commitInstall(sessionSet.first()); return
commitInstall(sessionMap.getValue(nextSession), nextSession); return
} else { } else {
enqueuedSessions.remove(sessionMap) enqueuedSessions.remove(sessionSet)
} }
} }
if (enqueuedSessions.isNotEmpty()) { if (enqueuedSessions.isNotEmpty()) {
enqueuedSessions.firstOrNull()?.let { sessionMap -> enqueuedSessions.firstOrNull()?.let { sessionSet ->
val nextSession = sessionMap.keys.first() commitInstall(sessionSet.first())
commitInstall(sessionMap.getValue(nextSession), nextSession)
} }
} else { } else {
// Nothing else in queue, unregister callback // Nothing else in queue, unregister callback
@@ -114,33 +113,37 @@ class SessionInstaller @Inject constructor(
override fun install(download: Download) { override fun install(download: Download) {
super.install(download) super.install(download)
val sessionMap = enqueuedSessions.find { it.values.contains(download.packageName) } val sessionSet = enqueuedSessions.find { set -> set.any { it.packageName == download.packageName } }
if (sessionMap != null) { if (sessionSet != null) {
Log.i("${download.packageName} already queued") Log.i("${download.packageName} already queued")
commitInstall(sessionMap.getValue(sessionMap.keys.first()), sessionMap.keys.first()) commitInstall(sessionSet.first())
} else { } else {
Log.i("Received session install request for ${download.packageName}") Log.i("Received session install request for ${download.packageName}")
val sessionIdMap = mutableMapOf<Int, String>() val sessionInfoSet = mutableSetOf<SessionInfo>()
download.sharedLibs.forEach { download.sharedLibs.forEach {
// Shared library packages cannot be updated // Shared library packages cannot be updated
if (!isSharedLibraryInstalled(context, it.packageName, it.versionCode)) { if (!isSharedLibraryInstalled(context, it.packageName, it.versionCode)) {
stageInstall(download.packageName, download.versionCode, it.packageName)?.let { sessionID -> stageInstall(download.packageName, download.versionCode, it.packageName)?.let { sessionID ->
sessionIdMap[sessionID] = it.packageName sessionInfoSet.add(SessionInfo(sessionID, it.packageName, it.versionCode))
} }
} }
} }
stageInstall(download.packageName, download.versionCode)?.let { sessionID -> stageInstall(download.packageName, download.versionCode)?.let { sessionID ->
sessionIdMap[sessionID] = download.packageName sessionInfoSet.add(
SessionInfo(
sessionID,
download.packageName,
download.versionCode,
download.displayName
)
)
} }
// Enqueue and trigger installation // Enqueue and trigger installation
enqueuedSessions.add(sessionIdMap) enqueuedSessions.add(sessionInfoSet)
commitInstall( commitInstall(sessionInfoSet.first())
sessionIdMap.getValue(sessionIdMap.keys.first()),
sessionIdMap.keys.first()
)
} }
} }
@@ -189,26 +192,26 @@ class SessionInstaller @Inject constructor(
} }
} }
private fun commitInstall(packageName: String, sessionId: Int) { private fun commitInstall(sessionInfo: SessionInfo) {
Log.i("Starting install session for $packageName") Log.i("Starting install session for ${sessionInfo.packageName}")
val session = packageInstaller.openSession(sessionId) val session = packageInstaller.openSession(sessionInfo.sessionId)
session.commit(getCallBackIntent(packageName, sessionId)!!.intentSender) session.commit(getCallBackIntent(sessionInfo)!!.intentSender)
session.close() session.close()
} }
private fun getCallBackIntent(packageName: String, sessionId: Int): PendingIntent? { private fun getCallBackIntent(sessionInfo: SessionInfo): PendingIntent? {
val callBackIntent = Intent(context, InstallerStatusReceiver::class.java).apply { val callBackIntent = Intent(context, InstallerStatusReceiver::class.java).apply {
action = ACTION_INSTALL_STATUS action = ACTION_INSTALL_STATUS
setPackage(context.packageName) setPackage(context.packageName)
putExtra(EXTRA_PACKAGE_NAME, packageName) putExtra(EXTRA_PACKAGE_NAME, sessionInfo.packageName)
putExtra(EXTRA_VERSION_CODE, download!!.versionCode) putExtra(EXTRA_VERSION_CODE, sessionInfo.versionCode)
putExtra(EXTRA_DISPLAY_NAME, download!!.displayName) putExtra(EXTRA_DISPLAY_NAME, sessionInfo.displayName)
addFlags(Intent.FLAG_RECEIVER_FOREGROUND) addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
} }
return PendingIntentCompat.getBroadcast( return PendingIntentCompat.getBroadcast(
context, context,
sessionId, sessionInfo.sessionId,
callBackIntent, callBackIntent,
PendingIntent.FLAG_UPDATE_CURRENT, PendingIntent.FLAG_UPDATE_CURRENT,
true true

View File

@@ -0,0 +1,8 @@
package com.aurora.store.data.model
data class SessionInfo(
val sessionId: Int,
val packageName: String,
val versionCode: Int,
val displayName: String = String()
)