From c0326b01cee66d3ad962b041bc3319e7ec1beb99 Mon Sep 17 00:00:00 2001 From: Weilin Xu Date: Mon, 15 Aug 2022 18:09:52 +0000 Subject: [PATCH] Add event logger to BroadcastRadio Service Add LocalLog event logger to BroadcastRadio Service to dump event log and limit the maximum number of log for radio module and tuner session. Bug: 240327417 Test: m -j, atest android.hardware.radio.tests.functional Change-Id: Ibb3de53b169cb0e8dadb418c9a553e3e2ab51d6c Merged-In: Ibb3de53b169cb0e8dadb418c9a553e3e2ab51d6c (cherry picked from commit b724e39d713f62e3b4672a8e6c78ab2db5f6ce5a) --- .../broadcastradio/hal2/RadioEventLogger.java | 44 +++++++++++++++++++ .../broadcastradio/hal2/RadioModule.java | 18 +++++--- .../broadcastradio/hal2/TunerSession.java | 42 ++++++++---------- 3 files changed, 76 insertions(+), 28 deletions(-) create mode 100644 services/core/java/com/android/server/broadcastradio/hal2/RadioEventLogger.java diff --git a/services/core/java/com/android/server/broadcastradio/hal2/RadioEventLogger.java b/services/core/java/com/android/server/broadcastradio/hal2/RadioEventLogger.java new file mode 100644 index 0000000000000..48112c452f024 --- /dev/null +++ b/services/core/java/com/android/server/broadcastradio/hal2/RadioEventLogger.java @@ -0,0 +1,44 @@ +/** + * Copyright (C) 2022 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.broadcastradio.hal2; + +import android.util.IndentingPrintWriter; +import android.util.LocalLog; +import android.util.Log; +import android.util.Slog; + +final class RadioEventLogger { + private final String mTag; + private final LocalLog mEventLogger; + + RadioEventLogger(String tag, int loggerQueueSize) { + mTag = tag; + mEventLogger = new LocalLog(loggerQueueSize); + } + + void logRadioEvent(String logFormat, Object... args) { + String log = String.format(logFormat, args); + mEventLogger.log(log); + if (Log.isLoggable(mTag, Log.DEBUG)) { + Slog.d(mTag, log); + } + } + + void dump(IndentingPrintWriter pw) { + mEventLogger.dump(pw); + } +} diff --git a/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java b/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java index 852aa66866f0e..0a23e385d67a6 100644 --- a/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java +++ b/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java @@ -55,12 +55,14 @@ import java.util.stream.Collectors; class RadioModule { private static final String TAG = "BcRadio2Srv.module"; + private static final int RADIO_EVENT_LOGGER_QUEUE_SIZE = 25; @NonNull private final IBroadcastRadio mService; @NonNull public final RadioManager.ModuleProperties mProperties; private final Object mLock; @NonNull private final Handler mHandler; + @NonNull private final RadioEventLogger mEventLogger; @GuardedBy("mLock") private ITunerSession mHalTunerSession; @@ -138,6 +140,7 @@ class RadioModule { mService = Objects.requireNonNull(service); mLock = Objects.requireNonNull(lock); mHandler = new Handler(Looper.getMainLooper()); + mEventLogger = new RadioEventLogger(TAG, RADIO_EVENT_LOGGER_QUEUE_SIZE); } public static @Nullable RadioModule tryLoadingModule(int idx, @NonNull String fqName, @@ -176,13 +179,14 @@ class RadioModule { public @NonNull TunerSession openSession(@NonNull android.hardware.radio.ITunerCallback userCb) throws RemoteException { - Slog.i(TAG, "Open TunerSession"); + mEventLogger.logRadioEvent("Open TunerSession"); synchronized (mLock) { if (mHalTunerSession == null) { Mutable hwSession = new Mutable<>(); mService.openSession(mHalTunerCallback, (result, session) -> { Convert.throwOnError("openSession", result); hwSession.value = session; + mEventLogger.logRadioEvent("New HIDL 2.0 tuner session is opened"); }); mHalTunerSession = Objects.requireNonNull(hwSession.value); } @@ -207,7 +211,7 @@ class RadioModule { // Copy the contents of mAidlTunerSessions into a local array because TunerSession.close() // must be called without mAidlTunerSessions locked because it can call // onTunerSessionClosed(). - Slog.i(TAG, "Close TunerSessions"); + mEventLogger.logRadioEvent("Close TunerSessions"); TunerSession[] tunerSessions; synchronized (mLock) { tunerSessions = new TunerSession[mAidlTunerSessions.size()]; @@ -320,7 +324,7 @@ class RadioModule { } onTunerSessionProgramListFilterChanged(null); if (mAidlTunerSessions.isEmpty() && mHalTunerSession != null) { - Slog.i(TAG, "Closing HAL tuner session"); + mEventLogger.logRadioEvent("Closing HAL tuner session"); try { mHalTunerSession.close(); } catch (RemoteException ex) { @@ -372,7 +376,7 @@ class RadioModule { public android.hardware.radio.ICloseHandle addAnnouncementListener(@NonNull int[] enabledTypes, @NonNull android.hardware.radio.IAnnouncementListener listener) throws RemoteException { - Slog.i(TAG, "Add AnnouncementListener"); + mEventLogger.logRadioEvent("Add AnnouncementListener"); ArrayList enabledList = new ArrayList<>(); for (int type : enabledTypes) { enabledList.add((byte)type); @@ -409,7 +413,7 @@ class RadioModule { } Bitmap getImage(int id) { - Slog.i(TAG, "Get image for id " + id); + mEventLogger.logRadioEvent("Get image for id %d", id); if (id == 0) throw new IllegalArgumentException("Image ID is missing"); byte[] rawImage; @@ -449,6 +453,10 @@ class RadioModule { } pw.decreaseIndent(); } + pw.printf("Radio module events:\n"); + pw.increaseIndent(); + mEventLogger.dump(pw); + pw.decreaseIndent(); pw.decreaseIndent(); } } diff --git a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java index 41f753c112161..918dc98e3a9e7 100644 --- a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java +++ b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java @@ -28,7 +28,6 @@ import android.hardware.radio.ProgramSelector; import android.hardware.radio.RadioManager; import android.os.RemoteException; import android.util.IndentingPrintWriter; -import android.util.Log; import android.util.MutableBoolean; import android.util.MutableInt; import android.util.Slog; @@ -41,8 +40,10 @@ import java.util.Objects; class TunerSession extends ITuner.Stub { private static final String TAG = "BcRadio2Srv.session"; private static final String kAudioDeviceName = "Radio tuner source"; + private static final int TUNER_EVENT_LOGGER_QUEUE_SIZE = 25; private final Object mLock; + @NonNull private final RadioEventLogger mEventLogger; private final RadioModule mModule; private final ITunerSession mHwSession; @@ -61,15 +62,12 @@ class TunerSession extends ITuner.Stub { mHwSession = Objects.requireNonNull(hwSession); mCallback = Objects.requireNonNull(callback); mLock = Objects.requireNonNull(lock); - } - - private boolean isDebugEnabled() { - return Log.isLoggable(TAG, Log.DEBUG); + mEventLogger = new RadioEventLogger(TAG, TUNER_EVENT_LOGGER_QUEUE_SIZE); } @Override public void close() { - if (isDebugEnabled()) Slog.d(TAG, "Close"); + mEventLogger.logRadioEvent("Close"); close(null); } @@ -81,7 +79,7 @@ class TunerSession extends ITuner.Stub { * @param error Optional error to send to client before session is closed. */ public void close(@Nullable Integer error) { - if (isDebugEnabled()) Slog.d(TAG, "Close on error " + error); + mEventLogger.logRadioEvent("Close on error %d", error); synchronized (mLock) { if (mIsClosed) return; if (error != null) { @@ -145,10 +143,8 @@ class TunerSession extends ITuner.Stub { @Override public void step(boolean directionDown, boolean skipSubChannel) throws RemoteException { - if (isDebugEnabled()) { - Slog.d(TAG, "Step with directionDown " + directionDown - + " skipSubChannel " + skipSubChannel); - } + mEventLogger.logRadioEvent("Step with direction %s, skipSubChannel? %s", + directionDown ? "down" : "up", skipSubChannel ? "yes" : "no"); synchronized (mLock) { checkNotClosedLocked(); int halResult = mHwSession.step(!directionDown); @@ -158,10 +154,8 @@ class TunerSession extends ITuner.Stub { @Override public void scan(boolean directionDown, boolean skipSubChannel) throws RemoteException { - if (isDebugEnabled()) { - Slog.d(TAG, "Scan with directionDown " + directionDown - + " skipSubChannel " + skipSubChannel); - } + mEventLogger.logRadioEvent("Scan with direction %s, skipSubChannel? %s", + directionDown ? "down" : "up", skipSubChannel ? "yes" : "no"); synchronized (mLock) { checkNotClosedLocked(); int halResult = mHwSession.scan(!directionDown, skipSubChannel); @@ -171,7 +165,7 @@ class TunerSession extends ITuner.Stub { @Override public void tune(ProgramSelector selector) throws RemoteException { - if (isDebugEnabled()) Slog.d(TAG, "Tune with selector " + selector); + mEventLogger.logRadioEvent("Tune with selector %s", selector); synchronized (mLock) { checkNotClosedLocked(); int halResult = mHwSession.tune(Convert.programSelectorToHal(selector)); @@ -195,7 +189,7 @@ class TunerSession extends ITuner.Stub { @Override public Bitmap getImage(int id) { - if (isDebugEnabled()) Slog.d(TAG, "Get image for " + id); + mEventLogger.logRadioEvent("Get image for %d", id); return mModule.getImage(id); } @@ -208,7 +202,7 @@ class TunerSession extends ITuner.Stub { @Override public void startProgramListUpdates(ProgramList.Filter filter) throws RemoteException { - if (isDebugEnabled()) Slog.d(TAG, "start programList updates " + filter); + mEventLogger.logRadioEvent("start programList updates %s", filter); // If the AIDL client provides a null filter, it wants all updates, so use the most broad // filter. if (filter == null) { @@ -267,7 +261,7 @@ class TunerSession extends ITuner.Stub { @Override public void stopProgramListUpdates() throws RemoteException { - if (isDebugEnabled()) Slog.d(TAG, "Stop programList updates"); + mEventLogger.logRadioEvent("Stop programList updates"); synchronized (mLock) { checkNotClosedLocked(); mProgramInfoCache = null; @@ -291,7 +285,7 @@ class TunerSession extends ITuner.Stub { @Override public boolean isConfigFlagSet(int flag) { - if (isDebugEnabled()) Slog.d(TAG, "Is ConfigFlagSet for " + ConfigFlag.toString(flag)); + mEventLogger.logRadioEvent("Is ConfigFlagSet for %s", ConfigFlag.toString(flag)); synchronized (mLock) { checkNotClosedLocked(); @@ -313,9 +307,7 @@ class TunerSession extends ITuner.Stub { @Override public void setConfigFlag(int flag, boolean value) throws RemoteException { - if (isDebugEnabled()) { - Slog.d(TAG, "Set ConfigFlag " + ConfigFlag.toString(flag) + " = " + value); - } + mEventLogger.logRadioEvent("Set ConfigFlag %s = %b", ConfigFlag.toString(flag), value); synchronized (mLock) { checkNotClosedLocked(); int halResult = mHwSession.setConfigFlag(flag, value); @@ -351,6 +343,10 @@ class TunerSession extends ITuner.Stub { pw.printf("ProgramInfoCache: %s\n", mProgramInfoCache); pw.printf("Config: %s\n", mDummyConfig); } + pw.printf("Tuner session events:\n"); + pw.increaseIndent(); + mEventLogger.dump(pw); + pw.decreaseIndent(); pw.decreaseIndent(); } }