Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
d034e7a
Fix missing newline at end of ExperimentalAppLockService.kt
ap0803apap-sketch Mar 7, 2026
b9506fd
Add RestrictSettingsState data class and enum
ap0803apap-sketch Mar 7, 2026
ff77160
Add RestrictSystemSettingsSection composable
ap0803apap-sketch Mar 7, 2026
c128bb7
Add BatteryProtection.kt for battery optimization exemption
ap0803apap-sketch Mar 7, 2026
5680a0f
Fix missing newline at end of AppLockRepository.kt
ap0803apap-sketch Mar 7, 2026
8136fc8
Refactor AppLockAccessibilityService for clarity and efficiency
ap0803apap-sketch Mar 7, 2026
c7ad15a
Enhance PreferencesRepository with system settings restrictions
ap0803apap-sketch Mar 7, 2026
b749ec3
Add system settings restriction methods to AppLockRepository
ap0803apap-sketch Mar 7, 2026
b9b643c
Implement SystemSettingsRestrictionManager for access control
ap0803apap-sketch Mar 7, 2026
12e64b9
Fix missing newline at end of PreferencesRepository.kt
ap0803apap-sketch Mar 7, 2026
62d406b
Add files via upload
ap0803apap-sketch Mar 7, 2026
879fa95
Implement system settings restrictions in PreferencesRepository
ap0803apap-sketch Mar 7, 2026
0544e99
Add system settings restriction methods to AppLockRepository
ap0803apap-sketch Mar 7, 2026
f17cc67
Refactor SystemSettingsRestrictionManager for clarity
ap0803apap-sketch Mar 7, 2026
951c63b
Add SettingsIntentInterceptor to block restricted settings
ap0803apap-sketch Mar 7, 2026
fe3dbc6
Implement system settings restrictions for anti-uninstall
ap0803apap-sketch Mar 7, 2026
8e3dfa3
Add permissions and receiver for system settings
ap0803apap-sketch Mar 7, 2026
d8b7740
Implement system settings restriction management
ap0803apap-sketch Mar 7, 2026
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
55 changes: 54 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:installLocation="internalOnly">

<!-- EXISTING PERMISSIONS -->
<uses-permission
android:name="android.permission.QUERY_ALL_PACKAGES"
tools:ignore="PackageVisibilityPolicy,QueryAllPackagesPermission" />
Expand All @@ -26,9 +27,12 @@
tools:ignore="ForegroundServicesPolicy" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SYSTEM_EXEMPTED" />

<uses-permission android:name="android.permission.SET_ACTIVITY_WATCHER" />

<!-- NEW PERMISSIONS FOR SYSTEM SETTINGS RESTRICTION -->
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
<uses-permission android:name="android.permission.ACCESS_DEVICE_ADMIN" />

<application
android:name=".AppLockApplication"
android:allowBackup="true"
Expand All @@ -43,6 +47,7 @@
android:theme="@style/Theme.AppLock"
tools:targetApi="33">

<!-- MAIN ACTIVITY -->
<activity
android:name=".MainActivity"
android:exported="true"
Expand All @@ -53,6 +58,7 @@
</intent-filter>
</activity>

<!-- LOCK SCREEN ACTIVITY -->
<activity
android:name=".features.lockscreen.ui.PasswordOverlayActivity"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
Expand All @@ -61,17 +67,20 @@
android:taskAffinity=""
android:theme="@android:style/Theme.Material.NoActionBar.TranslucentDecor" />

<!-- ADMIN DISABLE ACTIVITY -->
<activity
android:name=".features.admin.AdminDisableActivity"
android:exported="false"
android:theme="@style/Theme.AppLock" />

<!-- SHIZUKU SERVICE -->
<service
android:name=".services.ShizukuAppLockService"
android:enabled="true"
android:exported="false"
android:foregroundServiceType="specialUse|systemExempted" />

<!-- EXPERIMENTAL SERVICE -->
<service
android:name=".services.ExperimentalAppLockService"
android:enabled="true"
Expand All @@ -82,6 +91,7 @@
android:value="app_lock" />
</service>

<!-- ACCESSIBILITY SERVICE - UPDATED EVENT TYPES -->
<service
android:name=".services.AppLockAccessibilityService"
android:exported="false"
Expand All @@ -100,6 +110,7 @@
android:value="accessibility" />
</service>

<!-- DEVICE ADMIN RECEIVER -->
<receiver
android:name=".core.broadcast.DeviceAdmin"
android:description="@string/device_admin_description"
Expand All @@ -113,6 +124,7 @@
android:resource="@xml/device_admin_policies" />
</receiver>

<!-- BOOT RECEIVER -->
<receiver
android:name=".core.broadcast.BootReceiver"
android:enabled="true"
Expand All @@ -126,6 +138,45 @@
</intent-filter>
</receiver>

<!-- NEW: BROADCAST RECEIVER FOR SYSTEM SETTINGS INTENT INTERCEPTION -->
<receiver
android:name=".core.broadcast.SettingsIntentInterceptor"
android:exported="false"
android:enabled="true"
android:permission="android.permission.MANAGE_APP_PERMISSIONS">

<intent-filter android:priority="1000">
<!-- Overlay/Draw Over Apps Settings -->
<action android:name="android.intent.action.MANAGE_OVERLAY_PERMISSION" />
<action android:name="android.settings.MANAGE_OVERLAY_PERMISSION" />

<!-- Usage Access Settings -->
<action android:name="android.settings.USAGE_ACCESS_SETTINGS" />
<action android:name="android.intent.action.USAGE_ACCESS_SETTINGS" />

<!-- Accessibility Settings -->
<action android:name="android.settings.ACCESSIBILITY_SETTINGS" />
<action android:name="android.intent.action.ACCESSIBILITY_SETTINGS" />

<!-- Device Administrator Settings -->
<action android:name="android.settings.SECURITY_SETTINGS" />
<action android:name="android.intent.action.SECURITY_SETTINGS" />
<action android:name="com.android.settings.DEVICE_ADMIN_DELETE_CONFIRM" />
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
<action android:name="android.app.action.DEVICE_ADMIN_DISABLED" />

<!-- Battery Optimization Settings -->
<action android:name="android.settings.IGNORE_BATTERY_OPTIMIZATION_SETTINGS" />
<action android:name="android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<action android:name="android.intent.action.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />

<!-- Samsung-specific Settings -->
<action android:name="com.android.settings.MANAGE_APP_PERMISSIONS" />
<action android:name="com.sec.android.settings.MANAGE_PERMISSION" />
</intent-filter>
</receiver>

<!-- FILE PROVIDER -->
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
Expand All @@ -136,6 +187,7 @@
android:resource="@xml/file_paths" />
</provider>

<!-- SHIZUKU PROVIDER -->
<provider
android:name="rikka.shizuku.ShizukuProvider"
android:authorities="${applicationId}.shizuku"
Expand All @@ -145,4 +197,5 @@
android:permission="android.permission.INTERACT_ACROSS_USERS_FULL" />

</application>

</manifest>
22 changes: 22 additions & 0 deletions app/src/main/java/dev/pranav/applock/BatteryProtection.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package dev.pranav.applock.core.security

import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.PowerManager
import android.provider.Settings

fun enforceBatteryExemption(context: Context) {

val pm = context.getSystemService(PowerManager::class.java)

if (pm.isIgnoringBatteryOptimizations(context.packageName)) return

val intent = Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)

intent.data = Uri.parse("package:${context.packageName}")

intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK

context.startActivity(intent)
}
27 changes: 27 additions & 0 deletions app/src/main/java/dev/pranav/applock/RestrictSettingsState.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package dev.pranav.applock.core.security

data class RestrictSettingsState(

val blockOverlaySettings: Boolean = false,

val blockUsageAccessSettings: Boolean = false,

val blockAccessibilitySettings: Boolean = false,

val blockDeviceAdminSettings: Boolean = false,

val requireBatteryExemption: Boolean = false
)

enum class RestrictSetting {

OVERLAY,

USAGE,

ACCESSIBILITY,

DEVICE_ADMIN,

BATTERY
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package dev.pranav.applock.core.broadcast

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import dev.pranav.applock.core.utils.LogUtils
import dev.pranav.applock.core.utils.appLockRepository
import dev.pranav.applock.core.utils.systemSettingsRestrictionManager

/**
* COMPLETE FILE - Copy to app/src/main/java/dev/pranav/applock/core/broadcast/
*
* Broadcast receiver that intercepts attempts to open restricted system settings pages.
* Register in AndroidManifest.xml with the provided intent filters.
*/
class SettingsIntentInterceptor : BroadcastReceiver() {

override fun onReceive(context: Context, intent: Intent?) {
if (intent == null) {
return
}

try {
val repository = context.appLockRepository()

if (!repository.isAntiUninstallEnabled()) {
return
}

val restrictionManager = context.systemSettingsRestrictionManager()

if (restrictionManager.isIntentRestricted(intent)) {
blockAndShowLockScreen(context, intent)
abortBroadcast()
}
} catch (e: Exception) {
LogUtils.logError("Error in SettingsIntentInterceptor", e)
}
}

/**
* Block the settings intent and show lock screen instead.
*/
private fun blockAndShowLockScreen(context: Context, intent: Intent) {
try {
val action = intent.action ?: "Unknown"
LogUtils.logSecurityEvent("Blocked attempt to access settings: $action")

val lockScreenIntent = Intent(context, PasswordOverlayActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or
Intent.FLAG_ACTIVITY_CLEAR_TOP or
Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
putExtra("isRestrictedSettings", true)
putExtra("restrictedAction", intent.action)
}
context.startActivity(lockScreenIntent)

val homeIntent = Intent(Intent.ACTION_MAIN).apply {
addCategory(Intent.CATEGORY_HOME)
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
context.startActivity(homeIntent)
} catch (e: Exception) {
LogUtils.logError("Failed to block and show lock screen", e)
}
}

companion object {
private const val TAG = "SettingsIntentInterceptor"
}
}

/**
* Alternative implementation: Activity that intercepts settings intents.
* Can be used as a bridge activity to intercept intents before they reach system settings.
* Optional - only use if BroadcastReceiver approach doesn't work on your device.
*/
class SettingsIntentInterceptorActivity : android.app.Activity() {

override fun onCreate(savedInstanceState: android.os.Bundle?) {
super.onCreate(savedInstanceState)

try {
val intent = intent
val repository = applicationContext.appLockRepository()

if (repository.isAntiUninstallEnabled()) {
val restrictionManager = applicationContext.systemSettingsRestrictionManager()

if (restrictionManager.isIntentRestricted(intent)) {
LogUtils.logSecurityEvent("Blocked attempt to access settings: ${intent.action}")

val lockScreenIntent = Intent(applicationContext, PasswordOverlayActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or
Intent.FLAG_ACTIVITY_CLEAR_TOP or
Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
putExtra("isRestrictedSettings", true)
}
startActivity(lockScreenIntent)

finish()
return
}
}

startActivity(intent)
finish()
} catch (e: Exception) {
LogUtils.logError("Error in SettingsIntentInterceptorActivity", e)
finish()
}
}
}
Loading
Loading