[Ongoing Call Chip] Add analytics for when the chip becomes visible and
when the chip is clicked. Test: atest (+ new unit tests) and manual Bug: 183229367 Change-Id: Ib863dd8cfdda9e1cfa0d37cd145cecbb9cceb624
This commit is contained in:
@@ -61,6 +61,7 @@ import com.android.systemui.statusbar.phone.StatusBarIconController;
|
||||
import com.android.systemui.statusbar.phone.StatusBarIconControllerImpl;
|
||||
import com.android.systemui.statusbar.phone.StatusBarRemoteInputCallback;
|
||||
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
|
||||
import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallLogger;
|
||||
import com.android.systemui.statusbar.policy.RemoteInputUriController;
|
||||
import com.android.systemui.tracing.ProtoTracer;
|
||||
import com.android.systemui.util.DeviceConfigProxy;
|
||||
@@ -243,11 +244,12 @@ public interface StatusBarDependenciesModule {
|
||||
SystemClock systemClock,
|
||||
ActivityStarter activityStarter,
|
||||
@Main Executor mainExecutor,
|
||||
IActivityManager iActivityManager) {
|
||||
IActivityManager iActivityManager,
|
||||
OngoingCallLogger logger) {
|
||||
OngoingCallController ongoingCallController =
|
||||
new OngoingCallController(
|
||||
notifCollection, featureFlags, systemClock, activityStarter, mainExecutor,
|
||||
iActivityManager);
|
||||
iActivityManager, logger);
|
||||
ongoingCallController.init();
|
||||
return ongoingCallController;
|
||||
}
|
||||
|
||||
@@ -325,11 +325,13 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
|
||||
// Show the ongoing call chip only if there is an ongoing call *and* notification icons
|
||||
// are allowed. (The ongoing call chip occupies the same area as the notification icons,
|
||||
// so if the icons are disabled then the call chip should be, too.)
|
||||
if (hasOngoingCall && !disableNotifications) {
|
||||
boolean showOngoingCallChip = hasOngoingCall && !disableNotifications;
|
||||
if (showOngoingCallChip) {
|
||||
showOngoingCallChip(animate);
|
||||
} else {
|
||||
hideOngoingCallChip(animate);
|
||||
}
|
||||
mOngoingCallController.notifyChipVisibilityChanged(showOngoingCallChip);
|
||||
}
|
||||
|
||||
private boolean shouldHideNotificationIcons() {
|
||||
|
||||
@@ -49,7 +49,8 @@ class OngoingCallController @Inject constructor(
|
||||
private val systemClock: SystemClock,
|
||||
private val activityStarter: ActivityStarter,
|
||||
@Main private val mainExecutor: Executor,
|
||||
private val iActivityManager: IActivityManager
|
||||
private val iActivityManager: IActivityManager,
|
||||
private val logger: OngoingCallLogger
|
||||
) : CallbackController<OngoingCallListener> {
|
||||
|
||||
/** Null if there's no ongoing call. */
|
||||
@@ -104,7 +105,7 @@ class OngoingCallController @Inject constructor(
|
||||
/**
|
||||
* Sets the chip view that will contain ongoing call information.
|
||||
*
|
||||
* Should only be called from [CollapedStatusBarFragment].
|
||||
* Should only be called from [CollapsedStatusBarFragment].
|
||||
*/
|
||||
fun setChipView(chipView: ViewGroup) {
|
||||
this.chipView = chipView
|
||||
@@ -113,6 +114,16 @@ class OngoingCallController @Inject 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.
|
||||
*/
|
||||
@@ -150,6 +161,7 @@ class OngoingCallController @Inject constructor(
|
||||
timeView.start()
|
||||
|
||||
currentChipView.setOnClickListener {
|
||||
logger.logChipClicked()
|
||||
activityStarter.postStartActivityDismissingKeyguard(
|
||||
currentOngoingCallInfo.intent, 0,
|
||||
ActivityLaunchAnimator.Controller.fromView(it))
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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.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)
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,7 @@ import android.testing.TestableLooper
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.LinearLayout
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.internal.logging.testing.UiEventLoggerFake
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.plugins.ActivityStarter
|
||||
@@ -70,6 +71,7 @@ class OngoingCallControllerTest : SysuiTestCase() {
|
||||
|
||||
private val clock = FakeSystemClock()
|
||||
private val mainExecutor = FakeExecutor(clock)
|
||||
private val uiEventLoggerFake = UiEventLoggerFake()
|
||||
|
||||
private lateinit var controller: OngoingCallController
|
||||
private lateinit var notifCollectionListener: NotifCollectionListener
|
||||
@@ -99,7 +101,8 @@ class OngoingCallControllerTest : SysuiTestCase() {
|
||||
clock,
|
||||
mockActivityStarter,
|
||||
mainExecutor,
|
||||
mockIActivityManager)
|
||||
mockIActivityManager,
|
||||
OngoingCallLogger(uiEventLoggerFake))
|
||||
controller.init()
|
||||
controller.addCallback(mockOngoingCallListener)
|
||||
controller.setChipView(chipView)
|
||||
@@ -256,6 +259,28 @@ class OngoingCallControllerTest : SysuiTestCase() {
|
||||
.onOngoingCallStateChanged(anyBoolean())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun chipClicked_clickEventLogged() {
|
||||
notifCollectionListener.onEntryUpdated(createOngoingCallNotifEntry())
|
||||
|
||||
chipView.performClick()
|
||||
|
||||
assertThat(uiEventLoggerFake.numLogs()).isEqualTo(1)
|
||||
assertThat(uiEventLoggerFake.eventId(0))
|
||||
.isEqualTo(OngoingCallLogger.OngoingCallEvents.ONGOING_CALL_CLICKED.id)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun notifyChipVisibilityChanged_visibleEventLogged() {
|
||||
controller.notifyChipVisibilityChanged(true)
|
||||
|
||||
assertThat(uiEventLoggerFake.numLogs()).isEqualTo(1)
|
||||
assertThat(uiEventLoggerFake.eventId(0))
|
||||
.isEqualTo(OngoingCallLogger.OngoingCallEvents.ONGOING_CALL_VISIBLE.id)
|
||||
}
|
||||
// Other tests for notifyChipVisibilityChanged are in [OngoingCallLogger], since
|
||||
// [OngoingCallController.notifyChipVisibilityChanged] just delegates to that class.
|
||||
|
||||
private fun createOngoingCallNotifEntry(): NotificationEntry {
|
||||
val notificationEntryBuilder = NotificationEntryBuilder()
|
||||
notificationEntryBuilder.modifyNotification(context).style = ongoingCallStyle
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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.systemui.statusbar.phone.ongoingcall
|
||||
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.internal.logging.testing.UiEventLoggerFake
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.Test
|
||||
|
||||
@SmallTest
|
||||
class OngoingCallLoggerTest : SysuiTestCase() {
|
||||
private val uiEventLoggerFake = UiEventLoggerFake()
|
||||
private val ongoingCallLogger = OngoingCallLogger(uiEventLoggerFake)
|
||||
|
||||
@Test
|
||||
fun logChipClicked_clickEventLogged() {
|
||||
ongoingCallLogger.logChipClicked()
|
||||
|
||||
assertThat(uiEventLoggerFake.numLogs()).isEqualTo(1)
|
||||
assertThat(uiEventLoggerFake.eventId(0))
|
||||
.isEqualTo(OngoingCallLogger.OngoingCallEvents.ONGOING_CALL_CLICKED.id)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun logChipVisibilityChanged_changeFromInvisibleToVisible_visibleEventLogged() {
|
||||
ongoingCallLogger.logChipVisibilityChanged(false)
|
||||
ongoingCallLogger.logChipVisibilityChanged(true)
|
||||
|
||||
assertThat(uiEventLoggerFake.numLogs()).isEqualTo(1)
|
||||
assertThat(uiEventLoggerFake.eventId(0))
|
||||
.isEqualTo(OngoingCallLogger.OngoingCallEvents.ONGOING_CALL_VISIBLE.id)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun logChipVisibilityChanged_changeFromVisibleToInvisible_eventNotLogged() {
|
||||
// Setting the chip to visible here will trigger a log
|
||||
ongoingCallLogger.logChipVisibilityChanged(true)
|
||||
assertThat(uiEventLoggerFake.numLogs()).isEqualTo(1)
|
||||
|
||||
ongoingCallLogger.logChipVisibilityChanged(false)
|
||||
|
||||
// Expect that there were no new logs
|
||||
assertThat(uiEventLoggerFake.numLogs()).isEqualTo(1)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun logChipVisibilityChanged_visibleThenVisibleAgain_eventNotLogged() {
|
||||
// Setting the chip to visible here will trigger a log
|
||||
ongoingCallLogger.logChipVisibilityChanged(true)
|
||||
assertThat(uiEventLoggerFake.numLogs()).isEqualTo(1)
|
||||
|
||||
ongoingCallLogger.logChipVisibilityChanged(true)
|
||||
|
||||
// Expect that there were no new logs
|
||||
assertThat(uiEventLoggerFake.numLogs()).isEqualTo(1)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user