1 /* 2 * Copyright (C) 2019 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 18 19 import android.util.Log 20 import androidx.annotation.GuardedBy 21 import com.android.internal.util.Preconditions 22 import java.io.FileDescriptor 23 import java.io.PrintWriter 24 import java.lang.ref.WeakReference 25 import javax.inject.Inject 26 import javax.inject.Singleton 27 28 // TODO: Move all Dumpable dependencies to use DumpController 29 /** 30 * Controller that allows any [Dumpable] to subscribe and be dumped along with other SystemUI 31 * dependencies. 32 */ 33 @Singleton 34 class DumpController @Inject constructor() : Dumpable { 35 36 companion object { 37 private const val TAG = "DumpController" 38 private const val DEBUG = false 39 } 40 41 @GuardedBy("listeners") 42 private val listeners = mutableListOf<WeakReference<Dumpable>>() 43 val numListeners: Int 44 get() = listeners.size 45 46 /** 47 * Adds a [Dumpable] listener to be dumped. It will only be added if it is not already tracked. 48 * 49 * @param listener the [Dumpable] to be added 50 */ addListenernull51 fun addListener(listener: Dumpable) { 52 Preconditions.checkNotNull(listener, "The listener to be added cannot be null") 53 if (DEBUG) Log.v(TAG, "*** register callback for $listener") 54 synchronized<Unit>(listeners) { 55 if (listeners.any { it.get() == listener }) { 56 if (DEBUG) { 57 Log.e(TAG, "Object tried to add another callback") 58 } 59 } else { 60 listeners.add(WeakReference(listener)) 61 } 62 } 63 } 64 65 /** 66 * Removes a listener from the list of elements to be dumped. 67 * 68 * @param listener the [Dumpable] to be removed. 69 */ removeListenernull70 fun removeListener(listener: Dumpable) { 71 if (DEBUG) Log.v(TAG, "*** unregister callback for $listener") 72 synchronized(listeners) { 73 listeners.removeAll { it.get() == listener || it.get() == null } 74 } 75 } 76 77 /** 78 * Dump all the [Dumpable] registered with the controller 79 */ dumpnull80 override fun dump(fd: FileDescriptor?, pw: PrintWriter, args: Array<String>?) { 81 pw.println("DumpController state:") 82 synchronized(listeners) { 83 listeners.forEach { it.get()?.dump(fd, pw, args) } 84 } 85 } 86 } 87