microg: improve installer state detection

This commit is contained in:
Rahul Patel
2026-05-12 20:51:21 +05:30
parent 53aff0e24f
commit ff69759634
3 changed files with 60 additions and 21 deletions

View File

@@ -620,7 +620,7 @@ private fun ScreenContentApp(
is ExtraScreen.MicroG -> MicroGScreen( is ExtraScreen.MicroG -> MicroGScreen(
packageName = app.packageName, packageName = app.packageName,
onNavigateUp = ::onNavigateBack, onNavigateUp = ::onNavigateBack,
onIgnore = { onInstall(ignoreMicroG = it) } onProceed = { onInstall(ignoreMicroG = true) }
) )
is Screen.DevProfile -> DevProfileScreen( is Screen.DevProfile -> DevProfileScreen(

View File

@@ -56,14 +56,14 @@ import com.aurora.store.viewmodel.onboarding.MicroGViewModel
fun MicroGScreen( fun MicroGScreen(
packageName: String, packageName: String,
onNavigateUp: () -> Unit, onNavigateUp: () -> Unit,
onIgnore: (Boolean) -> Unit, onProceed: () -> Unit,
appDetailsViewModel: AppDetailsViewModel = hiltViewModel(key = packageName), appDetailsViewModel: AppDetailsViewModel = hiltViewModel(key = packageName),
viewModel: MicroGViewModel = hiltViewModel(), viewModel: MicroGViewModel = hiltViewModel(),
windowAdaptiveInfo: WindowAdaptiveInfo = currentWindowAdaptiveInfoV2() windowAdaptiveInfo: WindowAdaptiveInfo = currentWindowAdaptiveInfoV2()
) { ) {
val app by appDetailsViewModel.app.collectAsStateWithLifecycle() val app by appDetailsViewModel.app.collectAsStateWithLifecycle()
val topAppBarTitle = when { val topAppBarTitle = when {
windowAdaptiveInfo.isWindowCompact -> app!!.displayName windowAdaptiveInfo.isWindowCompact -> app?.displayName
else -> stringResource(R.string.onboarding_title_gsf) else -> stringResource(R.string.onboarding_title_gsf)
} }
@@ -73,7 +73,7 @@ fun MicroGScreen(
onNavigateUp = onNavigateUp, onNavigateUp = onNavigateUp,
onInstall = { viewModel.downloadMicroG() }, onInstall = { viewModel.downloadMicroG() },
onRetry = { viewModel.retryDownload() }, onRetry = { viewModel.retryDownload() },
onIgnore = onIgnore onProceed = onProceed
) )
} }
@@ -84,7 +84,7 @@ private fun ScreenContent(
onNavigateUp: () -> Unit = {}, onNavigateUp: () -> Unit = {},
onInstall: () -> Unit = {}, onInstall: () -> Unit = {},
onRetry: () -> Unit = {}, onRetry: () -> Unit = {},
onIgnore: (Boolean) -> Unit = {}, onProceed: () -> Unit = {},
windowAdaptiveInfo: WindowAdaptiveInfo = currentWindowAdaptiveInfoV2() windowAdaptiveInfo: WindowAdaptiveInfo = currentWindowAdaptiveInfoV2()
) { ) {
val context = LocalContext.current val context = LocalContext.current
@@ -123,7 +123,7 @@ private fun ScreenContent(
Button( Button(
modifier = Modifier.weight(1F), modifier = Modifier.weight(1F),
onClick = { onIgnore(uiState.isInstalled) }, onClick = onProceed,
enabled = !uiState.isInProgress enabled = !uiState.isInProgress
) { ) {
Text( Text(

View File

@@ -113,20 +113,33 @@ class MicroGViewModel @Inject constructor(
private val bundle = listOf(microGServiceApk, microGCompanionApk) private val bundle = listOf(microGServiceApk, microGCompanionApk)
init { init {
AuroraApp.events.installerEvent.onEach { AuroraApp.events.installerEvent.onEach { event ->
if (it is InstallerEvent.Installed) refresh() when (event) {
is InstallerEvent.Installed -> refresh()
is InstallerEvent.Uninstalled -> handleUninstall(event.packageName)
else -> {}
}
}.launchIn(AuroraApp.scope) }.launchIn(AuroraApp.scope)
combine( viewModelScope.launch {
downloadHelper.downloadsList, bundle.forEach { apk ->
networkProvider.status.onStart { emit(NetworkStatus.AVAILABLE) } val download = downloadHelper.getDownload(apk.packageName)
) { downloads, network -> if (download?.status == DownloadStatus.COMPLETED && !isBundleApkInstalled(apk)) {
val byPackage = downloads.associateBy { it.packageName } downloadHelper.removeDownload(apk.packageName)
MicroGUIState( }
items = bundle.map { apk -> buildItem(apk, byPackage[apk.packageName]) }, }
isOnline = network == NetworkStatus.AVAILABLE
) combine(
}.onEach { uiState = it }.launchIn(viewModelScope) downloadHelper.downloadsList,
networkProvider.status.onStart { emit(NetworkStatus.AVAILABLE) }
) { downloads, network ->
val byPackage = downloads.associateBy { it.packageName }
MicroGUIState(
items = bundle.map { apk -> buildItem(apk, byPackage[apk.packageName]) },
isOnline = network == NetworkStatus.AVAILABLE
)
}.onEach { uiState = it }.launchIn(viewModelScope)
}
} }
fun downloadMicroG() { fun downloadMicroG() {
@@ -147,18 +160,44 @@ class MicroGViewModel @Inject constructor(
} }
private suspend fun enqueueIfNeeded(apk: ExternalApk) { private suspend fun enqueueIfNeeded(apk: ExternalApk) {
if (apk.isInstalled(context)) { if (isBundleApkInstalled(apk)) {
AuroraApp.events.send(InstallerEvent.Installed(apk.packageName)) AuroraApp.events.send(InstallerEvent.Installed(apk.packageName))
} else { } else {
downloadHelper.enqueueStandalone(apk) downloadHelper.enqueueStandalone(apk)
} }
} }
// Validate against the microG-specific signature/version checks rather than mere package
// presence — a stock Play Store or older Companion would otherwise be reported as installed.
private fun isBundleApkInstalled(apk: ExternalApk): Boolean = when (apk.packageName) {
PACKAGE_NAME_GMS -> PackageUtil.hasSupportedMicroGVariant(context)
PACKAGE_NAME_PLAY_STORE -> PackageUtil.hasMicroGCompanion(context)
else -> apk.isInstalled(context)
}
private fun handleUninstall(packageName: String) {
val apk = bundle.find { it.packageName == packageName } ?: return
viewModelScope.launch {
downloadHelper.removeDownload(packageName)
uiState = uiState.copy(
items = uiState.items.map { item ->
if (item.packageName == apk.packageName) {
item.copy(status = InstallStatus.PENDING, progress = 0)
} else {
item
}
}
)
}
}
private fun refresh() { private fun refresh() {
uiState = uiState.copy( uiState = uiState.copy(
items = uiState.items.map { item -> items = uiState.items.map { item ->
val apk = bundle.find { it.packageName == item.packageName }
if (item.status != InstallStatus.INSTALLED && if (item.status != InstallStatus.INSTALLED &&
PackageUtil.isInstalled(context, item.packageName) apk != null &&
isBundleApkInstalled(apk)
) { ) {
item.copy(status = InstallStatus.INSTALLED) item.copy(status = InstallStatus.INSTALLED)
} else { } else {
@@ -170,7 +209,7 @@ class MicroGViewModel @Inject constructor(
private fun buildItem(apk: ExternalApk, download: Download?): ExternalItem { private fun buildItem(apk: ExternalApk, download: Download?): ExternalItem {
val state = when { val state = when {
apk.isInstalled(context) -> InstallStatus.INSTALLED isBundleApkInstalled(apk) -> InstallStatus.INSTALLED
download == null -> InstallStatus.PENDING download == null -> InstallStatus.PENDING
download.status == DownloadStatus.FAILED -> InstallStatus.FAILED download.status == DownloadStatus.FAILED -> InstallStatus.FAILED
download.status == DownloadStatus.CANCELLED -> InstallStatus.PENDING download.status == DownloadStatus.CANCELLED -> InstallStatus.PENDING