diff options
67 files changed, 930 insertions, 572 deletions
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index f141578f088d..617ed4e58e77 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -283,6 +283,12 @@ android:exported="true" /> + <!-- Service for dumping extremely verbose content during a bug report --> + <service android:name=".dump.SystemUIAuxiliaryDumpService" + android:exported="false" + android:permission="com.android.systemui.permission.SELF" + /> + <!-- On user switch, this service is started to ensure that the associated SystemUI process for the current user is started. See the resource "config_systemUIServiceComponentsPerUser". diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index f57571d8d4b4..97b21135d661 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -88,12 +88,12 @@ import com.android.internal.widget.LockPatternUtils; import com.android.settingslib.WirelessUtils; import com.android.settingslib.fuelgauge.BatteryStatus; import com.android.systemui.DejankUtils; -import com.android.systemui.DumpController; import com.android.systemui.Dumpable; import com.android.systemui.R; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.dump.DumpManager; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.TaskStackChangeListener; import com.android.systemui.statusbar.phone.KeyguardBypassController; @@ -1475,14 +1475,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab Context context, @Main Looper mainLooper, BroadcastDispatcher broadcastDispatcher, - DumpController dumpController, + DumpManager dumpManager, @Background Executor backgroundExecutor) { mContext = context; mSubscriptionManager = SubscriptionManager.from(context); mDeviceProvisioned = isDeviceProvisionedInSettingsDb(); mStrongAuthTracker = new StrongAuthTracker(context, this::notifyStrongAuthStateChanged); - dumpController.registerDumpable(this); mBackgroundExecutor = backgroundExecutor; + dumpManager.registerDumpable(getClass().getName(), this); mHandler = new Handler(mainLooper) { @Override diff --git a/packages/SystemUI/src/com/android/systemui/BootCompleteCacheImpl.kt b/packages/SystemUI/src/com/android/systemui/BootCompleteCacheImpl.kt index 310393bb46eb..aef1872f6520 100644 --- a/packages/SystemUI/src/com/android/systemui/BootCompleteCacheImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/BootCompleteCacheImpl.kt @@ -18,6 +18,7 @@ package com.android.systemui import android.util.Log import com.android.internal.annotations.GuardedBy +import com.android.systemui.dump.DumpManager import java.io.FileDescriptor import java.io.PrintWriter import java.lang.ref.WeakReference @@ -32,7 +33,7 @@ import javax.inject.Singleton * boot is completed. */ @Singleton -class BootCompleteCacheImpl @Inject constructor(private val dumpController: DumpController) : +class BootCompleteCacheImpl @Inject constructor(dumpManager: DumpManager) : BootCompleteCache, Dumpable { companion object { @@ -41,7 +42,7 @@ class BootCompleteCacheImpl @Inject constructor(private val dumpController: Dump } init { - dumpController.registerDumpable(TAG, this) + dumpManager.registerDumpable(TAG, this) } @GuardedBy("listeners") diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java index 69bc2596d411..a868cf58cf7c 100644 --- a/packages/SystemUI/src/com/android/systemui/Dependency.java +++ b/packages/SystemUI/src/com/android/systemui/Dependency.java @@ -42,6 +42,7 @@ import com.android.systemui.colorextraction.SysuiColorExtractor; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dock.DockManager; +import com.android.systemui.dump.DumpManager; import com.android.systemui.fragments.FragmentService; import com.android.systemui.keyguard.ScreenLifecycle; import com.android.systemui.keyguard.WakefulnessLifecycle; @@ -128,8 +129,6 @@ import com.android.systemui.wm.DisplayController; import com.android.systemui.wm.DisplayImeController; import com.android.systemui.wm.SystemWindows; -import java.io.FileDescriptor; -import java.io.PrintWriter; import java.util.function.Consumer; import javax.inject.Inject; @@ -211,6 +210,8 @@ public class Dependency { private final ArrayMap<Object, Object> mDependencies = new ArrayMap<>(); private final ArrayMap<Object, LazyDependencyCreator> mProviders = new ArrayMap<>(); + @Inject DumpManager mDumpManager; + @Inject Lazy<ActivityStarter> mActivityStarter; @Inject Lazy<BroadcastDispatcher> mBroadcastDispatcher; @Inject Lazy<AsyncSensorManager> mAsyncSensorManager; @@ -311,7 +312,6 @@ public class Dependency { @Inject Lazy<DevicePolicyManagerWrapper> mDevicePolicyManagerWrapper; @Inject Lazy<PackageManagerWrapper> mPackageManagerWrapper; @Inject Lazy<SensorPrivacyController> mSensorPrivacyController; - @Inject Lazy<DumpController> mDumpController; @Inject Lazy<DockManager> mDockManager; @Inject Lazy<ChannelEditorDialogController> mChannelEditorDialogController; @Inject Lazy<INotificationManager> mINotificationManager; @@ -505,7 +505,6 @@ public class Dependency { mProviders.put(DevicePolicyManagerWrapper.class, mDevicePolicyManagerWrapper::get); mProviders.put(PackageManagerWrapper.class, mPackageManagerWrapper::get); mProviders.put(SensorPrivacyController.class, mSensorPrivacyController::get); - mProviders.put(DumpController.class, mDumpController::get); mProviders.put(DockManager.class, mDockManager::get); mProviders.put(ChannelEditorDialogController.class, mChannelEditorDialogController::get); mProviders.put(INotificationManager.class, mINotificationManager::get); @@ -534,34 +533,6 @@ public class Dependency { sDependency = this; } - static void staticDump(FileDescriptor fd, PrintWriter pw, String[] args) { - sDependency.dump(fd, pw, args); - } - - /** - * {@see SystemUI.dump} - */ - public synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - // Make sure that the DumpController gets added to mDependencies, as they are only added - // with Dependency#get. - getDependency(DumpController.class); - getDependency(BroadcastDispatcher.class); - - // If an arg is specified, try to dump the dependency - String controller = args != null && args.length > 1 - ? args[1].toLowerCase() - : null; - if (controller != null) { - pw.println("Dumping controller=" + controller + ":"); - } else { - pw.println("Dumping existing controllers:"); - } - mDependencies.values().stream() - .filter(obj -> obj instanceof Dumpable && (controller == null - || obj.getClass().getName().toLowerCase().endsWith(controller))) - .forEach(o -> ((Dumpable) o).dump(fd, pw, args)); - } - protected final <T> T getDependency(Class<T> cls) { return getDependencyInner(cls); } @@ -576,6 +547,11 @@ public class Dependency { if (obj == null) { obj = createDependency(key); mDependencies.put(key, obj); + + // TODO: Get dependencies to register themselves instead + if (autoRegisterModulesForDump() && obj instanceof Dumpable) { + mDumpManager.registerDumpable(obj.getClass().getName(), (Dumpable) obj); + } } return obj; } @@ -593,6 +569,17 @@ public class Dependency { return provider.createDependency(); } + // Currently, there are situations in tests where we might create more than one instance of a + // thing that should be a singleton: the "real" one (created by Dagger, usually as a result of + // inflating a view), and a mocked one (injected into Dependency). If we register the mocked + // one, the DumpManager will throw an exception complaining (rightly) that we have too many + // things registered with that name. So in tests, we disable the auto-registration until the + // root cause is fixed, i.e. inflated views in tests with Dagger dependencies. + @VisibleForTesting + protected boolean autoRegisterModulesForDump() { + return true; + } + private static Dependency sDependency; /** @@ -605,6 +592,9 @@ public class Dependency { private <T> void destroyDependency(Class<T> cls, Consumer<T> destroy) { T dep = (T) mDependencies.remove(cls); + if (dep instanceof Dumpable) { + mDumpManager.unregisterDumpable(dep.getClass().getName()); + } if (dep != null && destroy != null) { destroy.accept(dep); } diff --git a/packages/SystemUI/src/com/android/systemui/DumpController.kt b/packages/SystemUI/src/com/android/systemui/DumpController.kt deleted file mode 100644 index 7a83a8948bb0..000000000000 --- a/packages/SystemUI/src/com/android/systemui/DumpController.kt +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.systemui - -import android.util.ArraySet -import android.util.Log -import androidx.annotation.GuardedBy -import java.io.FileDescriptor -import java.io.PrintWriter -import java.lang.ref.WeakReference -import java.util.Objects.requireNonNull -import javax.inject.Inject -import javax.inject.Singleton - -// TODO: Move all Dumpable dependencies to use DumpController -/** - * Controller that allows any [Dumpable] to subscribe and be dumped along with other SystemUI - * dependencies. - * - * To dump a specific dumpable on-demand: - * - * ``` - * $ adb shell dumpsys activity service com.android.systemui/.SystemUIService dependency DumpController <tag1>,<tag2>,<tag3> - * ``` - * - * Where tag1, tag2, etc. are the tags of the dumpables you want to dump. - */ -@Singleton -class DumpController @Inject constructor() : Dumpable { - - companion object { - private const val TAG = "DumpController" - private const val DEBUG = false - } - - @GuardedBy("listeners") - private val listeners = mutableListOf<RegisteredDumpable>() - val numListeners: Int - get() = listeners.size - - /** - * Adds a [Dumpable] dumpable to be dumped. - * - * @param dumpable the [Dumpable] to be added - */ - fun registerDumpable(dumpable: Dumpable) { - requireNonNull(dumpable, "The dumpable to be added cannot be null") - registerDumpable(dumpable.javaClass.simpleName, dumpable) - } - - /** - * Adds a [Dumpable] dumpable to be dumped. - * - * @param tag a string tag to associate with this dumpable. Tags must be globally unique; this - * method will throw if the same tag has already been registered. Tags can be used to - * filter output when debugging. - * @param dumpable the [Dumpable] to be added - */ - fun registerDumpable(tag: String, dumpable: Dumpable) { - requireNonNull(dumpable, "The dumpable to be added cannot be null") - if (DEBUG) Log.v(TAG, "*** register callback for $dumpable") - synchronized<Unit>(listeners) { - if (listeners.any { it.tag == tag }) { - throw IllegalArgumentException("Duplicate dumpable tag registered: $tag") - } else { - listeners.add(RegisteredDumpable(tag, WeakReference(dumpable))) - } - } - } - - /** - * Removes a dumpable from the list of elements to be dumped. - * - * @param dumpable the [Dumpable] to be removed. - */ - fun unregisterDumpable(dumpable: Dumpable) { - if (DEBUG) Log.v(TAG, "*** unregister callback for $dumpable") - synchronized(listeners) { - listeners.removeAll { it.dumpable.get() == dumpable || it.dumpable.get() == null } - } - } - - /** - * Dump all the [Dumpable] registered with the controller - */ - override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<String>) { - pw.println("DumpController state:") - - val filter = if (args.size >= 3 && args[0].toLowerCase() == "dependency" && - args[1] == "DumpController") { - ArraySet(args[2].split(',').map { it.toLowerCase() }) - } else { - null - } - - synchronized(listeners) { - listeners.forEach { - if (filter == null || filter.contains(it.tag.toLowerCase())) { - it.dumpable.get()?.dump(fd, pw, args) - } - } - } - } - - data class RegisteredDumpable(val tag: String, val dumpable: WeakReference<Dumpable>) -} diff --git a/packages/SystemUI/src/com/android/systemui/Dumpable.java b/packages/SystemUI/src/com/android/systemui/Dumpable.java index 10a064389384..2f6d903233a0 100644 --- a/packages/SystemUI/src/com/android/systemui/Dumpable.java +++ b/packages/SystemUI/src/com/android/systemui/Dumpable.java @@ -16,6 +16,8 @@ package com.android.systemui; import androidx.annotation.NonNull; +import com.android.systemui.dump.DumpManager; + import java.io.FileDescriptor; import java.io.PrintWriter; @@ -23,7 +25,7 @@ import java.io.PrintWriter; * Implemented by classes who want to be in: * {@code adb shell dumpsys activity service com.android.systemui} * - * @see DumpController + * @see DumpManager */ public interface Dumpable { diff --git a/packages/SystemUI/src/com/android/systemui/SystemUI.java b/packages/SystemUI/src/com/android/systemui/SystemUI.java index f795faf30603..e880cc8fd10a 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUI.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUI.java @@ -21,10 +21,18 @@ import android.content.Context; import android.content.res.Configuration; import android.os.Bundle; +import androidx.annotation.NonNull; + import java.io.FileDescriptor; import java.io.PrintWriter; -public abstract class SystemUI { +/** + * A top-level module of system UI code (sometimes called "system UI services" elsewhere in code). + * Which SystemUI modules are loaded can be controlled via a config resource. + * + * @see SystemUIApplication#startServicesIfNeeded() + */ +public abstract class SystemUI implements Dumpable { protected final Context mContext; public SystemUI(Context context) { @@ -36,7 +44,8 @@ public abstract class SystemUI { protected void onConfigurationChanged(Configuration newConfig) { } - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + @Override + public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) { } protected void onBootCompleted() { diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java index 13151527cd5f..cbdae4e6fe63 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java @@ -33,6 +33,7 @@ import android.util.TimingsTraceLog; import com.android.systemui.dagger.ContextComponentHelper; import com.android.systemui.dagger.SystemUIRootComponent; +import com.android.systemui.dump.DumpManager; import com.android.systemui.util.NotificationChannels; import java.lang.reflect.Constructor; @@ -171,6 +172,8 @@ public class SystemUIApplication extends Application implements } } + final DumpManager dumpManager = mRootComponent.createDumpManager(); + Log.v(TAG, "Starting SystemUI services for user " + Process.myUserHandle().getIdentifier() + "."); TimingsTraceLog log = new TimingsTraceLog("SystemUIBootTiming", @@ -209,6 +212,8 @@ public class SystemUIApplication extends Application implements if (mBootCompleteCache.isBootComplete()) { mServices[i].onBootCompleted(); } + + dumpManager.registerDumpable(mServices[i].getClass().getName(), mServices[i]); } mRootComponent.getInitController().executePostInitTasks(); log.traceEnd(); diff --git a/packages/SystemUI/src/com/android/systemui/SystemUISecondaryUserService.java b/packages/SystemUI/src/com/android/systemui/SystemUISecondaryUserService.java index 2d2d91db4fe1..f4ec6f75b06b 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUISecondaryUserService.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUISecondaryUserService.java @@ -20,9 +20,6 @@ import android.app.Service; import android.content.Intent; import android.os.IBinder; -import java.io.FileDescriptor; -import java.io.PrintWriter; - public class SystemUISecondaryUserService extends Service { @Override @@ -35,11 +32,4 @@ public class SystemUISecondaryUserService extends Service { public IBinder onBind(Intent intent) { return null; } - - @Override - protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - SystemUIService.dumpServices( - ((SystemUIApplication) getApplication()).getServices(), fd, pw, args); - } } - diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java index 41d83148e093..d0080886ae7a 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java @@ -16,7 +16,6 @@ package com.android.systemui; -import android.annotation.NonNull; import android.app.Service; import android.content.Intent; import android.os.Build; @@ -24,12 +23,13 @@ import android.os.Handler; import android.os.IBinder; import android.os.Process; import android.os.SystemProperties; +import android.os.UserHandle; import android.util.Slog; import com.android.internal.os.BinderInternal; import com.android.systemui.dagger.qualifiers.Main; -import com.android.systemui.shared.plugins.PluginManager; -import com.android.systemui.shared.plugins.PluginManagerImpl; +import com.android.systemui.dump.DumpManager; +import com.android.systemui.dump.SystemUIAuxiliaryDumpService; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -39,11 +39,15 @@ import javax.inject.Inject; public class SystemUIService extends Service { private final Handler mMainHandler; + private final DumpManager mDumpManager; @Inject - public SystemUIService(@Main Handler mainHandler) { + public SystemUIService( + @Main Handler mainHandler, + DumpManager dumpManager) { super(); mMainHandler = mainHandler; + mDumpManager = dumpManager; } @Override @@ -70,6 +74,11 @@ public class SystemUIService extends Service { } }, mMainHandler); } + + // Bind the dump service so we can dump extra info during a bug report + startServiceAsUser( + new Intent(getApplicationContext(), SystemUIAuxiliaryDumpService.class), + UserHandle.SYSTEM); } @Override @@ -79,62 +88,16 @@ public class SystemUIService extends Service { @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - dumpServices(((SystemUIApplication) getApplication()).getServices(), fd, pw, args); - - if (args == null || args.length == 0 || args[0].equals("--config")) { - dumpConfig(pw); + // If no args are passed, assume we're being dumped as part of a bug report (sadly, we have + // no better way to guess whether this is taking place). Set the appropriate dump priority + // (CRITICAL) to reflect that this is taking place. + String[] massagedArgs = args; + if (args.length == 0) { + massagedArgs = new String[] { + DumpManager.PRIORITY_ARG, + DumpManager.PRIORITY_ARG_CRITICAL}; } - } - static void dumpServices( - SystemUI[] services, FileDescriptor fd, PrintWriter pw, String[] args) { - if (args == null || args.length == 0) { - pw.println("dumping service: " + Dependency.class.getName()); - Dependency.staticDump(fd, pw, args); - for (SystemUI ui: services) { - pw.println("dumping service: " + ui.getClass().getName()); - ui.dump(fd, pw, args); - } - if (Build.IS_DEBUGGABLE) { - pw.println("dumping plugins:"); - ((PluginManagerImpl) Dependency.get(PluginManager.class)).dump(fd, pw, args); - } - } else { - String svc = args[0].toLowerCase(); - if (Dependency.class.getName().toLowerCase().endsWith(svc)) { - Dependency.staticDump(fd, pw, args); - } - for (SystemUI ui: services) { - String name = ui.getClass().getName().toLowerCase(); - if (name.endsWith(svc)) { - ui.dump(fd, pw, args); - } - } - } - } - - private void dumpConfig(@NonNull PrintWriter pw) { - pw.println("SystemUiServiceComponents configuration:"); - - pw.print("vendor component: "); - pw.println(getResources().getString(R.string.config_systemUIVendorServiceComponent)); - - dumpConfig(pw, "global", R.array.config_systemUIServiceComponents); - dumpConfig(pw, "per-user", R.array.config_systemUIServiceComponentsPerUser); - } - - private void dumpConfig(@NonNull PrintWriter pw, @NonNull String type, int resId) { - final String[] services = getResources().getStringArray(resId); - pw.print(type); pw.print(": "); - if (services == null) { - pw.println("N/A"); - return; - } - pw.print(services.length); - pw.println(" services"); - for (int i = 0; i < services.length; i++) { - pw.print(" "); pw.print(i); pw.print(": "); pw.println(services[i]); - } + mDumpManager.dump(fd, pw, massagedArgs); } } - diff --git a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java index 23d6458a30a5..941de2dc63ec 100644 --- a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java @@ -27,9 +27,9 @@ import android.util.Log; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import com.android.systemui.DumpController; import com.android.systemui.Dumpable; import com.android.systemui.dagger.qualifiers.Background; +import com.android.systemui.dump.DumpManager; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -79,8 +79,10 @@ public class AppOpsControllerImpl implements AppOpsController, }; @Inject - public AppOpsControllerImpl(Context context, - @Background Looper bgLooper, DumpController dumpController) { + public AppOpsControllerImpl( + Context context, + @Background Looper bgLooper, + DumpManager dumpManager) { mContext = context; mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); mBGHandler = new H(bgLooper); @@ -88,7 +90,7 @@ public class AppOpsControllerImpl implements AppOpsController, for (int i = 0; i < numOps; i++) { mCallbacksByCode.put(OPS[i], new ArraySet<>()); } - dumpController.registerDumpable(TAG, this); + dumpManager.registerDumpable(TAG, this); } @VisibleForTesting diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java index 170c25a82101..3707d61da37f 100644 --- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java +++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java @@ -30,8 +30,8 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.AssistUtils; import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; import com.android.keyguard.KeyguardUpdateMonitor; -import com.android.systemui.DumpController; import com.android.systemui.Dumpable; +import com.android.systemui.dump.DumpManager; import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.statusbar.phone.NavigationModeController; @@ -93,7 +93,7 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac DeviceConfigHelper deviceConfigHelper, Map<AssistHandleBehavior, BehaviorController> behaviorMap, NavigationModeController navigationModeController, - DumpController dumpController) { + DumpManager dumpManager) { mContext = context; mAssistUtils = assistUtils; mHandler = handler; @@ -115,7 +115,7 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac } }); - dumpController.registerDumpable(TAG, this); + dumpManager.registerDumpable(TAG, this); } @Override // AssistHandleCallbacks diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt index cedf7c354ccc..bd803fa76f13 100644 --- a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt +++ b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt @@ -31,6 +31,7 @@ import com.android.internal.annotations.VisibleForTesting import com.android.systemui.Dumpable import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.dump.DumpManager import java.io.FileDescriptor import java.io.PrintWriter import java.util.concurrent.Executor @@ -65,12 +66,18 @@ private const val DEBUG = true open class BroadcastDispatcher @Inject constructor ( private val context: Context, @Main private val mainHandler: Handler, - @Background private val bgLooper: Looper + @Background private val bgLooper: Looper, + dumpManager: DumpManager ) : Dumpable { // Only modify in BG thread private val receiversByUser = SparseArray<UserBroadcastDispatcher>(20) + init { + // TODO: Don't do this in the constructor + dumpManager.registerDumpable(javaClass.name, this) + } + /** * Register a receiver for broadcast with the dispatcher * @@ -112,10 +119,10 @@ open class BroadcastDispatcher @Inject constructor ( */ @JvmOverloads fun registerReceiver( - receiver: BroadcastReceiver, - filter: IntentFilter, - executor: Executor? = context.mainExecutor, - user: UserHandle = context.user + receiver: BroadcastReceiver, + filter: IntentFilter, + executor: Executor? = context.mainExecutor, + user: UserHandle = context.user ) { checkFilter(filter) this.handler diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java index de707b9527bb..a220dac0af41 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java @@ -69,10 +69,10 @@ import androidx.annotation.Nullable; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.NotificationVisibility; -import com.android.systemui.DumpController; import com.android.systemui.Dumpable; import com.android.systemui.R; import com.android.systemui.bubbles.dagger.BubbleModule; +import com.android.systemui.dump.DumpManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.PinnedStackListenerForwarder; @@ -286,12 +286,12 @@ public class BubbleController implements ConfigurationController.ConfigurationLi NotificationEntryManager entryManager, NotifPipeline notifPipeline, FeatureFlags featureFlags, - DumpController dumpController, + DumpManager dumpManager, FloatingContentCoordinator floatingContentCoordinator) { this(context, notificationShadeWindowController, statusBarStateController, shadeController, data, null /* synchronizer */, configurationController, interruptionStateProvider, zenModeController, notifUserManager, groupManager, entryManager, - notifPipeline, featureFlags, dumpController, floatingContentCoordinator); + notifPipeline, featureFlags, dumpManager, floatingContentCoordinator); } /** @@ -311,9 +311,9 @@ public class BubbleController implements ConfigurationController.ConfigurationLi NotificationEntryManager entryManager, NotifPipeline notifPipeline, FeatureFlags featureFlags, - DumpController dumpController, + DumpManager dumpManager, FloatingContentCoordinator floatingContentCoordinator) { - dumpController.registerDumpable(TAG, this); + dumpManager.registerDumpable(TAG, this); mContext = context; mShadeController = shadeController; mNotificationInterruptionStateProvider = interruptionStateProvider; diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java b/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java index f057d0b65294..ac97d8aab326 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/dagger/BubbleModule.java @@ -18,9 +18,9 @@ package com.android.systemui.bubbles.dagger; import android.content.Context; -import com.android.systemui.DumpController; import com.android.systemui.bubbles.BubbleController; import com.android.systemui.bubbles.BubbleData; +import com.android.systemui.dump.DumpManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.NotificationLockscreenUserManager; @@ -61,7 +61,7 @@ public interface BubbleModule { NotificationEntryManager entryManager, NotifPipeline notifPipeline, FeatureFlags featureFlags, - DumpController dumpController, + DumpManager dumpManager, FloatingContentCoordinator floatingContentCoordinator) { return new BubbleController( context, @@ -78,7 +78,7 @@ public interface BubbleModule { entryManager, notifPipeline, featureFlags, - dumpController, + dumpManager, floatingContentCoordinator); } } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java index 0db9ffc4f5bd..0ac1c1215a28 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerProxy.java @@ -29,13 +29,13 @@ import androidx.annotation.NonNull; import com.android.internal.annotations.VisibleForTesting; import com.android.keyguard.KeyguardUpdateMonitor; -import com.android.systemui.DumpController; import com.android.systemui.Dumpable; import com.android.systemui.classifier.brightline.BrightLineFalsingManager; import com.android.systemui.classifier.brightline.FalsingDataProvider; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dagger.qualifiers.UiBackground; import com.android.systemui.dock.DockManager; +import com.android.systemui.dump.DumpManager; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.FalsingPlugin; import com.android.systemui.plugins.PluginListener; @@ -75,7 +75,7 @@ public class FalsingManagerProxy implements FalsingManager, Dumpable { DisplayMetrics displayMetrics, ProximitySensor proximitySensor, DeviceConfigProxy deviceConfig, DockManager dockManager, KeyguardUpdateMonitor keyguardUpdateMonitor, - DumpController dumpController, + DumpManager dumpManager, @UiBackground Executor uiBgExecutor) { mDisplayMetrics = displayMetrics; mProximitySensor = proximitySensor; @@ -110,7 +110,7 @@ public class FalsingManagerProxy implements FalsingManager, Dumpable { pluginManager.addPluginListener(mPluginListener, FalsingPlugin.class); - dumpController.registerDumpable("FalsingManager", this); + dumpManager.registerDumpable("FalsingManager", this); } private void onDeviceConfigPropertiesChanged(Context context, String namespace) { diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt index 50ad515f0ae0..a2a08502a58f 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsControllerImpl.kt @@ -34,13 +34,13 @@ import android.util.ArrayMap import android.util.Log import com.android.internal.annotations.GuardedBy import com.android.internal.annotations.VisibleForTesting -import com.android.systemui.DumpController import com.android.systemui.Dumpable import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.controls.ControlStatus import com.android.systemui.controls.management.ControlsListingController import com.android.systemui.controls.ui.ControlsUiController import com.android.systemui.dagger.qualifiers.Background +import com.android.systemui.dump.DumpManager import com.android.systemui.util.concurrency.DelayableExecutor import java.io.FileDescriptor import java.io.PrintWriter @@ -59,7 +59,7 @@ class ControlsControllerImpl @Inject constructor ( private val listingController: ControlsListingController, private val broadcastDispatcher: BroadcastDispatcher, optionalWrapper: Optional<ControlsFavoritePersistenceWrapper>, - dumpController: DumpController + dumpManager: DumpManager ) : Dumpable, ControlsController { companion object { @@ -151,7 +151,7 @@ class ControlsControllerImpl @Inject constructor ( } init { - dumpController.registerDumpable(this) + dumpManager.registerDumpable(javaClass.name, this) if (available) { loadFavorites() } diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DefaultServiceBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DefaultServiceBinder.java index f006acf1694d..c95e81cd114b 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/DefaultServiceBinder.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/DefaultServiceBinder.java @@ -21,6 +21,7 @@ import android.app.Service; import com.android.systemui.ImageWallpaper; import com.android.systemui.SystemUIService; import com.android.systemui.doze.DozeService; +import com.android.systemui.dump.SystemUIAuxiliaryDumpService; import com.android.systemui.keyguard.KeyguardService; import com.android.systemui.screenrecord.RecordingService; import com.android.systemui.screenshot.TakeScreenshotService; @@ -62,6 +63,12 @@ public abstract class DefaultServiceBinder { /** */ @Binds @IntoMap + @ClassKey(SystemUIAuxiliaryDumpService.class) + public abstract Service bindSystemUIAuxiliaryDumpService(SystemUIAuxiliaryDumpService service); + + /** */ + @Binds + @IntoMap @ClassKey(TakeScreenshotService.class) public abstract Service bindTakeScreenshotService(TakeScreenshotService service); diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java index 030b504c9a7a..513580f55a87 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java @@ -24,8 +24,8 @@ import android.view.Choreographer; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.BootCompleteCache; import com.android.systemui.BootCompleteCacheImpl; -import com.android.systemui.DumpController; import com.android.systemui.assist.AssistModule; +import com.android.systemui.dump.DumpManager; import com.android.systemui.log.dagger.LogModule; import com.android.systemui.model.SysUiState; import com.android.systemui.plugins.statusbar.StatusBarStateController; @@ -85,16 +85,17 @@ public abstract class SystemUIModule { @Singleton @Provides @Nullable - static KeyguardLiftController provideKeyguardLiftController(Context context, + static KeyguardLiftController provideKeyguardLiftController( + Context context, StatusBarStateController statusBarStateController, AsyncSensorManager asyncSensorManager, KeyguardUpdateMonitor keyguardUpdateMonitor, - DumpController dumpController) { + DumpManager dumpManager) { if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FACE)) { return null; } return new KeyguardLiftController(statusBarStateController, asyncSensorManager, - keyguardUpdateMonitor, dumpController); + keyguardUpdateMonitor, dumpManager); } @Singleton @@ -102,14 +103,14 @@ public abstract class SystemUIModule { @Nullable static NotificationShadeWindowBlurController providesBlurController(BlurUtils blurUtils, SysuiStatusBarStateController statusBarStateController, - DumpController dumpController, BiometricUnlockController biometricUnlockController, + DumpManager dumpManager, BiometricUnlockController biometricUnlockController, KeyguardStateController keyguardStateController, NotificationShadeWindowController notificationShadeWindowController, Choreographer choreographer) { return blurUtils.supportsBlursOnWindows() ? new NotificationShadeWindowBlurController( statusBarStateController, blurUtils, biometricUnlockController, keyguardStateController, notificationShadeWindowController, choreographer, - dumpController) : null; + dumpManager) : null; } /** */ diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIRootComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIRootComponent.java index 12b9be11817a..18c3eacbc693 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIRootComponent.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIRootComponent.java @@ -25,6 +25,7 @@ import com.android.systemui.Dependency; import com.android.systemui.InitController; import com.android.systemui.SystemUIAppComponentFactory; import com.android.systemui.SystemUIFactory; +import com.android.systemui.dump.DumpManager; import com.android.systemui.fragments.FragmentService; import com.android.systemui.keyguard.KeyguardSliceProvider; import com.android.systemui.pip.phone.dagger.PipModule; @@ -76,6 +77,10 @@ public interface SystemUIRootComponent { @Singleton Dependency.DependencyInjector createDependency(); + /** */ + @Singleton + DumpManager createDumpManager(); + /** * FragmentCreator generates all Fragments that need injection. */ diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java index 96ae6c9ec4a2..a311a450c6b7 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeLog.java @@ -23,8 +23,8 @@ import androidx.annotation.NonNull; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; -import com.android.systemui.DumpController; import com.android.systemui.Dumpable; +import com.android.systemui.dump.DumpManager; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -56,7 +56,7 @@ public class DozeLog implements Dumpable { @Inject public DozeLog( KeyguardUpdateMonitor keyguardUpdateMonitor, - DumpController dumpController, + DumpManager dumpManager, DozeLogger logger) { mLogger = logger; mSince = System.currentTimeMillis(); @@ -76,7 +76,7 @@ public class DozeLog implements Dumpable { keyguardUpdateMonitor.registerCallback(mKeyguardCallback); } - dumpController.registerDumpable("DumpStats", this); + dumpManager.registerDumpable("DumpStats", this); } /** diff --git a/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt b/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt new file mode 100644 index 000000000000..59a7a328e9ae --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/dump/DumpManager.kt @@ -0,0 +1,367 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.dump + +import android.content.Context +import android.os.SystemClock +import android.os.Trace +import android.util.ArrayMap +import com.android.systemui.Dumpable +import com.android.systemui.R +import com.android.systemui.dump.DumpManager.Companion.PRIORITY_ARG_CRITICAL +import com.android.systemui.dump.DumpManager.Companion.PRIORITY_ARG_HIGH +import com.android.systemui.dump.DumpManager.Companion.PRIORITY_ARG_NORMAL +import com.android.systemui.log.LogBuffer +import java.io.FileDescriptor +import java.io.PrintWriter +import javax.inject.Inject +import javax.inject.Singleton + +/** + * Oversees SystemUI's output during bug reports (and dumpsys in general) + * + * When a bug report is taken, SystemUI dumps various diagnostic information that we hope will be + * useful for the eventual readers of the bug report. Code that wishes to participate in this dump + * should register itself here. + * + * Dump output is split into two sections, CRITICAL and NORMAL. All dumpables registered via + * [registerDumpable] appear in the CRITICAL section, while all [LogBuffer]s appear in the NORMAL + * section (due to their length). + * + * The CRITICAL and NORMAL sections can be found within a bug report by searching for + * "SERVICE com.android.systemui/.SystemUIService" and + * "SERVICE com.android.systemui/.dump.SystemUIAuxiliaryDumpService", respectively. + * + * Finally, some or all of the dump can be triggered on-demand via adb (see below). + * + * ``` + * # For the following, let <invocation> be: + * $ adb shell dumpsys activity service com.android.systemui/.SystemUIService + * + * # To dump specific target(s), specify one or more registered names: + * $ <invocation> NotifCollection + * $ <invocation> StatusBar FalsingManager BootCompleteCacheImpl + * + * # Log buffers can be dumped in the same way (and can even be mixed in with other dump targets, + * # although it's not clear why one would want such a thing): + * $ <invocation> NotifLog + * $ <invocation> StatusBar NotifLog BootCompleteCacheImpl + * + * # If passing -t or --tail, shows only the last N lines of any log buffers: + * $ <invocation> NotifLog --tail 100 + * + * # Dump targets are matched using String.endsWith(), so dumpables that register using their + * # fully-qualified class name can still be dumped using their short name: + * $ <invocation> com.android.keyguard.KeyguardUpdateMonitor + * $ <invocation> keyguard.KeyguardUpdateMonitor + * $ <invocation> KeyguardUpdateMonitor + * + * # To dump all dumpables or all buffers: + * $ <invocation> dumpables + * $ <invocation> buffers + * + * Finally, the following will simulate what we dump during the CRITICAL and NORMAL sections of a + * bug report: + * $ <invocation> bugreport-critical + * $ <invocation> bugreport-normal + * ``` + */ +@Singleton +class DumpManager @Inject constructor( + private val context: Context +) { + private val dumpables: MutableMap<String, RegisteredDumpable<Dumpable>> = ArrayMap() + private val buffers: MutableMap<String, RegisteredDumpable<LogBuffer>> = ArrayMap() + + /** + * Register a dumpable to be called during a bug report. The dumpable will be called during the + * CRITICAL section of the bug report, so don't dump an excessive amount of stuff here. + * + * @param name The name to register the dumpable under. This is typically the qualified class + * name of the thing being dumped (getClass().getName()), but can be anything as long as it + * doesn't clash with an existing registration. + */ + @Synchronized + fun registerDumpable(name: String, module: Dumpable) { + if (RESERVED_NAMES.contains(name)) { + throw IllegalArgumentException("'$name' is reserved") + } + + if (!canAssignToNameLocked(name, module)) { + throw IllegalArgumentException("'$name' is already registered") + } + + dumpables[name] = RegisteredDumpable(name, module) + } + + /** + * Unregisters a previously-registered dumpable. + */ + @Synchronized + fun unregisterDumpable(name: String) { + dumpables.remove(name) + } + + /** + * Register a [LogBuffer] to be dumped during a bug report. + */ + @Synchronized + fun registerBuffer(name: String, buffer: LogBuffer) { + if (!canAssignToNameLocked(name, buffer)) { + throw IllegalArgumentException("'$name' is already registered") + } + buffers[name] = RegisteredDumpable(name, buffer) + } + + /** + * Dump the diagnostics! Behavior can be controlled via [args]. + */ + @Synchronized + fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<String>) { + Trace.beginSection("DumpManager#dump()") + val start = SystemClock.uptimeMillis() + + val parsedArgs = try { + parseArgs(args) + } catch (e: ArgParseException) { + pw.println(e.message) + return + } + + when (parsedArgs.dumpPriority) { + PRIORITY_ARG_CRITICAL -> dumpCriticalLocked(fd, pw, parsedArgs) + PRIORITY_ARG_NORMAL -> dumpNormalLocked(pw, parsedArgs) + else -> dumpParameterizedLocked(fd, pw, parsedArgs) + } + + pw.println() + pw.println("Dump took ${SystemClock.uptimeMillis() - start}ms") + Trace.endSection() + } + + private fun dumpCriticalLocked(fd: FileDescriptor, pw: PrintWriter, args: ParsedArgs) { + dumpDumpablesLocked(fd, pw, args) + dumpConfig(pw) + } + + private fun dumpNormalLocked(pw: PrintWriter, args: ParsedArgs) { + dumpBuffersLocked(pw, args) + } + + private fun dumpParameterizedLocked(fd: FileDescriptor, pw: PrintWriter, args: ParsedArgs) { + when (args.command) { + "bugreport-critical" -> dumpCriticalLocked(fd, pw, args) + "bugreport-normal" -> dumpNormalLocked(pw, args) + "dumpables" -> dumpDumpablesLocked(fd, pw, args) + "buffers" -> dumpBuffersLocked(pw, args) + else -> dumpTargetsLocked(args.nonFlagArgs, fd, pw, args) + } + } + + private fun dumpTargetsLocked( + targets: List<String>, + fd: FileDescriptor, + pw: PrintWriter, + args: ParsedArgs + ) { + if (targets.isEmpty()) { + pw.println("Nothing to dump :(") + } else { + for (target in targets) { + dumpTarget(target, fd, pw, args) + } + } + } + + private fun dumpTarget( + target: String, + fd: FileDescriptor, + pw: PrintWriter, + args: ParsedArgs + ) { + if (target == "config") { + dumpConfig(pw) + return + } + + for (dumpable in dumpables.values) { + if (dumpable.name.endsWith(target)) { + dumpDumpable(dumpable, fd, pw, args) + return + } + } + + for (buffer in buffers.values) { + if (buffer.name.endsWith(target)) { + dumpBuffer(buffer, pw, args) + return + } + } + } + + private fun dumpDumpablesLocked(fd: FileDescriptor, pw: PrintWriter, args: ParsedArgs) { + for (module in dumpables.values) { + dumpDumpable(module, fd, pw, args) + } + } + + private fun dumpBuffersLocked(pw: PrintWriter, args: ParsedArgs) { + for (buffer in buffers.values) { + dumpBuffer(buffer, pw, args) + } + } + + private fun dumpDumpable( + dumpable: RegisteredDumpable<Dumpable>, + fd: FileDescriptor, + pw: PrintWriter, + args: ParsedArgs + ) { + pw.println() + pw.println("${dumpable.name}:") + pw.println("----------------------------------------------------------------------------") + dumpable.dumpable.dump(fd, pw, args.rawArgs) + } + + private fun dumpBuffer( + buffer: RegisteredDumpable<LogBuffer>, + pw: PrintWriter, + args: ParsedArgs + ) { + pw.println() + pw.println() + pw.println("BUFFER ${buffer.name}:") + pw.println("============================================================================") + buffer.dumpable.dump(pw, args.tailLength) + } + + private fun dumpConfig(pw: PrintWriter) { + pw.println("SystemUiServiceComponents configuration:") + pw.print("vendor component: ") + pw.println(context.resources.getString(R.string.config_systemUIVendorServiceComponent)) + dumpServiceList(pw, "global", R.array.config_systemUIServiceComponents) + dumpServiceList(pw, "per-user", R.array.config_systemUIServiceComponentsPerUser) + } + + private fun dumpServiceList(pw: PrintWriter, type: String, resId: Int) { + val services: Array<String>? = context.resources.getStringArray(resId) + pw.print(type) + pw.print(": ") + if (services == null) { + pw.println("N/A") + return + } + pw.print(services.size) + pw.println(" services") + for (i in services.indices) { + pw.print(" ") + pw.print(i) + pw.print(": ") + pw.println(services[i]) + } + } + + private fun parseArgs(args: Array<String>): ParsedArgs { + val mutArgs = args.toMutableList() + val pArgs = ParsedArgs(args, mutArgs) + + val iterator = mutArgs.iterator() + while (iterator.hasNext()) { + val arg = iterator.next() + if (arg.startsWith("-")) { + iterator.remove() + when (arg) { + PRIORITY_ARG -> { + pArgs.dumpPriority = readArgument(iterator, PRIORITY_ARG) { + if (PRIORITY_OPTIONS.contains(it)) { + it + } else { + throw IllegalArgumentException() + } + } + } + "-t", "--tail" -> { + pArgs.tailLength = readArgument(iterator, "--tail") { + it.toInt() + } + } + else -> { + throw ArgParseException("Unknown flag: $arg") + } + } + } + } + + if (mutArgs.isNotEmpty() && COMMANDS.contains(mutArgs[0])) { + pArgs.command = mutArgs.removeAt(0) + } + + return pArgs + } + + private fun <T> readArgument( + iterator: MutableIterator<String>, + flag: String, + parser: (arg: String) -> T + ): T { + if (!iterator.hasNext()) { + throw ArgParseException("Missing argument for $flag") + } + val value = iterator.next() + + return try { + parser(value).also { iterator.remove() } + } catch (e: Exception) { + throw ArgParseException("Invalid argument '$value' for flag $flag") + } + } + + private fun canAssignToNameLocked(name: String, newDumpable: Any): Boolean { + val existingDumpable = dumpables[name]?.dumpable ?: buffers[name]?.dumpable + return existingDumpable == null || newDumpable == existingDumpable + } + + companion object { + const val PRIORITY_ARG = "--dump-priority" + const val PRIORITY_ARG_CRITICAL = "CRITICAL" + const val PRIORITY_ARG_HIGH = "HIGH" + const val PRIORITY_ARG_NORMAL = "NORMAL" + } +} + +private val PRIORITY_OPTIONS = + arrayOf(PRIORITY_ARG_CRITICAL, PRIORITY_ARG_HIGH, PRIORITY_ARG_NORMAL) + +private val COMMANDS = arrayOf("bugreport-critical", "bugreport-normal", "buffers", "dumpables") + +private val RESERVED_NAMES = arrayOf("config", *COMMANDS) + +private data class RegisteredDumpable<T>( + val name: String, + val dumpable: T +) + +private class ParsedArgs( + val rawArgs: Array<String>, + val nonFlagArgs: List<String> +) { + var dumpPriority: String? = null + var tailLength: Int = 0 + var command: String? = null +} + +class ArgParseException(message: String) : Exception(message)
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/dump/SystemUIAuxiliaryDumpService.java b/packages/SystemUI/src/com/android/systemui/dump/SystemUIAuxiliaryDumpService.java new file mode 100644 index 000000000000..431cd6360b0b --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/dump/SystemUIAuxiliaryDumpService.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.dump; + +import android.app.Service; +import android.content.Intent; +import android.os.IBinder; + +import java.io.FileDescriptor; +import java.io.PrintWriter; + +import javax.inject.Inject; + +/** + * Service for dumping extremely verbose content during a bug report + * + * Our primary service, SystemUIService, is dumped during the CRITICAL section of a bug report. + * This has some advantages (we get to go first!), but also imposes strict limitations on how much + * we can dump. This service exists to handle any content that is too large to be safely dumped + * within those constraints, namely log buffers. It's dumped during the NORMAL section, along with + * all other services. + */ +public class SystemUIAuxiliaryDumpService extends Service { + private final DumpManager mDumpManager; + + @Inject + public SystemUIAuxiliaryDumpService(DumpManager dumpManager) { + mDumpManager = dumpManager; + } + + @Override + public IBinder onBind(Intent intent) { + return null; + } + + @Override + protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + // Simulate the NORMAL priority arg being passed to us + mDumpManager.dump( + fd, + pw, + new String[] { DumpManager.PRIORITY_ARG, DumpManager.PRIORITY_ARG_NORMAL }); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 2e6c9559d696..d688f0aa12e1 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -81,13 +81,13 @@ import com.android.keyguard.KeyguardSecurityView; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.keyguard.ViewMediatorCallback; -import com.android.systemui.DumpController; import com.android.systemui.Dumpable; import com.android.systemui.R; import com.android.systemui.SystemUI; import com.android.systemui.SystemUIFactory; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.qualifiers.UiBackground; +import com.android.systemui.dump.DumpManager; import com.android.systemui.keyguard.dagger.KeyguardModule; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.statusbar.phone.BiometricUnlockController; @@ -703,7 +703,7 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable { NotificationShadeWindowController notificationShadeWindowController, Lazy<StatusBarKeyguardViewManager> statusBarKeyguardViewManagerLazy, DismissCallbackRegistry dismissCallbackRegistry, - KeyguardUpdateMonitor keyguardUpdateMonitor, DumpController dumpController, + KeyguardUpdateMonitor keyguardUpdateMonitor, DumpManager dumpManager, @UiBackground Executor uiBgExecutor, PowerManager powerManager, TrustManager trustManager) { super(context); @@ -717,7 +717,7 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable { mUpdateMonitor = keyguardUpdateMonitor; mPM = powerManager; mTrustManager = trustManager; - dumpController.registerDumpable(this); + dumpManager.registerDumpable(getClass().getName(), this); mShowHomeOverLockscreen = DeviceConfig.getBoolean( DeviceConfig.NAMESPACE_SYSTEMUI, NAV_BAR_HANDLE_SHOW_OVER_LOCKSCREEN, diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java index 2ba0315af252..d7af36010dfa 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java @@ -22,9 +22,9 @@ import android.os.PowerManager; import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardUpdateMonitor; -import com.android.systemui.DumpController; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.qualifiers.UiBackground; +import com.android.systemui.dump.DumpManager; import com.android.systemui.keyguard.DismissCallbackRegistry; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.plugins.FalsingManager; @@ -59,7 +59,7 @@ public class KeyguardModule { Lazy<StatusBarKeyguardViewManager> statusBarKeyguardViewManagerLazy, DismissCallbackRegistry dismissCallbackRegistry, KeyguardUpdateMonitor updateMonitor, - DumpController dumpController, + DumpManager dumpManager, PowerManager powerManager, TrustManager trustManager, @UiBackground Executor uiBgExecutor) { @@ -72,7 +72,7 @@ public class KeyguardModule { statusBarKeyguardViewManagerLazy, dismissCallbackRegistry, updateMonitor, - dumpController, + dumpManager, uiBgExecutor, powerManager, trustManager); diff --git a/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt b/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt index 18c7baec1f74..7defef90380f 100644 --- a/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt +++ b/packages/SystemUI/src/com/android/systemui/log/LogBuffer.kt @@ -17,9 +17,9 @@ package com.android.systemui.log import android.util.Log -import com.android.systemui.DumpController -import com.android.systemui.Dumpable +import com.android.systemui.dump.DumpManager import com.android.systemui.log.dagger.LogModule +import java.io.PrintWriter import java.text.SimpleDateFormat import java.util.ArrayDeque import java.util.Locale @@ -35,11 +35,10 @@ import java.util.Locale * You can dump the entire buffer at any time by running: * * ``` - * $ adb shell dumpsys activity service com.android.systemui/.SystemUIService \ - * dependency DumpController <bufferName> + * $ adb shell dumpsys activity service com.android.systemui/.SystemUIService <bufferName> * ``` * - * where `bufferName` is the (case-sensitive) [name] passed to the constructor. + * ...where `bufferName` is the (case-sensitive) [name] passed to the constructor. * * By default, only messages of WARN level or higher are echoed to logcat, but this can be adjusted * locally (usually for debugging purposes). @@ -75,8 +74,8 @@ class LogBuffer( ) { private val buffer: ArrayDeque<LogMessageImpl> = ArrayDeque() - fun attach(dumpController: DumpController) { - dumpController.registerDumpable(name, onDump) + fun attach(dumpManager: DumpManager) { + dumpManager.registerBuffer(name, this) } /** @@ -174,22 +173,26 @@ class LogBuffer( } /** Converts the entire buffer to a newline-delimited string */ - fun dump(): String { + fun dump(pw: PrintWriter, tailLength: Int) { synchronized(buffer) { - val sb = StringBuilder() - for (message in buffer) { - dumpMessage(message, sb) + val start = if (tailLength <= 0) { 0 } else { buffer.size - tailLength } + + for ((i, message) in buffer.withIndex()) { + if (i >= start) { + dumpMessage(message, pw) + } } - return sb.toString() } } - private fun dumpMessage(message: LogMessage, sb: StringBuilder) { - sb.append(DATE_FORMAT.format(message.timestamp)) - .append(" ").append(message.level) - .append(" ").append(message.tag) - .append(" ").append(message.printer(message)) - .append("\n") + private fun dumpMessage(message: LogMessage, pw: PrintWriter) { + pw.print(DATE_FORMAT.format(message.timestamp)) + pw.print(" ") + pw.print(message.level) + pw.print(" ") + pw.print(message.tag) + pw.print(" ") + pw.println(message.printer(message)) } private fun echoToLogcat(message: LogMessage) { @@ -203,10 +206,6 @@ class LogBuffer( LogLevel.WTF -> Log.wtf(message.tag, strMessage) } } - - private val onDump = Dumpable { _, pw, _ -> - pw.println(dump()) - } } private const val TAG = "LogBuffer" diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java index 4a7469c1bd2d..14e3e9390825 100644 --- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java +++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java @@ -20,8 +20,8 @@ import android.content.ContentResolver; import android.os.Build; import android.os.Looper; -import com.android.systemui.DumpController; import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.dump.DumpManager; import com.android.systemui.log.LogBuffer; import com.android.systemui.log.LogcatEchoTracker; import com.android.systemui.log.LogcatEchoTrackerDebug; @@ -43,9 +43,9 @@ public class LogModule { @DozeLog public static LogBuffer provideDozeLogBuffer( LogcatEchoTracker bufferFilter, - DumpController dumpController) { + DumpManager dumpManager) { LogBuffer buffer = new LogBuffer("DozeLog", 100, 10, bufferFilter); - buffer.attach(dumpController); + buffer.attach(dumpManager); return buffer; } @@ -55,9 +55,9 @@ public class LogModule { @NotificationLog public static LogBuffer provideNotificationsLogBuffer( LogcatEchoTracker bufferFilter, - DumpController dumpController) { - LogBuffer buffer = new LogBuffer("NotifLog2", 1000, 10, bufferFilter); - buffer.attach(dumpController); + DumpManager dumpManager) { + LogBuffer buffer = new LogBuffer("NotifLog", 1000, 10, bufferFilter); + buffer.attach(dumpManager); return buffer; } @@ -67,9 +67,9 @@ public class LogModule { @QSLog public static LogBuffer provideQuickSettingsLogBuffer( LogcatEchoTracker bufferFilter, - DumpController dumpController) { + DumpManager dumpManager) { LogBuffer buffer = new LogBuffer("QSLog", 500, 10, bufferFilter); - buffer.attach(dumpController); + buffer.attach(dumpManager); return buffer; } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java index 53454d6afcd5..d2d90925cbe2 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java @@ -47,10 +47,10 @@ import com.android.settingslib.Utils; import com.android.settingslib.media.LocalMediaManager; import com.android.settingslib.media.MediaDevice; import com.android.systemui.Dependency; -import com.android.systemui.DumpController; import com.android.systemui.Dumpable; import com.android.systemui.R; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dump.DumpManager; import com.android.systemui.plugins.qs.DetailAdapter; import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.plugins.qs.QSTileView; @@ -103,7 +103,7 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne private QSDetail.Callback mCallback; private BrightnessController mBrightnessController; - private DumpController mDumpController; + private final DumpManager mDumpManager; private final QSLogger mQSLogger; protected QSTileHost mHost; @@ -148,13 +148,14 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne public QSPanel( @Named(VIEW_CONTEXT) Context context, AttributeSet attrs, - DumpController dumpController, + DumpManager dumpManager, BroadcastDispatcher broadcastDispatcher, QSLogger qsLogger ) { super(context, attrs); mContext = context; mQSLogger = qsLogger; + mDumpManager = dumpManager; setOrientation(VERTICAL); @@ -190,7 +191,6 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne mBrightnessController = new BrightnessController(getContext(), findViewById(R.id.brightness_slider), broadcastDispatcher); - mDumpController = dumpController; } @Override @@ -357,7 +357,7 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne if (mBrightnessMirrorController != null) { mBrightnessMirrorController.addCallback(this); } - if (mDumpController != null) mDumpController.registerDumpable(getDumpableTag(), this); + mDumpManager.registerDumpable(getDumpableTag(), this); } @Override @@ -372,7 +372,7 @@ public class QSPanel extends LinearLayout implements Tunable, Callback, Brightne if (mBrightnessMirrorController != null) { mBrightnessMirrorController.removeCallback(this); } - if (mDumpController != null) mDumpController.unregisterDumpable(this); + mDumpManager.unregisterDumpable(getDumpableTag()); if (mLocalMediaManager != null) { mLocalMediaManager.stopScan(); mLocalMediaManager.unregisterCallback(mDeviceCallback); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java index 73c42d4dae9a..938f9dbde6ff 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java @@ -30,12 +30,12 @@ import android.service.quicksettings.Tile; import android.text.TextUtils; import android.util.Log; -import com.android.systemui.DumpController; import com.android.systemui.Dumpable; import com.android.systemui.R; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.dump.DumpManager; import com.android.systemui.plugins.PluginListener; import com.android.systemui.plugins.qs.QSFactory; import com.android.systemui.plugins.qs.QSTile; @@ -81,7 +81,7 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D private final TileServices mServices; private final TunerService mTunerService; private final PluginManager mPluginManager; - private final DumpController mDumpController; + private final DumpManager mDumpManager; private final BroadcastDispatcher mBroadcastDispatcher; private final QSLogger mQSLogger; @@ -101,7 +101,7 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D PluginManager pluginManager, TunerService tunerService, Provider<AutoTileManager> autoTiles, - DumpController dumpController, + DumpManager dumpManager, BroadcastDispatcher broadcastDispatcher, Optional<StatusBar> statusBarOptional, QSLogger qsLogger) { @@ -109,7 +109,7 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D mContext = context; mTunerService = tunerService; mPluginManager = pluginManager; - mDumpController = dumpController; + mDumpManager = dumpManager; mQSLogger = qsLogger; mBroadcastDispatcher = broadcastDispatcher; @@ -119,7 +119,7 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D defaultFactory.setHost(this); mQsFactories.add(defaultFactory); pluginManager.addPluginListener(this, QSFactory.class, true); - mDumpController.registerDumpable(TAG, this); + mDumpManager.registerDumpable(TAG, this); mainHandler.post(() -> { // This is technically a hack to avoid circular dependency of @@ -141,7 +141,7 @@ public class QSTileHost implements QSHost, Tunable, PluginListener<QSFactory>, D mTunerService.removeTunable(this); mServices.destroy(); mPluginManager.removePluginListener(this); - mDumpController.unregisterDumpable(this); + mDumpManager.unregisterDumpable(TAG); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java index fda2f6a46f85..20efbcb3cc42 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java @@ -27,9 +27,9 @@ import android.view.View; import android.widget.LinearLayout; import com.android.systemui.Dependency; -import com.android.systemui.DumpController; import com.android.systemui.R; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dump.DumpManager; import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.plugins.qs.QSTile.SignalState; import com.android.systemui.plugins.qs.QSTile.State; @@ -70,11 +70,11 @@ public class QuickQSPanel extends QSPanel { public QuickQSPanel( @Named(VIEW_CONTEXT) Context context, AttributeSet attrs, - DumpController dumpController, + DumpManager dumpManager, BroadcastDispatcher broadcastDispatcher, QSLogger qsLogger ) { - super(context, attrs, dumpController, broadcastDispatcher, qsLogger); + super(context, attrs, dumpManager, broadcastDispatcher, qsLogger); if (mFooter != null) { removeView(mFooter.getView()); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt b/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt index 4bb8621f9988..34c0860c21a2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt @@ -24,10 +24,10 @@ import android.view.SurfaceControl import android.view.ViewRootImpl import androidx.annotation.VisibleForTesting import com.android.internal.util.IndentingPrintWriter -import com.android.systemui.DumpController import com.android.systemui.Dumpable import com.android.systemui.R import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.dump.DumpManager import java.io.FileDescriptor import java.io.PrintWriter import javax.inject.Inject @@ -36,7 +36,7 @@ import javax.inject.Singleton @Singleton open class BlurUtils @Inject constructor( @Main private val resources: Resources, - val dumpController: DumpController + dumpManager: DumpManager ) : Dumpable { private val minBlurRadius = resources.getDimensionPixelSize(R.dimen.min_window_blur_radius) private val maxBlurRadius = resources.getDimensionPixelSize(R.dimen.max_window_blur_radius) @@ -44,7 +44,7 @@ open class BlurUtils @Inject constructor( .getBoolean("ro.surface_flinger.supports_background_blur", false) init { - dumpController.registerDumpable(this) + dumpManager.registerDumpable(javaClass.name, this) } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowBlurController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowBlurController.kt index 85215ed3c40b..aadc4510170f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowBlurController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowBlurController.kt @@ -22,9 +22,9 @@ import android.animation.ValueAnimator import android.view.Choreographer import android.view.View import com.android.internal.util.IndentingPrintWriter -import com.android.systemui.DumpController import com.android.systemui.Dumpable import com.android.systemui.Interpolators +import com.android.systemui.dump.DumpManager import com.android.systemui.statusbar.phone.BiometricUnlockController import com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK import com.android.systemui.statusbar.phone.NotificationShadeWindowController @@ -47,7 +47,7 @@ class NotificationShadeWindowBlurController @Inject constructor( private val keyguardStateController: KeyguardStateController, private val notificationShadeWindowController: NotificationShadeWindowController, private val choreographer: Choreographer, - dumpController: DumpController + dumpManager: DumpManager ) : PanelExpansionListener, Dumpable { companion object { private const val WAKE_UP_ANIMATION_ENABLED = true @@ -131,7 +131,7 @@ class NotificationShadeWindowBlurController @Inject constructor( } init { - dumpController.registerDumpable(this) + dumpManager.registerDumpable(javaClass.name, this) if (WAKE_UP_ANIMATION_ENABLED) { keyguardStateController.addCallback(keyguardStateCallback) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java index 91d2de760696..749e5e2a769d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java @@ -58,8 +58,8 @@ import android.util.Pair; import androidx.annotation.NonNull; import com.android.internal.statusbar.IStatusBarService; -import com.android.systemui.DumpController; import com.android.systemui.Dumpable; +import com.android.systemui.dump.DumpManager; import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.notification.collection.coalescer.CoalescedEvent; import com.android.systemui.statusbar.notification.collection.coalescer.GroupCoalescer; @@ -130,13 +130,13 @@ public class NotifCollection implements Dumpable { @Inject public NotifCollection( IStatusBarService statusBarService, - DumpController dumpController, + DumpManager dumpManager, FeatureFlags featureFlags, NotifCollectionLogger logger) { Assert.isMainThread(); mStatusBarService = statusBarService; mLogger = logger; - dumpController.registerDumpable(TAG, this); + dumpManager.registerDumpable(TAG, this); mFeatureFlags = featureFlags; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java index be5c535b7f47..76311207fe6f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java @@ -34,8 +34,8 @@ import android.util.Pair; import androidx.annotation.NonNull; -import com.android.systemui.DumpController; import com.android.systemui.Dumpable; +import com.android.systemui.dump.DumpManager; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeSortListener; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeTransformGroupsListener; @@ -101,11 +101,11 @@ public class ShadeListBuilder implements Dumpable { public ShadeListBuilder( SystemClock systemClock, ShadeListBuilderLogger logger, - DumpController dumpController) { + DumpManager dumpManager) { Assert.isMainThread(); mSystemClock = systemClock; mLogger = logger; - dumpController.registerDumpable(TAG, this); + dumpManager.registerDumpable(TAG, this); } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java index 7a9547c573bb..7a22d75505e5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java @@ -16,8 +16,8 @@ package com.android.systemui.statusbar.notification.collection.coordinator; -import com.android.systemui.DumpController; import com.android.systemui.Dumpable; +import com.android.systemui.dump.DumpManager; import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSection; @@ -47,7 +47,7 @@ public class NotifCoordinators implements Dumpable { */ @Inject public NotifCoordinators( - DumpController dumpController, + DumpManager dumpManager, FeatureFlags featureFlags, KeyguardCoordinator keyguardCoordinator, RankingCoordinator rankingCoordinator, @@ -55,7 +55,7 @@ public class NotifCoordinators implements Dumpable { DeviceProvisionedCoordinator deviceProvisionedCoordinator, BubbleCoordinator bubbleCoordinator, PreparationCoordinator preparationCoordinator) { - dumpController.registerDumpable(TAG, this); + dumpManager.registerDumpable(TAG, this); mCoordinators.add(new HideLocallyDismissedNotifsCoordinator()); mCoordinators.add(keyguardCoordinator); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java index 959b00211c63..258f6d018057 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NotifPipelineInitializer.java @@ -18,8 +18,8 @@ package com.android.systemui.statusbar.notification.collection.init; import android.util.Log; -import com.android.systemui.DumpController; import com.android.systemui.Dumpable; +import com.android.systemui.dump.DumpManager; import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.NotificationListener; import com.android.systemui.statusbar.notification.collection.NotifCollection; @@ -47,7 +47,7 @@ public class NotifPipelineInitializer implements Dumpable { private final ShadeListBuilder mListBuilder; private final NotifCoordinators mNotifPluggableCoordinators; private final NotifInflaterImpl mNotifInflater; - private final DumpController mDumpController; + private final DumpManager mDumpManager; private final FeatureFlags mFeatureFlags; private final FakePipelineConsumer mFakePipelineConsumer = new FakePipelineConsumer(); @@ -60,14 +60,14 @@ public class NotifPipelineInitializer implements Dumpable { ShadeListBuilder listBuilder, NotifCoordinators notifCoordinators, NotifInflaterImpl notifInflater, - DumpController dumpController, + DumpManager dumpManager, FeatureFlags featureFlags) { mPipelineWrapper = pipelineWrapper; mGroupCoalescer = groupCoalescer; mNotifCollection = notifCollection; mListBuilder = listBuilder; mNotifPluggableCoordinators = notifCoordinators; - mDumpController = dumpController; + mDumpManager = dumpManager; mNotifInflater = notifInflater; mFeatureFlags = featureFlags; } @@ -77,7 +77,7 @@ public class NotifPipelineInitializer implements Dumpable { NotificationListener notificationService, NotificationRowBinderImpl rowBinder) { - mDumpController.registerDumpable("NotifPipeline", this); + mDumpManager.registerDumpable("NotifPipeline", this); // Setup inflation if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java index 1dde5c03a627..d5ded50870f0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java @@ -35,9 +35,9 @@ import com.android.keyguard.KeyguardConstants; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.systemui.Dependency; -import com.android.systemui.DumpController; import com.android.systemui.Dumpable; import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.dump.DumpManager; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.keyguard.ScreenLifecycle; import com.android.systemui.keyguard.WakefulnessLifecycle; @@ -179,7 +179,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp KeyguardUpdateMonitor keyguardUpdateMonitor, @Main Resources resources, KeyguardBypassController keyguardBypassController, DozeParameters dozeParameters, - MetricsLogger metricsLogger, DumpController dumpController) { + MetricsLogger metricsLogger, DumpManager dumpManager) { mContext = context; mPowerManager = context.getSystemService(PowerManager.class); mShadeController = shadeController; @@ -201,7 +201,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp mKeyguardBypassController = keyguardBypassController; mKeyguardBypassController.setUnlockController(this); mMetricsLogger = metricsLogger; - dumpController.registerDumpable(this); + dumpManager.registerDumpable(getClass().getName(), this); } public void setStatusBarKeyguardViewManager( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt index 03918e09be5a..0827511cac34 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt @@ -20,8 +20,8 @@ import android.content.Context import android.content.pm.PackageManager import android.hardware.biometrics.BiometricSourceType import android.provider.Settings -import com.android.systemui.DumpController import com.android.systemui.Dumpable +import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.NotificationLockscreenUserManager import com.android.systemui.statusbar.StatusBarState @@ -81,7 +81,7 @@ open class KeyguardBypassController : Dumpable { statusBarStateController: StatusBarStateController, lockscreenUserManager: NotificationLockscreenUserManager, keyguardStateController: KeyguardStateController, - dumpController: DumpController + dumpManager: DumpManager ) { this.mKeyguardStateController = keyguardStateController this.statusBarStateController = statusBarStateController @@ -91,7 +91,7 @@ open class KeyguardBypassController : Dumpable { return } - dumpController.registerDumpable("KeyguardBypassController", this) + dumpManager.registerDumpable("KeyguardBypassController", this) statusBarStateController.addCallback(object : StatusBarStateController.StateListener { override fun onStateChanged(newState: Int) { if (newState != StatusBarState.KEYGUARD) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt index 2258c7789822..74d9f5402e36 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt @@ -21,8 +21,8 @@ import android.hardware.TriggerEvent import android.hardware.TriggerEventListener import com.android.keyguard.KeyguardUpdateMonitor import com.android.keyguard.KeyguardUpdateMonitorCallback -import com.android.systemui.DumpController import com.android.systemui.Dumpable +import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.util.Assert import com.android.systemui.util.sensors.AsyncSensorManager @@ -33,7 +33,7 @@ class KeyguardLiftController constructor( private val statusBarStateController: StatusBarStateController, private val asyncSensorManager: AsyncSensorManager, private val keyguardUpdateMonitor: KeyguardUpdateMonitor, - dumpController: DumpController + dumpManager: DumpManager ) : StatusBarStateController.StateListener, Dumpable, KeyguardUpdateMonitorCallback() { private val pickupSensor = asyncSensorManager.getDefaultSensor(Sensor.TYPE_PICK_UP_GESTURE) @@ -41,7 +41,7 @@ class KeyguardLiftController constructor( private var bouncerVisible = false init { - dumpController.registerDumpable(this) + dumpManager.registerDumpable(javaClass.name, this) statusBarStateController.addCallback(this) keyguardUpdateMonitor.registerCallback(this) updateListeningState() diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java index 4ee13bf754dd..04211dff53b6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java @@ -41,9 +41,9 @@ import androidx.annotation.NonNull; import com.android.internal.util.IndentingPrintWriter; import com.android.keyguard.KeyguardUpdateMonitor; -import com.android.systemui.DumpController; import com.android.systemui.Dumpable; import com.android.systemui.dagger.qualifiers.Main; +import com.android.systemui.dump.DumpManager; import com.android.systemui.statusbar.NotificationMediaManager; import libcore.io.IoUtils; @@ -81,10 +81,10 @@ public class LockscreenWallpaper extends IWallpaperManagerCallback.Stub implemen public LockscreenWallpaper(WallpaperManager wallpaperManager, @Nullable IWallpaperManager iWallpaperManager, KeyguardUpdateMonitor keyguardUpdateMonitor, - DumpController dumpController, + DumpManager dumpManager, NotificationMediaManager mediaManager, @Main Handler mainHandler) { - dumpController.registerDumpable(getClass().getSimpleName(), this); + dumpManager.registerDumpable(getClass().getSimpleName(), this); mWallpaperManager = wallpaperManager; mCurrentUserId = ActivityManager.getCurrentUser(); mUpdateMonitor = keyguardUpdateMonitor; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java index 2dd42c20a78b..75f5023ce48a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java @@ -40,10 +40,10 @@ import android.view.ViewGroup; import android.view.WindowManager; import android.view.WindowManager.LayoutParams; -import com.android.systemui.DumpController; import com.android.systemui.Dumpable; import com.android.systemui.R; import com.android.systemui.colorextraction.SysuiColorExtractor; +import com.android.systemui.dump.DumpManager; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener; @@ -103,7 +103,7 @@ public class NotificationShadeWindowController implements Callback, Dumpable, StatusBarStateController statusBarStateController, ConfigurationController configurationController, KeyguardBypassController keyguardBypassController, SysuiColorExtractor colorExtractor, - DumpController dumpController) { + DumpManager dumpManager) { mContext = context; mWindowManager = windowManager; mActivityManager = activityManager; @@ -113,7 +113,7 @@ public class NotificationShadeWindowController implements Callback, Dumpable, mLpChanged = new LayoutParams(); mKeyguardBypassController = keyguardBypassController; mColorExtractor = colorExtractor; - dumpController.registerDumpable(this); + dumpManager.registerDumpable(getClass().getName(), this); mLockScreenDisplayTimeout = context.getResources() .getInteger(R.integer.config_lockScreenDisplayTimeout); diff --git a/packages/SystemUI/src/com/android/systemui/tracing/ProtoTracer.java b/packages/SystemUI/src/com/android/systemui/tracing/ProtoTracer.java index 3bef044a2526..25ae09840600 100644 --- a/packages/SystemUI/src/com/android/systemui/tracing/ProtoTracer.java +++ b/packages/SystemUI/src/com/android/systemui/tracing/ProtoTracer.java @@ -24,14 +24,14 @@ import android.os.SystemClock; import androidx.annotation.NonNull; -import com.android.systemui.DumpController; import com.android.systemui.Dumpable; +import com.android.systemui.dump.DumpManager; import com.android.systemui.shared.tracing.FrameProtoTracer; import com.android.systemui.shared.tracing.FrameProtoTracer.ProtoTraceParams; import com.android.systemui.shared.tracing.ProtoTraceable; -import com.android.systemui.tracing.nano.SystemUiTraceProto; import com.android.systemui.tracing.nano.SystemUiTraceEntryProto; import com.android.systemui.tracing.nano.SystemUiTraceFileProto; +import com.android.systemui.tracing.nano.SystemUiTraceProto; import com.google.protobuf.nano.MessageNano; @@ -59,10 +59,10 @@ public class ProtoTracer implements Dumpable, ProtoTraceParams<MessageNano, Syst SystemUiTraceProto> mProtoTracer; @Inject - public ProtoTracer(Context context, DumpController dumpController) { + public ProtoTracer(Context context, DumpManager dumpManager) { mContext = context; mProtoTracer = new FrameProtoTracer<>(this); - dumpController.registerDumpable(this); + dumpManager.registerDumpable(getClass().getName(), this); } @Override diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index 6a0939630bf2..6d614af95bac 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -62,9 +62,9 @@ import android.testing.TestableContext; import android.testing.TestableLooper; import com.android.internal.telephony.TelephonyIntents; -import com.android.systemui.DumpController; import com.android.systemui.SysuiTestCase; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dump.DumpManager; import com.android.systemui.statusbar.phone.KeyguardBypassController; import org.junit.Assert; @@ -96,7 +96,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { DATA_ROAMING_DISABLE, null, null, null, null, false, null, "", true, TEST_GROUP_UUID, TEST_CARRIER_ID, 0); @Mock - private DumpController mDumpController; + private DumpManager mDumpManager; @Mock private KeyguardUpdateMonitor.StrongAuthTracker mStrongAuthTracker; @Mock @@ -612,7 +612,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { protected TestableKeyguardUpdateMonitor(Context context) { super(context, TestableLooper.get(KeyguardUpdateMonitorTest.this).getLooper(), - mBroadcastDispatcher, mDumpController, mBackgroundExecutor); + mBroadcastDispatcher, mDumpManager, mBackgroundExecutor); mStrongAuthTracker = KeyguardUpdateMonitorTest.this.mStrongAuthTracker; } diff --git a/packages/SystemUI/tests/src/com/android/systemui/BootCompleteCacheTest.kt b/packages/SystemUI/tests/src/com/android/systemui/BootCompleteCacheTest.kt index 6e79157eb582..2551650c47d0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/BootCompleteCacheTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/BootCompleteCacheTest.kt @@ -18,12 +18,14 @@ package com.android.systemui import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest +import com.android.systemui.dump.DumpManager import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock +import org.mockito.Mockito.mock import org.mockito.Mockito.never import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations @@ -35,14 +37,12 @@ class BootCompleteCacheTest : SysuiTestCase() { private lateinit var bootCompleteCache: BootCompleteCacheImpl @Mock private lateinit var bootCompleteListener: BootCompleteCache.BootCompleteListener - @Mock - private lateinit var dumpController: DumpController @Before fun setUp() { MockitoAnnotations.initMocks(this) - bootCompleteCache = BootCompleteCacheImpl(dumpController) + bootCompleteCache = BootCompleteCacheImpl(mock(DumpManager::class.java)) } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java b/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java index bf2d4cd07165..475ddc1ea11a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/DependencyTest.java @@ -15,29 +15,20 @@ package com.android.systemui; import static org.junit.Assert.assertEquals; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; import android.os.Looper; import androidx.test.filters.SmallTest; -import com.android.systemui.Dependency.DependencyKey; import com.android.systemui.statusbar.policy.FlashlightController; import org.junit.Assert; import org.junit.Test; -import java.io.FileDescriptor; -import java.io.PrintWriter; - @SmallTest public class DependencyTest extends SysuiTestCase { - public static final DependencyKey<Dumpable> DUMPABLE = new DependencyKey<>("dumpable"); - @Test public void testClassDependency() { FlashlightController f = mock(FlashlightController.class); @@ -53,17 +44,6 @@ public class DependencyTest extends SysuiTestCase { } @Test - public void testDump() { - Dumpable d = mock(Dumpable.class); - String[] args = new String[0]; - FileDescriptor fd = mock(FileDescriptor.class); - mDependency.injectTestDependency(DUMPABLE, d); - Dependency.get(DUMPABLE); - mDependency.dump(fd, mock(PrintWriter.class), args); - verify(d).dump(eq(fd), any(), eq(args)); - } - - @Test public void testInitDependency() { Dependency.clearDependencies(); Dependency dependency = new Dependency(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/DumpControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/DumpControllerTest.kt deleted file mode 100644 index d921d5832a01..000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/DumpControllerTest.kt +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.systemui - -import android.testing.AndroidTestingRunner -import androidx.test.filters.SmallTest -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import org.mockito.ArgumentMatchers.any -import org.mockito.Mock -import org.mockito.Mockito.never -import org.mockito.Mockito.verify -import org.mockito.MockitoAnnotations -import java.io.FileDescriptor -import java.io.PrintWriter - -@RunWith(AndroidTestingRunner::class) -@SmallTest -class DumpControllerTest : SysuiTestCase() { - - private lateinit var controller: DumpController - @Mock private lateinit var callback1: Dumpable - @Mock private lateinit var callback2: Dumpable - @Mock private lateinit var callback3: Dumpable - @Mock private lateinit var fd: FileDescriptor - @Mock private lateinit var pw: PrintWriter - private val args = emptyArray<String>() - - @Before - fun setUp() { - MockitoAnnotations.initMocks(this) - - controller = DumpController() - } - - @Test(expected = IllegalArgumentException::class) - fun testListenerOnlyAddedOnce() { - controller.registerDumpable("cb1", callback1) - controller.registerDumpable("cb1", callback2) - } - - @Test - fun testListenersCalledOnDump() { - controller.apply { - registerDumpable("cb1", callback1) - registerDumpable("cb2", callback2) - } - - controller.dump(fd, pw, args) - - verify(callback1 /* only once */).dump(fd, pw, args) - verify(callback2 /* only once */).dump(fd, pw, args) - } - - @Test - fun testListenersAreFiltered() { - controller.apply { - registerDumpable("cb1", callback1) - registerDumpable("cb2", callback2) - registerDumpable("cb3", callback3) - } - - val args = arrayOf("dependency", "DumpController", "cb3,cb1") - controller.dump(fd, pw, args) - - verify(callback1 /* only once */).dump(fd, pw, args) - verify(callback2, never()).dump(fd, pw, args) - verify(callback3 /* only once */).dump(fd, pw, args) - } - - @Test - fun testFiltersAreNotCaseSensitive() { - controller.apply { - registerDumpable("cb1", callback1) - registerDumpable("cb2", callback2) - registerDumpable("cb3", callback3) - } - - val args = arrayOf("dependency", "DumpController", "CB3") - controller.dump(fd, pw, args) - - verify(callback1, never()).dump(fd, pw, args) - verify(callback2, never()).dump(fd, pw, args) - verify(callback3 /* only once */).dump(fd, pw, args) - } - - @Test - fun testFiltersAreIgnoredIfPrecedingArgsDontMatch() { - controller.apply { - registerDumpable("cb1", callback1) - registerDumpable("cb2", callback2) - registerDumpable("cb3", callback3) - } - - val args = arrayOf("", "", "cb2") - controller.dump(fd, pw, args) - - verify(callback1 /* only once */).dump(fd, pw, args) - verify(callback2 /* only once */).dump(fd, pw, args) - verify(callback3 /* only once */).dump(fd, pw, args) - } - - @Test - fun testRemoveListener() { - controller.apply { - registerDumpable("cb1", callback1) - registerDumpable("cb2", callback2) - unregisterDumpable(callback1) - } - - controller.dump(fd, pw, args) - - verify(callback1, never()).dump(any(), any(), any()) - verify(callback2 /* only once */).dump(fd, pw, args) - } -} diff --git a/packages/SystemUI/tests/src/com/android/systemui/TestableDependency.java b/packages/SystemUI/tests/src/com/android/systemui/TestableDependency.java index b3071f957fdb..a7f4fa5768b4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/TestableDependency.java +++ b/packages/SystemUI/tests/src/com/android/systemui/TestableDependency.java @@ -60,6 +60,11 @@ public class TestableDependency extends Dependency { return super.createDependency(key); } + @Override + protected boolean autoRegisterModulesForDump() { + return false; + } + public <T> boolean hasInstantiatedDependency(Class<T> key) { return mObjs.containsKey(key) || mInstantiatedObjects.contains(key); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java index e5ae1aacc771..d973bb12071a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java @@ -39,8 +39,8 @@ import android.testing.TestableLooper; import androidx.test.filters.SmallTest; -import com.android.systemui.DumpController; import com.android.systemui.SysuiTestCase; +import com.android.systemui.dump.DumpManager; import org.junit.Before; import org.junit.Test; @@ -67,7 +67,7 @@ public class AppOpsControllerTest extends SysuiTestCase { @Mock private AppOpsControllerImpl.H mMockHandler; @Mock - private DumpController mDumpController; + private DumpManager mDumpManager; private AppOpsControllerImpl mController; private TestableLooper mTestableLooper; @@ -84,7 +84,7 @@ public class AppOpsControllerTest extends SysuiTestCase { getContext().setMockPackageManager(mPackageManager); mController = - new AppOpsControllerImpl(mContext, mTestableLooper.getLooper(), mDumpController); + new AppOpsControllerImpl(mContext, mTestableLooper.getLooper(), mDumpManager); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleBehaviorControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleBehaviorControllerTest.java index f832b7bf769f..731101cb7329 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleBehaviorControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleBehaviorControllerTest.java @@ -23,6 +23,7 @@ import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; @@ -37,8 +38,8 @@ import androidx.test.filters.SmallTest; import com.android.internal.app.AssistUtils; import com.android.internal.config.sysui.SystemUiDeviceConfigFlags; -import com.android.systemui.DumpController; import com.android.systemui.SysuiTestCase; +import com.android.systemui.dump.DumpManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.recents.OverviewProxyService; import com.android.systemui.statusbar.phone.NavigationModeController; @@ -71,7 +72,6 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase { @Mock private AssistHandleReminderExpBehavior mMockReminderExpBehavior; @Mock private AssistHandleBehaviorController.BehaviorController mMockTestBehavior; @Mock private NavigationModeController mMockNavigationModeController; - @Mock private DumpController mMockDumpController; @Mock private AssistHandleViewController mMockAssistHandleViewController; @Before @@ -79,7 +79,6 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase { MockitoAnnotations.initMocks(this); mDependency.injectMockDependency(StatusBarStateController.class); mDependency.injectMockDependency(OverviewProxyService.class); - mDependency.injectMockDependency(DumpController.class); doAnswer(answerVoid(Runnable::run)).when(mMockHandler).post(any(Runnable.class)); doAnswer(answerVoid(Runnable::run)).when(mMockHandler) .postDelayed(any(Runnable.class), anyLong()); @@ -100,7 +99,7 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase { mMockDeviceConfigHelper, behaviorMap, mMockNavigationModeController, - mMockDumpController); + mock(DumpManager.class)); } @After diff --git a/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt index 22b18373e81d..3357c5863d46 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt @@ -27,6 +27,7 @@ import android.test.suitebuilder.annotation.SmallTest import android.testing.AndroidTestingRunner import android.testing.TestableLooper import com.android.systemui.SysuiTestCase +import com.android.systemui.dump.DumpManager import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.time.FakeSystemClock import junit.framework.Assert.assertSame @@ -94,6 +95,7 @@ class BroadcastDispatcherTest : SysuiTestCase() { mockContext, Handler(testableLooper.looper), testableLooper.looper, + mock(DumpManager::class.java), mapOf(0 to mockUBRUser0, 1 to mockUBRUser1)) // These should be valid filters @@ -236,8 +238,9 @@ class BroadcastDispatcherTest : SysuiTestCase() { context: Context, mainHandler: Handler, bgLooper: Looper, + dumpManager: DumpManager, var mockUBRMap: Map<Int, UserBroadcastDispatcher> - ) : BroadcastDispatcher(context, mainHandler, bgLooper) { + ) : BroadcastDispatcher(context, mainHandler, bgLooper, dumpManager) { override fun createUBRForUser(userId: Int): UserBroadcastDispatcher { return mockUBRMap.getOrDefault(userId, mock(UserBroadcastDispatcher::class.java)) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java index 5e4f971f71c9..30095935aed5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java @@ -54,10 +54,10 @@ import android.view.WindowManager; import androidx.test.filters.SmallTest; import com.android.internal.colorextraction.ColorExtractor; -import com.android.systemui.DumpController; import com.android.systemui.SystemUIFactory; import com.android.systemui.SysuiTestCase; import com.android.systemui.colorextraction.SysuiColorExtractor; +import com.android.systemui.dump.DumpManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.NotificationLockscreenUserManager; @@ -169,7 +169,7 @@ public class BubbleControllerTest extends SysuiTestCase { @Mock private FeatureFlags mFeatureFlagsOldPipeline; @Mock - private DumpController mDumpController; + private DumpManager mDumpManager; private SuperStatusBarViewFactory mSuperStatusBarViewFactory; private BubbleData mBubbleData; @@ -204,7 +204,7 @@ public class BubbleControllerTest extends SysuiTestCase { mNotificationShadeWindowController = new NotificationShadeWindowController(mContext, mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController, mConfigurationController, mKeyguardBypassController, mColorExtractor, - mDumpController); + mDumpManager); mNotificationShadeWindowController.setNotificationShadeView( mSuperStatusBarViewFactory.getNotificationShadeWindowView()); mNotificationShadeWindowController.attach(); @@ -234,7 +234,8 @@ public class BubbleControllerTest extends SysuiTestCase { mock(NotificationInterruptionStateProvider.HeadsUpSuppressor.class)); mBubbleData = new BubbleData(mContext); when(mFeatureFlagsOldPipeline.isNewNotifPipelineRenderingEnabled()).thenReturn(false); - mBubbleController = new TestableBubbleController(mContext, + mBubbleController = new TestableBubbleController( + mContext, mNotificationShadeWindowController, mStatusBarStateController, mShadeController, @@ -247,7 +248,7 @@ public class BubbleControllerTest extends SysuiTestCase { mNotificationEntryManager, mNotifPipeline, mFeatureFlagsOldPipeline, - mDumpController, + mDumpManager, mFloatingContentCoordinator); mBubbleController.setBubbleStateChangeListener(mBubbleStateChangeListener); mBubbleController.setExpandListener(mBubbleExpandListener); diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java index 6677b80a2eac..1187ceed3780 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java @@ -50,10 +50,10 @@ import android.view.WindowManager; import androidx.test.filters.SmallTest; import com.android.internal.colorextraction.ColorExtractor; -import com.android.systemui.DumpController; import com.android.systemui.SystemUIFactory; import com.android.systemui.SysuiTestCase; import com.android.systemui.colorextraction.SysuiColorExtractor; +import com.android.systemui.dump.DumpManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.NotificationLockscreenUserManager; @@ -163,7 +163,7 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase { @Mock private FeatureFlags mFeatureFlagsNewPipeline; @Mock - private DumpController mDumpController; + private DumpManager mDumpManager; private SuperStatusBarViewFactory mSuperStatusBarViewFactory; private BubbleData mBubbleData; @@ -198,7 +198,7 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase { mNotificationShadeWindowController = new NotificationShadeWindowController(mContext, mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController, mConfigurationController, mKeyguardBypassController, mColorExtractor, - mDumpController); + mDumpManager); mNotificationShadeWindowController.setNotificationShadeView( mSuperStatusBarViewFactory.getNotificationShadeWindowView()); mNotificationShadeWindowController.attach(); @@ -223,7 +223,8 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase { mock(NotificationInterruptionStateProvider.HeadsUpSuppressor.class)); mBubbleData = new BubbleData(mContext); when(mFeatureFlagsNewPipeline.isNewNotifPipelineRenderingEnabled()).thenReturn(true); - mBubbleController = new TestableBubbleController(mContext, + mBubbleController = new TestableBubbleController( + mContext, mNotificationShadeWindowController, mStatusBarStateController, mShadeController, @@ -236,7 +237,7 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase { mNotificationEntryManager, mNotifPipeline, mFeatureFlagsNewPipeline, - mDumpController, + mDumpManager, mFloatingContentCoordinator); mBubbleController.addNotifCallback(mNotifCallback); mBubbleController.setBubbleStateChangeListener(mBubbleStateChangeListener); diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java index f9849f46d24d..de1fb41ddbbd 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/TestableBubbleController.java @@ -18,7 +18,7 @@ package com.android.systemui.bubbles; import android.content.Context; -import com.android.systemui.DumpController; +import com.android.systemui.dump.DumpManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.NotificationLockscreenUserManager; @@ -51,13 +51,13 @@ public class TestableBubbleController extends BubbleController { NotificationEntryManager entryManager, NotifPipeline notifPipeline, FeatureFlags featureFlags, - DumpController dumpController, + DumpManager dumpManager, FloatingContentCoordinator floatingContentCoordinator) { super(context, notificationShadeWindowController, statusBarStateController, shadeController, data, Runnable::run, configurationController, interruptionStateProvider, zenModeController, lockscreenUserManager, groupManager, entryManager, - notifPipeline, featureFlags, dumpController, floatingContentCoordinator); + notifPipeline, featureFlags, dumpManager, floatingContentCoordinator); setInflateSynchronously(true); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java index 7fb711f2af50..545d2d4229b3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingManagerProxyTest.java @@ -28,11 +28,11 @@ import android.util.DisplayMetrics; import androidx.test.filters.SmallTest; import com.android.keyguard.KeyguardUpdateMonitor; -import com.android.systemui.DumpController; import com.android.systemui.SysuiTestCase; import com.android.systemui.classifier.brightline.BrightLineFalsingManager; import com.android.systemui.dock.DockManager; import com.android.systemui.dock.DockManagerFake; +import com.android.systemui.dump.DumpManager; import com.android.systemui.shared.plugins.PluginManager; import com.android.systemui.util.DeviceConfigProxy; import com.android.systemui.util.DeviceConfigProxyFake; @@ -56,6 +56,7 @@ public class FalsingManagerProxyTest extends SysuiTestCase { ProximitySensor mProximitySensor; @Mock(stubOnly = true) private KeyguardUpdateMonitor mKeyguardUpdateMonitor; + @Mock DumpManager mDumpManager; private FalsingManagerProxy mProxy; private DeviceConfigProxy mDeviceConfig; private DisplayMetrics mDisplayMetrics = new DisplayMetrics(); @@ -82,7 +83,7 @@ public class FalsingManagerProxyTest extends SysuiTestCase { public void test_brightLineFalsingManagerDisabled() { mProxy = new FalsingManagerProxy(getContext(), mPluginManager, mExecutor, mDisplayMetrics, mProximitySensor, mDeviceConfig, mDockManager, mKeyguardUpdateMonitor, - new DumpController(), mUiBgExecutor); + mDumpManager, mUiBgExecutor); assertThat(mProxy.getInternalFalsingManager(), instanceOf(FalsingManagerImpl.class)); } @@ -93,7 +94,7 @@ public class FalsingManagerProxyTest extends SysuiTestCase { mExecutor.runAllReady(); mProxy = new FalsingManagerProxy(getContext(), mPluginManager, mExecutor, mDisplayMetrics, mProximitySensor, mDeviceConfig, mDockManager, mKeyguardUpdateMonitor, - new DumpController(), mUiBgExecutor); + mDumpManager, mUiBgExecutor); assertThat(mProxy.getInternalFalsingManager(), instanceOf(BrightLineFalsingManager.class)); } @@ -101,7 +102,7 @@ public class FalsingManagerProxyTest extends SysuiTestCase { public void test_brightLineFalsingManagerToggled() throws InterruptedException { mProxy = new FalsingManagerProxy(getContext(), mPluginManager, mExecutor, mDisplayMetrics, mProximitySensor, mDeviceConfig, mDockManager, mKeyguardUpdateMonitor, - new DumpController(), mUiBgExecutor); + mDumpManager, mUiBgExecutor); assertThat(mProxy.getInternalFalsingManager(), instanceOf(FalsingManagerImpl.class)); mDeviceConfig.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt index e5ec2dd88767..488e418f6152 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsControllerImplTest.kt @@ -29,12 +29,12 @@ import android.service.controls.DeviceTypes import android.service.controls.actions.ControlAction import android.testing.AndroidTestingRunner import androidx.test.filters.SmallTest -import com.android.systemui.DumpController import com.android.systemui.SysuiTestCase import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.controls.ControlStatus import com.android.systemui.controls.management.ControlsListingController import com.android.systemui.controls.ui.ControlsUiController +import com.android.systemui.dump.DumpManager import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.time.FakeSystemClock import org.junit.Assert.assertEquals @@ -67,8 +67,6 @@ class ControlsControllerImplTest : SysuiTestCase() { @Mock private lateinit var bindingController: ControlsBindingController @Mock - private lateinit var dumpController: DumpController - @Mock private lateinit var pendingIntent: PendingIntent @Mock private lateinit var persistenceWrapper: ControlsFavoritePersistenceWrapper @@ -136,7 +134,7 @@ class ControlsControllerImplTest : SysuiTestCase() { listingController, broadcastDispatcher, Optional.of(persistenceWrapper), - dumpController + mock(DumpManager::class.java) ) assertTrue(controller.available) verify(broadcastDispatcher).registerReceiver( @@ -169,7 +167,7 @@ class ControlsControllerImplTest : SysuiTestCase() { listingController, broadcastDispatcher, Optional.of(persistenceWrapper), - dumpController + mock(DumpManager::class.java) ) assertEquals(listOf(TEST_CONTROL_INFO), controller_other.getFavoriteControls()) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/dump/DumpManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/dump/DumpManagerTest.kt new file mode 100644 index 000000000000..8d530ec0ef0a --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/dump/DumpManagerTest.kt @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.dump + +import androidx.test.filters.SmallTest +import com.android.systemui.Dumpable +import com.android.systemui.SysuiTestCase +import com.android.systemui.log.LogBuffer +import com.android.systemui.util.mockito.any +import org.junit.Before +import org.junit.Test +import org.mockito.Mock +import org.mockito.Mockito.anyInt +import org.mockito.Mockito.never +import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations +import java.io.FileDescriptor +import java.io.PrintWriter + +@SmallTest +class DumpManagerTest : SysuiTestCase() { + + private lateinit var dumpManager: DumpManager + + @Mock + private lateinit var fd: FileDescriptor + @Mock + private lateinit var pw: PrintWriter + + @Mock + private lateinit var dumpable1: Dumpable + @Mock + private lateinit var dumpable2: Dumpable + @Mock + private lateinit var dumpable3: Dumpable + + @Mock + private lateinit var buffer1: LogBuffer + @Mock + private lateinit var buffer2: LogBuffer + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + + dumpManager = DumpManager(mContext) + } + + @Test + fun testDumpablesCanBeDumpedSelectively() { + // GIVEN a variety of registered dumpables and buffers + dumpManager.registerDumpable("dumpable1", dumpable1) + dumpManager.registerDumpable("dumpable2", dumpable2) + dumpManager.registerDumpable("dumpable3", dumpable3) + dumpManager.registerBuffer("buffer1", buffer1) + dumpManager.registerBuffer("buffer2", buffer2) + + // WHEN some of them are dumped explicitly + val args = arrayOf("dumpable1", "dumpable3", "buffer2") + dumpManager.dump(fd, pw, args) + + // THEN only the requested ones have their dump() method called + verify(dumpable1).dump(fd, pw, args) + verify(dumpable2, never()).dump( + any(FileDescriptor::class.java), + any(PrintWriter::class.java), + any(Array<String>::class.java)) + verify(dumpable3).dump(fd, pw, args) + verify(buffer1, never()).dump(any(PrintWriter::class.java), anyInt()) + verify(buffer2).dump(pw, 0) + } + + @Test + fun testDumpableMatchingIsBasedOnEndOfTag() { + // GIVEN a dumpable registered to the manager + dumpManager.registerDumpable("com.android.foo.bar.dumpable1", dumpable1) + + // WHEN that module is dumped + val args = arrayOf("dumpable1") + dumpManager.dump(fd, pw, args) + + // THEN its dump() method is called + verify(dumpable1).dump(fd, pw, args) + } + + @Test + fun testCriticalDump() { + // GIVEN a variety of registered dumpables and buffers + dumpManager.registerDumpable("dumpable1", dumpable1) + dumpManager.registerDumpable("dumpable2", dumpable2) + dumpManager.registerDumpable("dumpable3", dumpable3) + dumpManager.registerBuffer("buffer1", buffer1) + dumpManager.registerBuffer("buffer2", buffer2) + + // WHEN a critical dump is requested + val args = arrayOf("--dump-priority", "CRITICAL") + dumpManager.dump(fd, pw, args) + + // THEN all modules are dumped (but no buffers) + verify(dumpable1).dump(fd, pw, args) + verify(dumpable2).dump(fd, pw, args) + verify(dumpable3).dump(fd, pw, args) + verify(buffer1, never()).dump(any(PrintWriter::class.java), anyInt()) + verify(buffer2, never()).dump(any(PrintWriter::class.java), anyInt()) + } + + @Test + fun testNormalDump() { + // GIVEN a variety of registered dumpables and buffers + dumpManager.registerDumpable("dumpable1", dumpable1) + dumpManager.registerDumpable("dumpable2", dumpable2) + dumpManager.registerDumpable("dumpable3", dumpable3) + dumpManager.registerBuffer("buffer1", buffer1) + dumpManager.registerBuffer("buffer2", buffer2) + + // WHEN a critical dump is requested + val args = arrayOf("--dump-priority", "NORMAL") + dumpManager.dump(fd, pw, args) + + // THEN all buffers are dumped (but no modules) + verify(dumpable1, never()).dump( + any(FileDescriptor::class.java), + any(PrintWriter::class.java), + any(Array<String>::class.java)) + verify(dumpable2, never()).dump( + any(FileDescriptor::class.java), + any(PrintWriter::class.java), + any(Array<String>::class.java)) + verify(dumpable3, never()).dump( + any(FileDescriptor::class.java), + any(PrintWriter::class.java), + any(Array<String>::class.java)) + verify(buffer1).dump(pw, 0) + verify(buffer2).dump(pw, 0) + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java index 9a707caaaece..9ef5520ee711 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java @@ -38,10 +38,10 @@ import androidx.test.filters.SmallTest; import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardUpdateMonitor; -import com.android.systemui.DumpController; import com.android.systemui.SysuiTestCase; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.classifier.FalsingManagerFake; +import com.android.systemui.dump.DumpManager; import com.android.systemui.statusbar.phone.NotificationShadeWindowController; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; import com.android.systemui.util.concurrency.FakeExecutor; @@ -66,7 +66,7 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { private @Mock NotificationShadeWindowController mNotificationShadeWindowController; private @Mock BroadcastDispatcher mBroadcastDispatcher; private @Mock DismissCallbackRegistry mDismissCallbackRegistry; - private @Mock DumpController mDumpController; + private @Mock DumpManager mDumpManager; private @Mock PowerManager mPowerManager; private @Mock TrustManager mTrustManager; private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock()); @@ -84,7 +84,7 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { mViewMediator = new KeyguardViewMediator( mContext, mFalsingManager, mLockPatternUtils, mBroadcastDispatcher, mNotificationShadeWindowController, () -> mStatusBarKeyguardViewManager, - mDismissCallbackRegistry, mUpdateMonitor, mDumpController, mUiBgExecutor, + mDismissCallbackRegistry, mUpdateMonitor, mDumpManager, mUiBgExecutor, mPowerManager, mTrustManager); mViewMediator.start(); } @@ -98,7 +98,7 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { @Test public void testRegisterDumpable() { - verify(mDumpController).registerDumpable(eq(mViewMediator)); + verify(mDumpManager).registerDumpable(KeyguardViewMediator.class.getName(), mViewMediator); verify(mNotificationShadeWindowController, never()).setKeyguardGoingAway(anyBoolean()); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java index d66845837bb7..1f494a69f953 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java @@ -36,11 +36,11 @@ import androidx.test.filters.Suppress; import com.android.internal.logging.MetricsLogger; import com.android.keyguard.CarrierText; import com.android.systemui.Dependency; -import com.android.systemui.DumpController; import com.android.systemui.R; import com.android.systemui.SystemUIFactory; import com.android.systemui.SysuiBaseFragmentTest; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dump.DumpManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSFactoryImpl; @@ -104,7 +104,7 @@ public class QSFragmentTest extends SysuiBaseFragmentTest { QSTileHost host = new QSTileHost(mContext, mock(StatusBarIconController.class), mock(QSFactoryImpl.class), new Handler(), Looper.myLooper(), mock(PluginManager.class), mock(TunerService.class), - () -> mock(AutoTileManager.class), mock(DumpController.class), + () -> mock(AutoTileManager.class), mock(DumpManager.class), mock(BroadcastDispatcher.class), Optional.of(mock(StatusBar.class)), mock(QSLogger.class)); qs.setHost(host); diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java index b126d3643438..45c0cdd6bfd2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.java @@ -35,9 +35,9 @@ import androidx.test.filters.SmallTest; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; -import com.android.systemui.DumpController; import com.android.systemui.SysuiTestCase; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dump.DumpManager; import com.android.systemui.plugins.qs.QSTileView; import com.android.systemui.qs.customize.QSCustomizer; import com.android.systemui.qs.logging.QSLogger; @@ -71,7 +71,7 @@ public class QSPanelTest extends SysuiTestCase { @Mock private BroadcastDispatcher mBroadcastDispatcher; @Mock - private DumpController mDumpController; + private DumpManager mDumpManager; @Mock private QSLogger mQSLogger; private ViewGroup mParentView; @@ -87,7 +87,7 @@ public class QSPanelTest extends SysuiTestCase { mTestableLooper = TestableLooper.get(this); mTestableLooper.runWithLooper(() -> { mMetricsLogger = mDependency.injectMockDependency(MetricsLogger.class); - mQsPanel = new QSPanel(mContext, null, mDumpController, mBroadcastDispatcher, + mQsPanel = new QSPanel(mContext, null, mDumpManager, mBroadcastDispatcher, mQSLogger); // Provides a parent with non-zero size for QSPanel mParentView = new FrameLayout(mContext); diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java index d0c32ce92c55..36a9ea6de5aa 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java @@ -39,10 +39,10 @@ import android.testing.TestableLooper.RunWithLooper; import androidx.test.filters.SmallTest; import com.android.internal.util.CollectionUtils; -import com.android.systemui.DumpController; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dump.DumpManager; import com.android.systemui.plugins.qs.QSFactory; import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.qs.external.CustomTile; @@ -89,7 +89,7 @@ public class QSTileHostTest extends SysuiTestCase { @Mock private Provider<AutoTileManager> mAutoTiles; @Mock - private DumpController mDumpController; + private DumpManager mDumpManager; @Mock private BroadcastDispatcher mBroadcastDispatcher; @Mock @@ -111,7 +111,7 @@ public class QSTileHostTest extends SysuiTestCase { mLooper = TestableLooper.get(this); mHandler = new Handler(mLooper.getLooper()); mQSTileHost = new TestQSTileHost(mContext, mIconController, mDefaultFactory, mHandler, - mLooper.getLooper(), mPluginManager, mTunerService, mAutoTiles, mDumpController, + mLooper.getLooper(), mPluginManager, mTunerService, mAutoTiles, mDumpManager, mBroadcastDispatcher, mStatusBar, mQSLogger); setUpTileFactory(); Settings.Secure.putStringForUser(mContext.getContentResolver(), QSTileHost.TILES_SETTING, @@ -226,10 +226,10 @@ public class QSTileHostTest extends SysuiTestCase { TestQSTileHost(Context context, StatusBarIconController iconController, QSFactoryImpl defaultFactory, Handler mainHandler, Looper bgLooper, PluginManager pluginManager, TunerService tunerService, - Provider<AutoTileManager> autoTiles, DumpController dumpController, + Provider<AutoTileManager> autoTiles, DumpManager dumpManager, BroadcastDispatcher broadcastDispatcher, StatusBar statusBar, QSLogger qsLogger) { super(context, iconController, defaultFactory, mainHandler, bgLooper, pluginManager, - tunerService, autoTiles, dumpController, broadcastDispatcher, + tunerService, autoTiles, dumpManager, broadcastDispatcher, Optional.of(statusBar), qsLogger); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java index ab6b304033d0..884e4c0f5205 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java @@ -30,9 +30,9 @@ import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; -import com.android.systemui.DumpController; import com.android.systemui.SysuiTestCase; import com.android.systemui.broadcast.BroadcastDispatcher; +import com.android.systemui.dump.DumpManager; import com.android.systemui.qs.QSTileHost; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.qs.tileimpl.QSFactoryImpl; @@ -76,7 +76,7 @@ public class TileServicesTest extends SysuiTestCase { @Mock private AutoTileManager mAutoTileManager; @Mock - private DumpController mDumpController; + private DumpManager mDumpManager; @Mock private StatusBar mStatusBar; @Mock @@ -95,7 +95,7 @@ public class TileServicesTest extends SysuiTestCase { mPluginManager, mTunerService, () -> mAutoTileManager, - mDumpController, + mDumpManager, mBroadcastDispatcher, Optional.of(mStatusBar), mQSLogger); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/BlurUtilsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/BlurUtilsTest.kt index c180a889a7ec..f48d693e3bb1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/BlurUtilsTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/BlurUtilsTest.kt @@ -20,22 +20,22 @@ import android.content.res.Resources import android.view.SurfaceControl import android.view.ViewRootImpl import androidx.test.filters.SmallTest -import com.android.systemui.DumpController import com.android.systemui.SysuiTestCase +import com.android.systemui.dump.DumpManager import org.junit.Before import org.junit.Test import org.mockito.Mock +import org.mockito.Mockito.`when` import org.mockito.Mockito.eq import org.mockito.Mockito.mock import org.mockito.Mockito.verify -import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations @SmallTest class BlurUtilsTest : SysuiTestCase() { @Mock lateinit var resources: Resources - @Mock lateinit var dumpController: DumpController + @Mock lateinit var dumpManager: DumpManager @Mock lateinit var transaction: SurfaceControl.Transaction lateinit var blurUtils: BlurUtils @@ -70,7 +70,7 @@ class BlurUtilsTest : SysuiTestCase() { verify(transaction).apply() } - inner class TestableBlurUtils() : BlurUtils(resources, dumpController) { + inner class TestableBlurUtils() : BlurUtils(resources, dumpManager) { override fun supportsBlursOnWindows(): Boolean { return true } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java index 605b59ef3974..b7184be7d567 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java @@ -62,8 +62,8 @@ import androidx.test.filters.SmallTest; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.NotificationVisibility; -import com.android.systemui.DumpController; import com.android.systemui.SysuiTestCase; +import com.android.systemui.dump.DumpManager; import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.RankingBuilder; import com.android.systemui.statusbar.notification.collection.NoManSimulator.NotifEvent; @@ -135,7 +135,7 @@ public class NotifCollectionTest extends SysuiTestCase { mCollection = new NotifCollection( mStatusBarService, - mock(DumpController.class), + mock(DumpManager.class), mFeatureFlags, mLogger); mCollection.attach(mGroupCoalescer); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java index e570ab8d7f41..546fce851fd1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java @@ -39,8 +39,8 @@ import android.util.ArrayMap; import androidx.test.filters.SmallTest; -import com.android.systemui.DumpController; import com.android.systemui.SysuiTestCase; +import com.android.systemui.dump.DumpManager; import com.android.systemui.statusbar.notification.collection.ShadeListBuilder.OnRenderListListener; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeSortListener; @@ -102,7 +102,7 @@ public class ShadeListBuilderTest extends SysuiTestCase { MockitoAnnotations.initMocks(this); allowTestableLooperAsMainThread(); - mListBuilder = new ShadeListBuilder(mSystemClock, mLogger, mock(DumpController.class)); + mListBuilder = new ShadeListBuilder(mSystemClock, mLogger, mock(DumpManager.class)); mListBuilder.setOnRenderListListener(mOnRenderListListener); mListBuilder.attach(mNotifCollection); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java index 813923d44216..d8d6018651f8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java @@ -39,8 +39,8 @@ import android.testing.TestableResources; import com.android.internal.logging.MetricsLogger; import com.android.keyguard.KeyguardUpdateMonitor; -import com.android.systemui.DumpController; import com.android.systemui.SysuiTestCase; +import com.android.systemui.dump.DumpManager; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.policy.KeyguardStateController; @@ -57,7 +57,7 @@ import org.mockito.MockitoAnnotations; public class BiometricsUnlockControllerTest extends SysuiTestCase { @Mock - private DumpController mDumpController; + private DumpManager mDumpManager; @Mock private NotificationMediaManager mMediaManager; @Mock @@ -107,7 +107,7 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase { mKeyguardViewMediator, mScrimController, mStatusBar, mShadeController, mNotificationShadeWindowController, mKeyguardStateController, mHandler, mUpdateMonitor, res.getResources(), mKeyguardBypassController, mDozeParameters, - mMetricsLogger, mDumpController); + mMetricsLogger, mDumpManager); mBiometricUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerTest.java index 2782f3d793a0..83e89bdce2d5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerTest.java @@ -32,9 +32,9 @@ import android.view.WindowManager; import androidx.test.filters.SmallTest; import com.android.internal.colorextraction.ColorExtractor; -import com.android.systemui.DumpController; import com.android.systemui.SysuiTestCase; import com.android.systemui.colorextraction.SysuiColorExtractor; +import com.android.systemui.dump.DumpManager; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.policy.ConfigurationController; @@ -59,7 +59,7 @@ public class NotificationShadeWindowControllerTest extends SysuiTestCase { @Mock private KeyguardBypassController mKeyguardBypassController; @Mock private SysuiColorExtractor mColorExtractor; @Mock ColorExtractor.GradientColors mGradientColors; - @Mock private DumpController mDumpController; + @Mock private DumpManager mDumpManager; private NotificationShadeWindowController mNotificationShadeWindowController; @@ -72,7 +72,7 @@ public class NotificationShadeWindowControllerTest extends SysuiTestCase { mNotificationShadeWindowController = new NotificationShadeWindowController(mContext, mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController, mConfigurationController, mKeyguardBypassController, mColorExtractor, - mDumpController); + mDumpManager); mNotificationShadeWindowController.setNotificationShadeView(mNotificationShadeWindowView); mNotificationShadeWindowController.attach(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt b/packages/SystemUI/tests/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt new file mode 100644 index 000000000000..3f095c7900f3 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.util.mockito + +/** + * Kotlin versions of popular mockito methods that can return null in situations when Kotlin expects + * a non-null value. Kotlin will throw an IllegalStateException when this takes place ("x must not + * be null"). To fix this, we can use methods that modify the return type to be nullable. This + * causes Kotlin to skip the null checks. + */ + +import org.mockito.ArgumentCaptor +import org.mockito.Mockito + +/** + * Returns Mockito.eq() as nullable type to avoid java.lang.IllegalStateException when + * null is returned. + * + * Generic T is nullable because implicitly bounded by Any?. + */ +fun <T> eq(obj: T): T = Mockito.eq<T>(obj) + +/** + * Returns Mockito.any() as nullable type to avoid java.lang.IllegalStateException when + * null is returned. + * + * Generic T is nullable because implicitly bounded by Any?. + */ +fun <T> any(type: Class<T>): T = Mockito.any<T>(type) + +/** + * Returns ArgumentCaptor.capture() as nullable type to avoid java.lang.IllegalStateException + * when null is returned. + * + * Generic T is nullable because implicitly bounded by Any?. + */ +fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture() + +/** + * Helper function for creating an argumentCaptor in kotlin. + * + * Generic T is nullable because implicitly bounded by Any?. + */ +inline fun <reified T : Any> argumentCaptor(): ArgumentCaptor<T> = + ArgumentCaptor.forClass(T::class.java) |