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.util.wakelock
18 
19 import android.os.PowerManager
20 import android.util.Log
21 import com.android.systemui.util.wakelock.WakeLock.Builder.NO_TIMEOUT
22 import java.util.concurrent.ConcurrentHashMap
23 import java.util.concurrent.atomic.AtomicInteger
24 
25 /**
26  * [PowerManager.WakeLock] wrapper that tracks acquire/release reasons and logs them if owning
27  * logger is enabled.
28  */
29 class ClientTrackingWakeLock(
30     private val pmWakeLock: PowerManager.WakeLock,
31     private val logger: WakeLockLogger?,
32     private val maxTimeout: Long
33 ) : WakeLock {
34 
35     private val activeClients = ConcurrentHashMap<String, AtomicInteger>()
36 
37     override fun acquire(why: String) {
38         val count = activeClients.computeIfAbsent(why) { _ -> AtomicInteger(0) }.incrementAndGet()
39         logger?.logAcquire(pmWakeLock, why, count)
40         if (maxTimeout == NO_TIMEOUT) {
41             pmWakeLock.acquire()
42         } else {
43             pmWakeLock.acquire(maxTimeout)
44         }
45     }
46 
47     override fun release(why: String) {
48         val count = activeClients[why]?.decrementAndGet() ?: -1
49         if (count < 0) {
50             Log.wtf(WakeLock.TAG, "Releasing WakeLock with invalid reason: $why")
51             // Restore count just in case.
52             activeClients[why]?.incrementAndGet()
53             return
54         }
55 
56         logger?.logRelease(pmWakeLock, why, count)
57         pmWakeLock.release()
58     }
59 
60     override fun wrap(r: Runnable): Runnable = WakeLock.wrapImpl(this, r)
61 
62     fun activeClients(): Int =
63         activeClients.reduceValuesToInt(Long.MAX_VALUE, AtomicInteger::get, 0, Integer::sum)
64 
65     override fun toString(): String {
66         return "active clients=${activeClients()}"
67     }
68 }
69