1 /*
2  *  Copyright (C) 2023 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 
18 package com.android.systemui.keyguard.data.quickaffordance
19 
20 import android.app.StatusBarManager
21 import android.app.admin.DevicePolicyManager
22 import android.content.Context
23 import android.content.Intent
24 import com.android.systemui.ActivityIntentHelper
25 import com.android.systemui.R
26 import com.android.systemui.animation.Expandable
27 import com.android.systemui.camera.CameraIntents
28 import com.android.systemui.camera.CameraIntentsWrapper
29 import com.android.systemui.common.shared.model.ContentDescription
30 import com.android.systemui.common.shared.model.Icon
31 import com.android.systemui.dagger.SysUISingleton
32 import com.android.systemui.dagger.qualifiers.Application
33 import com.android.systemui.dagger.qualifiers.Background
34 import com.android.systemui.settings.UserTracker
35 import javax.inject.Inject
36 import kotlinx.coroutines.CoroutineDispatcher
37 import kotlinx.coroutines.flow.Flow
38 import kotlinx.coroutines.flow.flow
39 import kotlinx.coroutines.withContext
40 
41 @SysUISingleton
42 class VideoCameraQuickAffordanceConfig
43 @Inject
44 constructor(
45     @Application private val context: Context,
46     private val cameraIntents: CameraIntentsWrapper,
47     private val activityIntentHelper: ActivityIntentHelper,
48     private val userTracker: UserTracker,
49     private val devicePolicyManager: DevicePolicyManager,
50     @Background private val backgroundDispatcher: CoroutineDispatcher,
51 ) : KeyguardQuickAffordanceConfig {
52 
53     private val intent: Intent by lazy {
54         cameraIntents.getVideoCameraIntent().apply {
55             putExtra(
56                 CameraIntents.EXTRA_LAUNCH_SOURCE,
57                 StatusBarManager.CAMERA_LAUNCH_SOURCE_QUICK_AFFORDANCE,
58             )
59         }
60     }
61 
62     override val key: String
63         get() = BuiltInKeyguardQuickAffordanceKeys.VIDEO_CAMERA
64 
65     override fun pickerName(): String = context.getString(R.string.video_camera)
66 
67     override val pickerIconResourceId: Int
68         get() = R.drawable.ic_videocam
69 
70     override val lockScreenState: Flow<KeyguardQuickAffordanceConfig.LockScreenState>
71         get() = flow {
72             emit(
73                 if (isLaunchable()) {
74                     KeyguardQuickAffordanceConfig.LockScreenState.Visible(
75                         icon =
76                             Icon.Resource(
77                                 R.drawable.ic_videocam,
78                                 ContentDescription.Resource(R.string.video_camera)
79                             )
80                     )
81                 } else {
82                     KeyguardQuickAffordanceConfig.LockScreenState.Hidden
83                 }
84             )
85         }
86 
87     override suspend fun getPickerScreenState(): KeyguardQuickAffordanceConfig.PickerScreenState {
88         return if (isLaunchable()) {
89             super.getPickerScreenState()
90         } else {
91             KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice
92         }
93     }
94 
95     override fun onTriggered(
96         expandable: Expandable?
97     ): KeyguardQuickAffordanceConfig.OnTriggeredResult {
98         return KeyguardQuickAffordanceConfig.OnTriggeredResult.StartActivity(
99             intent = intent,
100             canShowWhileLocked = false,
101         )
102     }
103 
104     private suspend fun isLaunchable(): Boolean {
105         return activityIntentHelper.getTargetActivityInfo(
106             intent,
107             userTracker.userId,
108             true,
109         ) != null &&
110             withContext(backgroundDispatcher) {
111                 !devicePolicyManager.getCameraDisabled(null, userTracker.userId)
112             }
113     }
114 }
115