Rewrite app installation

Fix  #4960
This commit is contained in:
南宫雪珊
2021-12-14 21:20:29 +08:00
committed by GitHub
parent 5a49bd3ac9
commit baa19f0ccf
10 changed files with 160 additions and 395 deletions

View File

@@ -1,18 +1,20 @@
package com.topjohnwu.magisk.core
import android.content.ContentProvider
import android.content.ContentValues
import android.content.Context
import android.content.pm.ProviderInfo
import android.database.Cursor
import android.net.Uri
import android.os.Bundle
import android.os.ParcelFileDescriptor
import android.os.ParcelFileDescriptor.MODE_READ_ONLY
import com.topjohnwu.magisk.FileProvider
import com.topjohnwu.magisk.core.su.SuCallbackHandler
import java.io.File
open class Provider : FileProvider() {
class Provider : ContentProvider() {
override fun attachInfo(context: Context, info: ProviderInfo?) {
override fun attachInfo(context: Context, info: ProviderInfo) {
super.attachInfo(context.wrap(), info)
}
@@ -36,4 +38,11 @@ open class Provider : FileProvider() {
fun PREFS_URI(pkg: String) =
Uri.Builder().scheme("content").authority("$pkg.provider").path("prefs_file").build()
}
override fun onCreate() = true
override fun getType(uri: Uri): String? = null
override fun insert(uri: Uri, values: ContentValues?): Uri? = null
override fun delete(uri: Uri, selection: String?, selectionArgs: Array<out String>?) = 0
override fun update(uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array<out String>?) = 0
override fun query(uri: Uri, projection: Array<out String>?, selection: String?, selectionArgs: Array<out String>?, sortOrder: String?): Cursor? = null
}

View File

@@ -73,8 +73,12 @@ sealed class Subject : Parcelable {
val externalFile get() = MediaStoreUtils.getFile("$title.apk").uri
override fun pendingIntent(context: Context) =
APKInstall.installIntent(context, file.toFile()).toPending(context)
override fun pendingIntent(context: Context): PendingIntent {
val receiver = APKInstall.register(context, null, null)
APKInstall.installapk(context, file.toFile())
val intent = receiver.waitIntent() ?: Intent()
return intent.toPending(context)
}
}
@SuppressLint("InlinedApi")

View File

@@ -1,7 +1,6 @@
package com.topjohnwu.magisk.core.tasks
import android.app.Activity
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.widget.Toast
@@ -27,7 +26,6 @@ import timber.log.Timber
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.lang.ref.WeakReference
import java.security.SecureRandom
object HideAPK {
@@ -41,8 +39,6 @@ object HideAPK {
const val MAX_LABEL_LENGTH = 32
private val svc get() = ServiceLocator.networkService
private val Context.APK_URI get() = Provider.APK_URI(packageName)
private val Context.PREFS_URI get() = Provider.PREFS_URI(packageName)
private fun genPackageName(): String {
val random = SecureRandom()
@@ -92,35 +88,16 @@ object HideAPK {
return true
}
private class WaitPackageReceiver(
private val pkg: String,
activity: Activity
) : BroadcastReceiver() {
private val activity = WeakReference(activity)
private fun launchApp(): Unit = activity.get()?.run {
val intent = packageManager.getLaunchIntentForPackage(pkg) ?: return
Config.suManager = if (pkg == APPLICATION_ID) "" else pkg
grantUriPermission(pkg, APK_URI, Intent.FLAG_GRANT_READ_URI_PERMISSION)
grantUriPermission(pkg, PREFS_URI, Intent.FLAG_GRANT_READ_URI_PERMISSION)
intent.putExtra(Const.Key.PREV_PKG, packageName)
startActivity(intent)
finish()
} ?: Unit
override fun onReceive(context: Context, intent: Intent) {
when (intent.action ?: return) {
Intent.ACTION_PACKAGE_REPLACED, Intent.ACTION_PACKAGE_ADDED -> {
val newPkg = intent.data?.encodedSchemeSpecificPart.orEmpty()
if (newPkg == pkg) {
context.unregisterReceiver(this)
launchApp()
}
}
}
}
private fun launchApp(activity: Activity, pkg: String) {
val intent = activity.packageManager.getLaunchIntentForPackage(pkg) ?: return
Config.suManager = if (pkg == APPLICATION_ID) "" else pkg
val self = activity.packageName
val flag = Intent.FLAG_GRANT_READ_URI_PERMISSION
activity.grantUriPermission(pkg, Provider.APK_URI(self), flag)
activity.grantUriPermission(pkg, Provider.PREFS_URI(self), flag)
intent.putExtra(Const.Key.PREV_PKG, self)
activity.startActivity(intent)
activity.finish()
}
private suspend fun patchAndHide(activity: Activity, label: String): Boolean {
@@ -141,9 +118,14 @@ object HideAPK {
return false
// Install and auto launch app
APKInstall.registerInstallReceiver(activity, WaitPackageReceiver(pkg, activity))
if (!Shell.su("adb_pm_install $repack").exec().isSuccess)
APKInstall.installHideResult(activity, repack)
val receiver = APKInstall.register(activity, pkg) {
launchApp(activity, pkg)
}
val cmd = "adb_pm_install $repack ${activity.applicationInfo.uid}"
if (!Shell.su(cmd).exec().isSuccess) {
APKInstall.installapk(activity, repack)
receiver.waitIntent()?.let { activity.startActivity(it) }
}
return true
}
@@ -157,8 +139,8 @@ object HideAPK {
val result = withContext(Dispatchers.IO) {
patchAndHide(activity, label)
}
dialog.dismiss()
if (!result) {
dialog.dismiss()
Utils.toast(R.string.failure, Toast.LENGTH_LONG)
}
}
@@ -171,11 +153,15 @@ object HideAPK {
show()
}
val apk = DynAPK.current(activity)
APKInstall.registerInstallReceiver(activity, WaitPackageReceiver(APPLICATION_ID, activity))
Shell.su("adb_pm_install $apk").submit {
val receiver = APKInstall.register(activity, APPLICATION_ID) {
launchApp(activity, APPLICATION_ID)
dialog.dismiss()
if (!it.isSuccess)
APKInstall.installHideResult(activity, apk)
}
val cmd = "adb_pm_install $apk ${activity.applicationInfo.uid}"
Shell.su(cmd).submit(Shell.EXECUTOR) { ret ->
if (ret.isSuccess) return@submit
APKInstall.installapk(activity, apk)
receiver.waitIntent()?.let { activity.startActivity(it) }
}
}
}

View File

@@ -129,9 +129,11 @@ adb_pm_install() {
local tmp=/data/local/tmp/temp.apk
cp -f "$1" $tmp
chmod 644 $tmp
su 2000 -c pm install $tmp || pm install $tmp
su 2000 -c pm install $tmp || pm install $tmp || su 1000 -c pm install $tmp
local res=$?
rm -f $tmp
# Note: change this will kill self
[ $res != 0 ] && appops set "$2" REQUEST_INSTALL_PACKAGES allow
return $res
}