1 /*
<lambda>null2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.android.wallpaper.weathereffects.sensor
18 
19 import android.app.KeyguardManager
20 import android.content.Context
21 import java.util.concurrent.Executor
22 
23 /** Controls user presence based on Keyguard and Live Wallpaper wake/sleep events. */
24 class UserPresenceController(
25     context: Context,
26     private var onUserPresenceChanged:
27         (newPresence: UserPresence, oldPresence: UserPresence) -> Unit
28 ) {
29 
30     /** The current user presence. It is [UserPresence.UNDEFINED] when it hasn't been set yet. */
31     private var userPresence: UserPresence = UserPresence.UNDEFINED
32         set(value) {
33             val oldValue = field
34             field = value
35             if (field != oldValue) onUserPresenceChanged(field, oldValue)
36         }
37 
38     private val keyguardManager =
39         context.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager?
40     private var keyguardListener: (Boolean) -> Unit = { locked: Boolean ->
41         updateUserPresence(isDeviceLocked = locked)
42     }
43 
44     private var deviceLocked: Boolean = keyguardManager?.isKeyguardLocked ?: false
45     private var deviceAwake: Boolean = true
46 
47     /** Start listening to the different sensors. */
48     fun start(executor: Executor) {
49         updateUserPresence(isDeviceLocked = keyguardManager?.isKeyguardLocked ?: false)
50         /*
51          * From KeyguardManager.java `keyguardListener` is saved into a map and thus won't add
52          * multiple of the same listener.
53          */
54         keyguardManager?.addKeyguardLockedStateListener(executor, keyguardListener)
55     }
56 
57     /** Stop listening to the different sensors. */
58     fun stop() {
59         keyguardManager?.removeKeyguardLockedStateListener(keyguardListener)
60     }
61 
62     /**
63      * Set the device wake state.
64      *
65      * @param isAwake if the device is awake. That means that the screen is not turned off or that
66      * the device is not in Ambient on Display mode.
67      */
68     fun setWakeState(isAwake: Boolean) {
69         updateUserPresence(isDeviceAwake = isAwake)
70     }
71 
72     /**
73      * Call when the keyguard is going away. This will happen before lock state is false (but it
74      * happens at the same time that unlock animation starts).
75      */
76     fun onKeyguardGoingAway() = updateUserPresence(isDeviceLocked = false)
77 
78     private fun updateUserPresence(
79         isDeviceAwake: Boolean = deviceAwake,
80         isDeviceLocked: Boolean = deviceLocked
81     ) {
82         this.deviceAwake = isDeviceAwake
83         this.deviceLocked = isDeviceLocked
84 
85         userPresence = when {
86             !deviceAwake -> UserPresence.AWAY
87             deviceLocked -> UserPresence.LOCKED
88             else -> UserPresence.ACTIVE // == awake && !locked.
89         }
90     }
91 
92     /** Define the different user presence available. */
93     enum class UserPresence {
94 
95         /**
96          * We don't know the status of the User presence (usually at the beginning of the session).
97          */
98         UNDEFINED,
99 
100         /** User is in AoD or with the screen off. */
101         AWAY,
102 
103         /** User is in lock screen. */
104         LOCKED,
105 
106         /** User is in the home screen or in an app. */
107         ACTIVE
108     }
109 }
110