Resolve SecurityException in installer, tweak installed notification.

Catch and ignore SecurityExceptions when cleaning up old installer
sessions. Catch and ignore session opening exceptions.

Reduce timeout for "Installed" notifications to 5s (as it was before).

Revert removal of intent data for the install prompt notification.
This commit is contained in:
Matthew Crossman 2022-01-04 20:50:48 +11:00
parent 375ab23edb
commit 3ea8cd8c66
No known key found for this signature in database
GPG Key ID: C6B942B019794CC2
2 changed files with 45 additions and 19 deletions

View File

@ -53,7 +53,17 @@ class DefaultInstaller(context: Context) : BaseInstaller(context) {
// clean up inactive sessions // clean up inactive sessions
sessionInstaller.mySessions sessionInstaller.mySessions
.filter { session -> !session.isActive } .filter { session -> !session.isActive }
.forEach { session -> sessionInstaller.abandonSession(session.sessionId) } .forEach { session ->
try {
sessionInstaller.abandonSession(session.sessionId)
}
catch (_: SecurityException) {
Log.w(
"DefaultInstaller",
"Attempted to abandon a session we do not own."
)
}
}
// start new session // start new session
val id = sessionInstaller.createSession(sessionParams) val id = sessionInstaller.createSession(sessionParams)
@ -67,24 +77,38 @@ class DefaultInstaller(context: Context) : BaseInstaller(context) {
var hasErrors = false var hasErrors = false
session.use { activeSession -> session.use { activeSession ->
activeSession.openWrite(packageName, 0, cacheFile.length()).use { packageStream -> try {
try { activeSession.openWrite(packageName, 0, cacheFile.length()).use { packageStream ->
cacheFile.inputStream().use { fileStream -> try {
fileStream.copyTo(packageStream) cacheFile.inputStream().use { fileStream ->
fileStream.copyTo(packageStream)
}
} catch (_: FileNotFoundException) {
Log.w(
"DefaultInstaller",
"Cache file does not seem to exist."
)
hasErrors = true
} catch (_: IOException) {
Log.w(
"DefaultInstaller",
"Failed to perform cache to package copy due to a bad pipe."
)
hasErrors = true
} }
} catch (e: FileNotFoundException) {
Log.w(
"DefaultInstaller",
"Cache file for DefaultInstaller does not seem to exist."
)
hasErrors = true
} catch (e: IOException) {
Log.w(
"DefaultInstaller",
"Failed to perform cache to package copy due to a bad pipe."
)
hasErrors = true
} }
} catch (_: SecurityException) {
Log.w(
"DefaultInstaller",
"Attempted to use a destroyed or sealed session when installing."
)
hasErrors = true
} catch (_: IOException) {
Log.w(
"DefaultInstaller",
"Couldn't open up active session file for copying install data."
)
hasErrors = true
} }
} }

View File

@ -7,13 +7,14 @@ import android.app.Service
import android.content.Intent import android.content.Intent
import android.content.pm.PackageInstaller import android.content.pm.PackageInstaller
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.net.Uri
import android.os.IBinder import android.os.IBinder
import android.view.ContextThemeWrapper import android.view.ContextThemeWrapper
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import com.looker.droidify.Common.NOTIFICATION_CHANNEL_INSTALLER import com.looker.droidify.Common.NOTIFICATION_CHANNEL_INSTALLER
import com.looker.droidify.Common.NOTIFICATION_ID_INSTALLER import com.looker.droidify.Common.NOTIFICATION_ID_INSTALLER
import com.looker.droidify.R
import com.looker.droidify.MainActivity import com.looker.droidify.MainActivity
import com.looker.droidify.R
import com.looker.droidify.utility.Utils import com.looker.droidify.utility.Utils
import com.looker.droidify.utility.extension.android.Android import com.looker.droidify.utility.extension.android.Android
import com.looker.droidify.utility.extension.android.notificationManager import com.looker.droidify.utility.extension.android.notificationManager
@ -28,7 +29,7 @@ class InstallerService : Service() {
const val KEY_ACTION = "installerAction" const val KEY_ACTION = "installerAction"
const val KEY_APP_NAME = "appName" const val KEY_APP_NAME = "appName"
const val ACTION_UNINSTALL = "uninstall" const val ACTION_UNINSTALL = "uninstall"
private const val INSTALLED_NOTIFICATION_TIMEOUT: Long = 10000 private const val INSTALLED_NOTIFICATION_TIMEOUT: Long = 5000
private const val NOTIFICATION_TAG_PREFIX = "install-" private const val NOTIFICATION_TAG_PREFIX = "install-"
} }
@ -183,6 +184,7 @@ class InstallerService : Service() {
0, 0,
Intent(this, MainActivity::class.java) Intent(this, MainActivity::class.java)
.setAction(MainActivity.ACTION_INSTALL) .setAction(MainActivity.ACTION_INSTALL)
.setData(Uri.parse("package:$name"))
.putExtra(Intent.EXTRA_INTENT, promptIntent) .putExtra(Intent.EXTRA_INTENT, promptIntent)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK), .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
if (Android.sdk(23)) PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE if (Android.sdk(23)) PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE