Merge "[Ongoing Call Chip] Add analytics for when the chip becomes visible and when the chip is clicked." into sc-dev

This commit is contained in:
Caitlin Cassidy
2021-05-12 19:01:36 +00:00
committed by Android (Google) Code Review
6 changed files with 177 additions and 6 deletions

View File

@@ -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;
}

View File

@@ -326,11 +326,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() {

View File

@@ -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))

View File

@@ -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
}
}

View File

@@ -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

View File

@@ -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)
}
}