From cd26c2a79224e57719b0e437111f662dea92198c Mon Sep 17 00:00:00 2001 From: BinTianqi Date: Wed, 7 Aug 2024 19:52:51 +0800 Subject: [PATCH] fix unable to uninstall app in Dhizuku mode fix unable to push CI builds to Telegram --- .github/workflows/build.yml | 2 +- .../android/content/pm/IPackageInstaller.java | 17 +++++++++ .../bintianqi/owndroid/InstallAppActivity.kt | 4 +- .../owndroid/dpm/ApplicationManage.kt | 2 +- .../java/com/bintianqi/owndroid/dpm/DPM.kt | 37 ++++++++++++++++++- .../bintianqi/owndroid/dpm/ManagedProfile.kt | 3 +- .../com/bintianqi/owndroid/dpm/Permissions.kt | 6 ++- app/src/main/res/values-tr/strings.xml | 2 +- app/src/main/res/values-zh-rCN/strings.xml | 2 +- app/src/main/res/values/strings.xml | 2 +- 10 files changed, 66 insertions(+), 11 deletions(-) create mode 100644 app/src/main/java/android/content/pm/IPackageInstaller.java diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8f52c3a..dd98e72 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -91,6 +91,6 @@ jobs: mv ./$RELEASE_SIGNED_PWD/app-release.apk ./$RELEASE_SIGNED_PWD.apk && rm -rf ./$RELEASE_SIGNED_PWD ../binaries/telegram-bot-api --api-id=${{ secrets.TELEGRAM_API_APP_ID }} --api-hash=${{ secrets.TELEGRAM_API_HASH }} --local 2>&1 > /dev/null & export token=${{ secrets.TELEGRAM_BOT_KEY }} - curl -v "http://127.0.0.1:8081/bot$token/sendMediaGroup?chat_id=-1002216379163&media=%5B%7B%22type%22%3A%22document%22%2C%22media%22%3A%22attach%3A%2F%2FdebugTest%22%7D%2C%7B%22type%22%3A%22document%22%2C%22media%22%3A%22attach%3A%2F%2FreleaseTest%22%7D%2C%7B%22type%22%3A%22document%22%2C%22media%22%3A%22attach%3A%2F%2FdebugSigned%22%7D%2C%7B%22type%22%3A%22document%22%2C%22media%22%3A%22attach%3A%2F%2FreleaseSigned%22%2C%22parse_mode%22%3A%22MarkdownV2%22%2C%22caption%22%3A${ESCAPED}%7D%5D" \ + curl -v "http://127.0.0.1:8081/bot$token/sendMediaGroup?chat_id=-1002216379163&media=%5B%7B%22type%22%3A%22document%22%2C%22media%22%3A%22attach%3A%2F%2FreleaseTest%22%7D%2C%7B%22type%22%3A%22document%22%2C%22media%22%3A%22attach%3A%2F%2FreleaseSigned%22%2C%22parse_mode%22%3A%22MarkdownV2%22%2C%22caption%22%3A${ESCAPED}%7D%5D" \ -F releaseTest="@$RELEASE_TEST_PWD.apk" \ -F releaseSigned="@$RELEASE_SIGNED_PWD.apk" diff --git a/app/src/main/java/android/content/pm/IPackageInstaller.java b/app/src/main/java/android/content/pm/IPackageInstaller.java new file mode 100644 index 0000000..1dc957a --- /dev/null +++ b/app/src/main/java/android/content/pm/IPackageInstaller.java @@ -0,0 +1,17 @@ +package android.content.pm; + +import android.os.Binder; +import android.os.IBinder; +import android.os.IInterface; + +import androidx.annotation.Keep; + +@Keep +public interface IPackageInstaller extends IInterface { + @Keep + abstract class Stub extends Binder implements IPackageInstaller { + public static IPackageInstaller asInterface(IBinder obj) { + throw new UnsupportedOperationException(); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/bintianqi/owndroid/InstallAppActivity.kt b/app/src/main/java/com/bintianqi/owndroid/InstallAppActivity.kt index 5b16ec6..21b9023 100644 --- a/app/src/main/java/com/bintianqi/owndroid/InstallAppActivity.kt +++ b/app/src/main/java/com/bintianqi/owndroid/InstallAppActivity.kt @@ -58,7 +58,7 @@ class InstallAppActivity: FragmentActivity() { ) fd?.close() withContext(Dispatchers.Main) { - status = "waiting" + status = "pending" apkInfoText = "${context.getString(R.string.package_name)}: ${apkInfo.packageName}\n" apkInfoText += "${context.getString(R.string.version_name)}: ${apkInfo.versionName}\n" apkInfoText += "${context.getString(R.string.version_code)}: ${apkInfo.versionCode}" @@ -79,7 +79,7 @@ class InstallAppActivity: FragmentActivity() { }, text = { Column { - AnimatedVisibility(status != "waiting") { + AnimatedVisibility(status != "pending") { LinearProgressIndicator(modifier = Modifier.fillMaxWidth()) } Text(text = apkInfoText, modifier = Modifier.padding(top = 4.dp)) diff --git a/app/src/main/java/com/bintianqi/owndroid/dpm/ApplicationManage.kt b/app/src/main/java/com/bintianqi/owndroid/dpm/ApplicationManage.kt index f4f9de4..6d03484 100644 --- a/app/src/main/java/com/bintianqi/owndroid/dpm/ApplicationManage.kt +++ b/app/src/main/java/com/bintianqi/owndroid/dpm/ApplicationManage.kt @@ -942,7 +942,7 @@ private fun UninstallApp(pkgName: String) { onClick = { val intent = Intent(context, PackageInstallerReceiver::class.java) val intentSender = PendingIntent.getBroadcast(context, 8, intent, PendingIntent.FLAG_IMMUTABLE).intentSender - val pkgInstaller = context.packageManager.packageInstaller + val pkgInstaller = context.getPI() pkgInstaller.uninstall(pkgName, intentSender) }, modifier = Modifier.fillMaxWidth() diff --git a/app/src/main/java/com/bintianqi/owndroid/dpm/DPM.kt b/app/src/main/java/com/bintianqi/owndroid/dpm/DPM.kt index bab61bb..29fbe4e 100644 --- a/app/src/main/java/com/bintianqi/owndroid/dpm/DPM.kt +++ b/app/src/main/java/com/bintianqi/owndroid/dpm/DPM.kt @@ -10,6 +10,7 @@ import android.app.admin.SystemUpdatePolicy import android.content.ComponentName import android.content.Context import android.content.Intent +import android.content.pm.IPackageInstaller import android.content.pm.PackageInstaller import android.os.Build.VERSION import androidx.activity.result.ActivityResultLauncher @@ -86,7 +87,7 @@ fun installPackage(context: Context, inputStream: InputStream) { } @SuppressLint("PrivateApi") -fun binderWrapperDevicePolicyManager(appContext: Context): DevicePolicyManager? { +private fun binderWrapperDevicePolicyManager(appContext: Context): DevicePolicyManager? { try { val context = appContext.createPackageContext(Dhizuku.getOwnerComponent().packageName, Context.CONTEXT_IGNORE_SECURITY) val manager = context.getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager @@ -105,6 +106,40 @@ fun binderWrapperDevicePolicyManager(appContext: Context): DevicePolicyManager? return null } +@SuppressLint("PrivateApi") +private fun binderWrapperPackageInstaller(appContext: Context): PackageInstaller? { + try { + val context = appContext.createPackageContext(Dhizuku.getOwnerComponent().packageName, Context.CONTEXT_IGNORE_SECURITY) + val installer = context.packageManager.packageInstaller + val field = installer.javaClass.getDeclaredField("mInstaller") + field.isAccessible = true + val oldInterface = field[installer] as IPackageInstaller + if (oldInterface is DhizukuBinderWrapper) return installer + val oldBinder = oldInterface.asBinder() + val newBinder = binderWrapper(oldBinder) + val newInterface = IPackageInstaller.Stub.asInterface(newBinder) + field[installer] = newInterface + return installer + } catch (e: Exception) { + dhizukuErrorStatus.value = 1 + } + return null +} + +fun Context.getPI(): PackageInstaller { + val sharedPref = this.getSharedPreferences("data", Context.MODE_PRIVATE) + if(sharedPref.getBoolean("dhizuku", false)) { + if (!Dhizuku.isPermissionGranted()) { + dhizukuErrorStatus.value = 2 + backToHomeStateFlow.value = true + return this.packageManager.packageInstaller + } + return binderWrapperPackageInstaller(this) ?: this.packageManager.packageInstaller + } else { + return this.packageManager.packageInstaller + } +} + fun Context.getDPM(): DevicePolicyManager { val sharedPref = this.getSharedPreferences("data", Context.MODE_PRIVATE) if(sharedPref.getBoolean("dhizuku", false)) { diff --git a/app/src/main/java/com/bintianqi/owndroid/dpm/ManagedProfile.kt b/app/src/main/java/com/bintianqi/owndroid/dpm/ManagedProfile.kt index 7360106..f6dcfe0 100644 --- a/app/src/main/java/com/bintianqi/owndroid/dpm/ManagedProfile.kt +++ b/app/src/main/java/com/bintianqi/owndroid/dpm/ManagedProfile.kt @@ -22,6 +22,7 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.text.KeyboardActions @@ -101,7 +102,7 @@ private fun Home(navCtrl: NavHostController) { Text( text = stringResource(R.string.work_profile), style = typography.headlineLarge, - modifier = Modifier.padding(top = 8.dp, bottom = 5.dp, start = 15.dp) + modifier = Modifier.padding(top = 8.dp, bottom = 5.dp).offset(x = (-8).dp) ) if(VERSION.SDK_INT >= 30 && context.isProfileOwner && dpm.isManagedProfile(receiver)) { SubPageItem(R.string.org_owned_work_profile, "", R.drawable.corporate_fare_fill0) { navCtrl.navigate("OrgOwnedWorkProfile") } diff --git a/app/src/main/java/com/bintianqi/owndroid/dpm/Permissions.kt b/app/src/main/java/com/bintianqi/owndroid/dpm/Permissions.kt index 5e0c45a..ccbd0e7 100644 --- a/app/src/main/java/com/bintianqi/owndroid/dpm/Permissions.kt +++ b/app/src/main/java/com/bintianqi/owndroid/dpm/Permissions.kt @@ -327,6 +327,7 @@ private fun DeviceOwner() { val context = LocalContext.current val dpm = context.getDPM() var deactivateDialog by remember { mutableStateOf(false) } + var resetPolicy by remember { mutableStateOf(true) } Column(modifier = Modifier.fillMaxSize().verticalScroll(rememberScrollState()).padding(horizontal = 8.dp)) { Spacer(Modifier.padding(vertical = 10.dp)) Text(text = stringResource(R.string.device_owner), style = typography.headlineLarge) @@ -357,7 +358,8 @@ private fun DeviceOwner() { text = { Column { if(sharedPref.getBoolean("dhizuku", false)) Text(stringResource(R.string.dhizuku_will_be_deactivated)) - Text(stringResource(R.string.will_reset_policy)) + Spacer(Modifier.padding(vertical = 4.dp)) + CheckBoxItem(text = R.string.reset_device_policy, checked = resetPolicy, operation = { resetPolicy = it }) } }, onDismissRequest = { deactivateDialog = false }, @@ -372,7 +374,7 @@ private fun DeviceOwner() { TextButton( onClick = { coroutine.launch { - context.resetDevicePolicy() + if(resetPolicy) context.resetDevicePolicy() dpm.clearDeviceOwnerApp(context.dpcPackageName) if(sharedPref.getBoolean("dhizuku", false)) { if (!Dhizuku.init(context)) { diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index a4d87e4..ea9acc3 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -64,7 +64,7 @@ Profil Sahibi Cihaz Sahibi Dhizuku will be deactivated - All device policies set by OwnDroid will be cleared + Reset device policy Cihaz Yöneticisini Etkinleştir Cihaz Bilgisi Cihaz Kimliği Doğrulama Desteği: diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 4608e77..b6464ce 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -60,7 +60,7 @@ 激活... Profile owner Device owner - 所有由OwnDroid设置的设备策略将被清除 + 重置设备策略 Dhizuku将被停用 激活Device admin 设备信息 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4529352..676b3c5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -64,7 +64,7 @@ Profile owner Device owner Dhizuku will be deactivated - All device policies set by OwnDroid will be cleared + Reset device policy Activate Device admin dpm set-active-admin com.bintianqi.owndroid/com.bintianqi.owndroid.Receiver dpm set-device-owner com.bintianqi.owndroid/com.bintianqi.owndroid.Receiver