From 5928dbb657e6398138b6035fe6f20a25269a272d Mon Sep 17 00:00:00 2001 From: BinTianqi Date: Thu, 25 Sep 2025 23:01:02 +0800 Subject: [PATCH] Bugfix and new APIs Fix permitted accessibility services and permitted ime, close #165 New APIs, close #166 Optimize shortcuts creation, add ShortcutUtils --- Readme-en.md | 6 + Readme.md | 6 + .../com/bintianqi/owndroid/ApiReceiver.kt | 16 +++ .../com/bintianqi/owndroid/MyViewModel.kt | 17 ++- .../java/com/bintianqi/owndroid/Receiver.kt | 3 - .../java/com/bintianqi/owndroid/Settings.kt | 4 +- .../com/bintianqi/owndroid/ShortcutUtils.kt | 57 +++++++++ .../owndroid/ShortcutsReceiverActivity.kt | 54 ++------- .../bintianqi/owndroid/dpm/Applications.kt | 6 +- .../java/com/bintianqi/owndroid/dpm/DPM.kt | 112 +++++++----------- 10 files changed, 158 insertions(+), 123 deletions(-) create mode 100644 app/src/main/java/com/bintianqi/owndroid/ShortcutUtils.kt diff --git a/Readme-en.md b/Readme-en.md index f4ecd7b..b367766 100644 --- a/Readme-en.md +++ b/Readme-en.md @@ -93,6 +93,8 @@ Samsung restricts Android's multiple users feature. There is currently no soluti ## API +OwnDroid provides an API based on Intent and BroadcastReceiver. + | ID | Extras | Minimum Android version | |--------------------------|------------------------|:-----------------------:| | `HIDE` | `package` | | @@ -104,6 +106,10 @@ Samsung restricts Android's multiple users feature. There is currently no soluti | `SET_PERMISSION_DEFAULT` | `package` `permission` | 6 | | `SET_PERMISSION_GRANTED` | `package` `permission` | 6 | | `SET_PERMISSION_DENIED` | `package` `permission` | 6 | +| `SET_CAMERA_DISABLED` | | | +| `SET_CAMERA_ENABLED` | | | +| `SET_USB_DISABLED` | | 12 | +| `SET_USB_ENABLED` | | 12 | | `LOCK` | | | | `REBOOT` | | 7 | diff --git a/Readme.md b/Readme.md index a2eb37d..3e4de41 100644 --- a/Readme.md +++ b/Readme.md @@ -91,6 +91,8 @@ user limit reached ## API +OwnDroid提供了一个基于Intent和BroadcastReceiver的API。 + | ID | Extra | 最小安卓版本 | |--------------------------|------------------------|:------:| | `HIDE` | `package` | | @@ -102,6 +104,10 @@ user limit reached | `SET_PERMISSION_DEFAULT` | `package` `permission` | 6 | | `SET_PERMISSION_GRANTED` | `package` `permission` | 6 | | `SET_PERMISSION_DENIED` | `package` `permission` | 6 | +| `SET_CAMERA_DISABLED` | | | +| `SET_CAMERA_ENABLED` | | | +| `SET_USB_DISABLED` | | 12 | +| `SET_USB_ENABLED` | | 12 | | `LOCK` | | | | `REBOOT` | | 7 | diff --git a/app/src/main/java/com/bintianqi/owndroid/ApiReceiver.kt b/app/src/main/java/com/bintianqi/owndroid/ApiReceiver.kt index aa784b4..5f12d1d 100644 --- a/app/src/main/java/com/bintianqi/owndroid/ApiReceiver.kt +++ b/app/src/main/java/com/bintianqi/owndroid/ApiReceiver.kt @@ -47,6 +47,22 @@ class ApiReceiver: BroadcastReceiver() { } "LOCK" -> { Privilege.DPM.lockNow(); true } "REBOOT" -> { Privilege.DPM.reboot(Privilege.DAR); true } + "SET_CAMERA_DISABLED" -> { + Privilege.DPM.setCameraDisabled(Privilege.DAR, true) + true + } + "SET_CAMERA_ENABLED" -> { + Privilege.DPM.setCameraDisabled(Privilege.DAR, false) + true + } + "SET_USB_DISABLED" -> { + Privilege.DPM.isUsbDataSignalingEnabled = false + true + } + "SET_USB_ENABLED" -> { + Privilege.DPM.isUsbDataSignalingEnabled = true + true + } else -> { log += "\nInvalid action" false diff --git a/app/src/main/java/com/bintianqi/owndroid/MyViewModel.kt b/app/src/main/java/com/bintianqi/owndroid/MyViewModel.kt index c3db43e..5f5d6ea 100644 --- a/app/src/main/java/com/bintianqi/owndroid/MyViewModel.kt +++ b/app/src/main/java/com/bintianqi/owndroid/MyViewModel.kt @@ -44,9 +44,10 @@ import com.bintianqi.owndroid.dpm.SystemOptionsStatus import com.bintianqi.owndroid.dpm.SystemUpdatePolicyInfo import com.bintianqi.owndroid.dpm.delegatedScopesList import com.bintianqi.owndroid.dpm.getPackageInstaller +import com.bintianqi.owndroid.dpm.handlePrivilegeChange import com.bintianqi.owndroid.dpm.isValidPackageName import com.bintianqi.owndroid.dpm.parsePackageInstallerMessage -import com.bintianqi.owndroid.dpm.permissionList +import com.bintianqi.owndroid.dpm.runtimePermissions import com.bintianqi.owndroid.dpm.temperatureTypes import com.rosan.dhizuku.api.Dhizuku import com.rosan.dhizuku.api.DhizukuRequestPermissionListener @@ -165,7 +166,7 @@ class MyViewModel(application: Application): AndroidViewModel(application) { @RequiresApi(23) fun getPackagePermissions(name: String) { if (name.isValidPackageName) { - packagePermissions.value = permissionList().associate { + packagePermissions.value = runtimePermissions.associate { it.permission to DPM.getPermissionGrantState(DAR, name, it.permission) } } else { @@ -458,7 +459,7 @@ class MyViewModel(application: Application): AndroidViewModel(application) { } fun setCameraDisabled(disabled: Boolean) { DPM.setCameraDisabled(DAR, disabled) - createShortcuts(application) + ShortcutUtils.setShortcut(application, MyShortcut.DisableCamera, !disabled) systemOptionsStatus.update { it.copy(cameraDisabled = DPM.getCameraDisabled(null)) } } fun setScreenCaptureDisabled(disabled: Boolean) { @@ -491,7 +492,7 @@ class MyViewModel(application: Application): AndroidViewModel(application) { } fun setMasterVolumeMuted(muted: Boolean) { DPM.setMasterVolumeMuted(DAR, muted) - createShortcuts(application) + ShortcutUtils.setShortcut(application, MyShortcut.Mute, !muted) systemOptionsStatus.update { it.copy(masterVolumeMuted = DPM.isMasterVolumeMuted(DAR)) } } @RequiresApi(26) @@ -812,6 +813,7 @@ class MyViewModel(application: Application): AndroidViewModel(application) { callback(false, null) } else { Privilege.updateStatus() + handlePrivilegeChange(application) callback( true, result.getString("output") + "\n" + result.getString("error") ) @@ -828,7 +830,10 @@ class MyViewModel(application: Application): AndroidViewModel(application) { if(shell.isRoot) { val result = Shell.cmd(ACTIVATE_DEVICE_OWNER_COMMAND).exec() val output = result.out.joinToString("\n") + "\n" + result.err.joinToString("\n") - Privilege.updateStatus() + if (result.isSuccess) { + Privilege.updateStatus() + handlePrivilegeChange(application) + } callback(result.isSuccess, output) } else { callback(false, application.getString(R.string.permission_denied)) @@ -840,12 +845,14 @@ class MyViewModel(application: Application): AndroidViewModel(application) { DPM.transferOwnership(DAR, MyAdminComponent, null) SP.dhizuku = false Privilege.initialize(application) + handlePrivilegeChange(application) callback(true, null) } fun activateDhizukuMode(callback: (Boolean, String?) -> Unit) { fun onSucceed() { SP.dhizuku = true Privilege.initialize(application) + handlePrivilegeChange(application) callback(true, null) } if (Dhizuku.init(application)) { diff --git a/app/src/main/java/com/bintianqi/owndroid/Receiver.kt b/app/src/main/java/com/bintianqi/owndroid/Receiver.kt index e7b88d9..362a873 100644 --- a/app/src/main/java/com/bintianqi/owndroid/Receiver.kt +++ b/app/src/main/java/com/bintianqi/owndroid/Receiver.kt @@ -11,7 +11,6 @@ import android.os.UserHandle import android.os.UserManager import androidx.core.app.NotificationCompat import com.bintianqi.owndroid.dpm.handleNetworkLogs -import com.bintianqi.owndroid.dpm.handlePrivilegeChange import com.bintianqi.owndroid.dpm.processSecurityLogs import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -35,13 +34,11 @@ class Receiver : DeviceAdminReceiver() { override fun onEnabled(context: Context, intent: Intent) { super.onEnabled(context, intent) Privilege.updateStatus() - handlePrivilegeChange(context) } override fun onDisabled(context: Context, intent: Intent) { super.onDisabled(context, intent) Privilege.updateStatus() - handlePrivilegeChange(context) } override fun onProfileProvisioningComplete(context: Context, intent: Intent) { diff --git a/app/src/main/java/com/bintianqi/owndroid/Settings.kt b/app/src/main/java/com/bintianqi/owndroid/Settings.kt index 530bccd..7691225 100644 --- a/app/src/main/java/com/bintianqi/owndroid/Settings.kt +++ b/app/src/main/java/com/bintianqi/owndroid/Settings.kt @@ -57,7 +57,6 @@ import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.unit.DpOffset import androidx.compose.ui.unit.dp import androidx.core.content.edit -import androidx.core.content.pm.ShortcutManagerCompat import androidx.core.net.toUri import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.bintianqi.owndroid.ui.FunctionItem @@ -155,8 +154,7 @@ fun SettingsOptionsScreen(onNavigateUp: () -> Unit) { R.string.shortcuts, icon = R.drawable.open_in_new, getState = { SP.shortcuts }, onCheckedChange = { SP.shortcuts = it - ShortcutManagerCompat.removeAllDynamicShortcuts(context) - createShortcuts(context) + ShortcutUtils.setAllShortcuts(context) } ) } diff --git a/app/src/main/java/com/bintianqi/owndroid/ShortcutUtils.kt b/app/src/main/java/com/bintianqi/owndroid/ShortcutUtils.kt new file mode 100644 index 0000000..45ca5fa --- /dev/null +++ b/app/src/main/java/com/bintianqi/owndroid/ShortcutUtils.kt @@ -0,0 +1,57 @@ +package com.bintianqi.owndroid + +import android.content.Context +import android.content.Intent +import androidx.core.content.pm.ShortcutInfoCompat +import androidx.core.content.pm.ShortcutManagerCompat +import androidx.core.graphics.drawable.IconCompat + +object ShortcutUtils { + fun setAllShortcuts(context: Context) { + if (SP.shortcuts) { + val list = listOf( + createShortcut(context, MyShortcut.Lock, true), + createShortcut(context, MyShortcut.DisableCamera, + !Privilege.DPM.getCameraDisabled(Privilege.DAR)), + createShortcut(context, MyShortcut.Mute, + !Privilege.DPM.isMasterVolumeMuted(Privilege.DAR)) + ) + ShortcutManagerCompat.setDynamicShortcuts(context, list) + } else { + ShortcutManagerCompat.removeAllDynamicShortcuts(context) + } + } + fun setShortcut(context: Context, shortcut: MyShortcut, state: Boolean) { + ShortcutManagerCompat.pushDynamicShortcut( + context, createShortcut(context, shortcut, state) + ) + } + private fun createShortcut( + context: Context, shortcut: MyShortcut, state: Boolean + ): ShortcutInfoCompat { + val icon = IconCompat.createWithResource( + context, + if (!state && shortcut.iconDisable != null) shortcut.iconDisable else shortcut.iconEnable + ) + return ShortcutInfoCompat.Builder(context, shortcut.id) + .setIcon(icon) + .setShortLabel(context.getText( + if (!state && shortcut.labelDisable != null) shortcut.labelDisable else shortcut.labelEnable + )) + .setIntent( + Intent(context, ShortcutsReceiverActivity::class.java) + .setAction("com.bintianqi.owndroid.action.${shortcut.id}") + ) + .build() + } +} + +enum class MyShortcut( + val id: String, val labelEnable: Int, val labelDisable: Int? = null, val iconEnable: Int, + val iconDisable: Int? = null +) { + Lock("LOCK", R.string.lock_screen, iconEnable = R.drawable.lock_fill0), + DisableCamera("DISABLE_CAMERA", R.string.disable_cam, R.string.enable_camera, + R.drawable.no_photography_fill0, R.drawable.photo_camera_fill0), + Mute("MUTE", R.string.mute, R.string.unmute, R.drawable.volume_off_fill0, R.drawable.volume_up_fill0) +} \ No newline at end of file diff --git a/app/src/main/java/com/bintianqi/owndroid/ShortcutsReceiverActivity.kt b/app/src/main/java/com/bintianqi/owndroid/ShortcutsReceiverActivity.kt index b8dee4a..780adb1 100644 --- a/app/src/main/java/com/bintianqi/owndroid/ShortcutsReceiverActivity.kt +++ b/app/src/main/java/com/bintianqi/owndroid/ShortcutsReceiverActivity.kt @@ -1,12 +1,8 @@ package com.bintianqi.owndroid import android.app.Activity -import android.content.Context -import android.content.Intent import android.os.Bundle -import androidx.core.content.pm.ShortcutInfoCompat -import androidx.core.content.pm.ShortcutManagerCompat -import androidx.core.graphics.drawable.IconCompat +import android.util.Log class ShortcutsReceiverActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { @@ -17,50 +13,24 @@ class ShortcutsReceiverActivity : Activity() { when (action) { "LOCK" -> Privilege.DPM.lockNow() "DISABLE_CAMERA" -> { - Privilege.DPM.setCameraDisabled(Privilege.DAR, !Privilege.DPM.getCameraDisabled(Privilege.DAR)) - createShortcuts(this) + val state = Privilege.DPM.getCameraDisabled(Privilege.DAR) + Privilege.DPM.setCameraDisabled(Privilege.DAR, !state) + ShortcutUtils.setShortcut(this, MyShortcut.DisableCamera, state) } "MUTE" -> { - Privilege.DPM.setMasterVolumeMuted(Privilege.DAR, !Privilege.DPM.isMasterVolumeMuted(Privilege.DAR)) - createShortcuts(this) + val state = Privilege.DPM.isMasterVolumeMuted(Privilege.DAR) + Privilege.DPM.setMasterVolumeMuted(Privilege.DAR, !state) + ShortcutUtils.setShortcut(this, MyShortcut.Mute, state) } } + Log.d(TAG, "Received intent: $action") + showOperationResultToast(true) } } finally { finish() } } -} - -fun createShortcuts(context: Context) { - if (!SP.shortcuts) return - val action = "com.bintianqi.owndroid.action" - val baseIntent = Intent(context, ShortcutsReceiverActivity::class.java) - val cameraDisabled = Privilege.DPM.getCameraDisabled(Privilege.DAR) - val muted = Privilege.DPM.isMasterVolumeMuted(Privilege.DAR) - val list = listOf( - ShortcutInfoCompat.Builder(context, "LOCK") - .setIcon(IconCompat.createWithResource(context, R.drawable.screen_lock_portrait_fill0)) - .setShortLabel(context.getString(R.string.lock_screen)) - .setIntent(Intent(baseIntent).setAction("$action.LOCK")), - ShortcutInfoCompat.Builder(context, "DISABLE_CAMERA") - .setIcon( - IconCompat.createWithResource( - context, - if (cameraDisabled) R.drawable.photo_camera_fill0 else R.drawable.no_photography_fill0 - ) - ) - .setShortLabel(context.getString(if (cameraDisabled) R.string.enable_camera else R.string.disable_cam)) - .setIntent(Intent(baseIntent).setAction("$action.DISABLE_CAMERA")), - ShortcutInfoCompat.Builder(context, "MUTE") - .setIcon( - IconCompat.createWithResource( - context, - if (muted) R.drawable.volume_up_fill0 else R.drawable.volume_off_fill0 - ) - ) - .setShortLabel(context.getString(if (muted) R.string.unmute else R.string.mute)) - .setIntent(Intent(baseIntent).setAction("$action.MUTE")) - ) - ShortcutManagerCompat.setDynamicShortcuts(context, list.map { it.build() }) + companion object { + private const val TAG = "ShortcutsReceiver" + } } diff --git a/app/src/main/java/com/bintianqi/owndroid/dpm/Applications.kt b/app/src/main/java/com/bintianqi/owndroid/dpm/Applications.kt index f8bab24..e043570 100644 --- a/app/src/main/java/com/bintianqi/owndroid/dpm/Applications.kt +++ b/app/src/main/java/com/bintianqi/owndroid/dpm/Applications.kt @@ -315,7 +315,7 @@ fun PermissionsManagerScreen( Spacer(Modifier.padding(vertical = 4.dp)) } } - items(permissionList(), { it.permission }) { + items(runtimePermissions, { it.permission }) { Row( verticalAlignment = Alignment.CenterVertically, modifier = Modifier @@ -630,11 +630,11 @@ fun PermittedAsAndImPackages( item { SwitchItem(R.string.allow_all, state = allowAll, onCheckedChange = { allowAll = it }) } - if (allowAll) items(packages, { it.name }) { + if (!allowAll) items(packages, { it.name }) { ApplicationItem(it) { setPackage(it.name, false) } } item { - if (allowAll) { + if (!allowAll) { PackageNameTextField(packageName, onChoosePackage, Modifier.padding(HorizontalPadding, 8.dp)) { packageName = it } Button( 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 8d01fb9..9eca2c1 100644 --- a/app/src/main/java/com/bintianqi/owndroid/dpm/DPM.kt +++ b/app/src/main/java/com/bintianqi/owndroid/dpm/DPM.kt @@ -13,14 +13,11 @@ import android.content.pm.IPackageInstaller import android.content.pm.PackageInstaller import android.os.Build.VERSION import android.util.Log -import androidx.annotation.DrawableRes import androidx.annotation.RequiresApi -import androidx.annotation.StringRes -import androidx.core.content.pm.ShortcutManagerCompat import com.bintianqi.owndroid.Privilege import com.bintianqi.owndroid.R import com.bintianqi.owndroid.SP -import com.bintianqi.owndroid.createShortcuts +import com.bintianqi.owndroid.ShortcutUtils import com.rosan.dhizuku.api.Dhizuku import com.rosan.dhizuku.api.DhizukuBinderWrapper import kotlinx.coroutines.flow.MutableStateFlow @@ -90,67 +87,49 @@ val dhizukuErrorStatus = MutableStateFlow(0) data class PermissionItem( val permission: String, - @StringRes val label: Int, - @DrawableRes val icon: Int, - val profileOwnerRestricted: Boolean = false + val label: Int, + val icon: Int, + val profileOwnerRestricted: Boolean = false, + val requiresApi: Int = 23 ) -fun permissionList(): List{ - val list = mutableListOf() - if(VERSION.SDK_INT >= 33) { - list.add(PermissionItem(Manifest.permission.POST_NOTIFICATIONS, R.string.permission_POST_NOTIFICATIONS, R.drawable.notifications_fill0)) - } - list.add(PermissionItem(Manifest.permission.READ_EXTERNAL_STORAGE, R.string.permission_READ_EXTERNAL_STORAGE, R.drawable.folder_fill0)) - list.add(PermissionItem(Manifest.permission.WRITE_EXTERNAL_STORAGE, R.string.permission_WRITE_EXTERNAL_STORAGE, R.drawable.folder_fill0)) - if(VERSION.SDK_INT >= 33) { - list.add(PermissionItem(Manifest.permission.READ_MEDIA_AUDIO, R.string.permission_READ_MEDIA_AUDIO, R.drawable.music_note_fill0)) - list.add(PermissionItem(Manifest.permission.READ_MEDIA_VIDEO, R.string.permission_READ_MEDIA_VIDEO, R.drawable.movie_fill0)) - list.add(PermissionItem(Manifest.permission.READ_MEDIA_IMAGES, R.string.permission_READ_MEDIA_IMAGES, R.drawable.image_fill0)) - } - list.add(PermissionItem(Manifest.permission.CAMERA, R.string.permission_CAMERA, R.drawable.photo_camera_fill0, true)) - list.add(PermissionItem(Manifest.permission.RECORD_AUDIO, R.string.permission_RECORD_AUDIO, R.drawable.mic_fill0, true)) - list.add(PermissionItem(Manifest.permission.ACCESS_COARSE_LOCATION, R.string.permission_ACCESS_COARSE_LOCATION, R.drawable.location_on_fill0, true)) - list.add(PermissionItem(Manifest.permission.ACCESS_FINE_LOCATION, R.string.permission_ACCESS_FINE_LOCATION, R.drawable.location_on_fill0, true)) - if(VERSION.SDK_INT >= 29) { - list.add(PermissionItem(Manifest.permission.ACCESS_BACKGROUND_LOCATION, R.string.permission_ACCESS_BACKGROUND_LOCATION, R.drawable.location_on_fill0, true)) - } - list.add(PermissionItem(Manifest.permission.READ_CONTACTS, R.string.permission_READ_CONTACTS, R.drawable.contacts_fill0)) - list.add(PermissionItem(Manifest.permission.WRITE_CONTACTS, R.string.permission_WRITE_CONTACTS, R.drawable.contacts_fill0)) - list.add(PermissionItem(Manifest.permission.READ_CALENDAR, R.string.permission_READ_CALENDAR, R.drawable.calendar_month_fill0)) - list.add(PermissionItem(Manifest.permission.WRITE_CALENDAR, R.string.permission_WRITE_CALENDAR, R.drawable.calendar_month_fill0)) - if(VERSION.SDK_INT >= 31) { - list.add(PermissionItem(Manifest.permission.BLUETOOTH_CONNECT, R.string.permission_BLUETOOTH_CONNECT, R.drawable.bluetooth_fill0)) - list.add(PermissionItem(Manifest.permission.BLUETOOTH_SCAN, R.string.permission_BLUETOOTH_SCAN, R.drawable.bluetooth_searching_fill0)) - list.add(PermissionItem(Manifest.permission.BLUETOOTH_ADVERTISE, R.string.permission_BLUETOOTH_ADVERTISE, R.drawable.bluetooth_fill0)) - } - if(VERSION.SDK_INT >= 33) { - list.add(PermissionItem(Manifest.permission.NEARBY_WIFI_DEVICES, R.string.permission_NEARBY_WIFI_DEVICES, R.drawable.wifi_fill0)) - } - list.add(PermissionItem(Manifest.permission.CALL_PHONE, R.string.permission_CALL_PHONE, R.drawable.call_fill0)) - if(VERSION.SDK_INT >= 26) { - list.add(PermissionItem(Manifest.permission.ANSWER_PHONE_CALLS, R.string.permission_ANSWER_PHONE_CALLS, R.drawable.call_fill0)) - list.add(PermissionItem(Manifest.permission.READ_PHONE_NUMBERS, R.string.permission_READ_PHONE_STATE, R.drawable.mobile_phone_fill0)) - } - list.add(PermissionItem(Manifest.permission.READ_PHONE_STATE, R.string.permission_READ_PHONE_STATE, R.drawable.mobile_phone_fill0)) - list.add(PermissionItem(Manifest.permission.USE_SIP, R.string.permission_USE_SIP, R.drawable.call_fill0)) - if(VERSION.SDK_INT >= 31) { - list.add(PermissionItem(Manifest.permission.UWB_RANGING, R.string.permission_UWB_RANGING, R.drawable.cell_tower_fill0)) - } - list.add(PermissionItem(Manifest.permission.READ_SMS, R.string.permission_READ_SMS, R.drawable.sms_fill0)) - list.add(PermissionItem(Manifest.permission.RECEIVE_SMS, R.string.permission_RECEIVE_SMS, R.drawable.sms_fill0)) - list.add(PermissionItem(Manifest.permission.SEND_SMS, R.string.permission_SEND_SMS, R.drawable.sms_fill0)) - list.add(PermissionItem(Manifest.permission.READ_CALL_LOG, R.string.permission_READ_CALL_LOG, R.drawable.call_log_fill0)) - list.add(PermissionItem(Manifest.permission.WRITE_CALL_LOG, R.string.permission_WRITE_CALL_LOG, R.drawable.call_log_fill0)) - list.add(PermissionItem(Manifest.permission.RECEIVE_WAP_PUSH, R.string.permission_RECEIVE_WAP_PUSH, R.drawable.wifi_fill0)) - list.add(PermissionItem(Manifest.permission.BODY_SENSORS, R.string.permission_BODY_SENSORS, R.drawable.sensors_fill0, true)) - if(VERSION.SDK_INT >= 33) { - list.add(PermissionItem(Manifest.permission.BODY_SENSORS_BACKGROUND, R.string.permission_BODY_SENSORS_BACKGROUND, R.drawable.sensors_fill0)) - } - if(VERSION.SDK_INT > 29) { - list.add(PermissionItem(Manifest.permission.ACTIVITY_RECOGNITION, R.string.permission_ACTIVITY_RECOGNITION, R.drawable.history_fill0, true)) - } - return list -} +@Suppress("InlinedApi") +val runtimePermissions = listOf( + PermissionItem(Manifest.permission.POST_NOTIFICATIONS, R.string.permission_POST_NOTIFICATIONS, R.drawable.notifications_fill0, requiresApi = 33), + PermissionItem(Manifest.permission.READ_EXTERNAL_STORAGE, R.string.permission_READ_EXTERNAL_STORAGE, R.drawable.folder_fill0), + PermissionItem(Manifest.permission.WRITE_EXTERNAL_STORAGE, R.string.permission_WRITE_EXTERNAL_STORAGE, R.drawable.folder_fill0), + PermissionItem(Manifest.permission.READ_MEDIA_AUDIO, R.string.permission_READ_MEDIA_AUDIO, R.drawable.music_note_fill0, requiresApi = 33), + PermissionItem(Manifest.permission.READ_MEDIA_VIDEO, R.string.permission_READ_MEDIA_VIDEO, R.drawable.movie_fill0, requiresApi = 33), + PermissionItem(Manifest.permission.READ_MEDIA_IMAGES, R.string.permission_READ_MEDIA_IMAGES, R.drawable.image_fill0, requiresApi = 33), + PermissionItem(Manifest.permission.CAMERA, R.string.permission_CAMERA, R.drawable.photo_camera_fill0, true), + PermissionItem(Manifest.permission.RECORD_AUDIO, R.string.permission_RECORD_AUDIO, R.drawable.mic_fill0, true), + PermissionItem(Manifest.permission.ACCESS_COARSE_LOCATION, R.string.permission_ACCESS_COARSE_LOCATION, R.drawable.location_on_fill0, true), + PermissionItem(Manifest.permission.ACCESS_FINE_LOCATION, R.string.permission_ACCESS_FINE_LOCATION, R.drawable.location_on_fill0, true), + PermissionItem(Manifest.permission.ACCESS_BACKGROUND_LOCATION, R.string.permission_ACCESS_BACKGROUND_LOCATION, R.drawable.location_on_fill0, true, 29), + PermissionItem(Manifest.permission.READ_CONTACTS, R.string.permission_READ_CONTACTS, R.drawable.contacts_fill0), + PermissionItem(Manifest.permission.WRITE_CONTACTS, R.string.permission_WRITE_CONTACTS, R.drawable.contacts_fill0), + PermissionItem(Manifest.permission.READ_CALENDAR, R.string.permission_READ_CALENDAR, R.drawable.calendar_month_fill0), + PermissionItem(Manifest.permission.WRITE_CALENDAR, R.string.permission_WRITE_CALENDAR, R.drawable.calendar_month_fill0), + PermissionItem(Manifest.permission.BLUETOOTH_CONNECT, R.string.permission_BLUETOOTH_CONNECT, R.drawable.bluetooth_fill0, requiresApi = 31), + PermissionItem(Manifest.permission.BLUETOOTH_SCAN, R.string.permission_BLUETOOTH_SCAN, R.drawable.bluetooth_searching_fill0, requiresApi = 31), + PermissionItem(Manifest.permission.BLUETOOTH_ADVERTISE, R.string.permission_BLUETOOTH_ADVERTISE, R.drawable.bluetooth_fill0, requiresApi = 31), + PermissionItem(Manifest.permission.NEARBY_WIFI_DEVICES, R.string.permission_NEARBY_WIFI_DEVICES, R.drawable.wifi_fill0, requiresApi = 33), + PermissionItem(Manifest.permission.CALL_PHONE, R.string.permission_CALL_PHONE, R.drawable.call_fill0), + PermissionItem(Manifest.permission.ANSWER_PHONE_CALLS, R.string.permission_ANSWER_PHONE_CALLS, R.drawable.call_fill0, requiresApi = 26), + PermissionItem(Manifest.permission.READ_PHONE_NUMBERS, R.string.permission_READ_PHONE_STATE, R.drawable.mobile_phone_fill0, requiresApi = 26), + PermissionItem(Manifest.permission.READ_PHONE_STATE, R.string.permission_READ_PHONE_STATE, R.drawable.mobile_phone_fill0), + PermissionItem(Manifest.permission.USE_SIP, R.string.permission_USE_SIP, R.drawable.call_fill0), + PermissionItem(Manifest.permission.UWB_RANGING, R.string.permission_UWB_RANGING, R.drawable.cell_tower_fill0, requiresApi = 31), + PermissionItem(Manifest.permission.READ_SMS, R.string.permission_READ_SMS, R.drawable.sms_fill0), + PermissionItem(Manifest.permission.RECEIVE_SMS, R.string.permission_RECEIVE_SMS, R.drawable.sms_fill0), + PermissionItem(Manifest.permission.SEND_SMS, R.string.permission_SEND_SMS, R.drawable.sms_fill0), + PermissionItem(Manifest.permission.READ_CALL_LOG, R.string.permission_READ_CALL_LOG, R.drawable.call_log_fill0), + PermissionItem(Manifest.permission.WRITE_CALL_LOG, R.string.permission_WRITE_CALL_LOG, R.drawable.call_log_fill0), + PermissionItem(Manifest.permission.RECEIVE_WAP_PUSH, R.string.permission_RECEIVE_WAP_PUSH, R.drawable.wifi_fill0), + PermissionItem(Manifest.permission.BODY_SENSORS, R.string.permission_BODY_SENSORS, R.drawable.sensors_fill0, true), + PermissionItem(Manifest.permission.BODY_SENSORS_BACKGROUND, R.string.permission_BODY_SENSORS_BACKGROUND, R.drawable.sensors_fill0, requiresApi = 33), + PermissionItem(Manifest.permission.ACTIVITY_RECOGNITION, R.string.permission_ACTIVITY_RECOGNITION, R.drawable.history_fill0, true, 29) +).filter { VERSION.SDK_INT >= it.requiresApi } @RequiresApi(26) fun handleNetworkLogs(context: Context, batchToken: Long) { @@ -468,16 +447,15 @@ fun parsePackageInstallerMessage(context: Context, result: Intent): String { fun handlePrivilegeChange(context: Context) { val privilege = Privilege.status.value SP.dhizukuServer = false + SP.shortcuts = privilege.activated if (privilege.activated) { - createShortcuts(context) + ShortcutUtils.setAllShortcuts(context) if (!privilege.dhizuku) { setDefaultAffiliationID() } } else { SP.isDefaultAffiliationIdSet = false - if(VERSION.SDK_INT >= 25) { - ShortcutManagerCompat.removeAllDynamicShortcuts(context) - } + ShortcutUtils.setAllShortcuts(context) SP.isApiEnabled = false } }