Skip to content

Commit

Permalink
Auto finish secure activities when the screen goes off
Browse files Browse the repository at this point in the history
(and the user is inactive for a certain short duration)
  • Loading branch information
MHShetty authored and thestinger committed Feb 9, 2025
1 parent 37990f8 commit b571fef
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 2 deletions.
53 changes: 53 additions & 0 deletions app/src/main/java/app/grapheneos/camera/AutoFinishOnSleep.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package app.grapheneos.camera

import android.app.Activity
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Handler
import android.os.Looper
import androidx.core.app.ActivityCompat

// Finishes the passed [activity] and the ones present below it in the stack if the screen
// turns off and the user is inactive for [WAITING_TIME_IN_MS] milliseconds
class AutoFinishOnSleep(val activity: Activity) {

companion object {
private const val TAG = "AutoFinishOnSleep"
private const val WAITING_TIME_IN_MS = 1500L

private val intentFilter = IntentFilter().apply {
addAction(Intent.ACTION_SCREEN_ON)
addAction(Intent.ACTION_SCREEN_OFF)
}
}

private val handler = Handler(Looper.getMainLooper())

private val runnable = Runnable {
ActivityCompat.finishAffinity(activity)
}

private val receiver = object: BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
when (intent?.action) {
Intent.ACTION_SCREEN_OFF -> {
handler.postDelayed(runnable, WAITING_TIME_IN_MS)
}

Intent.ACTION_SCREEN_ON -> {
handler.removeCallbacks(runnable)
}
}
}
}

fun start() {
activity.registerReceiver(receiver, intentFilter)
}

fun stop() {
activity.unregisterReceiver(receiver)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat
import androidx.viewpager2.widget.ViewPager2
import androidxc.exifinterface.media.ExifInterface
import app.grapheneos.camera.AutoFinishOnSleep
import app.grapheneos.camera.CapturedItem
import app.grapheneos.camera.CapturedItems
import app.grapheneos.camera.GSlideTransformer
Expand Down Expand Up @@ -70,6 +71,8 @@ class InAppGallery : AppCompatActivity() {

private lateinit var rootView: View

private val autoFinisher = AutoFinishOnSleep(this)

private var lastViewedMediaItem : CapturedItem? = null

private lateinit var windowInsetsController: WindowInsetsControllerCompat
Expand Down Expand Up @@ -446,6 +449,7 @@ class InAppGallery : AppCompatActivity() {
if (isSecureMode) {
setShowWhenLocked(true)
setTurnScreenOn(true)
autoFinisher.start()
}

ogColor = ContextCompat.getColor(this, R.color.system_neutral1_900)
Expand Down Expand Up @@ -637,6 +641,9 @@ class InAppGallery : AppCompatActivity() {
super.onDestroy()
asyncLoaderOfCapturedItems.shutdownNow()
asyncImageLoader.shutdownNow()
if (isSecureMode) {
autoFinisher.stop()
}
}

fun vibrateDevice() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
package app.grapheneos.camera.ui.activities

class MoreSettingsSecure : MoreSettings()
import android.os.Bundle
import app.grapheneos.camera.AutoFinishOnSleep

class MoreSettingsSecure : MoreSettings() {

private val autoFinisher = AutoFinishOnSleep(this)

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
autoFinisher.start()
}

override fun onDestroy() {
super.onDestroy()
autoFinisher.stop()
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package app.grapheneos.camera.ui.activities

import android.content.SharedPreferences
import android.os.Bundle
import app.grapheneos.camera.AutoFinishOnSleep
import app.grapheneos.camera.CapturedItem
import app.grapheneos.camera.util.EphemeralSharedPrefsNamespace
import app.grapheneos.camera.util.getPrefs
Expand All @@ -9,6 +11,18 @@ open class SecureMainActivity : MainActivity(), SecureActivity {
val capturedItems = ArrayList<CapturedItem>()
val ephemeralPrefsNamespace = EphemeralSharedPrefsNamespace()

private val autoFinisher = AutoFinishOnSleep(this)

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
autoFinisher.start()
}

override fun onDestroy() {
super.onDestroy()
autoFinisher.stop()
}

override fun getSharedPreferences(name: String, mode: Int): SharedPreferences {
return ephemeralPrefsNamespace.getPrefs(this, name, mode, cloneOriginal = true)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import androidx.core.view.ViewCompat
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import androidx.lifecycle.Lifecycle
import app.grapheneos.camera.AutoFinishOnSleep
import app.grapheneos.camera.R
import app.grapheneos.camera.databinding.VideoPlayerBinding
import app.grapheneos.camera.util.getParcelableExtra
Expand All @@ -32,6 +33,10 @@ class VideoPlayer : AppCompatActivity() {

private lateinit var binding: VideoPlayerBinding

private val autoFinisher = AutoFinishOnSleep(this)

private var isSecureMode = false

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
Expand All @@ -42,10 +47,15 @@ class VideoPlayer : AppCompatActivity() {
windowInsetsController.show(WindowInsetsCompat.Type.systemBars())

val intent = this.intent
if (intent.getBooleanExtra(IN_SECURE_MODE, false)) {

isSecureMode = intent.getBooleanExtra(IN_SECURE_MODE, false)

if (isSecureMode) {
setShowWhenLocked(true)
setTurnScreenOn(true)
autoFinisher.start()
}

binding = VideoPlayerBinding.inflate(layoutInflater)
setContentView(binding.root)

Expand Down Expand Up @@ -165,4 +175,11 @@ class VideoPlayer : AppCompatActivity() {
alpha(1f)
}
}

override fun onDestroy() {
super.onDestroy()
if (isSecureMode) {
this.autoFinisher.stop()
}
}
}

0 comments on commit b571fef

Please sign in to comment.