From f28066d4a4aac394c21128005a470f250fac0e13 Mon Sep 17 00:00:00 2001 From: Ricky Niu Date: Tue, 29 Jun 2021 17:42:37 +0800 Subject: [PATCH] [Android Auto] Add USB UEVENT and broadcast intent history in dump_sys Record all USB Uevent and broadcast intent history in dumpsys. This will not be covered by other system log and kernel log. Test: Android Auto team checked Bug: 186495455 Signed-off-by: Ricky Niu Change-Id: I914969bd67c40f5f56218154521dd48681b6b1dd --- core/proto/android/service/usb.proto | 2 + .../android/server/usb/UsbDeviceLogger.java | 143 ++++++++++++++++++ .../android/server/usb/UsbDeviceManager.java | 10 ++ .../usb/UsbProfileGroupSettingsManager.java | 11 +- 4 files changed, 164 insertions(+), 2 deletions(-) create mode 100644 services/usb/java/com/android/server/usb/UsbDeviceLogger.java diff --git a/core/proto/android/service/usb.proto b/core/proto/android/service/usb.proto index 45f8c132fbf03..97097ff912199 100644 --- a/core/proto/android/service/usb.proto +++ b/core/proto/android/service/usb.proto @@ -72,6 +72,7 @@ message UsbHandlerProto { optional bool adb_enabled = 14; optional string kernel_state = 15; optional string kernel_function_list = 16; + optional string uevent = 17; } message UsbAccessoryProto { @@ -315,6 +316,7 @@ message UsbProfileGroupSettingsManagerProto { optional int32 parent_user_id = 1; repeated UsbSettingsDevicePreferenceProto device_preferences = 2; repeated UsbSettingsAccessoryPreferenceProto accessory_preferences = 3; + optional string intent = 4; } message UsbSettingsDevicePreferenceProto { diff --git a/services/usb/java/com/android/server/usb/UsbDeviceLogger.java b/services/usb/java/com/android/server/usb/UsbDeviceLogger.java new file mode 100644 index 0000000000000..fab00bcda9418 --- /dev/null +++ b/services/usb/java/com/android/server/usb/UsbDeviceLogger.java @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2021 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.server.usb; + +import android.util.Log; + +import com.android.internal.annotations.GuardedBy; +import com.android.internal.util.dump.DualDumpOutputStream; + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.LinkedList; + +/** +* Constructor UsbDeviceLogger class +*/ +public class UsbDeviceLogger { + private final Object mLock = new Object(); + + // ring buffer of events to log. + @GuardedBy("mLock") + private final LinkedList mEvents; + + private final String mTitle; + + // the maximum number of events to keep in log + private final int mMemSize; + + /** + * Constructor for Event class. + */ + public abstract static class Event { + // formatter for timestamps + private static final SimpleDateFormat sFormat = new SimpleDateFormat("MM-dd HH:mm:ss:SSS"); + + private final Calendar mCalendar; + + Event() { + mCalendar = Calendar.getInstance(); + } + + /** + * Convert event to String + * @return StringBuilder + */ + public String toString() { + return (new StringBuilder(String.format("%tm-%td %tH:%tM:%tS.%tL", + mCalendar, mCalendar, mCalendar, mCalendar, mCalendar, mCalendar))) + .append(" ").append(eventToString()).toString(); + } + + /** + * Causes the string message for the event to appear in the logcat. + * Here is an example of how to create a new event (a StringEvent), adding it to the logger + * (an instance of UsbDeviceLoggerr) while also making it show in the logcat: + *
+         *     myLogger.log(
+         *         (new StringEvent("something for logcat and logger")).printLog(MyClass.TAG) );
+         * 
+ * @param tag the tag for the android.util.Log.v + * @return the same instance of the event + */ + public Event printLog(String tag) { + Log.i(tag, eventToString()); + return this; + } + + /** + * Convert event to String. + * This method is only called when the logger history is about to the dumped, + * so this method is where expensive String conversions should be made, not when the Event + * subclass is created. + * Timestamp information will be automatically added, do not include it. + * @return a string representation of the event that occurred. + */ + public abstract String eventToString(); + } + + /** + * Constructor StringEvent class + */ + public static class StringEvent extends Event { + private final String mMsg; + + public StringEvent(String msg) { + mMsg = msg; + } + + @Override + public String eventToString() { + return mMsg; + } + } + + /** + * Constructor for logger. + * @param size the maximum number of events to keep in log + * @param title the string displayed before the recorded log + */ + public UsbDeviceLogger(int size, String title) { + mEvents = new LinkedList(); + mMemSize = size; + mTitle = title; + } + + /** + * Constructor for logger. + * @param evt the maximum number of events to keep in log + */ + public synchronized void log(Event evt) { + synchronized (mLock) { + if (mEvents.size() >= mMemSize) { + mEvents.removeFirst(); + } + mEvents.add(evt); + } + } + + /** + * Constructor for logger. + * @param dump the maximum number of events to keep in log + * @param id the category of events + */ + public synchronized void dump(DualDumpOutputStream dump, long id) { + dump.write("USB Event Log", id, mTitle); + for (Event evt : mEvents) { + dump.write("USB Event", id, evt.toString()); + } + } +} diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java index b9666437d829e..27aabb59ce764 100644 --- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java +++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java @@ -191,6 +191,8 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser */ private static final int ACCESSORY_HANDSHAKE_TIMEOUT = 10 * 1000; + private static final int DUMPSYS_LOG_BUFFER = 200; + private static final String BOOT_MODE_PROPERTY = "ro.bootmode"; private static final String ADB_NOTIFICATION_CHANNEL_ID_TV = "usbdevicemanager.adb.tv"; @@ -210,6 +212,8 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser private static Set sDenyInterfaces; private HashMap mControlFds; + private static UsbDeviceLogger sEventLogger; + static { sDenyInterfaces = new HashSet<>(); sDenyInterfaces.add(UsbConstants.USB_CLASS_AUDIO); @@ -232,9 +236,11 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser @Override public void onUEvent(UEventObserver.UEvent event) { if (DEBUG) Slog.v(TAG, "USB UEVENT: " + event.toString()); + sEventLogger.log(new UsbDeviceLogger.StringEvent("USB UEVENT: " + event.toString())); String state = event.get("USB_STATE"); String accessory = event.get("ACCESSORY"); + if (state != null) { mHandler.updateState(state); } else if ("GETPROTOCOL".equals(accessory)) { @@ -382,6 +388,8 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser mUEventObserver = new UsbUEventObserver(); mUEventObserver.startObserving(USB_STATE_MATCH); mUEventObserver.startObserving(ACCESSORY_START_MATCH); + + sEventLogger = new UsbDeviceLogger(DUMPSYS_LOG_BUFFER, "UsbDeviceManager activity"); } UsbProfileGroupSettingsManager getCurrentSettings() { @@ -814,6 +822,7 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser protected void sendStickyBroadcast(Intent intent) { mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); + sEventLogger.log(new UsbDeviceLogger.StringEvent("USB intent: " + intent)); } private void updateUsbFunctions() { @@ -2285,6 +2294,7 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser if (mHandler != null) { mHandler.dump(dump, "handler", UsbDeviceManagerProto.HANDLER); + sEventLogger.dump(dump, UsbHandlerProto.UEVENT); } dump.end(token); diff --git a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java index f638660540645..bb0c4e903ff80 100644 --- a/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java +++ b/services/usb/java/com/android/server/usb/UsbProfileGroupSettingsManager.java @@ -60,7 +60,6 @@ import android.util.Xml; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.Immutable; import com.android.internal.content.PackageMonitor; -import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.XmlUtils; import com.android.internal.util.dump.DualDumpOutputStream; @@ -75,7 +74,6 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.net.ProtocolException; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; @@ -86,6 +84,8 @@ class UsbProfileGroupSettingsManager { private static final String TAG = UsbProfileGroupSettingsManager.class.getSimpleName(); private static final boolean DEBUG = false; + private static final int DUMPSYS_LOG_BUFFER = 200; + /** Legacy settings file, before multi-user */ private static final File sSingleUserSettingsFile = new File( "/data/system/usb_device_manager.xml"); @@ -130,6 +130,8 @@ class UsbProfileGroupSettingsManager { @GuardedBy("mLock") private boolean mIsWriteSettingsScheduled; + private static UsbDeviceLogger sEventLogger; + /** * A package of a user. */ @@ -260,6 +262,9 @@ class UsbProfileGroupSettingsManager { device, false /* showMtpNotification */)); mUsbHandlerManager = usbResolveActivityManager; + + sEventLogger = new UsbDeviceLogger(DUMPSYS_LOG_BUFFER, + "UsbProfileGroupSettingsManager activity"); } /** @@ -965,6 +970,7 @@ class UsbProfileGroupSettingsManager { matches, mAccessoryPreferenceMap.get(new AccessoryFilter(accessory))); } + sEventLogger.log(new UsbDeviceLogger.StringEvent("accessoryAttached: " + intent)); resolveActivity(intent, matches, defaultActivity, null, accessory); } @@ -1518,6 +1524,7 @@ class UsbProfileGroupSettingsManager { } } + sEventLogger.dump(dump, UsbProfileGroupSettingsManagerProto.INTENT); dump.end(token); }