Skip to content

Commit

Permalink
complete SessionBasedInstallSession if it's a self-update which succe…
Browse files Browse the repository at this point in the history
…eded

partial fix for #33
  • Loading branch information
solrudev committed Jan 6, 2024
1 parent 3dfb17c commit 2c245c1
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@
package ru.solrudev.ackpine.impl.database.dao

import androidx.annotation.RestrictTo
import androidx.room.*
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Transaction
import ru.solrudev.ackpine.impl.database.AckpineDatabase
import ru.solrudev.ackpine.impl.database.model.InstallUriEntity
import ru.solrudev.ackpine.impl.database.model.SessionEntity
Expand Down Expand Up @@ -60,6 +64,10 @@ internal abstract class InstallSessionDao protected constructor(private val data
@Query("SELECT * FROM sessions")
abstract fun getInstallSessions(): List<SessionEntity.InstallSession>

@Transaction
@Query("SELECT * FROM sessions WHERE state = 'COMMITTED'")
abstract fun getCommittedInstallSessions(): List<SessionEntity.InstallSession>

@Query("INSERT OR IGNORE INTO sessions_install_failures(session_id, failure) VALUES (:id, :failure)")
protected abstract fun insertInstallFailure(id: String, failure: InstallFailure)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ internal class PackageInstallerImpl internal constructor(
private val installSessionFactory: InstallSessionFactory
) : PackageInstaller {

init {
// When install session is a self-update, session is stuck in Committed state after new process start.
// We initialize sessions in Committed state eagerly, so that they can complete themselves if they are in fact
// completed. There shouldn't be many of these sessions.
initializeCommittedSessions()
}

private val sessions = ConcurrentHashMap<UUID, ProgressSession<InstallFailure>>()

@Volatile
Expand Down Expand Up @@ -110,6 +117,13 @@ internal class PackageInstallerImpl internal constructor(
return initializeSessions { sessions -> sessions.filter { it.isActive } }
}

private fun initializeCommittedSessions() = executor.execute {
for (session in installSessionDao.getCommittedInstallSessions()) {
val installSession = session.toInstallSession()
sessions[installSession.id] = installSession
}
}

@SuppressLint("RestrictedApi")
private inline fun initializeSessions(
crossinline transform: (Iterable<ProgressSession<InstallFailure>>) -> List<ProgressSession<InstallFailure>>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ import ru.solrudev.ackpine.impl.session.helpers.launchConfirmation
import ru.solrudev.ackpine.installer.InstallFailure
import ru.solrudev.ackpine.session.Progress
import ru.solrudev.ackpine.session.Session
import ru.solrudev.ackpine.session.Session.State.Committed
import ru.solrudev.ackpine.session.Session.State.Succeeded
import ru.solrudev.ackpine.session.parameters.Confirmation
import ru.solrudev.ackpine.session.parameters.NotificationData
import java.util.UUID
Expand Down Expand Up @@ -90,7 +92,14 @@ internal class SessionBasedInstallSession internal constructor(

init {
serialExecutor.execute {
nativeSessionId = nativeSessionIdDao.getNativeSessionId(id.toString()) ?: -1
val nativeSessionId = nativeSessionIdDao.getNativeSessionId(id.toString()) ?: -1
this.nativeSessionId = nativeSessionId
// When install session is a self-update, session is stuck in Committed state after new process start.
// Fails are guaranteed to be handled by PackageInstallerStatusReceiver,
// so if native session doesn't exist, it can only mean that it succeeded.
if (initialState is Committed && packageInstaller.getSessionInfo(nativeSessionId) == null) {
complete(Succeeded)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package ru.solrudev.ackpine.installer
import android.content.Context
import android.os.Handler
import com.google.common.util.concurrent.ListenableFuture
import ru.solrudev.ackpine.helpers.SerialExecutor
import ru.solrudev.ackpine.impl.database.AckpineDatabase
import ru.solrudev.ackpine.impl.installer.InstallSessionFactoryImpl
import ru.solrudev.ackpine.impl.installer.PackageInstallerImpl
Expand Down Expand Up @@ -111,7 +112,7 @@ public interface PackageInstaller {
return PackageInstallerImpl(
database.installSessionDao(),
database.sessionProgressDao(),
PackageInstallerPlugin.executor,
SerialExecutor(PackageInstallerPlugin.executor),
InstallSessionFactoryImpl(
context.applicationContext,
database.sessionDao(),
Expand Down

0 comments on commit 2c245c1

Please sign in to comment.