From 3f5e2b89ca4a867b03fd1959740fc950ced2d286 Mon Sep 17 00:00:00 2001 From: Seth Schroeder Date: Mon, 1 Jul 2024 10:17:17 +0100 Subject: [PATCH 1/3] #1234 fix: don't crash app if API changes for granting permissions in the system --- .../permissions/AndroidPermissionAdapter.kt | 35 +++++++++++-------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/io/github/sds100/keymapper/system/permissions/AndroidPermissionAdapter.kt b/app/src/main/java/io/github/sds100/keymapper/system/permissions/AndroidPermissionAdapter.kt index 5a11d0fe93..468d5c5c4d 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/permissions/AndroidPermissionAdapter.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/permissions/AndroidPermissionAdapter.kt @@ -54,12 +54,12 @@ class AndroidPermissionAdapter( const val REQUEST_CODE_SHIZUKU_PERMISSION = 1 } - private val iPackageManager: IPackageManager by lazy { + private val shizukuPackageManager: IPackageManager by lazy { val binder = ShizukuBinderWrapper(SystemServiceHelper.getSystemService("package")) IPackageManager.Stub.asInterface(binder) } - private val iPermissionManager: IPermissionManager by lazy { + private val shizukuPermissionManager: IPermissionManager by lazy { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { HiddenApiBypass.addHiddenApiExemptions( "Landroid/permission", @@ -151,19 +151,24 @@ class AndroidPermissionAdapter( private fun grantPermissionWithShizuku(permissionName: String) { val userId = Process.myUserHandle()!!.getIdentifier() - // In Android 12 this method was moved from IPackageManager to IPermissionManager - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - iPermissionManager.grantRuntimePermission( - Constants.PACKAGE_NAME, - permissionName, - userId, - ) - } else { - iPackageManager.grantRuntimePermission( - Constants.PACKAGE_NAME, - permissionName, - userId, - ) + try { + // In Android 12 this method was moved from IPackageManager to IPermissionManager + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + shizukuPermissionManager.grantRuntimePermission( + Constants.PACKAGE_NAME, + permissionName, + userId, + ) + } else { + shizukuPackageManager.grantRuntimePermission( + Constants.PACKAGE_NAME, + permissionName, + userId, + ) + } + // The API may change in future Android versions so don't crash the whole app + // just for this shizuku permission feature. + } catch (_: NoSuchMethodError) { } } From de6ac728b5090d0c90d7f1b500a2aec08c31daa9 Mon Sep 17 00:00:00 2001 From: Seth Schroeder Date: Mon, 1 Jul 2024 10:29:54 +0100 Subject: [PATCH 2/3] #1234 upgrade Shizuku version --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 687eb67679..45c91fe4b7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -143,7 +143,7 @@ dependencies { def epoxy_version = "4.6.2" def splitties_version = "3.0.0-beta01" def multidex_version = "2.0.1" - def shizuku_version = '12.1.0' + def shizuku_version = '13.1.5' implementation fileTree(include: ['*.jar'], dir: 'libs') From 7089dfcce87d62bbb16fb1f0626edf0093f6c9a9 Mon Sep 17 00:00:00 2001 From: Seth Schroeder Date: Sun, 7 Jul 2024 10:50:06 +0200 Subject: [PATCH 3/3] #1234 fix: try different methods of granting permissions on Android 14 --- app/build.gradle | 1 + .../permission/IPermissionManager.aidl | 6 ---- .../permissions/AndroidPermissionAdapter.kt | 30 ++++++++++++++-- settings.gradle | 1 + systemstubs/.gitignore | 1 + systemstubs/build.gradle.kts | 36 +++++++++++++++++++ systemstubs/consumer-rules.pro | 0 systemstubs/proguard-rules.pro | 21 +++++++++++ .../permission/IPermissionManager.java | 17 +++++++++ 9 files changed, 105 insertions(+), 8 deletions(-) delete mode 100644 app/src/main/aidl/android/permission/IPermissionManager.aidl create mode 100644 systemstubs/.gitignore create mode 100644 systemstubs/build.gradle.kts create mode 100644 systemstubs/consumer-rules.pro create mode 100644 systemstubs/proguard-rules.pro create mode 100644 systemstubs/src/main/java/android/permission/IPermissionManager.java diff --git a/app/build.gradle b/app/build.gradle index e7a1c78d74..f983238f33 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -160,6 +160,7 @@ dependencies { // androidx implementation 'androidx.legacy:legacy-support-core-ui:1.0.0' implementation 'androidx.core:core-ktx:1.13.1' + compileOnly project(':systemstubs') implementation 'androidx.fragment:fragment-ktx:1.4.1' implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0' diff --git a/app/src/main/aidl/android/permission/IPermissionManager.aidl b/app/src/main/aidl/android/permission/IPermissionManager.aidl deleted file mode 100644 index e35617f4fc..0000000000 --- a/app/src/main/aidl/android/permission/IPermissionManager.aidl +++ /dev/null @@ -1,6 +0,0 @@ -package android.permission; - -// Only on Android 12+ -interface IPermissionManager { - void grantRuntimePermission(String packageName, String permissionName, int userId); -} \ No newline at end of file diff --git a/app/src/main/java/io/github/sds100/keymapper/system/permissions/AndroidPermissionAdapter.kt b/app/src/main/java/io/github/sds100/keymapper/system/permissions/AndroidPermissionAdapter.kt index 468d5c5c4d..0fdd75aaee 100644 --- a/app/src/main/java/io/github/sds100/keymapper/system/permissions/AndroidPermissionAdapter.kt +++ b/app/src/main/java/io/github/sds100/keymapper/system/permissions/AndroidPermissionAdapter.kt @@ -152,8 +152,34 @@ class AndroidPermissionAdapter( val userId = Process.myUserHandle()!!.getIdentifier() try { - // In Android 12 this method was moved from IPackageManager to IPermissionManager - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + // In revisions of Android 14 the method to grant permissions changed + // so try them all. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { + try { + shizukuPermissionManager.grantRuntimePermission( + Constants.PACKAGE_NAME, + permissionName, + ctx.deviceId, + userId, + ) + } catch (_: NoSuchMethodError) { + try { + shizukuPermissionManager.grantRuntimePermission( + Constants.PACKAGE_NAME, + permissionName, + "0", + userId, + ) + } catch (_: NoSuchMethodError) { + shizukuPermissionManager.grantRuntimePermission( + Constants.PACKAGE_NAME, + permissionName, + userId, + ) + } + } + // In Android 11 this method was moved from IPackageManager to IPermissionManager. + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { shizukuPermissionManager.grantRuntimePermission( Constants.PACKAGE_NAME, permissionName, diff --git a/settings.gradle b/settings.gradle index e7b4def49c..a2a582b50a 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1,2 @@ include ':app' +include ':systemstubs' diff --git a/systemstubs/.gitignore b/systemstubs/.gitignore new file mode 100644 index 0000000000..42afabfd2a --- /dev/null +++ b/systemstubs/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/systemstubs/build.gradle.kts b/systemstubs/build.gradle.kts new file mode 100644 index 0000000000..7121b0ba36 --- /dev/null +++ b/systemstubs/build.gradle.kts @@ -0,0 +1,36 @@ +plugins { + id("com.android.library") + id("org.jetbrains.kotlin.android") +} + +android { + namespace = "io.github.sds100.keymapper.systemstubs" + compileSdk = 34 + + defaultConfig { + minSdk = 21 + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + consumerProguardFiles("consumer-rules.pro") + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro", + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + } + kotlinOptions { + jvmTarget = "1.8" + } +} + +dependencies { +} diff --git a/systemstubs/consumer-rules.pro b/systemstubs/consumer-rules.pro new file mode 100644 index 0000000000..e69de29bb2 diff --git a/systemstubs/proguard-rules.pro b/systemstubs/proguard-rules.pro new file mode 100644 index 0000000000..481bb43481 --- /dev/null +++ b/systemstubs/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/systemstubs/src/main/java/android/permission/IPermissionManager.java b/systemstubs/src/main/java/android/permission/IPermissionManager.java new file mode 100644 index 0000000000..29e7bc0f86 --- /dev/null +++ b/systemstubs/src/main/java/android/permission/IPermissionManager.java @@ -0,0 +1,17 @@ +package android.permission; + +import android.os.IBinder; + +public interface IPermissionManager extends android.os.IInterface { + void grantRuntimePermission(String packageName, String permissionName, int userId); + + void grantRuntimePermission(String packageName, String permissionName, int deviceId, int userId); + + void grantRuntimePermission(String packageName, String permissionName, String persistentDeviceId, int userId); + + abstract class Stub extends android.os.Binder implements IPermissionManager { + public static IPermissionManager asInterface(IBinder obj) { + throw new RuntimeException("Stub!"); + } + } +} \ No newline at end of file