Loading packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt +14 −0 Original line number Diff line number Diff line Loading @@ -17,12 +17,17 @@ package com.android.systemui.statusbar.dagger import com.android.systemui.CoreStartable import com.android.systemui.dagger.SysUISingleton import com.android.systemui.log.LogBuffer import com.android.systemui.log.LogBufferFactory import com.android.systemui.statusbar.data.StatusBarDataLayerModule import com.android.systemui.statusbar.phone.LightBarController import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallLog import com.android.systemui.statusbar.ui.SystemBarUtilsProxyImpl import dagger.Binds import dagger.Module import dagger.Provides import dagger.multibindings.ClassKey import dagger.multibindings.IntoMap Loading @@ -45,4 +50,13 @@ abstract class StatusBarModule { @IntoMap @ClassKey(LightBarController::class) abstract fun bindLightBarController(impl: LightBarController): CoreStartable companion object { @Provides @SysUISingleton @OngoingCallLog fun provideOngoingCallLogBuffer(factory: LogBufferFactory): LogBuffer { return factory.create("OngoingCall", 75) } } } packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java +0 −3 Original line number Diff line number Diff line Loading @@ -661,9 +661,6 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue } else { hideOngoingActivityChip(animate); } if (!Flags.statusBarScreenSharingChips()) { mOngoingCallController.notifyChipVisibilityChanged(showOngoingActivityChip); } } private boolean shouldHideStatusBar() { Loading packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt +54 −28 Original line number Diff line number Diff line Loading @@ -23,7 +23,6 @@ import android.app.Notification.CallStyle.CALL_TYPE_ONGOING import android.app.PendingIntent import android.app.UidObserver import android.content.Context import android.util.Log import android.view.View import androidx.annotation.VisibleForTesting import com.android.internal.jank.InteractionJankMonitor Loading @@ -35,6 +34,8 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.dump.DumpManager import com.android.systemui.log.LogBuffer import com.android.systemui.log.core.LogLevel import com.android.systemui.plugins.ActivityStarter import com.android.systemui.res.R import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer Loading Loading @@ -68,11 +69,11 @@ constructor( private val activityStarter: ActivityStarter, @Main private val mainExecutor: Executor, private val iActivityManager: IActivityManager, private val logger: OngoingCallLogger, private val dumpManager: DumpManager, private val statusBarWindowController: StatusBarWindowController, private val swipeStatusBarAwayGestureHandler: SwipeStatusBarAwayGestureHandler, private val statusBarModeRepository: StatusBarModeRepositoryStore, @OngoingCallLog private val logger: LogBuffer, ) : CallbackController<OngoingCallListener>, Dumpable, CoreStartable { private var isFullscreen: Boolean = false /** Non-null if there's an active call notification. */ Loading Loading @@ -122,8 +123,20 @@ constructor( callNotificationInfo = newOngoingCallInfo if (newOngoingCallInfo.isOngoing) { logger.log( TAG, LogLevel.DEBUG, { str1 = newOngoingCallInfo.key }, { "Call notif *is* ongoing -> showing chip. key=$str1" }, ) updateChip() } else { logger.log( TAG, LogLevel.DEBUG, { str1 = newOngoingCallInfo.key }, { "Call notif not ongoing -> hiding chip. key=$str1" }, ) removeChip() } } Loading @@ -131,6 +144,12 @@ constructor( override fun onEntryRemoved(entry: NotificationEntry, reason: Int) { if (entry.sbn.key == callNotificationInfo?.key) { logger.log( TAG, LogLevel.DEBUG, { str1 = entry.sbn.key }, { "Call notif removed -> hiding chip. key=$str1" }, ) removeChip() } } Loading @@ -151,7 +170,8 @@ constructor( /** * Sets the chip view that will contain ongoing call information. * * Should only be called from [CollapsedStatusBarFragment]. * Should only be called from * [com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment]. */ fun setChipView(chipView: View) { tearDownChipView() Loading @@ -164,15 +184,6 @@ constructor( } } /** * Called when the chip's visibility may have changed. * * Should only be called from [CollapsedStatusBarFragment]. */ fun notifyChipVisibilityChanged(chipIsVisible: Boolean) { logger.logChipVisibilityChanged(chipIsVisible) } /** * Returns true if there's an active ongoing call that should be displayed in a status bar chip. */ Loading Loading @@ -250,16 +261,14 @@ constructor( // If we failed to update the chip, don't store the call info. Then [hasOngoingCall] // will return false and we fall back to typical notification handling. callNotificationInfo = null if (DEBUG) { Log.w( logger.log( TAG, "Ongoing call chip view could not be found; " + "Not displaying chip in status bar" LogLevel.WARNING, {}, { "Ongoing call chip view could not be found; Not displaying chip in status bar" }, ) } } } private fun updateChipClickListener() { if (Flags.statusBarScreenSharingChips()) { Loading @@ -275,7 +284,6 @@ constructor( val intent = callNotificationInfo?.intent if (currentChipView != null && backgroundView != null && intent != null) { currentChipView.setOnClickListener { logger.logChipClicked() activityStarter.postStartActivityDismissingKeyguard( intent, ActivityTransitionAnimator.Controller.fromView( Loading Loading @@ -333,9 +341,7 @@ constructor( * detected. */ private fun onSwipeAwayGestureDetected() { if (DEBUG) { Log.d(TAG, "Swipe away gesture detected") } logger.log(TAG, LogLevel.DEBUG, {}, { "Swipe away gesture detected" }) callNotificationInfo = callNotificationInfo?.copy(statusBarSwipedAway = true) statusBarWindowController.setOngoingProcessRequiresStatusBarVisible(false) swipeStatusBarAwayGestureHandler.removeOnGestureDetectedCallback(TAG) Loading Loading @@ -368,7 +374,10 @@ constructor( pw.println("Call app visible: ${uidObserver.isCallAppVisible}") } /** Our implementation of a [IUidObserver]. */ /** * Observer to tell us when the app that posted the ongoing call notification is visible so that * we don't show the call chip at the same time (since the timers could be out-of-sync). */ inner class CallAppUidObserver : UidObserver() { /** True if the application managing the call is visible to the user. */ var isCallAppVisible: Boolean = false Loading @@ -395,6 +404,12 @@ constructor( isProcessVisibleToUser( iActivityManager.getUidProcessState(uid, context.opPackageName) ) logger.log( TAG, LogLevel.DEBUG, { bool1 = isCallAppVisible }, { "On uid observer registration, isCallAppVisible=$bool1" }, ) if (isRegistered) { return } Loading @@ -406,7 +421,13 @@ constructor( ) isRegistered = true } catch (se: SecurityException) { Log.e(TAG, "Security exception when trying to set up uid observer: $se") logger.log( TAG, LogLevel.ERROR, {}, { "Security exception when trying to set up uid observer" }, se, ) } } Loading @@ -431,6 +452,12 @@ constructor( val oldIsCallAppVisible = isCallAppVisible isCallAppVisible = isProcessVisibleToUser(procState) if (oldIsCallAppVisible != isCallAppVisible) { logger.log( TAG, LogLevel.DEBUG, { bool1 = isCallAppVisible }, { "#onUidStateChanged. isCallAppVisible=$bool1" }, ) // Animations may be run as a result of the call's state change, so ensure // the listener is notified on the main thread. mainExecutor.execute { sendStateChangeEvent() } Loading @@ -443,5 +470,4 @@ private fun isCallNotification(entry: NotificationEntry): Boolean { return entry.sbn.notification.isStyle(Notification.CallStyle::class.java) } private const val TAG = "OngoingCallController" private val DEBUG = Log.isLoggable(TAG, Log.DEBUG) private const val TAG = OngoingCallRepository.TAG packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallLogger.kt→packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallLog.kt +27 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 The Android Open Source Project * Copyright (C) 2024 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. Loading @@ -16,43 +16,12 @@ package com.android.systemui.statusbar.phone.ongoingcall import androidx.annotation.VisibleForTesting import com.android.internal.logging.UiEvent import com.android.internal.logging.UiEventLogger import com.android.systemui.dagger.SysUISingleton import javax.inject.Inject /** A class to log events for the ongoing call chip. */ @SysUISingleton class OngoingCallLogger @Inject constructor(private val logger: UiEventLogger) { private var chipIsVisible: Boolean = false /** Logs that the ongoing call chip was clicked. */ fun logChipClicked() { logger.log(OngoingCallEvents.ONGOING_CALL_CLICKED) } import javax.inject.Qualifier /** * If needed, logs that the ongoing call chip's visibility has changed. * * For now, only logs when the chip changes from not visible to visible. * Logs for events related to ongoing call notifications and their corresponding status bar chip. */ fun logChipVisibilityChanged(chipIsVisible: Boolean) { if (chipIsVisible && chipIsVisible != this.chipIsVisible) { logger.log(OngoingCallEvents.ONGOING_CALL_VISIBLE) } this.chipIsVisible = chipIsVisible } @VisibleForTesting enum class OngoingCallEvents(val metricId: Int) : UiEventLogger.UiEventEnum { @UiEvent(doc = "The ongoing call chip became visible") ONGOING_CALL_VISIBLE(813), @UiEvent(doc = "The ongoing call chip was clicked") ONGOING_CALL_CLICKED(814); override fun getId() = metricId } } @Qualifier @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class OngoingCallLog packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/data/repository/OngoingCallRepository.kt +18 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,9 @@ package com.android.systemui.statusbar.phone.ongoingcall.data.repository import com.android.systemui.dagger.SysUISingleton import com.android.systemui.log.LogBuffer import com.android.systemui.log.core.LogLevel import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallLog import com.android.systemui.statusbar.phone.ongoingcall.shared.model.OngoingCallModel import javax.inject.Inject import kotlinx.coroutines.flow.MutableStateFlow Loading @@ -32,7 +35,11 @@ import kotlinx.coroutines.flow.asStateFlow * classes both refer to this repository. */ @SysUISingleton class OngoingCallRepository @Inject constructor() { class OngoingCallRepository @Inject constructor( @OngoingCallLog private val logger: LogBuffer, ) { private val _ongoingCallState = MutableStateFlow<OngoingCallModel>(OngoingCallModel.NoCall) /** The current ongoing call state. */ val ongoingCallState: StateFlow<OngoingCallModel> = _ongoingCallState.asStateFlow() Loading @@ -42,6 +49,16 @@ class OngoingCallRepository @Inject constructor() { * [com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController]. */ fun setOngoingCallState(state: OngoingCallModel) { logger.log( TAG, LogLevel.DEBUG, { str1 = state::class.simpleName }, { "Repo#setOngoingCallState: $str1" }, ) _ongoingCallState.value = state } companion object { const val TAG = "OngoingCall" } } Loading
packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt +14 −0 Original line number Diff line number Diff line Loading @@ -17,12 +17,17 @@ package com.android.systemui.statusbar.dagger import com.android.systemui.CoreStartable import com.android.systemui.dagger.SysUISingleton import com.android.systemui.log.LogBuffer import com.android.systemui.log.LogBufferFactory import com.android.systemui.statusbar.data.StatusBarDataLayerModule import com.android.systemui.statusbar.phone.LightBarController import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallLog import com.android.systemui.statusbar.ui.SystemBarUtilsProxyImpl import dagger.Binds import dagger.Module import dagger.Provides import dagger.multibindings.ClassKey import dagger.multibindings.IntoMap Loading @@ -45,4 +50,13 @@ abstract class StatusBarModule { @IntoMap @ClassKey(LightBarController::class) abstract fun bindLightBarController(impl: LightBarController): CoreStartable companion object { @Provides @SysUISingleton @OngoingCallLog fun provideOngoingCallLogBuffer(factory: LogBufferFactory): LogBuffer { return factory.create("OngoingCall", 75) } } }
packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java +0 −3 Original line number Diff line number Diff line Loading @@ -661,9 +661,6 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue } else { hideOngoingActivityChip(animate); } if (!Flags.statusBarScreenSharingChips()) { mOngoingCallController.notifyChipVisibilityChanged(showOngoingActivityChip); } } private boolean shouldHideStatusBar() { Loading
packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt +54 −28 Original line number Diff line number Diff line Loading @@ -23,7 +23,6 @@ import android.app.Notification.CallStyle.CALL_TYPE_ONGOING import android.app.PendingIntent import android.app.UidObserver import android.content.Context import android.util.Log import android.view.View import androidx.annotation.VisibleForTesting import com.android.internal.jank.InteractionJankMonitor Loading @@ -35,6 +34,8 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.dump.DumpManager import com.android.systemui.log.LogBuffer import com.android.systemui.log.core.LogLevel import com.android.systemui.plugins.ActivityStarter import com.android.systemui.res.R import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer Loading Loading @@ -68,11 +69,11 @@ constructor( private val activityStarter: ActivityStarter, @Main private val mainExecutor: Executor, private val iActivityManager: IActivityManager, private val logger: OngoingCallLogger, private val dumpManager: DumpManager, private val statusBarWindowController: StatusBarWindowController, private val swipeStatusBarAwayGestureHandler: SwipeStatusBarAwayGestureHandler, private val statusBarModeRepository: StatusBarModeRepositoryStore, @OngoingCallLog private val logger: LogBuffer, ) : CallbackController<OngoingCallListener>, Dumpable, CoreStartable { private var isFullscreen: Boolean = false /** Non-null if there's an active call notification. */ Loading Loading @@ -122,8 +123,20 @@ constructor( callNotificationInfo = newOngoingCallInfo if (newOngoingCallInfo.isOngoing) { logger.log( TAG, LogLevel.DEBUG, { str1 = newOngoingCallInfo.key }, { "Call notif *is* ongoing -> showing chip. key=$str1" }, ) updateChip() } else { logger.log( TAG, LogLevel.DEBUG, { str1 = newOngoingCallInfo.key }, { "Call notif not ongoing -> hiding chip. key=$str1" }, ) removeChip() } } Loading @@ -131,6 +144,12 @@ constructor( override fun onEntryRemoved(entry: NotificationEntry, reason: Int) { if (entry.sbn.key == callNotificationInfo?.key) { logger.log( TAG, LogLevel.DEBUG, { str1 = entry.sbn.key }, { "Call notif removed -> hiding chip. key=$str1" }, ) removeChip() } } Loading @@ -151,7 +170,8 @@ constructor( /** * Sets the chip view that will contain ongoing call information. * * Should only be called from [CollapsedStatusBarFragment]. * Should only be called from * [com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment]. */ fun setChipView(chipView: View) { tearDownChipView() Loading @@ -164,15 +184,6 @@ constructor( } } /** * Called when the chip's visibility may have changed. * * Should only be called from [CollapsedStatusBarFragment]. */ fun notifyChipVisibilityChanged(chipIsVisible: Boolean) { logger.logChipVisibilityChanged(chipIsVisible) } /** * Returns true if there's an active ongoing call that should be displayed in a status bar chip. */ Loading Loading @@ -250,16 +261,14 @@ constructor( // If we failed to update the chip, don't store the call info. Then [hasOngoingCall] // will return false and we fall back to typical notification handling. callNotificationInfo = null if (DEBUG) { Log.w( logger.log( TAG, "Ongoing call chip view could not be found; " + "Not displaying chip in status bar" LogLevel.WARNING, {}, { "Ongoing call chip view could not be found; Not displaying chip in status bar" }, ) } } } private fun updateChipClickListener() { if (Flags.statusBarScreenSharingChips()) { Loading @@ -275,7 +284,6 @@ constructor( val intent = callNotificationInfo?.intent if (currentChipView != null && backgroundView != null && intent != null) { currentChipView.setOnClickListener { logger.logChipClicked() activityStarter.postStartActivityDismissingKeyguard( intent, ActivityTransitionAnimator.Controller.fromView( Loading Loading @@ -333,9 +341,7 @@ constructor( * detected. */ private fun onSwipeAwayGestureDetected() { if (DEBUG) { Log.d(TAG, "Swipe away gesture detected") } logger.log(TAG, LogLevel.DEBUG, {}, { "Swipe away gesture detected" }) callNotificationInfo = callNotificationInfo?.copy(statusBarSwipedAway = true) statusBarWindowController.setOngoingProcessRequiresStatusBarVisible(false) swipeStatusBarAwayGestureHandler.removeOnGestureDetectedCallback(TAG) Loading Loading @@ -368,7 +374,10 @@ constructor( pw.println("Call app visible: ${uidObserver.isCallAppVisible}") } /** Our implementation of a [IUidObserver]. */ /** * Observer to tell us when the app that posted the ongoing call notification is visible so that * we don't show the call chip at the same time (since the timers could be out-of-sync). */ inner class CallAppUidObserver : UidObserver() { /** True if the application managing the call is visible to the user. */ var isCallAppVisible: Boolean = false Loading @@ -395,6 +404,12 @@ constructor( isProcessVisibleToUser( iActivityManager.getUidProcessState(uid, context.opPackageName) ) logger.log( TAG, LogLevel.DEBUG, { bool1 = isCallAppVisible }, { "On uid observer registration, isCallAppVisible=$bool1" }, ) if (isRegistered) { return } Loading @@ -406,7 +421,13 @@ constructor( ) isRegistered = true } catch (se: SecurityException) { Log.e(TAG, "Security exception when trying to set up uid observer: $se") logger.log( TAG, LogLevel.ERROR, {}, { "Security exception when trying to set up uid observer" }, se, ) } } Loading @@ -431,6 +452,12 @@ constructor( val oldIsCallAppVisible = isCallAppVisible isCallAppVisible = isProcessVisibleToUser(procState) if (oldIsCallAppVisible != isCallAppVisible) { logger.log( TAG, LogLevel.DEBUG, { bool1 = isCallAppVisible }, { "#onUidStateChanged. isCallAppVisible=$bool1" }, ) // Animations may be run as a result of the call's state change, so ensure // the listener is notified on the main thread. mainExecutor.execute { sendStateChangeEvent() } Loading @@ -443,5 +470,4 @@ private fun isCallNotification(entry: NotificationEntry): Boolean { return entry.sbn.notification.isStyle(Notification.CallStyle::class.java) } private const val TAG = "OngoingCallController" private val DEBUG = Log.isLoggable(TAG, Log.DEBUG) private const val TAG = OngoingCallRepository.TAG
packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallLogger.kt→packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallLog.kt +27 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 The Android Open Source Project * Copyright (C) 2024 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. Loading @@ -16,43 +16,12 @@ package com.android.systemui.statusbar.phone.ongoingcall import androidx.annotation.VisibleForTesting import com.android.internal.logging.UiEvent import com.android.internal.logging.UiEventLogger import com.android.systemui.dagger.SysUISingleton import javax.inject.Inject /** A class to log events for the ongoing call chip. */ @SysUISingleton class OngoingCallLogger @Inject constructor(private val logger: UiEventLogger) { private var chipIsVisible: Boolean = false /** Logs that the ongoing call chip was clicked. */ fun logChipClicked() { logger.log(OngoingCallEvents.ONGOING_CALL_CLICKED) } import javax.inject.Qualifier /** * If needed, logs that the ongoing call chip's visibility has changed. * * For now, only logs when the chip changes from not visible to visible. * Logs for events related to ongoing call notifications and their corresponding status bar chip. */ fun logChipVisibilityChanged(chipIsVisible: Boolean) { if (chipIsVisible && chipIsVisible != this.chipIsVisible) { logger.log(OngoingCallEvents.ONGOING_CALL_VISIBLE) } this.chipIsVisible = chipIsVisible } @VisibleForTesting enum class OngoingCallEvents(val metricId: Int) : UiEventLogger.UiEventEnum { @UiEvent(doc = "The ongoing call chip became visible") ONGOING_CALL_VISIBLE(813), @UiEvent(doc = "The ongoing call chip was clicked") ONGOING_CALL_CLICKED(814); override fun getId() = metricId } } @Qualifier @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class OngoingCallLog
packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/data/repository/OngoingCallRepository.kt +18 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,9 @@ package com.android.systemui.statusbar.phone.ongoingcall.data.repository import com.android.systemui.dagger.SysUISingleton import com.android.systemui.log.LogBuffer import com.android.systemui.log.core.LogLevel import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallLog import com.android.systemui.statusbar.phone.ongoingcall.shared.model.OngoingCallModel import javax.inject.Inject import kotlinx.coroutines.flow.MutableStateFlow Loading @@ -32,7 +35,11 @@ import kotlinx.coroutines.flow.asStateFlow * classes both refer to this repository. */ @SysUISingleton class OngoingCallRepository @Inject constructor() { class OngoingCallRepository @Inject constructor( @OngoingCallLog private val logger: LogBuffer, ) { private val _ongoingCallState = MutableStateFlow<OngoingCallModel>(OngoingCallModel.NoCall) /** The current ongoing call state. */ val ongoingCallState: StateFlow<OngoingCallModel> = _ongoingCallState.asStateFlow() Loading @@ -42,6 +49,16 @@ class OngoingCallRepository @Inject constructor() { * [com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController]. */ fun setOngoingCallState(state: OngoingCallModel) { logger.log( TAG, LogLevel.DEBUG, { str1 = state::class.simpleName }, { "Repo#setOngoingCallState: $str1" }, ) _ongoingCallState.value = state } companion object { const val TAG = "OngoingCall" } }