Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1135,6 +1135,20 @@
android:value="android.service.quicksettings.CATEGORY_UTILITIES" />
</service>

<service
android:name=".services.tiles.LockdownTileService"
android:exported="true"
android:icon="@drawable/rounded_lock_24"
android:label="@string/tile_lockdown_mode"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE" />
</intent-filter>
<meta-data
android:name="android.service.quicksettings.TILE_CATEGORY"
android:value="android.service.quicksettings.CATEGORY_UTILITIES" />
</service>

<provider
android:name=".external.ExternalControlProvider"
android:authorities="${applicationId}.external"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,8 @@ class SettingsRepository(private val context: Context) {
const val KEY_POCKET_MODE_LOCK_SCREEN_ONLY = "pocket_mode_lock_screen_only"
const val KEY_KEEP_PREFS = "keep_prefs"
const val KEY_TRANSLATION_MODE_DO_NOT_SHOW_WARNING = "translation_mode_do_not_show_warning"

const val KEY_LOCKDOWN_MODE = "lockdown_mode"
}

fun isTranslationModeWarningSuppressed(): Boolean = getBoolean(KEY_TRANSLATION_MODE_DO_NOT_SHOW_WARNING, false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1459,6 +1459,33 @@ object FeatureRegistry {
override fun isEnabled(viewModel: MainViewModel) = false
override fun onToggle(viewModel: MainViewModel, context: Context, enabled: Boolean) {}
override fun isDeviceSupported(context: Context) = DeviceUtils.isGoogleDevice()
}
},

object : Feature(
id = "Lockdown mode",
title = R.string.tile_lockdown_mode,
iconRes = R.drawable.rounded_lock_24,
category = R.string.cat_tools,
description = R.string.tile_lockdown_mode_desc,
aboutDescription = R.string.tile_lockdown_mode_about_desc,
permissionKeys = listOf(
if (ShellUtils.isRootEnabled(EssentialsApp.context)) "ROOT" else
"SHIZUKU"
),
showToggle = true,
isVisibleInMain = false,
hasMoreSettings = false,
parentFeatureId = "Security",
isBeta = true,
) {
override fun isEnabled(viewModel: MainViewModel): Boolean =
viewModel.isLockdownModeEnabled.value

override fun isToggleEnabled(viewModel: MainViewModel, context: Context): Boolean =
ShellUtils.hasPermission(context)

override fun onToggle(viewModel: MainViewModel, context: Context, enabled: Boolean) =
viewModel.toggleLockdownMode()
},
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package com.sameerasw.essentials.services.tiles

import android.accessibilityservice.AccessibilityService
import android.graphics.drawable.Icon
import android.os.Build
import android.service.quicksettings.Tile
import android.view.KeyEvent
import android.widget.Toast
import androidx.annotation.RequiresApi
import com.sameerasw.essentials.R
import com.sameerasw.essentials.data.repository.SettingsRepository
import com.sameerasw.essentials.utils.PermissionUtils
import com.sameerasw.essentials.utils.ShellUtils

class LockdownTileService : BaseTileService() {
@RequiresApi(Build.VERSION_CODES.P)
@Suppress("StartActivityAndCollapseDeprecated")
override fun onTileClick() {
if (ShellUtils.hasPermission(this)) {
if (lockdownModeStatus()) {
ShellUtils.runCommand(
this,
"cmd lock_settings require-strong-auth STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN --user 0"
)
} else {
ShellUtils.runCommand(this, "input keyevent ${KeyEvent.KEYCODE_POWER}")
}
return
}

if (PermissionUtils.isAccessibilityServiceEnabled(this)) {
ScreenOffAccessibilityService.instance?.performGlobalAction(AccessibilityService.GLOBAL_ACTION_LOCK_SCREEN)
return
}

Toast.makeText(
this,
"Missing Accessibility/Shizuku permission",
Toast.LENGTH_SHORT
).show()
}

override fun getTileLabel(): String = getString(R.string.tile_lockdown_mode)

override fun getTileSubtitle(): String {
return if (getTileState() == Tile.STATE_ACTIVE) getString(R.string.tile_active) else getString(
R.string.tile_inactive
)
}

override fun hasFeaturePermission(): Boolean {
val status =
PermissionUtils.isAccessibilityServiceEnabled(this) || ShellUtils.hasPermission(this)
return status
}

override fun getTileIcon(): Icon = Icon.createWithResource(this, R.drawable.rounded_lock_24)

override fun getTileState(): Int {
return if (lockdownModeStatus() && ShellUtils.hasPermission(this)) Tile.STATE_ACTIVE else Tile.STATE_INACTIVE
}

private fun lockdownModeStatus(): Boolean {
return getSharedPreferences("essentials_prefs", MODE_PRIVATE)
.getBoolean(SettingsRepository.KEY_LOCKDOWN_MODE, false)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ import com.sameerasw.essentials.services.tiles.DeveloperOptionsTileService
import com.sameerasw.essentials.services.tiles.DynamicNightLightTileService
import com.sameerasw.essentials.services.tiles.FlashlightPulseTileService
import com.sameerasw.essentials.services.tiles.FlashlightTileService
import com.sameerasw.essentials.services.tiles.LockdownTileService
import com.sameerasw.essentials.services.tiles.MapsPowerSavingTileService
import com.sameerasw.essentials.services.tiles.MonoAudioTileService
import com.sameerasw.essentials.services.tiles.NfcTileService
Expand Down Expand Up @@ -346,6 +347,14 @@ fun QuickSettingsTilesSettingsUI(
R.string.about_desc_charge_optimization,
R.string.cat_utils,
isSupported = { _ -> DeviceUtils.isGoogleDevice() }
),
QSTileInfo(
R.string.tile_lockdown_mode,
R.drawable.rounded_lock_24,
LockdownTileService::class.java,
listOf("ACCESSIBILITY", if (ShellUtils.isRootEnabled(context)) "ROOT" else "SHIZUKU"),
R.string.tile_lockdown_mode_about_desc,
R.string.cat_privacy
)
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1607,6 +1607,7 @@ class MainViewModel : ViewModel() {
startBatteryNotificationService(context)
}

isLockdownModeEnabled.value = settingsRepository.getBoolean(SettingsRepository.KEY_LOCKDOWN_MODE)
}

private fun startBatteryNotificationService(context: Context) {
Expand Down Expand Up @@ -4588,4 +4589,10 @@ class MainViewModel : ViewModel() {
var cachedIsUpdateAvailable: Boolean = false
var cachedUpdateInfo: UpdateInfo? = null
}

val isLockdownModeEnabled = mutableStateOf(false)
fun toggleLockdownMode() {
settingsRepository.putBoolean(SettingsRepository.KEY_LOCKDOWN_MODE, !isLockdownModeEnabled.value)
isLockdownModeEnabled.value = !isLockdownModeEnabled.value
}
}
3 changes: 3 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,9 @@
<string name="charge_opt_long_press_title">Toggle Options</string>
<string name="charge_opt_long_press_desc">Choose which charging modes to switch between when tapping the Quick Settings tile.</string>
<string name="permission_missing">Permission missing</string>
<string name="tile_lockdown_mode">Lockdown</string>
<string name="tile_lockdown_mode_desc">Force require pin/pattern to unlock</string>
<string name="tile_lockdown_mode_about_desc">Lock your phone or Lockdown if lockdown mode is turned on.\n\nLockdown mode disables weak unlock methods like face/fingerprint and require pattern or pin securely to unlock your phone.\n\nBoth works with Shizuku and normal lock works with Accessibility too.</string>


<!-- Screen Locked Security -->
Expand Down
Loading