AppInstaller: Always use intent based uninstallation of apps

This requests user's confirmation before uninstallation every time which
is what we want to happen as well.

Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
This commit is contained in:
Aayush Gupta
2024-01-20 15:12:57 +05:30
parent b46d232956
commit 859d32d878
8 changed files with 21 additions and 156 deletions

View File

@@ -40,13 +40,3 @@ inline fun <reified T : Context> Context.newIntent(flags: Int, extras: Bundle):
intent.putExtras(extras)
return intent
}
fun Intent.applyUninstallActionCompat() {
if (isPAndAbove()) {
action = Intent.ACTION_DELETE
} else {
@Suppress("DEPRECATION")
action = Intent.ACTION_UNINSTALL_PACKAGE
putExtra(Intent.EXTRA_RETURN_RESULT, true)
}
}

View File

@@ -21,9 +21,12 @@
package com.aurora.store.data.installer
import android.content.Context
import android.content.Intent
import android.content.pm.PackageInstaller
import android.content.pm.PackageManager
import android.net.Uri
import com.aurora.extensions.isOAndAbove
import com.aurora.extensions.isPAndAbove
import com.aurora.store.BuildConfig
import com.aurora.store.R
import com.aurora.store.util.PackageUtil
@@ -91,6 +94,20 @@ open class AppInstaller private constructor(var context: Context) {
return Shizuku.checkSelfPermission() == PackageManager.PERMISSION_GRANTED
}
fun uninstall(context: Context, packageName: String) {
val intent = Intent().apply {
data = Uri.fromParts("package", packageName, null)
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
if (isPAndAbove()) {
action = Intent.ACTION_DELETE
} else {
@Suppress("DEPRECATION")
action = Intent.ACTION_UNINSTALL_PACKAGE
putExtra(Intent.EXTRA_RETURN_RESULT, true)
}
}
context.startActivity(intent)
}
}
val choiceAndInstaller = HashMap<Int, IInstaller>()

View File

@@ -21,9 +21,7 @@ package com.aurora.store.data.installer
interface IInstaller {
fun install(packageName: String, files: List<Any>)
fun uninstall(packageName: String)
fun clearQueue()
fun isAlreadyQueued(packageName: String): Boolean
fun removeFromInstallQueue(packageName: String)
}
}

View File

@@ -20,10 +20,8 @@
package com.aurora.store.data.installer
import android.content.Context
import android.content.Intent
import android.net.Uri
import androidx.core.content.FileProvider
import com.aurora.extensions.applyUninstallActionCompat
import com.aurora.store.AuroraApplication
import com.aurora.store.BuildConfig
import com.aurora.store.data.event.InstallerEvent
@@ -45,17 +43,6 @@ abstract class InstallerBase(protected var context: Context) : IInstaller {
AuroraApplication.enqueuedInstalls.remove(packageName)
}
override fun uninstall(packageName: String) {
val uri = Uri.fromParts("package", packageName, null)
val intent = Intent().apply {
data = uri
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
applyUninstallActionCompat()
}
context.startActivity(intent)
}
open fun postError(packageName: String, error: String?, extra: String?) {
Log.e("Service Error :$error")
@@ -75,4 +62,4 @@ abstract class InstallerBase(protected var context: Context) : IInstaller {
file
)
}
}
}

View File

@@ -57,30 +57,6 @@ class RootInstaller(context: Context) : InstallerBase(context) {
}
}
override fun uninstall(packageName: String) {
if (Shell.getShell().isRoot) {
val result: Shell.Result =
Shell.cmd("pm uninstall --user 0 $packageName")
.exec()
val response = result.out
if (response[0] != "Success") {
postError(
packageName,
context.getString(R.string.installer_status_failure),
parseError(result)
)
}
} else {
postError(
packageName,
context.getString(R.string.installer_status_failure),
context.getString(R.string.installer_root_unavailable)
)
Log.e(" >>>>>>>>>>>>>>>>>>>>>>>>>> NO ROOT ACCESS <<<<<<<<<<<<<<<<<<<<<<<<<<<<<")
}
}
private fun xInstall(packageName: String, files: List<File>) {
var totalSize = 0

View File

@@ -98,85 +98,6 @@ class ServiceInstaller(context: Context) : InstallerBase(context) {
}
}
override fun uninstall(packageName: String) {
executor.execute {
val readyWithAction = AtomicBoolean(false)
Handler(Looper.getMainLooper()).post {
val serviceConnection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName, binder: IBinder) {
if (isAlreadyQueued(packageName)) {
if (::serviceConnection.isInitialized) {
context.unbindService(serviceConnection)
}
readyWithAction.set(true)
return
}
AuroraApplication.enqueuedInstalls.add(packageName)
val service = IPrivilegedService.Stub.asInterface(binder)
if (service.hasPrivilegedPermissions()) {
Log.i(context.getString(R.string.installer_service_available))
val callback = object : IPrivilegedCallback.Stub() {
override fun handleResult(packageName: String, returnCode: Int) {}
override fun handleResultX(
packageName: String,
returnCode: Int,
extra: String?
) {
removeFromInstallQueue(packageName)
handleCallbackUninstall(packageName, returnCode, extra)
readyWithAction.set(true)
}
}
try {
service.deletePackageX(
packageName,
2,
BuildConfig.APPLICATION_ID,
callback
)
} catch (e: RemoteException) {
Log.e("Failed to connect Aurora Services")
removeFromInstallQueue(packageName)
readyWithAction.set(true)
}
} else {
removeFromInstallQueue(packageName)
postError(
packageName,
context.getString(R.string.installer_status_failure),
context.getString(R.string.installer_service_misconfigured)
)
readyWithAction.set(true)
}
}
override fun onServiceDisconnected(name: ComponentName) {
removeFromInstallQueue(packageName)
Log.e("Disconnected from Aurora Services")
readyWithAction.set(true)
}
}
val intent = Intent(PRIVILEGED_EXTENSION_SERVICE_INTENT)
intent.setPackage(PRIVILEGED_EXTENSION_PACKAGE_NAME)
context.bindService(
intent,
serviceConnection,
Context.BIND_AUTO_CREATE
)
}
while (!readyWithAction.get()) {
Thread.sleep(1000)
}
}
}
private fun xInstall(packageName: String, uriList: List<Uri>, fileList: List<String>) {
executor.execute {
val readyWithAction = AtomicBoolean(false)

View File

@@ -64,7 +64,6 @@ import com.aurora.store.data.ViewState
import com.aurora.store.data.event.BusEvent
import com.aurora.store.data.event.InstallerEvent
import com.aurora.store.data.installer.AppInstaller
import com.aurora.store.data.installer.RootInstaller
import com.aurora.store.data.model.DownloadStatus
import com.aurora.store.data.providers.AuthProvider
import com.aurora.store.databinding.FragmentDetailsBinding
@@ -89,7 +88,6 @@ import com.aurora.store.viewmodel.details.AppDetailsViewModel
import com.aurora.store.viewmodel.details.DetailsClusterViewModel
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetBehavior.BottomSheetCallback
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import org.greenrobot.eventbus.EventBus
@@ -375,7 +373,7 @@ class AppDetailsFragment : BaseFragment(R.layout.fragment_details) {
}
R.id.action_uninstall -> {
uninstallApp()
AppInstaller.uninstall(requireContext(), app.packageName)
}
R.id.menu_download_manual -> {
@@ -440,27 +438,6 @@ class AppDetailsFragment : BaseFragment(R.layout.fragment_details) {
}
}
@Synchronized
private fun uninstallApp() {
val installer = AppInstaller.getInstance(requireContext()).getPreferredInstaller()
if (installer is RootInstaller) {
MaterialAlertDialogBuilder(requireContext())
.setTitle(app.displayName)
.setMessage(requireContext().getString(R.string.action_uninstall_confirmation))
.setPositiveButton(requireContext().getString(android.R.string.ok)) { _, _ ->
installer.uninstall(app.packageName)
}
.setNegativeButton(requireContext().getString(android.R.string.cancel)) { dialog, _ ->
dialog.dismiss()
}
.create()
.show()
} else {
installer.uninstall(app.packageName)
}
}
private fun inflatePartialApp() {
if (::app.isInitialized) {
attachHeader()

View File

@@ -115,8 +115,7 @@ class AppMenuSheet : BaseBottomSheet() {
}
R.id.action_uninstall -> {
AppInstaller.getInstance(requireContext())
.getPreferredInstaller().uninstall(args.app.packageName)
AppInstaller.uninstall(requireContext(), args.app.packageName)
}
R.id.action_info -> {