diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java index 32f505ecf00..74ff6134dcf 100644 --- a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java +++ b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java @@ -20,6 +20,7 @@ import static com.android.settings.slices.CustomSliceRegistry.BLUETOOTH_DEVICES_ import static com.android.settings.slices.CustomSliceRegistry.CONTEXTUAL_NOTIFICATION_CHANNEL_SLICE_URI; import static com.android.settings.slices.CustomSliceRegistry.CONTEXTUAL_WIFI_SLICE_URI; +import android.app.settings.SettingsEnums; import android.content.Context; import android.database.ContentObserver; import android.database.Cursor; @@ -32,7 +33,9 @@ import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import com.android.settings.R; +import com.android.settings.homepage.contextualcards.logging.ContextualCardLogUtils; import com.android.settings.overlay.FeatureFactory; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import com.android.settingslib.utils.AsyncLoaderCompat; import java.util.ArrayList; @@ -162,10 +165,16 @@ public class ContextualCardLoader extends AsyncLoaderCompat return visibleCards; } finally { if (!CardContentProvider.DELETE_CARD_URI.equals(mNotifyUri)) { - final ContextualCardFeatureProvider contextualCardFeatureProvider = - FeatureFactory.getFactory(mContext) - .getContextualCardFeatureProvider(mContext); - contextualCardFeatureProvider.logContextualCardDisplay(visibleCards, hiddenCards); + final MetricsFeatureProvider metricsFeatureProvider = + FeatureFactory.getFactory(mContext).getMetricsFeatureProvider(); + + metricsFeatureProvider.action(mContext, + SettingsEnums.ACTION_CONTEXTUAL_CARD_SHOW, + ContextualCardLogUtils.buildCardListLog(visibleCards)); + + metricsFeatureProvider.action(mContext, + SettingsEnums.ACTION_CONTEXTUAL_CARD_NOT_SHOW, + ContextualCardLogUtils.buildCardListLog(hiddenCards)); } } } diff --git a/src/com/android/settings/homepage/contextualcards/logging/ContextualCardLogUtils.java b/src/com/android/settings/homepage/contextualcards/logging/ContextualCardLogUtils.java new file mode 100644 index 00000000000..585eca3db6b --- /dev/null +++ b/src/com/android/settings/homepage/contextualcards/logging/ContextualCardLogUtils.java @@ -0,0 +1,263 @@ +/* + * Copyright (C) 2019 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.settings.homepage.contextualcards.logging; + +import android.util.Log; + +import androidx.slice.widget.EventInfo; + +import com.android.settings.homepage.contextualcards.ContextualCard; + +import java.util.ArrayList; +import java.util.List; + +/** + * Utils of building contextual card to string, and parse string back to {@link CardLog} + */ +public class ContextualCardLogUtils { + + private static final String TAG = "ContextualCardLogUtils"; + + private static final class TapTarget { + static int TARGET_DEFAULT = 0; + static int TARGET_TITLE = 1; + static int TARGET_TOGGLE = 2; + static int TARGET_SLIDER = 3; + } + + /** + * Log data for a general contextual card event + */ + public static class CardLog { + private final String mSliceUri; + private final double mRankingScore; + + public CardLog(Builder builder) { + mSliceUri = builder.mSliceUri; + mRankingScore = builder.mRankingScore; + } + + public String getSliceUri() { + return mSliceUri; + } + + public double getRankingScore() { + return mRankingScore; + } + + public static class Builder { + private String mSliceUri; + private double mRankingScore; + + public Builder setSliceUri(String sliceUri) { + mSliceUri = sliceUri; + return this; + } + + public Builder setRankingScore(double rankingScore) { + mRankingScore = rankingScore; + return this; + } + public CardLog build() { + return new CardLog(this); + } + } + } + + /** + * Log data for a contextual card click event + */ + public static class CardClickLog extends CardLog { + private final int mSliceRow; + private final int mSliceTapTarget; + private final int mUiPosition; + + public CardClickLog(Builder builder) { + super(builder); + mSliceRow = builder.mSliceRow; + mSliceTapTarget = builder.mSliceTapTarget; + mUiPosition = builder.mUiPosition; + } + + public int getSliceRow() { + return mSliceRow; + } + + public int getSliceTapTarget() { + return mSliceTapTarget; + } + + public int getUiPosition() { + return mUiPosition; + } + + public static class Builder extends CardLog.Builder { + private int mSliceRow; + private int mSliceTapTarget; + private int mUiPosition; + + public Builder setSliceRow(int sliceRow) { + mSliceRow = sliceRow; + return this; + } + + public Builder setSliceTapTarget(int sliceTapTarget) { + mSliceTapTarget = sliceTapTarget; + return this; + } + + public Builder setUiPosition(int uiPosition) { + mUiPosition = uiPosition; + return this; + } + @Override + public CardClickLog build() { + return new CardClickLog(this); + } + } + } + + /** + * Serialize {@link ContextualCard} click event to string + * + * @param card Clicked Contextual card. + * @param sliceRow A Slice can contains multiple row, which row are we clicked + * @param tapTarget Integer value of {@link TapTarget} + * @param uiPosition Contextual card position in Listview + */ + public static String buildCardClickLog(ContextualCard card, int sliceRow, int tapTarget, + int uiPosition) { + final StringBuilder log = new StringBuilder(); + log.append(card.getTextSliceUri()).append("|") + .append(card.getRankingScore()).append("|") + .append(sliceRow).append("|") + .append(actionTypeToTapTarget(tapTarget)).append("|") + .append(uiPosition); + return log.toString(); + } + + /** + * Parse string to a {@link CardClickLog} + */ + public static CardClickLog parseCardClickLog(String clickLog) { + if (clickLog != null) { + final String[] parts = clickLog.split("\\|"); + if (parts.length < 5) { + return null; + } + try { + final CardClickLog.Builder builder = new CardClickLog.Builder(); + builder.setSliceRow(Integer.parseInt(parts[2])) + .setSliceTapTarget(Integer.parseInt(parts[3])) + .setUiPosition(Integer.parseInt(parts[4])) + .setSliceUri(parts[0]) + .setRankingScore(Double.parseDouble(parts[1])); + return builder.build(); + } catch (Exception e) { + Log.e(TAG, "error parsing log", e); + return null; + } + } + return null; + } + + /** + * Serialize {@link ContextualCard} to string + * + * @param card Contextual card. + */ + public static String buildCardDismissLog(ContextualCard card) { + final StringBuilder log = new StringBuilder(); + log.append(card.getTextSliceUri()) + .append("|") + .append(card.getRankingScore()); + return log.toString(); + } + + /** + * Parse string to a {@link CardLog} + */ + public static CardLog parseCardDismissLog(String dismissLog) { + if (dismissLog != null) { + final String[] parts = dismissLog.split("\\|"); + if (parts.length < 2) { + return null; + } + try { + final CardLog.Builder builder = new CardLog.Builder(); + builder.setSliceUri(parts[0]) + .setRankingScore(Double.parseDouble(parts[1])); + return builder.build(); + } catch (Exception e) { + Log.e(TAG, "error parsing log", e); + return null; + } + } + return null; + } + + /** + * Serialize List of {@link ContextualCard} to string + */ + public static String buildCardListLog(List cards) { + final StringBuilder log = new StringBuilder(); + log.append(cards.size()); + for (ContextualCard card : cards) { + log.append("|").append(card.getTextSliceUri()) + .append("|").append(card.getRankingScore()); + } + return log.toString(); + } + + /** + * Parse string to a List of {@link CardLog} + */ + public static List parseCardListLog(String listLog) { + final List logList = new ArrayList<>(); + try { + final String[] parts = listLog.split("\\|"); + if (Integer.parseInt(parts[0]) < 0) { + return logList; + } + final int size = parts.length; + for (int i = 1; i < size; ) { + final CardLog.Builder builder = new CardLog.Builder(); + builder.setSliceUri(parts[i++]) + .setRankingScore(Double.parseDouble(parts[i++])); + logList.add(builder.build()); + } + } catch (Exception e) { + Log.e(TAG, "error parsing log", e); + return logList; + } + return logList; + } + + public static int actionTypeToTapTarget(int actionType) { + switch (actionType) { + case EventInfo.ACTION_TYPE_CONTENT: + return TapTarget.TARGET_TITLE; + case EventInfo.ACTION_TYPE_TOGGLE: + return TapTarget.TARGET_TOGGLE; + case EventInfo.ACTION_TYPE_SLIDER: + return TapTarget.TARGET_SLIDER; + default: + Log.w(TAG, "unknown type " + actionType); + return TapTarget.TARGET_DEFAULT; + } + } +} diff --git a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardController.java b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardController.java index 07e23de5cb6..05513771b8c 100644 --- a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardController.java +++ b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardController.java @@ -16,6 +16,7 @@ package com.android.settings.homepage.contextualcards.slices; +import android.app.settings.SettingsEnums; import android.content.Context; import android.content.Intent; import android.os.Build; @@ -27,10 +28,11 @@ import com.android.settings.R; import com.android.settings.homepage.contextualcards.CardDatabaseHelper; import com.android.settings.homepage.contextualcards.ContextualCard; import com.android.settings.homepage.contextualcards.ContextualCardController; -import com.android.settings.homepage.contextualcards.ContextualCardFeatureProvider; import com.android.settings.homepage.contextualcards.ContextualCardFeedbackDialog; +import com.android.settings.homepage.contextualcards.logging.ContextualCardLogUtils; import com.android.settings.homepage.contextualcards.ContextualCardUpdateListener; import com.android.settings.overlay.FeatureFactory; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import com.android.settingslib.utils.ThreadUtils; /** @@ -70,9 +72,13 @@ public class SliceContextualCardController implements ContextualCardController { dbHelper.markContextualCardAsDismissed(mContext, card.getName()); }); showFeedbackDialog(card); - final ContextualCardFeatureProvider contextualCardFeatureProvider = - FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider(mContext); - contextualCardFeatureProvider.logContextualCardDismiss(card); + + final MetricsFeatureProvider metricsFeatureProvider = + FeatureFactory.getFactory(mContext).getMetricsFeatureProvider(); + + metricsFeatureProvider.action(mContext, + SettingsEnums.ACTION_CONTEXTUAL_CARD_DISMISS, + ContextualCardLogUtils.buildCardDismissLog(card)); } @Override diff --git a/src/com/android/settings/homepage/contextualcards/slices/SliceDeferredSetupCardRendererHelper.java b/src/com/android/settings/homepage/contextualcards/slices/SliceDeferredSetupCardRendererHelper.java index 630839c1340..ea9e424cb38 100644 --- a/src/com/android/settings/homepage/contextualcards/slices/SliceDeferredSetupCardRendererHelper.java +++ b/src/com/android/settings/homepage/contextualcards/slices/SliceDeferredSetupCardRendererHelper.java @@ -17,6 +17,7 @@ package com.android.settings.homepage.contextualcards.slices; import android.app.PendingIntent; +import android.app.settings.SettingsEnums; import android.content.Context; import android.util.Log; import android.view.View; @@ -33,8 +34,9 @@ import androidx.slice.widget.EventInfo; import com.android.settings.R; import com.android.settings.homepage.contextualcards.ContextualCard; -import com.android.settings.homepage.contextualcards.ContextualCardFeatureProvider; +import com.android.settings.homepage.contextualcards.logging.ContextualCardLogUtils; import com.android.settings.overlay.FeatureFactory; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; /** * Card renderer helper for {@link ContextualCard} built as slice deferred setup card. @@ -65,10 +67,14 @@ class SliceDeferredSetupCardRendererHelper { } catch (PendingIntent.CanceledException e) { Log.w(TAG, "Failed to start intent " + primaryAction.getTitle()); } - final ContextualCardFeatureProvider contextualCardFeatureProvider = - FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider(mContext); - contextualCardFeatureProvider.logContextualCardClick(card, 0 /* row */, + final String log = ContextualCardLogUtils.buildCardClickLog(card, 0 /* row */, EventInfo.ACTION_TYPE_CONTENT, view.getAdapterPosition()); + + final MetricsFeatureProvider metricsFeatureProvider = + FeatureFactory.getFactory(mContext).getMetricsFeatureProvider(); + + metricsFeatureProvider.action(mContext, + SettingsEnums.ACTION_CONTEXTUAL_CARD_CLICK, log); }); } diff --git a/src/com/android/settings/homepage/contextualcards/slices/SliceFullCardRendererHelper.java b/src/com/android/settings/homepage/contextualcards/slices/SliceFullCardRendererHelper.java index bb58e6d077e..a9a83466496 100644 --- a/src/com/android/settings/homepage/contextualcards/slices/SliceFullCardRendererHelper.java +++ b/src/com/android/settings/homepage/contextualcards/slices/SliceFullCardRendererHelper.java @@ -16,6 +16,7 @@ package com.android.settings.homepage.contextualcards.slices; +import android.app.settings.SettingsEnums; import android.content.Context; import android.view.View; import android.widget.LinearLayout; @@ -26,8 +27,9 @@ import androidx.slice.widget.SliceView; import com.android.settings.R; import com.android.settings.homepage.contextualcards.ContextualCard; -import com.android.settings.homepage.contextualcards.ContextualCardFeatureProvider; +import com.android.settings.homepage.contextualcards.logging.ContextualCardLogUtils; import com.android.settings.overlay.FeatureFactory; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; /** * Card renderer helper for {@link ContextualCard} built as slice full card. @@ -54,11 +56,14 @@ class SliceFullCardRendererHelper { // Set this listener so we can log the interaction users make on the slice cardHolder.sliceView.setOnSliceActionListener( (eventInfo, sliceItem) -> { - final ContextualCardFeatureProvider contextualCardFeatureProvider = - FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider( - mContext); - contextualCardFeatureProvider.logContextualCardClick(card, eventInfo.rowIndex, + final String log = ContextualCardLogUtils.buildCardClickLog(card, eventInfo.rowIndex, eventInfo.actionType, cardHolder.getAdapterPosition()); + + final MetricsFeatureProvider metricsFeatureProvider = + FeatureFactory.getFactory(mContext).getMetricsFeatureProvider(); + + metricsFeatureProvider.action(mContext, + SettingsEnums.ACTION_CONTEXTUAL_CARD_CLICK, log); }); // Customize slice view for Settings diff --git a/src/com/android/settings/homepage/contextualcards/slices/SliceHalfCardRendererHelper.java b/src/com/android/settings/homepage/contextualcards/slices/SliceHalfCardRendererHelper.java index 6bb22087925..f7745423fb4 100644 --- a/src/com/android/settings/homepage/contextualcards/slices/SliceHalfCardRendererHelper.java +++ b/src/com/android/settings/homepage/contextualcards/slices/SliceHalfCardRendererHelper.java @@ -17,6 +17,7 @@ package com.android.settings.homepage.contextualcards.slices; import android.app.PendingIntent; +import android.app.settings.SettingsEnums; import android.content.Context; import android.util.Log; import android.view.View; @@ -32,8 +33,9 @@ import androidx.slice.widget.EventInfo; import com.android.settings.R; import com.android.settings.homepage.contextualcards.ContextualCard; -import com.android.settings.homepage.contextualcards.ContextualCardFeatureProvider; +import com.android.settings.homepage.contextualcards.logging.ContextualCardLogUtils; import com.android.settings.overlay.FeatureFactory; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; /** * Card renderer helper for {@link ContextualCard} built as slice half card. @@ -63,10 +65,14 @@ class SliceHalfCardRendererHelper { } catch (PendingIntent.CanceledException e) { Log.w(TAG, "Failed to start intent " + primaryAction.getTitle()); } - final ContextualCardFeatureProvider contextualCardFeatureProvider = - FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider(mContext); - contextualCardFeatureProvider.logContextualCardClick(card, 0 /* row */, + final String log = ContextualCardLogUtils.buildCardClickLog(card, 0 /* row */, EventInfo.ACTION_TYPE_CONTENT, view.getAdapterPosition()); + + final MetricsFeatureProvider metricsFeatureProvider = + FeatureFactory.getFactory(mContext).getMetricsFeatureProvider(); + + metricsFeatureProvider.action(mContext, + SettingsEnums.ACTION_CONTEXTUAL_CARD_CLICK, log); }); } diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java index 40e69391b4d..d3f64993251 100644 --- a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java +++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java @@ -22,12 +22,15 @@ import static com.android.settings.homepage.contextualcards.ContextualCardLoader import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; +import android.app.settings.SettingsEnums; import android.content.Context; import android.net.Uri; @@ -182,8 +185,10 @@ public class ContextualCardLoaderTest { mContextualCardLoader.getDisplayableCards(new ArrayList<>()); - verify(mFakeFeatureFactory.mContextualCardFeatureProvider).logContextualCardDisplay( - anyList(), anyList()); + verify(mFakeFeatureFactory.metricsFeatureProvider).action(any(), + eq(SettingsEnums.ACTION_CONTEXTUAL_CARD_SHOW), any(String.class)); + verify(mFakeFeatureFactory.metricsFeatureProvider).action(any(), + eq(SettingsEnums.ACTION_CONTEXTUAL_CARD_NOT_SHOW), any(String.class)); } @Test diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/logging/ContextualCardLogUtilsTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/logging/ContextualCardLogUtilsTest.java new file mode 100644 index 00000000000..5207315b3fa --- /dev/null +++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/logging/ContextualCardLogUtilsTest.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2018 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.settings.homepage.contextualcards.logging; + +import static com.google.common.truth.Truth.assertThat; + +import android.net.Uri; + +import com.android.settings.homepage.contextualcards.ContextualCard; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; + +import java.util.ArrayList; +import java.util.List; + +@RunWith(RobolectricTestRunner.class) +public class ContextualCardLogUtilsTest { + + private static final String TEST_URI = "content://test/test2"; + private static final double TEST_SCORE = 0.12345f; + + private static final ContextualCard TEST_CARD = + new ContextualCard.Builder() + .setSliceUri(Uri.parse(TEST_URI)) + .setRankingScore(TEST_SCORE) + .build(); + + @Test + public void parseCardDismissLog_notValid_returnNull() { + assertThat(ContextualCardLogUtils.parseCardDismissLog(TEST_URI + "|" + TEST_URI)).isNull(); + } + + @Test + public void parseCardDismissLog_isValid_returnCorrectData() { + final String log = ContextualCardLogUtils.buildCardDismissLog(TEST_CARD); + + final ContextualCardLogUtils.CardLog cardLog = ContextualCardLogUtils.parseCardDismissLog( + log); + + assertThat(cardLog.getSliceUri()).isEqualTo(TEST_URI); + assertThat(cardLog.getRankingScore()).isEqualTo(TEST_SCORE); + } + + @Test + public void parseCardClickLog_isValid_returnCorrectData() { + final int row = 1; + final int target = 2; + final int position = 3; + final String log = ContextualCardLogUtils.buildCardClickLog(TEST_CARD, row, target, + position); + + final ContextualCardLogUtils.CardClickLog cardClickLog = + ContextualCardLogUtils.parseCardClickLog(log); + + assertThat(cardClickLog.getSliceUri()).isEqualTo(TEST_URI); + assertThat(cardClickLog.getRankingScore()).isEqualTo(TEST_SCORE); + assertThat(cardClickLog.getSliceRow()).isEqualTo(row); + assertThat(cardClickLog.getSliceTapTarget()).isEqualTo( + ContextualCardLogUtils.actionTypeToTapTarget(target)); + assertThat(cardClickLog.getUiPosition()).isEqualTo(position); + } + + @Test + public void parseCardClickList_isValid_returnCorrectData() { + final ContextualCard testcard = + new ContextualCard.Builder() + .setSliceUri(Uri.parse("testtest")) + .setRankingScore(-1d) + .build(); + final List cardList = new ArrayList<>(); + cardList.add(TEST_CARD); + cardList.add(testcard); + final String log = ContextualCardLogUtils.buildCardListLog(cardList); + + final List cardClickLogList = + ContextualCardLogUtils.parseCardListLog(log); + + assertThat(cardClickLogList.size()).isEqualTo(2); + assertThat(cardClickLogList.get(0).getSliceUri()).isEqualTo(TEST_URI); + assertThat(cardClickLogList.get(0).getRankingScore()).isEqualTo(TEST_SCORE); + assertThat(cardClickLogList.get(1).getSliceUri()).isEqualTo("testtest"); + assertThat(cardClickLogList.get(1).getRankingScore()).isEqualTo(-1d); + } +} \ No newline at end of file diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardControllerTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardControllerTest.java index 94fbb978767..51d25237081 100644 --- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardControllerTest.java +++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardControllerTest.java @@ -18,13 +18,15 @@ package com.android.settings.homepage.contextualcards.slices; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.any; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; +import android.app.settings.SettingsEnums; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; @@ -96,7 +98,8 @@ public class SliceContextualCardControllerTest { cr.close(); assertThat(qryDismissed).isEqualTo(1); - verify(mFeatureFactory.mContextualCardFeatureProvider).logContextualCardDismiss(card); + verify(mFeatureFactory.metricsFeatureProvider).action(any(), + eq(SettingsEnums.ACTION_CONTEXTUAL_CARD_DISMISS), any(String.class)); } @Test