refactor: break down AppInstallProcessor into collaborator classes
Description
This MR refactors AppInstallProcessor into smaller, tightly scoped, unit-testable components while preserving current behaviour and keeping the public API (mostly) unchanged.
Please review the MR commit by commit to understand how the refactoring evolved. Otherwise, you can review the changes at once; for your aid in the review process, a diagram, and a guide have been added in the Technical details section.
Technical details
Before refactor
Before the refactor, AppInstallProcessor was effectively the central class for almost all install-related responsibilities.
classDiagram
class AppInstallProcessor_PreRefactor {
+initAppInstall(...)
+enqueueFusedDownload(...)
+canEnqueue(...)
+validateAgeLimit(...)
+awaitInvokeAgeLimitEvent(...)
+updateDownloadUrls(...)
+processInstall(...)
+checkDownloadingState(...)
+startAppInstallationProcess(...)
+handleFusedDownloadStatus(...)
+checkUpdateWork(...)
+showNotificationOnUpdateEnded(...)
}
class EventBus
class StorageComputer
class ParentalControlAuthenticator
class UpdatesDao
class UpdatesNotifier
class AppInstallComponents
class ApplicationRepository
class AppLoungeDataStore
class StorageNotificationManager
class DownloadManagerUtils
class AppManager
class ValidateAppAgeLimitUseCase
AppInstallProcessor_PreRefactor --> AppInstallComponents
AppInstallProcessor_PreRefactor --> ApplicationRepository
AppInstallProcessor_PreRefactor --> AppLoungeDataStore
AppInstallProcessor_PreRefactor --> StorageNotificationManager
AppInstallProcessor_PreRefactor --> DownloadManagerUtils
AppInstallProcessor_PreRefactor --> AppManager
AppInstallProcessor_PreRefactor --> ValidateAppAgeLimitUseCase
AppInstallProcessor_PreRefactor --> EventBus
AppInstallProcessor_PreRefactor --> StorageComputer
AppInstallProcessor_PreRefactor --> ParentalControlAuthenticator
AppInstallProcessor_PreRefactor --> UpdatesDao
AppInstallProcessor_PreRefactor --> UpdatesNotifier
After refactor
This diagram gives a reviewer-friendly starting point for the install/update flow under:
app/src/main/java/foundation/e/apps/data/install/core/app/src/main/java/foundation/e/apps/data/install/core/helper/data/src/main/java/foundation/e/apps/data/installation/core/
It also includes the small remaining boundary types used by that flow:
app/src/main/java/foundation/e/apps/data/install/wrapper/AppEventDispatcher.ktdata/src/main/java/foundation/e/apps/data/installation/port/InstallationDownloadStatusUpdater.ktdata/src/main/java/foundation/e/apps/data/installation/port/InstallationCompletionNotifier.kt
classDiagram
direction LR
class AppInstallationFacade
class InstallationRequest
class InstallationEnqueuer
class PreEnqueueChecker
class DownloadUrlRefresher
class AgeLimiter
class DevicePreconditions
class InstallationProcessor
class AppManager
class InstallationDownloadStatusUpdater
class InstallationCompletionNotifier
class InstallationCompletionHandler
class AppEventDispatcher
class ParentalControlAuthenticator
class StorageComputer
class UpdatesDao
class UpdatesNotifier
AppInstallationFacade --> InstallationRequest : creates AppInstall
AppInstallationFacade --> InstallationEnqueuer : enqueue path
AppInstallationFacade --> InstallationProcessor : process path
InstallationEnqueuer --> PreEnqueueChecker : validates before enqueue
PreEnqueueChecker --> DownloadUrlRefresher
PreEnqueueChecker --> AgeLimiter
PreEnqueueChecker --> DevicePreconditions
AgeLimiter --> AppEventDispatcher : emits age-limit event
AgeLimiter --> ParentalControlAuthenticator : awaits PIN auth
DevicePreconditions --> AppEventDispatcher : emits device errors
DevicePreconditions --> StorageComputer : checks free space
InstallationProcessor --> AppManager : install and status changes
InstallationProcessor --> InstallationDownloadStatusUpdater : refreshes downloads
InstallationProcessor --> InstallationCompletionNotifier : finishes update flow
InstallationCompletionNotifier <|.. InstallationCompletionHandler
InstallationCompletionHandler --> AppManager : reads install result
InstallationCompletionHandler --> UpdatesDao : tracks updated apps
InstallationCompletionHandler --> UpdatesNotifier : shows update summary
Reading guide
- Start at
AppInstallationFacade. - The enqueue side stays in
app:InstallationRequest -> InstallationEnqueuer -> PreEnqueueChecker. -
PreEnqueueCheckerfans out into three app-side checks: URL refresh, age-limit validation, and device preconditions. -
AppEventDispatcherremains as a small app-local seam for event dispatch. - The processing side lives across
appanddata:InstallationProcessoris indata, and it only depends on the two remaining install ports:InstallationDownloadStatusUpdaterInstallationCompletionNotifier
-
InstallationCompletionHandleris the app-side implementation of the completion port. It now talks directly toUpdatesDaoandUpdatesNotifier. -
AppManageris the main shared collaborator across both enqueue and processing paths.
Layer split
-
app: facade, enqueue flow, event dispatch, update notification, and completion handling -
data:InstallationProcessor, install models/repository, and the two remaining install ports - Current boundary:
dataonly abstracts what it cannot depend on fromapp
Tests
Issues
https://gitlab.e.foundation/e/os/backlog/-/issues/4177
https://gitlab.e.foundation/e/os/backlog/-/issues/4165