• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.android.systemui.common.usagestats.data.repository
18 
19 import android.app.usage.UsageEvents
20 import android.app.usage.UsageEventsQuery
21 import android.app.usage.UsageStatsManager
22 import com.android.app.tracing.coroutines.withContextTraced as withContext
23 import com.android.systemui.common.usagestats.data.model.UsageStatsQuery
24 import com.android.systemui.common.usagestats.shared.model.ActivityEventModel
25 import com.android.systemui.common.usagestats.shared.model.ActivityEventModel.Lifecycle
26 import com.android.systemui.dagger.SysUISingleton
27 import com.android.systemui.dagger.qualifiers.Background
28 import javax.inject.Inject
29 import kotlin.coroutines.CoroutineContext
30 
31 /** Repository for querying UsageStatsManager */
32 interface UsageStatsRepository {
33     /** Query activity events. */
34     suspend fun queryActivityEvents(query: UsageStatsQuery): List<ActivityEventModel>
35 }
36 
37 @SysUISingleton
38 class UsageStatsRepositoryImpl
39 @Inject
40 constructor(
41     @Background private val bgContext: CoroutineContext,
42     private val usageStatsManager: UsageStatsManager,
43 ) : UsageStatsRepository {
44     private companion object {
45         const val TAG = "UsageStatsRepository"
46     }
47 
queryActivityEventsnull48     override suspend fun queryActivityEvents(query: UsageStatsQuery): List<ActivityEventModel> =
49         withContext("$TAG#queryActivityEvents", bgContext) {
50             val systemQuery: UsageEventsQuery =
51                 UsageEventsQuery.Builder(query.startTime, query.endTime)
52                     .apply {
53                         setUserId(query.user.identifier)
54                         setEventTypes(
55                             UsageEvents.Event.ACTIVITY_RESUMED,
56                             UsageEvents.Event.ACTIVITY_PAUSED,
57                             UsageEvents.Event.ACTIVITY_STOPPED,
58                             UsageEvents.Event.ACTIVITY_DESTROYED,
59                         )
60                         if (query.packageNames.isNotEmpty()) {
61                             setPackageNames(*query.packageNames.toTypedArray())
62                         }
63                     }
64                     .build()
65 
66             val events: UsageEvents? = usageStatsManager.queryEvents(systemQuery)
67 
68             buildList {
69                 events.forEachEvent { event ->
70                     val lifecycle =
71                         when (event.eventType) {
72                             UsageEvents.Event.ACTIVITY_RESUMED -> Lifecycle.RESUMED
73                             UsageEvents.Event.ACTIVITY_PAUSED -> Lifecycle.PAUSED
74                             UsageEvents.Event.ACTIVITY_STOPPED -> Lifecycle.STOPPED
75                             UsageEvents.Event.ACTIVITY_DESTROYED -> Lifecycle.DESTROYED
76                             else -> Lifecycle.UNKNOWN
77                         }
78 
79                     add(
80                         ActivityEventModel(
81                             instanceId = event.instanceId,
82                             packageName = event.packageName,
83                             lifecycle = lifecycle,
84                             timestamp = event.timeStamp,
85                         )
86                     )
87                 }
88             }
89         }
90 }
91 
forEachEventnull92 private inline fun UsageEvents?.forEachEvent(action: (UsageEvents.Event) -> Unit) {
93     this ?: return
94     val event = UsageEvents.Event()
95     while (getNextEvent(event)) {
96         action(event)
97     }
98 }
99