Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e58e0c6e authored by Raff Tsai's avatar Raff Tsai
Browse files

Log contextual card is visible and homepage is displayed event

Bug: 79698338
Test: Robolectric
Change-Id: I89ac5ed2765729d8571e84d3a050f0aa07385caa
parent e4128eca
Loading
Loading
Loading
Loading
+31 −6
Original line number Diff line number Diff line
@@ -16,8 +16,10 @@

package com.android.settings.homepage.contextualcards;

import android.annotation.NonNull;
import android.content.Context;
import android.content.Intent;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;

@@ -25,6 +27,7 @@ import androidx.annotation.VisibleForTesting;
import androidx.slice.widget.EventInfo;

import com.android.settings.R;
import com.android.settings.intelligence.ContextualCardProto.ContextualCardList;

import java.util.List;

@@ -38,10 +41,6 @@ public class ContextualCardFeatureProviderImpl implements ContextualCardFeatureP
    // Contextual card shows, log card name and rank
    private static final int CONTEXTUAL_CARD_SHOW = 39;

    // Contextual card is eligible to be shown, but doesn't rank high
    // enough, log card name and score
    private static final int CONTEXTUAL_CARD_NOT_SHOW = 40;

    // Contextual card is dismissed, log card name
    private static final int CONTEXTUAL_CARD_DISMISS = 41;

@@ -67,6 +66,11 @@ public class ContextualCardFeatureProviderImpl implements ContextualCardFeatureP
    // log type
    private static final String EXTRA_CONTEXTUALCARD_ACTION_TYPE = "type";

    // displayed contextual cards
    private static final String EXTRA_CONTEXTUALCARD_VISIBLE = "visible";

    // hidden contextual cards
    private static final String EXTRA_CONTEXTUALCARD_HIDDEN = "hidden";

    // Contextual card tap target
    private static final int TARGET_DEFAULT = 0;
@@ -82,6 +86,10 @@ public class ContextualCardFeatureProviderImpl implements ContextualCardFeatureP

    @Override
    public void logHomepageDisplay(Context context, Long latency) {
        final Intent intent = new Intent();
        intent.putExtra(EXTRA_CONTEXTUALCARD_ACTION_TYPE, CONTEXTUAL_HOME_SHOW);
        intent.putExtra(EXTRA_LATENCY, latency);
        sendBroadcast(context, intent);
    }

    @Override
@@ -94,8 +102,13 @@ public class ContextualCardFeatureProviderImpl implements ContextualCardFeatureP
    }

    @Override
    public void logContextualCardDisplay(Context context, List<ContextualCard> showCards,
    public void logContextualCardDisplay(Context context, List<ContextualCard> visibleCards,
            List<ContextualCard> hiddenCards) {
        final Intent intent = new Intent();
        intent.putExtra(EXTRA_CONTEXTUALCARD_ACTION_TYPE, CONTEXTUAL_CARD_SHOW);
        intent.putExtra(EXTRA_CONTEXTUALCARD_VISIBLE, serialize(visibleCards));
        intent.putExtra(EXTRA_CONTEXTUALCARD_HIDDEN, serialize(hiddenCards));
        sendBroadcast(context, intent);
    }

    @Override
@@ -116,7 +129,7 @@ public class ContextualCardFeatureProviderImpl implements ContextualCardFeatureP
        final String action = context.getString(R.string.config_settingsintelligence_log_action);
        if (!TextUtils.isEmpty(action)) {
            intent.setAction(action);
            context.sendBroadcast(intent);
            context.sendBroadcastAsUser(intent, UserHandle.ALL);
        }
    }

@@ -133,4 +146,16 @@ public class ContextualCardFeatureProviderImpl implements ContextualCardFeatureP
                return TARGET_DEFAULT;
        }
    }

    @VisibleForTesting
    @NonNull
    byte[] serialize(List<ContextualCard> cards) {
        final ContextualCardList.Builder builder = ContextualCardList.newBuilder();
        cards.stream().forEach(card -> builder.addCard(
                com.android.settings.intelligence.ContextualCardProto.ContextualCard.newBuilder()
                        .setSliceUri(card.getSliceUri().toString())
                        .setCardName(card.getName())
                        .build()));
        return builder.build().toByteArray();
    }
}
+43 −17
Original line number Diff line number Diff line
@@ -20,6 +20,9 @@ import static android.app.slice.Slice.HINT_ERROR;

import static androidx.slice.widget.SliceLiveData.SUPPORTED_SPECS;

import static com.android.settings.slices.CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI;
import static com.android.settings.slices.CustomSliceRegistry.WIFI_SLICE_URI;

import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.Context;
@@ -34,7 +37,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.slice.Slice;

import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.utils.AsyncLoaderCompat;

import java.util.ArrayList;
@@ -103,27 +106,50 @@ public class ContextualCardLoader extends AsyncLoaderCompat<List<ContextualCard>
        return getFinalDisplayableCards(result);
    }

    // Get final displayed cards and log what cards will be displayed/hidden
    @VisibleForTesting
    List<ContextualCard> getFinalDisplayableCards(List<ContextualCard> candidates) {
        List<ContextualCard> eligibleCards = filterEligibleCards(candidates);
        eligibleCards = eligibleCards.stream().limit(DEFAULT_CARD_COUNT).collect(
                Collectors.toList());
        final List<ContextualCard> eligibleCards = filterEligibleCards(candidates);
        final List<ContextualCard> visibleCards = new ArrayList<>();
        final List<ContextualCard> hiddenCards = new ArrayList<>();

        final int size = eligibleCards.size();
        for (int i = 0; i < size; i++) {
            if (i < DEFAULT_CARD_COUNT) {
                visibleCards.add(eligibleCards.get(i));
            } else {
                hiddenCards.add(eligibleCards.get(i));
            }
        }

        if (eligibleCards.size() <= 2 || getNumberOfLargeCard(eligibleCards) == 0) {
            return eligibleCards;
        try {
            // The maximum cards are four small cards OR
            // one large card with two small cards OR
            // two large cards
            if (visibleCards.size() <= 2 || getNumberOfLargeCard(visibleCards) == 0) {
                // four small cards
                return visibleCards;
            }

        if (eligibleCards.size() == DEFAULT_CARD_COUNT) {
            eligibleCards.remove(eligibleCards.size() - 1);
            if (visibleCards.size() == DEFAULT_CARD_COUNT) {
                hiddenCards.add(visibleCards.remove(visibleCards.size() - 1));
            }

        if (getNumberOfLargeCard(eligibleCards) == 1) {
            return eligibleCards;
            if (getNumberOfLargeCard(visibleCards) == 1) {
                // One large card with two small cards
                return visibleCards;
            }

        eligibleCards.remove(eligibleCards.size() - 1);
            hiddenCards.add(visibleCards.remove(visibleCards.size() - 1));

        return eligibleCards;
            // Two large cards
            return visibleCards;
        } finally {
            final ContextualCardFeatureProvider contextualCardFeatureProvider =
                    FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider();
            contextualCardFeatureProvider.logContextualCardDisplay(mContext, visibleCards,
                    hiddenCards);
        }
    }

    @VisibleForTesting
@@ -169,8 +195,8 @@ public class ContextualCardLoader extends AsyncLoaderCompat<List<ContextualCard>

    private int getNumberOfLargeCard(List<ContextualCard> cards) {
        return (int) cards.stream()
                .filter(card -> card.getSliceUri().equals(CustomSliceRegistry.WIFI_SLICE_URI)
                        || card.getSliceUri().equals(CustomSliceRegistry.CONNECTED_DEVICE_SLICE_URI))
                .filter(card -> card.getSliceUri().equals(WIFI_SLICE_URI)
                        || card.getSliceUri().equals(CONNECTED_DEVICE_SLICE_URI))
                .count();
    }

+8 −2
Original line number Diff line number Diff line
@@ -16,8 +16,7 @@

package com.android.settings.homepage.contextualcards;

import static com.android.settings.homepage.contextualcards.ContextualCardLoader
        .CARD_CONTENT_LOADER_ID;
import static com.android.settings.homepage.contextualcards.ContextualCardLoader.CARD_CONTENT_LOADER_ID;

import static java.util.stream.Collectors.groupingBy;

@@ -33,6 +32,7 @@ import androidx.annotation.VisibleForTesting;
import androidx.loader.app.LoaderManager;
import androidx.loader.content.Loader;

import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;

@@ -72,6 +72,7 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo
    private final List<LifecycleObserver> mLifecycleObservers;

    private ContextualCardUpdateListener mListener;
    private long mStartTime;

    public ContextualCardManager(Context context, Lifecycle lifecycle) {
        mContext = context;
@@ -86,6 +87,7 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo
    }

    void loadContextualCards(ContextualCardsFragment fragment) {
        mStartTime = System.currentTimeMillis();
        final CardContentLoaderCallbacks cardContentLoaderCallbacks =
                new CardContentLoaderCallbacks(mContext);
        cardContentLoaderCallbacks.setListener(this);
@@ -168,6 +170,10 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo
    @Override
    public void onFinishCardLoading(List<ContextualCard> cards) {
        onContextualCardUpdated(cards.stream().collect(groupingBy(ContextualCard::getCardType)));
        final long elapsedTime = System.currentTimeMillis() - mStartTime;
        final ContextualCardFeatureProvider contextualCardFeatureProvider =
                FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider();
        contextualCardFeatureProvider.logHomepageDisplay(mContext, elapsedTime);
    }

    public ControllerRendererPool getControllerRendererPool() {
+43 −2
Original line number Diff line number Diff line
@@ -16,13 +16,20 @@

package com.android.settings.homepage.contextualcards;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;

import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.UserHandle;

import com.android.settings.intelligence.ContextualCardProto.ContextualCardList;
import com.android.settings.testutils.SettingsRobolectricTestRunner;

import org.junit.Before;
@@ -31,6 +38,9 @@ import org.junit.runner.RunWith;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;

import java.util.ArrayList;
import java.util.List;

@RunWith(SettingsRobolectricTestRunner.class)
public class ContextualCardFeatureProviderImplTest {

@@ -48,7 +58,7 @@ public class ContextualCardFeatureProviderImplTest {
        final Intent intent = new Intent();
        mImpl.sendBroadcast(mContext, intent);

        verify(mContext, never()).sendBroadcast(intent);
        verify(mContext, never()).sendBroadcastAsUser(intent, UserHandle.ALL);
    }

    @Test
@@ -57,6 +67,37 @@ public class ContextualCardFeatureProviderImplTest {
        final Intent intent = new Intent();
        mImpl.sendBroadcast(mContext, intent);

        verify(mContext).sendBroadcast(intent);
        verify(mContext).sendBroadcastAsUser(intent, UserHandle.ALL);
    }

    @Test
    @Config(qualifiers = "mcc999")
    public void logContextualCardDisplay_hasAction_sendBroadcast() {
        mImpl.logContextualCardDisplay(mContext, new ArrayList<>(), new ArrayList<>());

        verify(mContext).sendBroadcastAsUser(any(Intent.class), any());
    }

    @Test
    public void serialize_hasSizeTwo_returnSizeTwo() {
        final List<ContextualCard> cards = new ArrayList<>();
        cards.add(new ContextualCard.Builder()
                .setName("name1")
                .setSliceUri(Uri.parse("uri1"))
                .build());
        cards.add(new ContextualCard.Builder()
                .setName("name2")
                .setSliceUri(Uri.parse("uri2"))
                .build());


        final byte[] data = mImpl.serialize(cards);

        try {
            assertThat(ContextualCardList
                    .parseFrom(data).getCardCount()).isEqualTo(cards.size());
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }
}
 No newline at end of file