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 package com.android.systemui.controls.controller
18 
19 import android.content.Context
20 import android.os.Handler
21 import android.os.UserHandle
22 import com.android.internal.content.PackageMonitor
23 import com.android.systemui.dagger.qualifiers.Application
24 import com.android.systemui.dagger.qualifiers.Background
25 import dagger.assisted.Assisted
26 import dagger.assisted.AssistedFactory
27 import dagger.assisted.AssistedInject
28 import java.util.concurrent.atomic.AtomicBoolean
29 
30 /** [PackageMonitor] that tracks when [packageName] has finished updating for user [user]. */
31 class PackageUpdateMonitor
32 @AssistedInject
33 constructor(
34     @Assisted private val user: UserHandle,
35     @Assisted private val packageName: String,
36     @Assisted private val callback: Runnable,
37     @Background private val bgHandler: Handler,
38     @Application private val context: Context,
39 ) : PackageMonitor() {
40 
41     private val monitoring = AtomicBoolean(false)
42 
43     @AssistedFactory
44     fun interface Factory {
45         /**
46          * Create a [PackageUpdateMonitor] for a given [user] and [packageName]. It will run
47          * [callback] every time the package finishes updating.
48          */
49         fun create(user: UserHandle, packageName: String, callback: Runnable): PackageUpdateMonitor
50     }
51 
52     /** Start monitoring for package updates. No-op if already monitoring. */
53     fun startMonitoring() {
54         if (monitoring.compareAndSet(/* expected */ false, /* new */ true)) {
55             register(context, user, false, bgHandler)
56         }
57     }
58 
59     /** Stop monitoring for package updates. No-op if not monitoring. */
60     fun stopMonitoring() {
61         if (monitoring.compareAndSet(/* expected */ true, /* new */ false)) {
62             unregister()
63         }
64     }
65 
66     /**
67      * If the package and the user match the ones for this [PackageUpdateMonitor], it will run
68      * [callback].
69      */
70     override fun onPackageUpdateFinished(packageName: String?, uid: Int) {
71         super.onPackageUpdateFinished(packageName, uid)
72         if (packageName == this.packageName && UserHandle.getUserHandleForUid(uid) == user) {
73             callback.run()
74         }
75     }
76 }
77