Skip to content

Commit

Permalink
some refactors and refine operation records
Browse files Browse the repository at this point in the history
  • Loading branch information
TinyHai committed May 26, 2024
1 parent 1b8968e commit 9af3c02
Show file tree
Hide file tree
Showing 22 changed files with 406 additions and 179 deletions.
5 changes: 3 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,11 @@

<activity
android:name=".AuthActivity"
android:excludeFromRecents="true"
android:exported="false"
android:taskAffinity=""
android:excludeFromRecents="true"
android:noHistory="true"
android:taskAffinity=".Auth"
android:windowSoftInputMode="stateAlwaysHidden"
android:theme="@style/Theme.AppCompat.DayNight.Dialog" />

<receiver
Expand Down
1 change: 1 addition & 0 deletions app/src/main/aidl/cn/tinyhai/ban_uninstall/auth/IAuth.aidl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ interface IAuth {
boolean authenticate(String sha256);
oneway void agree(int opId);
oneway void prevent(int opId);
boolean isValid(int opId);

List<OpRecord> getAllOpRecord();
void clearAllOpRecord();
Expand Down
35 changes: 25 additions & 10 deletions app/src/main/java/cn/tinyhai/ban_uninstall/AuthActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,15 @@ import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable
import android.os.Bundle
import android.util.Log
import android.view.Window
import androidx.activity.addCallback
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.produceState
Expand Down Expand Up @@ -57,11 +55,18 @@ class AuthActivity : AppCompatActivity() {

viewModel.setup(authClient, authData)

if (!viewModel.isValid()) {
finish()
return
}

onBackPressedDispatcher.addCallback {
viewModel.onPrevent()
finish()
}

Log.i(TAG, "$this: $authData")

setContent {
AppTheme {
val scope = rememberCoroutineScope()
Expand Down Expand Up @@ -125,6 +130,10 @@ class AuthActivity : AppCompatActivity() {
}
finish()
}

override fun finish() {
super.finishAndRemoveTask()
}
}

@Composable
Expand Down Expand Up @@ -159,17 +168,23 @@ private fun ConfirmDialogContent(
append(stringResource(id = R.string.text_try_op, opTypeText.lowercase()))
}
Surface(
shape = RoundedCornerShape(16.dp),
shape = RoundedCornerShape(28.dp),
) {
Column(Modifier.padding(16.dp)) {
Column(
modifier = Modifier
.widthIn(280.dp, 560.dp)
.padding(24.dp),
) {
Text(
text = opTypeText,
style = MaterialTheme.typography.headlineMedium
style = MaterialTheme.typography.headlineSmall
)
Spacer(modifier = Modifier.height(16.dp))
Text(text = opContentText)
AppInfoContent(authData.appInfo)
Spacer(modifier = Modifier.height(16.dp))
Text(text = opContentText, style = MaterialTheme.typography.bodyLarge)
ProvideTextStyle(MaterialTheme.typography.bodyMedium) {
AppInfoContent(authData.appInfo)
}
Spacer(modifier = Modifier.height(24.dp))
Row(horizontalArrangement = Arrangement.End, modifier = Modifier.fillMaxWidth()) {
TextButton(onClick = { onCancel() }) {
Text(text = stringResource(R.string.text_prevent))
Expand Down
9 changes: 2 additions & 7 deletions app/src/main/java/cn/tinyhai/ban_uninstall/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import cn.tinyhai.ban_uninstall.transact.client.TransactClient
import cn.tinyhai.ban_uninstall.ui.theme.AppTheme
import cn.tinyhai.compose.dragdrop.AnimatedDragDropBox
import com.ramcosta.composedestinations.DestinationsNavHost
import com.ramcosta.composedestinations.animations.defaults.DefaultFadingTransitions
import com.ramcosta.composedestinations.generated.NavGraphs

class MainActivity : ComponentActivity() {
Expand All @@ -20,12 +20,7 @@ class MainActivity : ComponentActivity() {
enableEdgeToEdge()
setContent {
AppTheme {
AnimatedDragDropBox(
scale = 1.5f,
alpha = 0.6f,
) {
DestinationsNavHost(NavGraphs.root)
}
DestinationsNavHost(NavGraphs.root, defaultTransitions = DefaultFadingTransitions)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ class AuthClient(
service.prevent(opId)
}

override fun isValid(opId: Int): Boolean {
return service.isValid(opId)
}

override fun getAllOpRecord(): List<OpRecord> {
return service.allOpRecord ?: emptyList()
}
Expand Down Expand Up @@ -103,8 +107,6 @@ class AuthClient(
putExtras(bundle)
addFlags(
Intent.FLAG_ACTIVITY_NEW_TASK
or Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
or Intent.FLAG_ACTIVITY_NO_HISTORY
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,40 +205,55 @@ object AuthService : IAuth.Stub() {

private fun wrapWithPendingOp(
opRecord: OpRecord,
onConfirm: () -> Unit,
onCancel: () -> Unit
onAgree: () -> Unit,
onPrevent: () -> Unit
): PendingOpList.PendingOp {
return object : PendingOpList.PendingOp {
override fun confirm() {
onConfirm()
override fun agree() {
onAgree()
opRecordList.add(opRecord, OpResult.Allowed)
}

override fun cancel() {
onCancel()
override fun prevent() {
onPrevent()
opRecordList.add(opRecord, OpResult.Prevented)
}
}
}

override fun agree(opId: Int) {
val calling = Binder.clearCallingIdentity()
val ident = Binder.clearCallingIdentity()
try {
pendingOp.remove(opId)?.confirm()
pendingOp.remove(opId)?.agree()
} finally {
Binder.restoreCallingIdentity(calling)
Binder.restoreCallingIdentity(ident)
}
}

override fun prevent(opId: Int) {
val calling = Binder.clearCallingIdentity()
val ident = Binder.clearCallingIdentity()
try {
pendingOp.remove(opId)?.cancel()
pendingOp.remove(opId)?.prevent()
} finally {
Binder.restoreCallingIdentity(calling)
Binder.restoreCallingIdentity(ident)
}
}

fun preventAll() {
val ident = Binder.clearCallingIdentity()
try {
pendingOp.removeAll().forEach {
it.prevent()
}
} finally {
Binder.restoreCallingIdentity(ident)
}
}

override fun isValid(opId: Int): Boolean {
return pendingOp.contains(opId)
}

override fun getAllOpRecord(): List<OpRecord> {
return opRecordList.toList()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cn.tinyhai.ban_uninstall.auth.server

import android.util.SparseArray
import androidx.core.util.valueIterator

class PendingOpList {
private var counter = 0
Expand All @@ -15,14 +16,28 @@ class PendingOpList {
}
}

fun contains(opId: Int): Boolean {
return synchronized(pending) {
pending[opId] != null
}
}

fun remove(opId: Int): PendingOp? {
return synchronized(pending) {
pending[opId]?.also { pending.remove(opId) }
}
}

fun removeAll(): List<PendingOp> {
return synchronized(pending) {
Iterable { pending.valueIterator() }.toList().also {
pending.clear()
}
}
}

interface PendingOp {
fun confirm()
fun cancel()
fun agree()
fun prevent()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ package cn.tinyhai.ban_uninstall.hooker

import android.content.Context
import cn.tinyhai.ban_uninstall.XposedInit
import cn.tinyhai.ban_uninstall.receiver.PackageChangeReceiver
import cn.tinyhai.ban_uninstall.receiver.RestartMainReceiver
import cn.tinyhai.ban_uninstall.transact.entities.ActiveMode
import cn.tinyhai.ban_uninstall.transact.server.TransactService
import cn.tinyhai.ban_uninstall.utils.SystemContextHolder
import cn.tinyhai.xp.annotation.*
import cn.tinyhai.xp.hook.logger.XPLogger
import de.robv.android.xposed.XC_MethodHook
import de.robv.android.xposed.XposedBridge
import de.robv.android.xposed.XposedHelpers
import de.robv.android.xposed.callbacks.XC_LoadPackage

Expand Down Expand Up @@ -76,6 +76,7 @@ class HookGetSystemContext(
logger.info("systemContext: $systemContext")
systemContext?.let {
SystemContextHolder.onSystemContext(it)
PackageChangeReceiver().register(it)
if (XposedInit.activeMode == ActiveMode.Root) {
RestartMainReceiver.send(it)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package cn.tinyhai.ban_uninstall.receiver

import android.annotation.SuppressLint
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Handler
import androidx.core.content.ContextCompat
import cn.tinyhai.ban_uninstall.BuildConfig
import cn.tinyhai.ban_uninstall.auth.server.AuthService
import cn.tinyhai.ban_uninstall.configs.Configs
import cn.tinyhai.ban_uninstall.transact.server.TransactService
import cn.tinyhai.ban_uninstall.utils.XPLogUtils

@SuppressLint("PrivateApi")
class PackageChangeReceiver : BroadcastReceiver() {

private val intentFilter = IntentFilter().apply {
addAction(Intent.ACTION_PACKAGE_FULLY_REMOVED)
addAction(Intent.ACTION_PACKAGE_REPLACED)
addDataScheme("package")
}

private val registerReceiverForAllUsers by lazy {
try {
Context::class.java.getDeclaredMethod(
"registerReceiverForAllUsers",
BroadcastReceiver::class.java,
IntentFilter::class.java,
String::class.java,
Handler::class.java
)
} catch (e: NoSuchMethodException) {
null
}
}

private val getSendingUserId by lazy {
BroadcastReceiver::class.java.getDeclaredMethod("getSendingUserId")
.also { it.isAccessible = true }
}

override fun onReceive(context: Context, intent: Intent) {
if (!intentFilter.hasAction(intent.action)) {
return
}

val sendingUserId = getSendingUserId.invoke(this) as Int
val uri = intent.data
val packageName = uri?.encodedSchemeSpecificPart
when (intent.action) {
Intent.ACTION_PACKAGE_REPLACED -> {
XPLogUtils.log("pkg replace uri = $uri, userId = $sendingUserId")
if (packageName == BuildConfig.APPLICATION_ID && sendingUserId == 0) {
AuthService.preventAll()
}
}

Intent.ACTION_PACKAGE_FULLY_REMOVED -> {
XPLogUtils.log("pkg uninstall uri = $uri, userId = $sendingUserId")
packageName?.let {
TransactService.onPkgUninstall(packageName, sendingUserId)
}
if (packageName == BuildConfig.APPLICATION_ID && sendingUserId == 0) {
XPLogUtils.log("self package removed")
Configs.onSelfRemoved()
}
}
}
}

fun register(context: Context) {
XPLogUtils.log("register PackageChangeReceiver")
registerReceiverForAllUsers?.let {
it.invoke(
context,
this,
intentFilter,
null,
null
)
Unit
} ?: ContextCompat.registerReceiver(
context, this, intentFilter,
ContextCompat.RECEIVER_NOT_EXPORTED
)
}
}
Loading

0 comments on commit 9af3c02

Please sign in to comment.