Add log feature
- Add ContextualCardFeatureProvider to handle card interaction Bug: 79698338 Test: manual Change-Id: I2a76f5ccfd07072a98ee927bed7dc39731d4cb09
This commit is contained in:
@@ -151,6 +151,9 @@
|
|||||||
com.android.settings.intelligence
|
com.android.settings.intelligence
|
||||||
</string>
|
</string>
|
||||||
|
|
||||||
|
<!-- Settings intelligence interaction log intent action -->
|
||||||
|
<string name="config_settingsintelligence_log_action" translatable="false"></string>
|
||||||
|
|
||||||
<!-- Emergency app package name -->
|
<!-- Emergency app package name -->
|
||||||
<string name="config_emergency_package_name" translatable="false">
|
<string name="config_emergency_package_name" translatable="false">
|
||||||
com.android.emergency
|
com.android.emergency
|
||||||
|
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/** Feature provider for the contextual card feature. */
|
||||||
|
public interface ContextualCardFeatureProvider {
|
||||||
|
|
||||||
|
/** Homepage displays. */
|
||||||
|
public void logHomepageDisplay(Context context, Long latency);
|
||||||
|
|
||||||
|
/** When user clicks dismiss in contextual card */
|
||||||
|
public void logContextualCardDismiss(Context context, ContextualCard card);
|
||||||
|
|
||||||
|
/** After ContextualCardManager decides which cards will be displayed/hidden */
|
||||||
|
public void logContextualCardDisplay(Context context, List<ContextualCard> showedCards,
|
||||||
|
List<ContextualCard> hiddenCards);
|
||||||
|
|
||||||
|
/** When user clicks toggle/title area of a contextual card. */
|
||||||
|
public void logContextualCardClick(Context context, ContextualCard card, int row,
|
||||||
|
int tapTarget);
|
||||||
|
}
|
@@ -0,0 +1,136 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.VisibleForTesting;
|
||||||
|
import androidx.slice.widget.EventInfo;
|
||||||
|
|
||||||
|
import com.android.settings.R;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ContextualCardFeatureProviderImpl implements ContextualCardFeatureProvider {
|
||||||
|
private static final String TAG = "ContextualCardFeature";
|
||||||
|
|
||||||
|
// Contextual card interaction logs
|
||||||
|
// Settings Homepage shows
|
||||||
|
private static final int CONTEXTUAL_HOME_SHOW = 38;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
// Contextual card is clicked , log card name, score, tap area
|
||||||
|
private static final int CONTEXTUAL_CARD_CLICK = 42;
|
||||||
|
|
||||||
|
// SettingsLogBroadcastReceiver contracts
|
||||||
|
// contextual card name
|
||||||
|
private static final String EXTRA_CONTEXTUALCARD_NAME = "name";
|
||||||
|
|
||||||
|
// contextual card score
|
||||||
|
private static final String EXTRA_CONTEXTUALCARD_SCORE = "score";
|
||||||
|
|
||||||
|
// contextual card clicked row
|
||||||
|
private static final String EXTRA_CONTEXTUALCARD_ROW = "row";
|
||||||
|
|
||||||
|
// contextual card tap target
|
||||||
|
private static final String EXTRA_CONTEXTUALCARD_TAP_TARGET = "target";
|
||||||
|
|
||||||
|
// contextual homepage display latency
|
||||||
|
private static final String EXTRA_LATENCY = "latency";
|
||||||
|
|
||||||
|
// log type
|
||||||
|
private static final String EXTRA_CONTEXTUALCARD_ACTION_TYPE = "type";
|
||||||
|
|
||||||
|
|
||||||
|
// Contextual card tap target
|
||||||
|
private static final int TARGET_DEFAULT = 0;
|
||||||
|
|
||||||
|
// Click title area
|
||||||
|
private static final int TARGET_TITLE = 1;
|
||||||
|
|
||||||
|
// Click toggle
|
||||||
|
private static final int TARGET_TOGGLE = 2;
|
||||||
|
|
||||||
|
// Click slider
|
||||||
|
private static final int TARGET_SLIDER = 3;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void logHomepageDisplay(Context context, Long latency) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void logContextualCardDismiss(Context context, ContextualCard card) {
|
||||||
|
final Intent intent = new Intent();
|
||||||
|
intent.putExtra(EXTRA_CONTEXTUALCARD_ACTION_TYPE, CONTEXTUAL_CARD_DISMISS);
|
||||||
|
intent.putExtra(EXTRA_CONTEXTUALCARD_NAME, card.getName());
|
||||||
|
intent.putExtra(EXTRA_CONTEXTUALCARD_SCORE, card.getRankingScore());
|
||||||
|
sendBroadcast(context, intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void logContextualCardDisplay(Context context, List<ContextualCard> showCards,
|
||||||
|
List<ContextualCard> hiddenCards) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void logContextualCardClick(Context context, ContextualCard card, int row,
|
||||||
|
int actionType) {
|
||||||
|
final Intent intent = new Intent();
|
||||||
|
intent.putExtra(EXTRA_CONTEXTUALCARD_ACTION_TYPE, CONTEXTUAL_CARD_CLICK);
|
||||||
|
intent.putExtra(EXTRA_CONTEXTUALCARD_NAME, card.getName());
|
||||||
|
intent.putExtra(EXTRA_CONTEXTUALCARD_SCORE, card.getRankingScore());
|
||||||
|
intent.putExtra(EXTRA_CONTEXTUALCARD_ROW, row);
|
||||||
|
intent.putExtra(EXTRA_CONTEXTUALCARD_TAP_TARGET, actionTypeToTapTarget(actionType));
|
||||||
|
sendBroadcast(context, intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
void sendBroadcast(final Context context, final Intent intent) {
|
||||||
|
intent.setPackage(context.getString(R.string.config_settingsintelligence_package_name));
|
||||||
|
final String action = context.getString(R.string.config_settingsintelligence_log_action);
|
||||||
|
if (!TextUtils.isEmpty(action)) {
|
||||||
|
intent.setAction(action);
|
||||||
|
context.sendBroadcast(intent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int actionTypeToTapTarget(int actionType) {
|
||||||
|
switch (actionType) {
|
||||||
|
case EventInfo.ACTION_TYPE_CONTENT:
|
||||||
|
return TARGET_TITLE;
|
||||||
|
case EventInfo.ACTION_TYPE_TOGGLE:
|
||||||
|
return TARGET_TOGGLE;
|
||||||
|
case EventInfo.ACTION_TYPE_SLIDER:
|
||||||
|
return TARGET_SLIDER;
|
||||||
|
default:
|
||||||
|
Log.w(TAG, "unknown type " + actionType);
|
||||||
|
return TARGET_DEFAULT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -26,8 +26,10 @@ import com.android.settings.R;
|
|||||||
import com.android.settings.homepage.contextualcards.CardDatabaseHelper;
|
import com.android.settings.homepage.contextualcards.CardDatabaseHelper;
|
||||||
import com.android.settings.homepage.contextualcards.ContextualCard;
|
import com.android.settings.homepage.contextualcards.ContextualCard;
|
||||||
import com.android.settings.homepage.contextualcards.ContextualCardController;
|
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.ContextualCardFeedbackDialog;
|
||||||
import com.android.settings.homepage.contextualcards.ContextualCardUpdateListener;
|
import com.android.settings.homepage.contextualcards.ContextualCardUpdateListener;
|
||||||
|
import com.android.settings.overlay.FeatureFactory;
|
||||||
import com.android.settingslib.utils.ThreadUtils;
|
import com.android.settingslib.utils.ThreadUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -67,6 +69,9 @@ public class SliceContextualCardController implements ContextualCardController {
|
|||||||
dbHelper.markContextualCardAsDismissed(mContext, card.getName());
|
dbHelper.markContextualCardAsDismissed(mContext, card.getName());
|
||||||
});
|
});
|
||||||
showFeedbackDialog(card);
|
showFeedbackDialog(card);
|
||||||
|
final ContextualCardFeatureProvider contexualCardFeatureProvider =
|
||||||
|
FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider();
|
||||||
|
contexualCardFeatureProvider.logContextualCardDismiss(mContext, card);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -20,6 +20,7 @@ import android.content.ContentResolver;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
|
import android.util.ArraySet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
@@ -38,10 +39,13 @@ import androidx.slice.widget.SliceView;
|
|||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.homepage.contextualcards.ContextualCard;
|
import com.android.settings.homepage.contextualcards.ContextualCard;
|
||||||
|
import com.android.settings.homepage.contextualcards.ContextualCardFeatureProvider;
|
||||||
import com.android.settings.homepage.contextualcards.ContextualCardRenderer;
|
import com.android.settings.homepage.contextualcards.ContextualCardRenderer;
|
||||||
import com.android.settings.homepage.contextualcards.ControllerRendererPool;
|
import com.android.settings.homepage.contextualcards.ControllerRendererPool;
|
||||||
|
import com.android.settings.overlay.FeatureFactory;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Card renderer for {@link ContextualCard} built as slices.
|
* Card renderer for {@link ContextualCard} built as slices.
|
||||||
@@ -58,6 +62,7 @@ public class SliceContextualCardRenderer implements ContextualCardRenderer,
|
|||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private final LifecycleOwner mLifecycleOwner;
|
private final LifecycleOwner mLifecycleOwner;
|
||||||
private final ControllerRendererPool mControllerRendererPool;
|
private final ControllerRendererPool mControllerRendererPool;
|
||||||
|
private final Set<ContextualCard> mCardSet;
|
||||||
|
|
||||||
public SliceContextualCardRenderer(Context context, LifecycleOwner lifecycleOwner,
|
public SliceContextualCardRenderer(Context context, LifecycleOwner lifecycleOwner,
|
||||||
ControllerRendererPool controllerRendererPool) {
|
ControllerRendererPool controllerRendererPool) {
|
||||||
@@ -65,6 +70,7 @@ public class SliceContextualCardRenderer implements ContextualCardRenderer,
|
|||||||
mLifecycleOwner = lifecycleOwner;
|
mLifecycleOwner = lifecycleOwner;
|
||||||
mSliceLiveDataMap = new ArrayMap<>();
|
mSliceLiveDataMap = new ArrayMap<>();
|
||||||
mControllerRendererPool = controllerRendererPool;
|
mControllerRendererPool = controllerRendererPool;
|
||||||
|
mCardSet = new ArraySet<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -99,6 +105,7 @@ public class SliceContextualCardRenderer implements ContextualCardRenderer,
|
|||||||
sliceLiveData = SliceLiveData.fromUri(mContext, uri);
|
sliceLiveData = SliceLiveData.fromUri(mContext, uri);
|
||||||
mSliceLiveDataMap.put(uri.toString(), sliceLiveData);
|
mSliceLiveDataMap.put(uri.toString(), sliceLiveData);
|
||||||
}
|
}
|
||||||
|
mCardSet.add(card);
|
||||||
|
|
||||||
sliceLiveData.removeObservers(mLifecycleOwner);
|
sliceLiveData.removeObservers(mLifecycleOwner);
|
||||||
sliceLiveData.observe(mLifecycleOwner, slice -> {
|
sliceLiveData.observe(mLifecycleOwner, slice -> {
|
||||||
@@ -128,14 +135,27 @@ public class SliceContextualCardRenderer implements ContextualCardRenderer,
|
|||||||
|
|
||||||
final Button btnRemove = cardHolder.itemView.findViewById(R.id.remove);
|
final Button btnRemove = cardHolder.itemView.findViewById(R.id.remove);
|
||||||
btnRemove.setOnClickListener(v -> {
|
btnRemove.setOnClickListener(v -> {
|
||||||
mControllerRendererPool.getController(mContext, card.getCardType()).onDismissed(
|
mControllerRendererPool.getController(mContext, card.getCardType()).onDismissed(card);
|
||||||
card);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSliceAction(@NonNull EventInfo eventInfo, @NonNull SliceItem sliceItem) {
|
public void onSliceAction(@NonNull EventInfo eventInfo, @NonNull SliceItem sliceItem) {
|
||||||
//TODO(b/79698338): Log user interaction
|
//TODO(b/79698338): Log user interaction
|
||||||
|
|
||||||
|
// sliceItem.getSlice().getUri() is like
|
||||||
|
// content://android.settings.slices/action/wifi/_gen/0/_gen/0
|
||||||
|
// contextualCard.getSliceUri() is prefix of sliceItem.getSlice().getUri()
|
||||||
|
for (ContextualCard card : mCardSet) {
|
||||||
|
if (sliceItem.getSlice().getUri().toString().startsWith(
|
||||||
|
card.getSliceUri().toString())) {
|
||||||
|
ContextualCardFeatureProvider contexualCardFeatureProvider =
|
||||||
|
FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider();
|
||||||
|
contexualCardFeatureProvider.logContextualCardClick(mContext, card,
|
||||||
|
eventInfo.rowIndex, eventInfo.actionType);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class SliceViewHolder extends RecyclerView.ViewHolder {
|
public static class SliceViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
@@ -28,6 +28,7 @@ import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
|
|||||||
import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider;
|
import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider;
|
||||||
import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
|
import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
|
||||||
import com.android.settings.gestures.AssistGestureFeatureProvider;
|
import com.android.settings.gestures.AssistGestureFeatureProvider;
|
||||||
|
import com.android.settings.homepage.contextualcards.ContextualCardFeatureProvider;
|
||||||
import com.android.settings.localepicker.LocaleFeatureProvider;
|
import com.android.settings.localepicker.LocaleFeatureProvider;
|
||||||
import com.android.settings.panel.PanelFeatureProvider;
|
import com.android.settings.panel.PanelFeatureProvider;
|
||||||
import com.android.settings.search.SearchFeatureProvider;
|
import com.android.settings.search.SearchFeatureProvider;
|
||||||
@@ -108,6 +109,8 @@ public abstract class FeatureFactory {
|
|||||||
|
|
||||||
public abstract PanelFeatureProvider getPanelFeatureProvider();
|
public abstract PanelFeatureProvider getPanelFeatureProvider();
|
||||||
|
|
||||||
|
public abstract ContextualCardFeatureProvider getContextualCardFeatureProvider();
|
||||||
|
|
||||||
public static final class FactoryNotFoundException extends RuntimeException {
|
public static final class FactoryNotFoundException extends RuntimeException {
|
||||||
public FactoryNotFoundException(Throwable throwable) {
|
public FactoryNotFoundException(Throwable throwable) {
|
||||||
super("Unable to create factory. Did you misconfigure Proguard?", throwable);
|
super("Unable to create factory. Did you misconfigure Proguard?", throwable);
|
||||||
|
@@ -40,6 +40,8 @@ import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
|
|||||||
import com.android.settings.fuelgauge.PowerUsageFeatureProviderImpl;
|
import com.android.settings.fuelgauge.PowerUsageFeatureProviderImpl;
|
||||||
import com.android.settings.gestures.AssistGestureFeatureProvider;
|
import com.android.settings.gestures.AssistGestureFeatureProvider;
|
||||||
import com.android.settings.gestures.AssistGestureFeatureProviderImpl;
|
import com.android.settings.gestures.AssistGestureFeatureProviderImpl;
|
||||||
|
import com.android.settings.homepage.contextualcards.ContextualCardFeatureProvider;
|
||||||
|
import com.android.settings.homepage.contextualcards.ContextualCardFeatureProviderImpl;
|
||||||
import com.android.settings.localepicker.LocaleFeatureProvider;
|
import com.android.settings.localepicker.LocaleFeatureProvider;
|
||||||
import com.android.settings.localepicker.LocaleFeatureProviderImpl;
|
import com.android.settings.localepicker.LocaleFeatureProviderImpl;
|
||||||
import com.android.settings.panel.PanelFeatureProvider;
|
import com.android.settings.panel.PanelFeatureProvider;
|
||||||
@@ -75,6 +77,7 @@ public class FeatureFactoryImpl extends FeatureFactory {
|
|||||||
private SlicesFeatureProvider mSlicesFeatureProvider;
|
private SlicesFeatureProvider mSlicesFeatureProvider;
|
||||||
private AccountFeatureProvider mAccountFeatureProvider;
|
private AccountFeatureProvider mAccountFeatureProvider;
|
||||||
private PanelFeatureProvider mPanelFeatureProvider;
|
private PanelFeatureProvider mPanelFeatureProvider;
|
||||||
|
private ContextualCardFeatureProvider mContextualCardFeatureProvider;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SupportFeatureProvider getSupportFeatureProvider(Context context) {
|
public SupportFeatureProvider getSupportFeatureProvider(Context context) {
|
||||||
@@ -220,4 +223,11 @@ public class FeatureFactoryImpl extends FeatureFactory {
|
|||||||
}
|
}
|
||||||
return mPanelFeatureProvider;
|
return mPanelFeatureProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ContextualCardFeatureProvider getContextualCardFeatureProvider() {
|
||||||
|
if (mContextualCardFeatureProvider == null) {
|
||||||
|
mContextualCardFeatureProvider = new ContextualCardFeatureProviderImpl();
|
||||||
|
}
|
||||||
|
return mContextualCardFeatureProvider;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -73,6 +73,11 @@
|
|||||||
<item>fake_package/fake_service</item>
|
<item>fake_package/fake_service</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<!-- Settings intelligence interaction log intent action -->
|
||||||
|
<string name="config_settingsintelligence_log_action" translatable="false">
|
||||||
|
aaa.bbb.ccc
|
||||||
|
</string>
|
||||||
|
|
||||||
<!-- List of packages that should be whitelisted for slice uri access. Do not translate -->
|
<!-- List of packages that should be whitelisted for slice uri access. Do not translate -->
|
||||||
<string-array name="slice_whitelist_package_names" translatable="false">
|
<string-array name="slice_whitelist_package_names" translatable="false">
|
||||||
<item>com.android.settings.slice_whitelist_package</item>
|
<item>com.android.settings.slice_whitelist_package</item>
|
||||||
|
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
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 com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.robolectric.RuntimeEnvironment;
|
||||||
|
import org.robolectric.annotation.Config;
|
||||||
|
|
||||||
|
@RunWith(SettingsRobolectricTestRunner.class)
|
||||||
|
public class ContextualCardFeatureProviderImplTest {
|
||||||
|
|
||||||
|
private Context mContext;
|
||||||
|
private ContextualCardFeatureProviderImpl mImpl;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
mContext = spy(RuntimeEnvironment.application);
|
||||||
|
mImpl = new ContextualCardFeatureProviderImpl();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sendBroadcast_emptyAction_notSendBroadcast() {
|
||||||
|
final Intent intent = new Intent();
|
||||||
|
mImpl.sendBroadcast(mContext, intent);
|
||||||
|
|
||||||
|
verify(mContext, never()).sendBroadcast(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Config(qualifiers = "mcc999")
|
||||||
|
public void sendBroadcast_hasAction_sendBroadcast() {
|
||||||
|
final Intent intent = new Intent();
|
||||||
|
mImpl.sendBroadcast(mContext, intent);
|
||||||
|
|
||||||
|
verify(mContext).sendBroadcast(intent);
|
||||||
|
}
|
||||||
|
}
|
@@ -18,9 +18,10 @@ package com.android.settings.homepage.contextualcards.slices;
|
|||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.Mockito.any;
|
||||||
import static org.mockito.Mockito.doNothing;
|
import static org.mockito.Mockito.doNothing;
|
||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
@@ -33,6 +34,7 @@ import com.android.settings.homepage.contextualcards.CardDatabaseHelper;
|
|||||||
import com.android.settings.homepage.contextualcards.ContextualCard;
|
import com.android.settings.homepage.contextualcards.ContextualCard;
|
||||||
import com.android.settings.homepage.contextualcards.ContextualCardFeedbackDialog;
|
import com.android.settings.homepage.contextualcards.ContextualCardFeedbackDialog;
|
||||||
import com.android.settings.homepage.contextualcards.ContextualCardsFragment;
|
import com.android.settings.homepage.contextualcards.ContextualCardsFragment;
|
||||||
|
import com.android.settings.testutils.FakeFeatureFactory;
|
||||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
@@ -57,6 +59,7 @@ public class SliceContextualCardControllerTest {
|
|||||||
private CardContentProvider mProvider;
|
private CardContentProvider mProvider;
|
||||||
private ContentResolver mResolver;
|
private ContentResolver mResolver;
|
||||||
private SliceContextualCardController mController;
|
private SliceContextualCardController mController;
|
||||||
|
private FakeFeatureFactory mFeatureFactory;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
@@ -67,6 +70,7 @@ public class SliceContextualCardControllerTest {
|
|||||||
mProvider);
|
mProvider);
|
||||||
mResolver = mContext.getContentResolver();
|
mResolver = mContext.getContentResolver();
|
||||||
mController = spy(new SliceContextualCardController(mContext));
|
mController = spy(new SliceContextualCardController(mContext));
|
||||||
|
mFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -75,7 +79,8 @@ public class SliceContextualCardControllerTest {
|
|||||||
mResolver.insert(providerUri, generateOneRow());
|
mResolver.insert(providerUri, generateOneRow());
|
||||||
doNothing().when(mController).showFeedbackDialog(any(ContextualCard.class));
|
doNothing().when(mController).showFeedbackDialog(any(ContextualCard.class));
|
||||||
|
|
||||||
mController.onDismissed(getTestSliceCard());
|
final ContextualCard card = getTestSliceCard();
|
||||||
|
mController.onDismissed(card);
|
||||||
|
|
||||||
final String[] columns = {CardDatabaseHelper.CardColumns.CARD_DISMISSED};
|
final String[] columns = {CardDatabaseHelper.CardColumns.CARD_DISMISSED};
|
||||||
final String selection = CardDatabaseHelper.CardColumns.NAME + "=?";
|
final String selection = CardDatabaseHelper.CardColumns.NAME + "=?";
|
||||||
@@ -86,6 +91,8 @@ public class SliceContextualCardControllerTest {
|
|||||||
cr.close();
|
cr.close();
|
||||||
|
|
||||||
assertThat(qryDismissed).isEqualTo(1);
|
assertThat(qryDismissed).isEqualTo(1);
|
||||||
|
verify(mFeatureFactory.mContextualCardFeatureProvider).logContextualCardDismiss(
|
||||||
|
mContext, card);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@@ -28,6 +28,7 @@ import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
|
|||||||
import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider;
|
import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider;
|
||||||
import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
|
import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
|
||||||
import com.android.settings.gestures.AssistGestureFeatureProvider;
|
import com.android.settings.gestures.AssistGestureFeatureProvider;
|
||||||
|
import com.android.settings.homepage.contextualcards.ContextualCardFeatureProvider;
|
||||||
import com.android.settings.localepicker.LocaleFeatureProvider;
|
import com.android.settings.localepicker.LocaleFeatureProvider;
|
||||||
import com.android.settings.overlay.DockUpdaterFeatureProvider;
|
import com.android.settings.overlay.DockUpdaterFeatureProvider;
|
||||||
import com.android.settings.overlay.FeatureFactory;
|
import com.android.settings.overlay.FeatureFactory;
|
||||||
@@ -63,6 +64,7 @@ public class FakeFeatureFactory extends FeatureFactory {
|
|||||||
public final AssistGestureFeatureProvider assistGestureFeatureProvider;
|
public final AssistGestureFeatureProvider assistGestureFeatureProvider;
|
||||||
public final AccountFeatureProvider mAccountFeatureProvider;
|
public final AccountFeatureProvider mAccountFeatureProvider;
|
||||||
public final PanelFeatureProvider mPanelFeatureProvider;
|
public final PanelFeatureProvider mPanelFeatureProvider;
|
||||||
|
public final ContextualCardFeatureProvider mContextualCardFeatureProvider;
|
||||||
|
|
||||||
public SlicesFeatureProvider slicesFeatureProvider;
|
public SlicesFeatureProvider slicesFeatureProvider;
|
||||||
public SearchFeatureProvider searchFeatureProvider;
|
public SearchFeatureProvider searchFeatureProvider;
|
||||||
@@ -105,6 +107,7 @@ public class FakeFeatureFactory extends FeatureFactory {
|
|||||||
slicesFeatureProvider = mock(SlicesFeatureProvider.class);
|
slicesFeatureProvider = mock(SlicesFeatureProvider.class);
|
||||||
mAccountFeatureProvider = mock(AccountFeatureProvider.class);
|
mAccountFeatureProvider = mock(AccountFeatureProvider.class);
|
||||||
mPanelFeatureProvider = mock(PanelFeatureProvider.class);
|
mPanelFeatureProvider = mock(PanelFeatureProvider.class);
|
||||||
|
mContextualCardFeatureProvider = mock(ContextualCardFeatureProvider.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -191,4 +194,8 @@ public class FakeFeatureFactory extends FeatureFactory {
|
|||||||
public PanelFeatureProvider getPanelFeatureProvider() {
|
public PanelFeatureProvider getPanelFeatureProvider() {
|
||||||
return mPanelFeatureProvider;
|
return mPanelFeatureProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ContextualCardFeatureProvider getContextualCardFeatureProvider() {
|
||||||
|
return mContextualCardFeatureProvider;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user