Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,9 @@ internal class InstallSessionFactoryImpl internal constructor(
SessionBasedInstallSession(
loggerProvider,
applicationContext,
packageInstallerService,
packageInstallerService = lazy(LazyThreadSafetyMode.NONE) {
packageInstallerService.value.bind(id)
},
apks = parameters.apks.toList(),
id,
initialState = Session.State.Pending,
Expand Down Expand Up @@ -252,16 +254,20 @@ internal class InstallSessionFactoryImpl internal constructor(
val initialProgress = installSession.getProgress(sessionProgressDao)
val nativeSessionId = installSession.nativeSessionId ?: -1
val plugins = runCatching { installSession.getPlugins() }
val boundPackageInstallerService: Lazy<PackageInstallerService>
val session = ackpineServiceProviders.createSessionWithService(
serviceClass = PackageInstallerService::class,
defaultService = defaultPackageInstallerService,
sessionId = sessionId,
pluginClasses = plugins
) { packageInstallerService ->
boundPackageInstallerService = lazy(LazyThreadSafetyMode.NONE) {
packageInstallerService.value.bind(sessionId)
}
SessionBasedInstallSession(
loggerProvider,
applicationContext,
packageInstallerService,
boundPackageInstallerService,
apks = installSession.uris.map(String::toUri),
sessionId,
initialState, initialProgress,
Expand Down Expand Up @@ -309,8 +315,10 @@ internal class InstallSessionFactoryImpl internal constructor(
// Fails are guaranteed to be handled by PackageInstallerStatusReceiver (in case of self-update
// success is not always handled), so if native session doesn't exist, it can only mean that it succeeded.
// There may be latency from the receiver, so we delay this to allow the receiver to kick in.
val packageInstaller = applicationContext.packageManager.packageInstaller
if (initialState is Committed && packageInstaller.getSessionInfo(nativeSessionId) == null) {
if (
initialState is Committed
&& boundPackageInstallerService.value.getSessionInfo(nativeSessionId) == null
) {
logger.info(
"Scheduling success fallback for dead native session %s of session %s",
nativeSessionId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ import androidx.concurrent.futures.CallbackToFutureAdapter.Completer
import com.google.common.util.concurrent.ListenableFuture
import ru.solrudev.ackpine.Ackpine
import ru.solrudev.ackpine.AckpineThreadPool
import ru.solrudev.ackpine.helpers.concurrent.Locks
import ru.solrudev.ackpine.helpers.concurrent.computeIfAbsentCompat
import ru.solrudev.ackpine.impl.database.AckpineDatabase
import ru.solrudev.ackpine.impl.database.dao.InstallSessionDao
import ru.solrudev.ackpine.impl.database.model.SessionEntity
import ru.solrudev.ackpine.impl.database.toEntityList
import ru.solrudev.ackpine.impl.helpers.concurrent.BinarySemaphore
import ru.solrudev.ackpine.impl.helpers.concurrent.Locks
import ru.solrudev.ackpine.impl.helpers.concurrent.computeIfAbsentCompat
import ru.solrudev.ackpine.impl.helpers.concurrent.withPermit
import ru.solrudev.ackpine.impl.helpers.executeWithCompleter
import ru.solrudev.ackpine.impl.helpers.executeWithSemaphore
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ package ru.solrudev.ackpine.impl.plugability

import android.content.Context
import androidx.annotation.RestrictTo
import ru.solrudev.ackpine.impl.helpers.concurrent.Locks
import ru.solrudev.ackpine.impl.helpers.concurrent.computeIfAbsentCompat
import ru.solrudev.ackpine.helpers.concurrent.Locks
import ru.solrudev.ackpine.helpers.concurrent.computeIfAbsentCompat
import ru.solrudev.ackpine.plugability.AckpinePlugin
import java.util.concurrent.ConcurrentHashMap
import kotlin.reflect.KClass
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ import ru.solrudev.ackpine.plugability.AckpinePluginCache
import ru.solrudev.ackpine.plugability.AckpinePluginContainer
import java.util.ServiceLoader
import java.util.UUID
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
import kotlin.reflect.KClass

@RestrictTo(RestrictTo.Scope.LIBRARY)
Expand Down Expand Up @@ -63,6 +66,7 @@ internal class AckpineServiceProviders(
}
}

@OptIn(ExperimentalContracts::class)
@JvmSynthetic
internal fun <S : AckpineService, R : CompletableSession<*>> createSessionWithService(
serviceClass: KClass<S>,
Expand All @@ -79,6 +83,9 @@ internal class AckpineServiceProviders(
},
sessionFactory: (Lazy<S>) -> R
): R {
contract {
callsInPlace(sessionFactory, InvocationKind.EXACTLY_ONCE)
}
val service = serviceProviders.mapCatching { providers ->
if (providers.isEmpty()) {
logger.debug(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ public interface PackageInstallerService : AckpineService {
*/
public val uid: Int

/**
* Returns a service delegate bound to the Ackpine session with ID equal to [sessionId].
*/
public fun bind(sessionId: UUID): PackageInstallerService = this

/**
* @param ackpineSessionId ID of the Ackpine install session.
* @see PackageInstaller.createSession
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ import androidx.concurrent.futures.CallbackToFutureAdapter.Completer
import com.google.common.util.concurrent.ListenableFuture
import ru.solrudev.ackpine.Ackpine
import ru.solrudev.ackpine.AckpineThreadPool
import ru.solrudev.ackpine.helpers.concurrent.Locks
import ru.solrudev.ackpine.helpers.concurrent.computeIfAbsentCompat
import ru.solrudev.ackpine.impl.database.AckpineDatabase
import ru.solrudev.ackpine.impl.database.dao.UninstallSessionDao
import ru.solrudev.ackpine.impl.database.model.SessionEntity
import ru.solrudev.ackpine.impl.database.toEntityList
import ru.solrudev.ackpine.impl.helpers.concurrent.BinarySemaphore
import ru.solrudev.ackpine.impl.helpers.concurrent.Locks
import ru.solrudev.ackpine.impl.helpers.concurrent.computeIfAbsentCompat
import ru.solrudev.ackpine.impl.helpers.executeWithCompleter
import ru.solrudev.ackpine.impl.helpers.executeWithSemaphore
import ru.solrudev.ackpine.impl.logging.AckpineLoggerProvider
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,9 @@ internal class UninstallSessionFactoryImpl internal constructor(
PackageInstallerBasedUninstallSession(
loggerProvider,
applicationContext,
packageInstallerService,
packageInstallerService = lazy(LazyThreadSafetyMode.NONE) {
packageInstallerService.value.bind(id)
},
parameters.packageName,
id, initialState,
parameters.confirmation,
Expand Down Expand Up @@ -165,7 +167,9 @@ internal class UninstallSessionFactoryImpl internal constructor(
PackageInstallerBasedUninstallSession(
loggerProvider,
applicationContext,
packageInstallerService,
packageInstallerService = lazy(LazyThreadSafetyMode.NONE) {
packageInstallerService.value.bind(sessionId)
},
packageName,
sessionId, initialState,
confirmation,
Expand Down
8 changes: 4 additions & 4 deletions ackpine-plugins/libsu/api/libsu.api
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ public final class ru/solrudev/ackpine/libsu/LibsuInstallCapabilities : ru/solru

public final class ru/solrudev/ackpine/libsu/LibsuPlugin : ru/solrudev/ackpine/privileged/PrivilegedPlugin {
public fun <init> ()V
public synthetic fun createInstallCapabilities (Lru/solrudev/ackpine/capabilities/CapabilityStatus;Lru/solrudev/ackpine/capabilities/CapabilityStatus;Lru/solrudev/ackpine/capabilities/CapabilityStatus;Lru/solrudev/ackpine/capabilities/CapabilityStatus;Lru/solrudev/ackpine/capabilities/CapabilityStatus;Lru/solrudev/ackpine/capabilities/CapabilityStatus;Lru/solrudev/ackpine/capabilities/CapabilityStatus;)Lru/solrudev/ackpine/privileged/PrivilegedInstallCapabilities;
public synthetic fun createUninstallCapabilities (Lru/solrudev/ackpine/capabilities/CapabilityStatus;Lru/solrudev/ackpine/capabilities/CapabilityStatus;Lru/solrudev/ackpine/capabilities/CapabilityStatus;)Lru/solrudev/ackpine/privileged/PrivilegedUninstallCapabilities;
public synthetic fun createInstallCapabilities (Lru/solrudev/ackpine/privileged/PrivilegedInstallCapabilities$Snapshot;)Lru/solrudev/ackpine/privileged/PrivilegedInstallCapabilities;
public synthetic fun createUninstallCapabilities (Lru/solrudev/ackpine/privileged/PrivilegedUninstallCapabilities$Snapshot;)Lru/solrudev/ackpine/privileged/PrivilegedUninstallCapabilities;
}

public final class ru/solrudev/ackpine/libsu/LibsuPlugin$InstallParameters : ru/solrudev/ackpine/privileged/PrivilegedInstallParameters {
public static final field Companion Lru/solrudev/ackpine/libsu/LibsuPlugin$InstallParameters$Companion;
public static final field DEFAULT Lru/solrudev/ackpine/libsu/LibsuPlugin$InstallParameters;
public synthetic fun <init> (ZZZZZZLjava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (Lru/solrudev/ackpine/privileged/PrivilegedInstallParameters$Snapshot;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
}

public final class ru/solrudev/ackpine/libsu/LibsuPlugin$InstallParameters$Builder : ru/solrudev/ackpine/privileged/PrivilegedInstallParameters$Builder {
Expand All @@ -25,7 +25,7 @@ public final class ru/solrudev/ackpine/libsu/LibsuPlugin$InstallParameters$Compa
public final class ru/solrudev/ackpine/libsu/LibsuPlugin$UninstallParameters : ru/solrudev/ackpine/privileged/PrivilegedUninstallParameters {
public static final field Companion Lru/solrudev/ackpine/libsu/LibsuPlugin$UninstallParameters$Companion;
public static final field DEFAULT Lru/solrudev/ackpine/libsu/LibsuPlugin$UninstallParameters;
public synthetic fun <init> (ZZZLkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (Lru/solrudev/ackpine/privileged/PrivilegedUninstallParameters$Snapshot;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
}

public final class ru/solrudev/ackpine/libsu/LibsuPlugin$UninstallParameters$Builder : ru/solrudev/ackpine/privileged/PrivilegedUninstallParameters$Builder {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
{
"formatVersion": 1,
"database": {
"version": 3,
"identityHash": "cefdcadb013a880d44ecfa5f5c614d92",
"entities": [
{
"tableName": "libsu_install_parameters",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`session_id` TEXT NOT NULL, `bypass_low_target_sdk_block` INTEGER NOT NULL, `allow_test` INTEGER NOT NULL, `replace_existing` INTEGER NOT NULL, `request_downgrade` INTEGER NOT NULL, `grant_all_requested_permissions` INTEGER NOT NULL, `all_users` INTEGER NOT NULL, `installer_package_name` TEXT NOT NULL DEFAULT '', `target_user_id` INTEGER NOT NULL DEFAULT -2, PRIMARY KEY(`session_id`))",
"fields": [
{
"fieldPath": "sessionId",
"columnName": "session_id",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "bypassLowTargetSdkBlock",
"columnName": "bypass_low_target_sdk_block",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "allowTest",
"columnName": "allow_test",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "replaceExisting",
"columnName": "replace_existing",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "requestDowngrade",
"columnName": "request_downgrade",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "grantAllRequestedPermissions",
"columnName": "grant_all_requested_permissions",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "allUsers",
"columnName": "all_users",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "installerPackageName",
"columnName": "installer_package_name",
"affinity": "TEXT",
"notNull": true,
"defaultValue": "''"
},
{
"fieldPath": "targetUserId",
"columnName": "target_user_id",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "-2"
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"session_id"
]
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "libsu_uninstall_parameters",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`session_id` TEXT NOT NULL, `keep_data` INTEGER NOT NULL, `all_users` INTEGER NOT NULL, `system_app` INTEGER NOT NULL DEFAULT false, `target_user_id` INTEGER NOT NULL DEFAULT -2, PRIMARY KEY(`session_id`))",
"fields": [
{
"fieldPath": "sessionId",
"columnName": "session_id",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "keepData",
"columnName": "keep_data",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "allUsers",
"columnName": "all_users",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "systemApp",
"columnName": "system_app",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "false"
},
{
"fieldPath": "targetUserId",
"columnName": "target_user_id",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "-2"
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"session_id"
]
},
"indices": [],
"foreignKeys": []
}
],
"views": [],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'cefdcadb013a880d44ecfa5f5c614d92')"
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

package ru.solrudev.ackpine.libsu

import ru.solrudev.ackpine.capabilities.CapabilityStatus
import ru.solrudev.ackpine.privileged.PrivilegedInstallCapabilities
import ru.solrudev.ackpine.privileged.PrivilegedUninstallCapabilities

Expand All @@ -28,22 +27,8 @@ import ru.solrudev.ackpine.privileged.PrivilegedUninstallCapabilities
* here is determined solely from the Android API level and the effective installer type.
*/
public class LibsuInstallCapabilities internal constructor(
bypassLowTargetSdkBlock: CapabilityStatus,
allowTest: CapabilityStatus,
replaceExisting: CapabilityStatus,
requestDowngrade: CapabilityStatus,
grantAllRequestedPermissions: CapabilityStatus,
allUsers: CapabilityStatus,
installerPackageName: CapabilityStatus
) : PrivilegedInstallCapabilities(
bypassLowTargetSdkBlock,
allowTest,
replaceExisting,
requestDowngrade,
grantAllRequestedPermissions,
allUsers,
installerPackageName
) {
snapshot: Snapshot
) : PrivilegedInstallCapabilities(snapshot) {
override fun getName(): String = "LibsuInstallCapabilities"
}

Expand All @@ -55,9 +40,7 @@ public class LibsuInstallCapabilities internal constructor(
* support here is determined solely from the Android API level and the effective uninstaller type.
*/
public class LibsuUninstallCapabilities internal constructor(
keepData: CapabilityStatus,
allUsers: CapabilityStatus,
systemApp: CapabilityStatus
) : PrivilegedUninstallCapabilities(keepData, allUsers, systemApp) {
snapshot: Snapshot
) : PrivilegedUninstallCapabilities(snapshot) {
override fun getName(): String = "LibsuUninstallCapabilities"
}
Loading