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.statusbar.connectivity
18 
19 import android.content.Context
20 import android.net.ConnectivityManager
21 import android.net.wifi.WifiManager
22 import android.os.Handler
23 import android.os.SimpleClock
24 import androidx.lifecycle.Lifecycle
25 import com.android.systemui.dagger.SysUISingleton
26 import com.android.systemui.dagger.qualifiers.Main
27 import com.android.systemui.util.concurrency.ThreadFactory
28 import com.android.systemui.util.time.SystemClock
29 import com.android.wifitrackerlib.WifiPickerTracker
30 import com.android.wifitrackerlib.WifiPickerTracker.WifiPickerTrackerCallback
31 import java.time.Clock
32 import java.time.ZoneOffset
33 import javax.inject.Inject
34 
35 /**
36  * Factory for creating [WifiPickerTracker] for SysUI.
37  *
38  * Uses the same time intervals as the Settings page for Wifi.
39  */
40 @SysUISingleton
41 class WifiPickerTrackerFactory
42 @Inject
43 constructor(
44     private val context: Context,
45     private val wifiManager: WifiManager?,
46     private val connectivityManager: ConnectivityManager,
47     private val systemClock: SystemClock,
48     @Main private val mainHandler: Handler,
49     private val threadFactory: ThreadFactory,
50 ) {
51     private val clock: Clock =
52         object : SimpleClock(ZoneOffset.UTC) {
millisnull53             override fun millis(): Long {
54                 return systemClock.elapsedRealtime()
55             }
56         }
57     val isSupported: Boolean
58         get() = wifiManager != null
59 
60     /**
61      * Creates a [WifiPickerTracker] instance.
62      *
63      * @param name a name to identify the worker thread used for [WifiPickerTracker] operations.
64      * @return a new [WifiPickerTracker] or null if [WifiManager] is null.
65      */
createnull66     fun create(
67         lifecycle: Lifecycle,
68         listener: WifiPickerTrackerCallback,
69         name: String,
70     ): WifiPickerTracker? {
71         return if (wifiManager == null) {
72             null
73         } else
74             WifiPickerTracker(
75                 lifecycle,
76                 context,
77                 wifiManager,
78                 connectivityManager,
79                 mainHandler,
80                 // WifiPickerTracker can take tens of seconds to finish operations, so it can't use
81                 // the default background handler (it would block all other background operations).
82                 // Use a custom handler instead.
83                 threadFactory.buildHandlerOnNewThread("WifiPickerTracker-$name"),
84                 clock,
85                 MAX_SCAN_AGE_MILLIS,
86                 SCAN_INTERVAL_MILLIS,
87                 listener,
88             )
89     }
90 
91     companion object {
92         /** Max age of tracked WifiEntries. */
93         private const val MAX_SCAN_AGE_MILLIS: Long = 15000
94         /** Interval between initiating WifiPickerTracker scans. */
95         private const val SCAN_INTERVAL_MILLIS: Long = 10000
96     }
97 }
98