Fall back to session installer when chosen installer is unavailable
Address #1386 The Shizuku branch of getPreferredInstaller() already fell back to the session installer, but the guard hasShizukuPerm() called Shizuku.checkSelfPermission(), which throws when the binder is not alive (Shizuku disabled). The exception escaped before the fallback could run, so installs failed instead of falling back. - Guard hasShizukuPerm() on Shizuku.pingBinder() and swallow failures so it returns false (instead of throwing) when Shizuku is unavailable, letting the existing fallback run. This also fixes canInstallSilently(). - Detect when any chosen installer resolves to the default and optionally inform the user via a toast, gated by notifyOnFallback so cancel/remove callers stay silent while real install paths surface it.
This commit is contained in:
@@ -174,8 +174,9 @@ class DownloadHelper @Inject constructor(
|
||||
if (existing != null && existing.versionCode == download.versionCode) {
|
||||
if (existing.canInstall(context)) {
|
||||
Log.i(TAG, "${download.packageName} already downloaded, installing directly")
|
||||
runCatching { appInstaller.getPreferredInstaller().install(existing) }
|
||||
.onFailure { Log.e(TAG, "Failed to install ${download.packageName}", it) }
|
||||
runCatching {
|
||||
appInstaller.getPreferredInstaller(notifyOnFallback = true).install(existing)
|
||||
}.onFailure { Log.e(TAG, "Failed to install ${download.packageName}", it) }
|
||||
return
|
||||
}
|
||||
if (existing.isActive) {
|
||||
|
||||
@@ -25,13 +25,17 @@ import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.util.Log
|
||||
import androidx.core.content.pm.PackageInfoCompat
|
||||
import com.aurora.Constants.PACKAGE_NAME_GMS
|
||||
import com.aurora.extensions.TAG
|
||||
import com.aurora.extensions.getUpdateOwnerPackageNameCompat
|
||||
import com.aurora.extensions.isOAndAbove
|
||||
import com.aurora.extensions.isPAndAbove
|
||||
import com.aurora.extensions.isSAndAbove
|
||||
import com.aurora.extensions.toast
|
||||
import com.aurora.store.BuildConfig
|
||||
import com.aurora.store.R
|
||||
import com.aurora.store.data.installer.ShizukuInstaller.Companion.SHIZUKU_PACKAGE_NAME
|
||||
import com.aurora.store.data.installer.base.IInstaller
|
||||
import com.aurora.store.data.model.Installer
|
||||
@@ -172,8 +176,15 @@ class AppInstaller @Inject constructor(
|
||||
fun hasShizukuOrSui(context: Context): Boolean = isOAndAbove &&
|
||||
(PackageUtil.isInstalled(context, SHIZUKU_PACKAGE_NAME) || Sui.isSui())
|
||||
|
||||
fun hasShizukuPerm(): Boolean =
|
||||
Shizuku.checkSelfPermission() == PackageManager.PERMISSION_GRANTED
|
||||
// Shizuku.checkSelfPermission() throws when the binder is not alive (Shizuku
|
||||
// disabled/not running), so guard on pingBinder() and swallow any failure to let
|
||||
// callers fall back gracefully instead of crashing.
|
||||
fun hasShizukuPerm(): Boolean = try {
|
||||
Shizuku.pingBinder() &&
|
||||
Shizuku.checkSelfPermission() == PackageManager.PERMISSION_GRANTED
|
||||
} catch (_: Exception) {
|
||||
false
|
||||
}
|
||||
|
||||
fun uninstall(context: Context, packageName: String) {
|
||||
val intent = Intent().apply {
|
||||
@@ -196,31 +207,47 @@ class AppInstaller @Inject constructor(
|
||||
|
||||
fun getMicroGInstaller(): IInstaller = microGInstaller
|
||||
|
||||
fun getPreferredInstaller(): IInstaller = when (getCurrentInstaller(context)) {
|
||||
Installer.SESSION -> sessionInstaller
|
||||
/**
|
||||
* Returns the installer for the user's chosen mode, transparently falling back to the
|
||||
* default (session) installer when that mode is currently unavailable, e.g. the chosen
|
||||
* Shizuku installer when Shizuku is disabled.
|
||||
* @param notifyOnFallback Whether to inform the user via a toast when a fallback happens
|
||||
*/
|
||||
fun getPreferredInstaller(notifyOnFallback: Boolean = false): IInstaller {
|
||||
val selected = getCurrentInstaller(context)
|
||||
val installer = when (selected) {
|
||||
Installer.SESSION -> sessionInstaller
|
||||
|
||||
Installer.NATIVE -> nativeInstaller
|
||||
Installer.NATIVE -> nativeInstaller
|
||||
|
||||
Installer.ROOT -> if (hasRootAccess()) rootInstaller else defaultInstaller
|
||||
Installer.ROOT -> if (hasRootAccess()) rootInstaller else defaultInstaller
|
||||
|
||||
Installer.SERVICE -> if (hasAuroraService(context)) {
|
||||
serviceInstaller
|
||||
} else {
|
||||
defaultInstaller
|
||||
Installer.SERVICE -> if (hasAuroraService(context)) {
|
||||
serviceInstaller
|
||||
} else {
|
||||
defaultInstaller
|
||||
}
|
||||
|
||||
Installer.AM -> if (hasAppManager(context)) amInstaller else defaultInstaller
|
||||
|
||||
Installer.SHIZUKU -> if (hasShizukuOrSui(context) && hasShizukuPerm()) {
|
||||
shizukuInstaller
|
||||
} else {
|
||||
defaultInstaller
|
||||
}
|
||||
|
||||
Installer.MICROG -> if (hasMicroGInstaller(context)) {
|
||||
microGInstaller
|
||||
} else {
|
||||
defaultInstaller
|
||||
}
|
||||
}
|
||||
|
||||
Installer.AM -> if (hasAppManager(context)) amInstaller else defaultInstaller
|
||||
|
||||
Installer.SHIZUKU -> if (hasShizukuOrSui(context) && hasShizukuPerm()) {
|
||||
shizukuInstaller
|
||||
} else {
|
||||
defaultInstaller
|
||||
if (selected != Installer.SESSION && installer === defaultInstaller) {
|
||||
Log.i(TAG, "$selected installer unavailable, falling back to session installer")
|
||||
if (notifyOnFallback) context.toast(R.string.installer_fallback_session)
|
||||
}
|
||||
|
||||
Installer.MICROG -> if (hasMicroGInstaller(context)) {
|
||||
microGInstaller
|
||||
} else {
|
||||
defaultInstaller
|
||||
}
|
||||
return installer
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,7 +252,7 @@ class DownloadWorker @AssistedInject constructor(
|
||||
private suspend fun onSuccess(): Result {
|
||||
return withContext(NonCancellable) {
|
||||
return@withContext try {
|
||||
appInstaller.getPreferredInstaller().install(download)
|
||||
appInstaller.getPreferredInstaller(notifyOnFallback = true).install(download)
|
||||
Result.success()
|
||||
} catch (exception: Exception) {
|
||||
Log.e(TAG, "Failed to install ${download.packageName}", exception)
|
||||
|
||||
@@ -75,7 +75,7 @@ class DownloadsViewModel @Inject constructor(
|
||||
|
||||
fun install(download: Download) {
|
||||
try {
|
||||
appInstaller.getPreferredInstaller().install(download)
|
||||
appInstaller.getPreferredInstaller(notifyOnFallback = true).install(download)
|
||||
} catch (exception: Exception) {
|
||||
Log.e(TAG, "Failed to install ${download.packageName}", exception)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user