Skip to content

Commit

Permalink
Allow to customize Requester and Executor
Browse files Browse the repository at this point in the history
  • Loading branch information
SanmerDev committed Nov 21, 2023
1 parent 4b76032 commit 4351088
Show file tree
Hide file tree
Showing 29 changed files with 797 additions and 229 deletions.
66 changes: 66 additions & 0 deletions app/schemas/dev.sanmer.pi.database.AppDatabase/2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
{
"formatVersion": 1,
"database": {
"version": 2,
"identityHash": "2f898d36eac649a9827b70b7bb6d234b",
"entities": [
{
"tableName": "packages",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`packageName` TEXT NOT NULL, `authorized` INTEGER NOT NULL, PRIMARY KEY(`packageName`))",
"fields": [
{
"fieldPath": "packageName",
"columnName": "packageName",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "authorized",
"columnName": "authorized",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"packageName"
]
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "settings",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`key` TEXT NOT NULL, `value` TEXT NOT NULL, PRIMARY KEY(`key`))",
"fields": [
{
"fieldPath": "key",
"columnName": "key",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "value",
"columnName": "value",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"key"
]
},
"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, '2f898d36eac649a9827b70b7bb6d234b')"
]
}
}
5 changes: 5 additions & 0 deletions app/src/main/kotlin/dev/sanmer/pi/app/Const.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,9 @@ object Const {
object MIME {
const val APK = "application/vnd.android.package-archive"
}

object Settings {
const val REQUESTER_PACKAGE_NAME = "REQUESTER_PACKAGE_NAME"
const val EXECUTOR_PACKAGE_NAME = "EXECUTOR_PACKAGE_NAME"
}
}
14 changes: 14 additions & 0 deletions app/src/main/kotlin/dev/sanmer/pi/compat/PackageInfoCompat.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package dev.sanmer.pi.compat

import android.content.pm.PackageInfo
import android.content.pm.PackageInfoHidden
import dev.rikka.tools.refine.Refine

object PackageInfoCompat {
val PackageInfo.isOverlayPackage get() =
Refine.unsafeCast<PackageInfoHidden>(this)
.isOverlayPackage

val PackageInfo.isPreinstalled get() =
lastUpdateTime <= 1230768000000 // 2009-01-01 08:00:00 GMT+8
}
115 changes: 31 additions & 84 deletions app/src/main/kotlin/dev/sanmer/pi/compat/PackageManagerCompat.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package dev.sanmer.pi.compat

import android.content.ComponentName
import android.content.Intent
import android.content.IntentFilter
import android.content.IntentSender
import android.content.pm.ApplicationInfo
import android.content.pm.IPackageInstaller
import android.content.pm.IPackageInstallerSession
import android.content.pm.IPackageManager
Expand All @@ -14,8 +12,8 @@ import android.content.pm.PackageInstallerHidden.SessionParamsHidden
import android.content.pm.PackageManager
import android.content.pm.PackageManagerHidden
import android.content.pm.ParceledListSlice
import android.content.pm.ResolveInfo
import android.content.pm.VersionedPackage
import android.os.Process
import dev.rikka.tools.refine.Refine
import dev.sanmer.pi.BuildConfig
import kotlinx.coroutines.Dispatchers
Expand All @@ -28,8 +26,6 @@ import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine

object PackageManagerCompat {
private const val INSTALLER_PACKAGE_NAME= BuildConfig.APPLICATION_ID

private val packageManager: IPackageManager by lazy {
IPackageManager.Stub.asInterface(
ShizukuBinderWrapper(SystemServiceHelper.getSystemService("package"))
Expand All @@ -42,33 +38,30 @@ object PackageManagerCompat {
)
}

private val packageInstaller: PackageInstaller by lazy {
if (BuildCompat.atLeastS) {
private fun getPackageInstaller(installerPackageName: String): PackageInstaller {
return if (BuildCompat.atLeastS) {
Refine.unsafeCast(
PackageInstallerHidden(installer, INSTALLER_PACKAGE_NAME, null, 0)
PackageInstallerHidden(installer, installerPackageName, null, 0)
)
} else {
Refine.unsafeCast(
PackageInstallerHidden(installer, INSTALLER_PACKAGE_NAME, 0)
PackageInstallerHidden(installer, installerPackageName, 0)
)
}
}

private fun createSession(params: PackageInstaller.SessionParams): PackageInstaller.Session {
private fun createSession(
installerPackageName: String,
params: PackageInstaller.SessionParams
): PackageInstaller.Session {
val packageInstaller = getPackageInstaller(installerPackageName)
val sessionId = packageInstaller.createSession(params)
val iSession = IPackageInstallerSession.Stub.asInterface(
ShizukuBinderWrapper(installer.openSession(sessionId).asBinder())
)
return Refine.unsafeCast(PackageInstallerHidden.SessionHidden(iSession))
}

private fun uninstallPackage(packageName: String, intentSender: IntentSender) {
installer.uninstall(
VersionedPackage(packageName, PackageManager.VERSION_CODE_HIGHEST),
INSTALLER_PACKAGE_NAME, 0, intentSender, 0
)
}

fun getPackageUid(packageName: String, flags: Int, userId: Int): Int {
return if (BuildCompat.atLeastT) {
packageManager.getPackageUid(packageName, flags.toLong(), userId)
Expand All @@ -85,6 +78,14 @@ object PackageManagerCompat {
}
}

fun getApplicationInfo(packageName: String, flags: Int, userId: Int): ApplicationInfo {
return if (BuildCompat.atLeastT) {
packageManager.getApplicationInfo(packageName, flags.toLong(), userId)
} else {
packageManager.getApplicationInfo(packageName, flags, userId)
}
}

fun getInstalledPackages(flags: Int, userId: Int): List<PackageInfo> {
val packages: ParceledListSlice<PackageInfo>? = if (BuildCompat.atLeastT) {
packageManager.getInstalledPackages(flags.toLong(), userId)
Expand All @@ -99,56 +100,20 @@ object PackageManagerCompat {
}
}

fun addPreferredActivity(filter: IntentFilter, match: Int, set: Array<ComponentName>, activity: ComponentName, userId: Int) {
if (BuildCompat.atLeastS) {
packageManager.addPreferredActivity(filter, match, set, activity, userId, true)
} else {
packageManager.addPreferredActivity(filter, match, set, activity, userId)
}
}

fun clearPackagePreferredActivities(packageName: String) {
packageManager.clearPackagePreferredActivities(packageName)
}

fun getPreferredActivities(packageName: String?): List<Pair<ComponentName, IntentFilter>> {
val outFilters = ArrayList<IntentFilter>()
val outActivities = ArrayList<ComponentName>()
packageManager.getPreferredActivities(outFilters, outActivities, packageName)

return outActivities.zip(outFilters)
}

fun queryIntentActivities(
intent: Intent,
resolvedType: String,
flags: Int,
userId: Int
): List<ResolveInfo> {
val resolveInfo: ParceledListSlice<ResolveInfo>? = if (BuildCompat.atLeastT) {
packageManager.queryIntentActivities(intent, resolvedType, flags.toLong(), userId)
} else {
packageManager.queryIntentActivities(intent, resolvedType, flags, userId)
}

return if (resolveInfo != null) {
resolveInfo.list
} else {
emptyList()
}
}

fun getHomeActivities(): ComponentName {
val outHomeCandidates = ArrayList<ResolveInfo>()
return packageManager.getHomeActivities(outHomeCandidates)
}

suspend fun install(packageFile: File, packageName: String, originatingPackageName: String?): Int = withContext(Dispatchers.IO) {
suspend fun install(
packageFile: File,
packageName: String,
installer: String,
originating: String
): Int = withContext(Dispatchers.IO) {
try {
val params = PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL)

if (originatingPackageName != null) {
val originatingUid = getPackageUid(originatingPackageName, 0, 0)
val originatingUid = runCatching {
getPackageUid(originating, 0, 0)
}.getOrDefault(Process.INVALID_UID)

if (originatingUid != Process.INVALID_UID) {
params.setOriginatingUid(originatingUid)
}

Expand All @@ -157,7 +122,7 @@ object PackageManagerCompat {
Refine.unsafeCast<SessionParamsHidden>(params).installFlags = flags

val input = packageFile.inputStream()
createSession(params).use { session ->
createSession(installer, params).use { session ->
session.openWrite(packageName, 0, input.available().toLong()).use { output ->
input.copyTo(output)
session.fsync(output)
Expand All @@ -182,22 +147,4 @@ object PackageManagerCompat {
PackageInstaller.STATUS_FAILURE
}
}

suspend fun uninstall(packageName: String): Int = withContext(Dispatchers.IO) {
try {
val intent = suspendCoroutine { cont ->
val adapter = IntentSenderCompat.IIntentSenderAdaptor {
cont.resume(it)
}
val intentSender = IntentSenderCompat.newInstance(adapter)
uninstallPackage(packageName, intentSender)
}

Timber.i("Uninstall failed: $packageName")
intent.getIntExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_FAILURE)
} catch (e: Exception) {
Timber.e(e, "Uninstall failed: $packageName")
PackageInstaller.STATUS_FAILURE
}
}
}
16 changes: 15 additions & 1 deletion app/src/main/kotlin/dev/sanmer/pi/database/AppDatabase.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,31 @@ import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.migration.Migration
import dev.sanmer.pi.database.dao.PackageDao
import dev.sanmer.pi.database.dao.SettingDao
import dev.sanmer.pi.database.entity.PackageInfoEntity
import dev.sanmer.pi.database.entity.SettingEntity

@Database(entities = [PackageInfoEntity::class], version = 1)
@Database(entities = [PackageInfoEntity::class,SettingEntity::class], version = 2)
abstract class AppDatabase : RoomDatabase() {
abstract fun packageDao(): PackageDao
abstract fun settingDao(): SettingDao

companion object {
fun build(context: Context): AppDatabase {
return Room.databaseBuilder(context, AppDatabase::class.java, "pi")
.addMigrations(
MIGRATION_1_2
)
.build()
}

private val MIGRATION_1_2 = Migration(1, 2) {
it.execSQL("CREATE TABLE IF NOT EXISTS settings (" +
"key TEXT NOT NULL, " +
"value TEXT NOT NULL, " +
"PRIMARY KEY(key))")
}
}
}
23 changes: 23 additions & 0 deletions app/src/main/kotlin/dev/sanmer/pi/database/dao/SettingDao.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package dev.sanmer.pi.database.dao

import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import dev.sanmer.pi.database.entity.SettingEntity
import kotlinx.coroutines.flow.Flow

@Dao
interface SettingDao {
@Query("SELECT value FROM settings WHERE `key` = :key")
fun getByKeyAsFlow(key: String): Flow<String>

@Query("SELECT value FROM settings WHERE `key` = :key")
suspend fun getByKey(key: String): String?

@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(value: SettingEntity)

@Query("DELETE FROM settings")
suspend fun deleteAll()
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import dev.sanmer.pi.database.AppDatabase
import dev.sanmer.pi.database.dao.PackageDao
import dev.sanmer.pi.database.dao.SettingDao
import javax.inject.Singleton

@Module
Expand All @@ -22,4 +23,8 @@ object DatabaseModule {
@Provides
@Singleton
fun providesPackageDao(db: AppDatabase): PackageDao = db.packageDao()

@Provides
@Singleton
fun providesSettingDao(db: AppDatabase): SettingDao = db.settingDao()
}
10 changes: 10 additions & 0 deletions app/src/main/kotlin/dev/sanmer/pi/database/entity/SettingEntity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package dev.sanmer.pi.database.entity

import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity(tableName = "settings")
data class SettingEntity(
@PrimaryKey val key: String,
val value: String
)
Loading

0 comments on commit 4351088

Please sign in to comment.