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