<lambda>null1 package com.android.systemui.statusbar.notification.collection.notifcollection
2 
3 import android.os.Handler
4 import android.util.ArrayMap
5 import android.util.Log
6 import com.android.systemui.Dumpable
7 import com.android.systemui.statusbar.notification.collection.NotificationEntry
8 import com.android.systemui.util.asIndenting
9 import com.android.systemui.util.printCollection
10 import com.android.systemui.util.println
11 import com.android.systemui.util.withIncreasedIndent
12 import java.io.PrintWriter
13 
14 /**
15  * A helpful class that implements the core contract of the lifetime extender internally,
16  * making it easier for coordinators to interact with them
17  */
18 abstract class SelfTrackingLifetimeExtender(
19     private val tag: String,
20     private val name: String,
21     private val debug: Boolean,
22     private val mainHandler: Handler
23 ) : NotifLifetimeExtender, Dumpable {
24     private lateinit var mCallback: NotifLifetimeExtender.OnEndLifetimeExtensionCallback
25     protected val mEntriesExtended = ArrayMap<String, NotificationEntry>()
26     private var mEnding = false
27 
28     /**
29      * When debugging, warn if the call is happening during and "end lifetime extension" call.
30      *
31      * Note: this will warn a lot! The pipeline explicitly re-invokes all lifetime extenders
32      * whenever one ends, giving all of them a chance to re-up their lifetime extension.
33      */
34     private fun warnIfEnding() {
35         if (debug && mEnding) Log.w(tag, "reentrant code while ending a lifetime extension")
36     }
37 
38     fun endAllLifetimeExtensions() {
39         // clear the map before iterating over a copy of the items, because the pipeline will
40         // always give us another chance to extend the lifetime again, and we don't want
41         // concurrent modification
42         val entries = mEntriesExtended.values.toList()
43         if (debug) Log.d(tag, "$name.endAllLifetimeExtensions() entries=$entries")
44         mEntriesExtended.clear()
45         warnIfEnding()
46         mEnding = true
47         entries.forEach { mCallback.onEndLifetimeExtension(this, it) }
48         mEnding = false
49     }
50 
51     fun endLifetimeExtensionAfterDelay(key: String, delayMillis: Long) {
52         if (debug) {
53             Log.d(tag, "$name.endLifetimeExtensionAfterDelay" +
54                     "(key=$key, delayMillis=$delayMillis)" +
55                     " isExtending=${isExtending(key)}")
56         }
57         if (isExtending(key)) {
58             mainHandler.postDelayed({ endLifetimeExtension(key) }, delayMillis)
59         }
60     }
61 
62     fun endLifetimeExtension(key: String) {
63         if (debug) {
64             Log.d(tag, "$name.endLifetimeExtension(key=$key)" +
65                     " isExtending=${isExtending(key)}")
66         }
67         warnIfEnding()
68         mEnding = true
69         mEntriesExtended.remove(key)?.let { removedEntry ->
70             mCallback.onEndLifetimeExtension(this, removedEntry)
71         }
72         mEnding = false
73     }
74 
75     fun isExtending(key: String) = mEntriesExtended.contains(key)
76 
77     final override fun getName(): String = name
78 
79     final override fun maybeExtendLifetime(entry: NotificationEntry, reason: Int): Boolean {
80         val shouldExtend = queryShouldExtendLifetime(entry)
81         if (debug) {
82             Log.d(tag, "$name.shouldExtendLifetime(key=${entry.key}, reason=$reason)" +
83                     " isExtending=${isExtending(entry.key)}" +
84                     " shouldExtend=$shouldExtend")
85         }
86         warnIfEnding()
87         if (shouldExtend && mEntriesExtended.put(entry.key, entry) == null) {
88             onStartedLifetimeExtension(entry)
89         }
90         return shouldExtend
91     }
92 
93     final override fun cancelLifetimeExtension(entry: NotificationEntry) {
94         if (debug) {
95             Log.d(tag, "$name.cancelLifetimeExtension(key=${entry.key})" +
96                     " isExtending=${isExtending(entry.key)}")
97         }
98         warnIfEnding()
99         mEntriesExtended.remove(entry.key)
100         onCanceledLifetimeExtension(entry)
101     }
102 
103     abstract fun queryShouldExtendLifetime(entry: NotificationEntry): Boolean
104     open fun onStartedLifetimeExtension(entry: NotificationEntry) {}
105     open fun onCanceledLifetimeExtension(entry: NotificationEntry) {}
106 
107     final override fun setCallback(callback: NotifLifetimeExtender.OnEndLifetimeExtensionCallback) {
108         mCallback = callback
109     }
110 
111     final override fun dump(pw: PrintWriter, args: Array<out String>) = pw.asIndenting().run {
112         println("LifetimeExtender", name)
113         withIncreasedIndent {
114             printCollection("mEntriesExtended", mEntriesExtended.keys)
115         }
116     }
117 }