• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 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.android.systemui.keyboard.shortcut.data.repository
18 
19 import android.content.Context
20 import android.content.pm.LauncherActivityInfo
21 import android.content.pm.LauncherApps
22 import android.os.Handler
23 import android.os.UserHandle
24 import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
25 import com.android.systemui.dagger.SysUISingleton
26 import com.android.systemui.dagger.qualifiers.Background
27 import com.android.systemui.settings.UserTracker
28 import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow
29 import java.util.concurrent.Executor
30 import javax.inject.Inject
31 import kotlinx.coroutines.channels.awaitClose
32 import kotlinx.coroutines.flow.Flow
33 
34 @SysUISingleton
35 class UserVisibleAppsRepository
36 @Inject
37 constructor(
38     private val userTracker: UserTracker,
39     @Background private val bgExecutor: Executor,
40     @Background private val bgHandler: Handler,
41     private val launcherApps: LauncherApps,
42 ) {
43 
44     val userVisibleApps: Flow<List<LauncherActivityInfo>>
<lambda>null45         get() = conflatedCallbackFlow {
46             val packageChangeCallback: LauncherApps.Callback =
47                 object : LauncherApps.Callback() {
48                     override fun onPackageAdded(packageName: String, userHandle: UserHandle) {
49                         trySendWithFailureLogging(
50                             element = retrieveLauncherApps(),
51                             loggingTag = TAG,
52                             elementDescription = ON_PACKAGE_ADDED,
53                         )
54                     }
55 
56                     override fun onPackageChanged(packageName: String, userHandle: UserHandle) {
57                         trySendWithFailureLogging(
58                             element = retrieveLauncherApps(),
59                             loggingTag = TAG,
60                             elementDescription = ON_PACKAGE_CHANGED,
61                         )
62                     }
63 
64                     override fun onPackageRemoved(packageName: String, userHandle: UserHandle) {
65                         trySendWithFailureLogging(
66                             element = retrieveLauncherApps(),
67                             loggingTag = TAG,
68                             elementDescription = ON_PACKAGE_REMOVED,
69                         )
70                     }
71 
72                     override fun onPackagesAvailable(
73                         packages: Array<out String>,
74                         userHandle: UserHandle,
75                         replacing: Boolean,
76                     ) {
77                         trySendWithFailureLogging(
78                             element = retrieveLauncherApps(),
79                             loggingTag = TAG,
80                             elementDescription = ON_PACKAGES_AVAILABLE,
81                         )
82                     }
83 
84                     override fun onPackagesUnavailable(
85                         packages: Array<out String>,
86                         userHandle: UserHandle,
87                         replacing: Boolean,
88                     ) {
89                         trySendWithFailureLogging(
90                             element = retrieveLauncherApps(),
91                             loggingTag = TAG,
92                             elementDescription = ON_PACKAGES_UNAVAILABLE,
93                         )
94                     }
95                 }
96 
97             val userChangeCallback =
98                 object : UserTracker.Callback {
99                     override fun onUserChanged(newUser: Int, userContext: Context) {
100                         trySendWithFailureLogging(
101                             element = retrieveLauncherApps(),
102                             loggingTag = TAG,
103                             elementDescription = ON_USER_CHANGED,
104                         )
105                     }
106                 }
107 
108             userTracker.addCallback(userChangeCallback, bgExecutor)
109             launcherApps.registerCallback(packageChangeCallback, bgHandler)
110 
111             trySendWithFailureLogging(
112                 element = retrieveLauncherApps(),
113                 loggingTag = TAG,
114                 elementDescription = INITIAL_VALUE,
115             )
116 
117             awaitClose {
118                 userTracker.removeCallback(userChangeCallback)
119                 launcherApps.unregisterCallback(packageChangeCallback)
120             }
121         }
122 
retrieveLauncherAppsnull123     private fun retrieveLauncherApps(): List<LauncherActivityInfo> {
124         return launcherApps.getActivityList(/* packageName= */ null, userTracker.userHandle)
125     }
126 
127     private companion object {
128         const val TAG = "UserVisibleAppsRepository"
129         const val ON_PACKAGE_ADDED = "onPackageAdded"
130         const val ON_PACKAGE_CHANGED = "onPackageChanged"
131         const val ON_PACKAGE_REMOVED = "onPackageRemoved"
132         const val ON_PACKAGES_AVAILABLE = "onPackagesAvailable"
133         const val ON_PACKAGES_UNAVAILABLE = "onPackagesUnavailable"
134         const val ON_USER_CHANGED = "onUserChanged"
135         const val INITIAL_VALUE = "InitialValue"
136     }
137 }
138