Skip to content

Commit

Permalink
application trigger
Browse files Browse the repository at this point in the history
  • Loading branch information
lucky committed Jul 14, 2022
1 parent ebf2a59 commit 712ef42
Show file tree
Hide file tree
Showing 77 changed files with 532 additions and 10 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ locks a device and optionally runs wipe.
Also you can:
* fire when a device was not unlocked for X time
* fire when a USB data connection is made while a device is locked
* fire when a fake messenger app is launched
* fire when a duress password is entered (companion app: [Duress](https://github.com/x13a/Duress))

The app works in `Work Profile` too. Use [Shelter](https://github.com/PeterCxy/Shelter) to install
Expand Down
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ android {
applicationId "me.lucky.wasted"
minSdk 23
targetSdk 32
versionCode 34
versionName "1.5.5"
versionCode 35
versionName "1.5.6"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
Expand Down
72 changes: 72 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -156,5 +156,77 @@
</intent-filter>
</receiver>

<activity
android:name=".trigger.application.ApplicationActivity"
android:noHistory="true"
android:theme="@android:style/Theme.NoDisplay"
android:enabled="false"
android:exported="false">
</activity>

<activity-alias
android:name=".trigger.application.SignalActivity"
android:targetActivity=".trigger.application.ApplicationActivity"
android:noHistory="true"
android:theme="@android:style/Theme.NoDisplay"
android:label="@string/signal"
android:icon="@mipmap/ic_signal"
android:roundIcon="@mipmap/ic_signal_round"
android:enabled="false"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>

<activity-alias
android:name=".trigger.application.TelegramActivity"
android:targetActivity=".trigger.application.ApplicationActivity"
android:noHistory="true"
android:theme="@android:style/Theme.NoDisplay"
android:label="@string/telegram"
android:icon="@mipmap/ic_telegram"
android:roundIcon="@mipmap/ic_telegram_round"
android:enabled="false"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>

<activity-alias
android:name=".trigger.application.ThreemaActivity"
android:targetActivity=".trigger.application.ApplicationActivity"
android:noHistory="true"
android:theme="@android:style/Theme.NoDisplay"
android:label="@string/threema"
android:icon="@mipmap/ic_threema"
android:roundIcon="@mipmap/ic_threema_round"
android:enabled="false"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>

<activity-alias
android:name=".trigger.application.SessionActivity"
android:targetActivity=".trigger.application.ApplicationActivity"
android:noHistory="true"
android:theme="@android:style/Theme.NoDisplay"
android:label="@string/session"
android:icon="@mipmap/ic_session"
android:roundIcon="@mipmap/ic_session_round"
android:enabled="false"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity-alias>

</application>
</manifest>
1 change: 1 addition & 0 deletions app/src/main/java/me/lucky/wasted/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ open class MainActivity : AppCompatActivity() {
R.id.nav_trigger_tile -> TileFragment()
R.id.nav_trigger_notification -> NotificationFragment()
R.id.nav_trigger_lock -> LockFragment()
R.id.nav_trigger_application -> ApplicationFragment()
R.id.top_settings -> SettingsFragment()
else -> MainFragment()
}
Expand Down
13 changes: 13 additions & 0 deletions app/src/main/java/me/lucky/wasted/Preferences.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class Preferences(ctx: Context, encrypted: Boolean = true) {
private const val TRIGGERS = "triggers"
private const val TRIGGER_LOCK_COUNT = "trigger_lock_count"
private const val TRIGGER_TILE_DELAY = "trigger_tile_delay"
private const val TRIGGER_APPLICATION_OPTIONS = "trigger_application_options"

private const val FILE_NAME = "sec_shared_prefs"

Expand Down Expand Up @@ -85,6 +86,10 @@ class Preferences(ctx: Context, encrypted: Boolean = true) {
get() = prefs.getLong(TRIGGER_TILE_DELAY, DEFAULT_TRIGGER_TILE_DELAY)
set(value) = prefs.edit { putLong(TRIGGER_TILE_DELAY, value) }

var triggerApplicationOptions: Int
get() = prefs.getInt(TRIGGER_APPLICATION_OPTIONS, 0)
set(value) = prefs.edit { putInt(TRIGGER_APPLICATION_OPTIONS, value) }

fun registerListener(listener: SharedPreferences.OnSharedPreferenceChangeListener) =
prefs.registerOnSharedPreferenceChangeListener(listener)

Expand Down Expand Up @@ -114,4 +119,12 @@ enum class Trigger(val value: Int) {
NOTIFICATION(1 shl 4),
LOCK(1 shl 5),
USB(1 shl 6),
APPLICATION(1 shl 7),
}

enum class ApplicationOption(val value: Int) {
SIGNAL(1),
TELEGRAM(1 shl 1),
THREEMA(1 shl 2),
SESSION(1 shl 3),
}
32 changes: 31 additions & 1 deletion app/src/main/java/me/lucky/wasted/Utils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class Utils(private val ctx: Context) {
setBroadcastEnabled(enabled && triggers.and(Trigger.BROADCAST.value) != 0)
setNotificationEnabled(enabled && triggers.and(Trigger.NOTIFICATION.value) != 0)
updateForegroundRequiredEnabled()
updateApplicationEnabled()
}

fun setPanicKitEnabled(enabled: Boolean) {
Expand All @@ -60,6 +61,29 @@ class Utils(private val ctx: Context) {
fun setNotificationEnabled(enabled: Boolean) =
setComponentEnabled(NotificationListenerService::class.java, enabled)

fun updateApplicationEnabled() {
val prefix = "${ctx.packageName}.trigger.application"
val prefs = Preferences(ctx)
val options = prefs.triggerApplicationOptions
val enabled = prefs.isEnabled && prefs.triggers.and(Trigger.APPLICATION.value) != 0
setComponentEnabled(
"$prefix.SignalActivity",
enabled && options.and(ApplicationOption.SIGNAL.value) != 0,
)
setComponentEnabled(
"$prefix.TelegramActivity",
enabled && options.and(ApplicationOption.TELEGRAM.value) != 0,
)
setComponentEnabled(
"$prefix.ThreemaActivity",
enabled && options.and(ApplicationOption.THREEMA.value) != 0,
)
setComponentEnabled(
"$prefix.SessionActivity",
enabled && options.and(ApplicationOption.SESSION.value) != 0,
)
}

fun updateForegroundRequiredEnabled() {
val prefs = Preferences(ctx)
val enabled = prefs.isEnabled
Expand All @@ -78,8 +102,14 @@ class Utils(private val ctx: Context) {
}

private fun setComponentEnabled(cls: Class<*>, enabled: Boolean) =
setComponentEnabled(ComponentName(ctx, cls), enabled)

private fun setComponentEnabled(cls: String, enabled: Boolean) =
setComponentEnabled(ComponentName(ctx, cls), enabled)

private fun setComponentEnabled(componentName: ComponentName, enabled: Boolean) =
ctx.packageManager.setComponentEnabledSetting(
ComponentName(ctx, cls),
componentName,
if (enabled) PackageManager.COMPONENT_ENABLED_STATE_ENABLED else
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP,
Expand Down
95 changes: 95 additions & 0 deletions app/src/main/java/me/lucky/wasted/fragment/ApplicationFragment.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package me.lucky.wasted.fragment

import android.content.Context
import android.content.SharedPreferences
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment

import me.lucky.wasted.ApplicationOption
import me.lucky.wasted.Preferences
import me.lucky.wasted.Utils
import me.lucky.wasted.databinding.FragmentApplicationBinding

class ApplicationFragment : Fragment() {
private lateinit var binding: FragmentApplicationBinding
private lateinit var ctx: Context
private lateinit var prefs: Preferences
private lateinit var prefsdb: Preferences
private val utils by lazy { Utils(ctx) }

private val prefsListener = SharedPreferences.OnSharedPreferenceChangeListener { _, key ->
prefs.copyTo(prefsdb, key)
}

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?,
): View {
binding = FragmentApplicationBinding.inflate(inflater, container, false)
init()
setup()
return binding.root
}

override fun onStart() {
super.onStart()
prefs.registerListener(prefsListener)
}

override fun onStop() {
super.onStop()
prefs.unregisterListener(prefsListener)
}

private fun init() {
ctx = requireContext()
prefs = Preferences(ctx)
prefsdb = Preferences(ctx, encrypted = false)
binding.apply {
val options = prefs.triggerApplicationOptions
signal.isChecked = options.and(ApplicationOption.SIGNAL.value) != 0
telegram.isChecked = options.and(ApplicationOption.TELEGRAM.value) != 0
threema.isChecked = options.and(ApplicationOption.THREEMA.value) != 0
session.isChecked = options.and(ApplicationOption.SESSION.value) != 0
}
}

private fun setup() = binding.apply {
signal.setOnCheckedChangeListener { _, isChecked ->
prefs.triggerApplicationOptions = Utils.setFlag(
prefs.triggerApplicationOptions,
ApplicationOption.SIGNAL.value,
isChecked,
)
utils.updateApplicationEnabled()
}
telegram.setOnCheckedChangeListener { _, isChecked ->
prefs.triggerApplicationOptions = Utils.setFlag(
prefs.triggerApplicationOptions,
ApplicationOption.TELEGRAM.value,
isChecked,
)
utils.updateApplicationEnabled()
}
threema.setOnCheckedChangeListener { _, isChecked ->
prefs.triggerApplicationOptions = Utils.setFlag(
prefs.triggerApplicationOptions,
ApplicationOption.THREEMA.value,
isChecked,
)
utils.updateApplicationEnabled()
}
session.setOnCheckedChangeListener { _, isChecked ->
prefs.triggerApplicationOptions = Utils.setFlag(
prefs.triggerApplicationOptions,
ApplicationOption.SESSION.value,
isChecked,
)
utils.updateApplicationEnabled()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class SettingsFragment : Fragment() {
notification.isChecked = triggers.and(Trigger.NOTIFICATION.value) != 0
lock.isChecked = triggers.and(Trigger.LOCK.value) != 0
usb.isChecked = triggers.and(Trigger.USB.value) != 0
application.isChecked = triggers.and(Trigger.APPLICATION.value) != 0
}
}

Expand Down Expand Up @@ -93,5 +94,9 @@ class SettingsFragment : Fragment() {
prefs.triggers = Utils.setFlag(prefs.triggers, Trigger.USB.value, isChecked)
utils.updateForegroundRequiredEnabled()
}
application.setOnCheckedChangeListener { _, isChecked ->
prefs.triggers = Utils.setFlag(prefs.triggers, Trigger.APPLICATION.value, isChecked)
utils.updateApplicationEnabled()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package me.lucky.wasted.trigger.application

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity

import me.lucky.wasted.Preferences
import me.lucky.wasted.Trigger
import me.lucky.wasted.admin.DeviceAdminManager

class ApplicationActivity : AppCompatActivity() {
private val prefs by lazy { Preferences(this) }
private val admin by lazy { DeviceAdminManager(this) }

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (!prefs.isEnabled || prefs.triggers.and(Trigger.APPLICATION.value) == 0) {
finishAndRemoveTask()
return
}
try {
admin.lockNow()
if (prefs.isWipeData) admin.wipeData()
} catch (exc: SecurityException) {}
finishAndRemoveTask()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,8 @@ import me.lucky.wasted.trigger.broadcast.BroadcastReceiver
class ShortcutActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (Preferences(this).triggers.and(Trigger.SHORTCUT.value) == 0) {
finishAndRemoveTask()
return
}
BroadcastReceiver.panic(this, intent)
if (Preferences(this).triggers.and(Trigger.SHORTCUT.value) != 0)
BroadcastReceiver.panic(this, intent)
finishAndRemoveTask()
}
}
35 changes: 35 additions & 0 deletions app/src/main/res/drawable-v24/ic_telegram_foreground.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<group android:scaleX="0.07452"
android:scaleY="0.07452"
android:translateX="16.74"
android:translateY="16.74">
<path
android:pathData="M500,500m-500,0a500,500 0,1 1,1000 0a500,500 0,1 1,-1000 0"
android:strokeWidth="1"
android:fillType="evenOdd"
android:strokeColor="#00000000">
<aapt:attr name="android:fillColor">
<gradient
android:startX="500"
android:startY="-0"
android:endX="500"
android:endY="992.6"
android:type="linear">
<item android:offset="0" android:color="#FF2AABEE"/>
<item android:offset="1" android:color="#FF229ED9"/>
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M226.3,494.7C372.1,431.2 469.3,389.4 517.9,369.1C656.8,311.4 685.6,301.3 704.4,301C708.6,300.9 717.8,302 723.8,306.8C728.9,310.9 730.3,316.5 730.9,320.4C731.6,324.2 732.4,333.1 731.8,340C724.2,419.1 691.7,611 675.1,699.5C668.1,737 654.3,749.5 640.9,750.8C611.9,753.4 589.9,731.6 561.7,713.2C517.7,684.3 492.9,666.3 450.2,638.2C400.8,605.7 432.8,587.8 460.9,558.6C468.3,550.9 596.2,434.6 598.7,424C599,422.7 599.3,417.8 596.4,415.2C593.4,412.6 589.1,413.5 586,414.2C581.6,415.2 511.3,461.6 375.1,553.6C355.2,567.3 337.1,573.9 320.9,573.6C303,573.2 268.7,563.5 243.2,555.2C211.9,545 187,539.6 189.1,522.3C190.3,513.3 202.7,504.1 226.3,494.7Z"
android:strokeWidth="1"
android:fillColor="#FFFFFF"
android:fillType="evenOdd"
android:strokeColor="#00000000"/>
</group>
</vector>
Loading

0 comments on commit 712ef42

Please sign in to comment.