Loading res/values/config.xml +3 −0 Original line number Diff line number Diff line Loading @@ -151,6 +151,9 @@ com.android.settings.intelligence </string> <!-- Settings intelligence interaction log intent action --> <string name="config_settingsintelligence_log_action" translatable="false"></string> <!-- Emergency app package name --> <string name="config_emergency_package_name" translatable="false"> com.android.emergency Loading src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProvider.java 0 → 100644 +39 −0 Original line number Diff line number Diff line /* * 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); } src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImpl.java 0 → 100644 +136 −0 Original line number Diff line number Diff line /* * 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; } } } src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardController.java +5 −0 Original line number Diff line number Diff line Loading @@ -26,8 +26,10 @@ 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.ContextualCardUpdateListener; import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.utils.ThreadUtils; /** Loading Loading @@ -67,6 +69,9 @@ public class SliceContextualCardController implements ContextualCardController { dbHelper.markContextualCardAsDismissed(mContext, card.getName()); }); showFeedbackDialog(card); final ContextualCardFeatureProvider contexualCardFeatureProvider = FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider(); contexualCardFeatureProvider.logContextualCardDismiss(mContext, card); } @Override Loading src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java +22 −2 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.content.ContentResolver; import android.content.Context; import android.net.Uri; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; import android.view.View; import android.widget.Button; Loading @@ -38,10 +39,13 @@ 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.ContextualCardRenderer; import com.android.settings.homepage.contextualcards.ControllerRendererPool; import com.android.settings.overlay.FeatureFactory; import java.util.Map; import java.util.Set; /** * Card renderer for {@link ContextualCard} built as slices. Loading @@ -58,6 +62,7 @@ public class SliceContextualCardRenderer implements ContextualCardRenderer, private final Context mContext; private final LifecycleOwner mLifecycleOwner; private final ControllerRendererPool mControllerRendererPool; private final Set<ContextualCard> mCardSet; public SliceContextualCardRenderer(Context context, LifecycleOwner lifecycleOwner, ControllerRendererPool controllerRendererPool) { Loading @@ -65,6 +70,7 @@ public class SliceContextualCardRenderer implements ContextualCardRenderer, mLifecycleOwner = lifecycleOwner; mSliceLiveDataMap = new ArrayMap<>(); mControllerRendererPool = controllerRendererPool; mCardSet = new ArraySet<>(); } @Override Loading Loading @@ -99,6 +105,7 @@ public class SliceContextualCardRenderer implements ContextualCardRenderer, sliceLiveData = SliceLiveData.fromUri(mContext, uri); mSliceLiveDataMap.put(uri.toString(), sliceLiveData); } mCardSet.add(card); sliceLiveData.removeObservers(mLifecycleOwner); sliceLiveData.observe(mLifecycleOwner, slice -> { Loading Loading @@ -128,14 +135,27 @@ public class SliceContextualCardRenderer implements ContextualCardRenderer, final Button btnRemove = cardHolder.itemView.findViewById(R.id.remove); btnRemove.setOnClickListener(v -> { mControllerRendererPool.getController(mContext, card.getCardType()).onDismissed( card); mControllerRendererPool.getController(mContext, card.getCardType()).onDismissed(card); }); } @Override public void onSliceAction(@NonNull EventInfo eventInfo, @NonNull SliceItem sliceItem) { //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 { Loading Loading
res/values/config.xml +3 −0 Original line number Diff line number Diff line Loading @@ -151,6 +151,9 @@ com.android.settings.intelligence </string> <!-- Settings intelligence interaction log intent action --> <string name="config_settingsintelligence_log_action" translatable="false"></string> <!-- Emergency app package name --> <string name="config_emergency_package_name" translatable="false"> com.android.emergency Loading
src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProvider.java 0 → 100644 +39 −0 Original line number Diff line number Diff line /* * 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); }
src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImpl.java 0 → 100644 +136 −0 Original line number Diff line number Diff line /* * 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; } } }
src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardController.java +5 −0 Original line number Diff line number Diff line Loading @@ -26,8 +26,10 @@ 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.ContextualCardUpdateListener; import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.utils.ThreadUtils; /** Loading Loading @@ -67,6 +69,9 @@ public class SliceContextualCardController implements ContextualCardController { dbHelper.markContextualCardAsDismissed(mContext, card.getName()); }); showFeedbackDialog(card); final ContextualCardFeatureProvider contexualCardFeatureProvider = FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider(); contexualCardFeatureProvider.logContextualCardDismiss(mContext, card); } @Override Loading
src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java +22 −2 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.content.ContentResolver; import android.content.Context; import android.net.Uri; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; import android.view.View; import android.widget.Button; Loading @@ -38,10 +39,13 @@ 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.ContextualCardRenderer; import com.android.settings.homepage.contextualcards.ControllerRendererPool; import com.android.settings.overlay.FeatureFactory; import java.util.Map; import java.util.Set; /** * Card renderer for {@link ContextualCard} built as slices. Loading @@ -58,6 +62,7 @@ public class SliceContextualCardRenderer implements ContextualCardRenderer, private final Context mContext; private final LifecycleOwner mLifecycleOwner; private final ControllerRendererPool mControllerRendererPool; private final Set<ContextualCard> mCardSet; public SliceContextualCardRenderer(Context context, LifecycleOwner lifecycleOwner, ControllerRendererPool controllerRendererPool) { Loading @@ -65,6 +70,7 @@ public class SliceContextualCardRenderer implements ContextualCardRenderer, mLifecycleOwner = lifecycleOwner; mSliceLiveDataMap = new ArrayMap<>(); mControllerRendererPool = controllerRendererPool; mCardSet = new ArraySet<>(); } @Override Loading Loading @@ -99,6 +105,7 @@ public class SliceContextualCardRenderer implements ContextualCardRenderer, sliceLiveData = SliceLiveData.fromUri(mContext, uri); mSliceLiveDataMap.put(uri.toString(), sliceLiveData); } mCardSet.add(card); sliceLiveData.removeObservers(mLifecycleOwner); sliceLiveData.observe(mLifecycleOwner, slice -> { Loading Loading @@ -128,14 +135,27 @@ public class SliceContextualCardRenderer implements ContextualCardRenderer, final Button btnRemove = cardHolder.itemView.findViewById(R.id.remove); btnRemove.setOnClickListener(v -> { mControllerRendererPool.getController(mContext, card.getCardType()).onDismissed( card); mControllerRendererPool.getController(mContext, card.getCardType()).onDismissed(card); }); } @Override public void onSliceAction(@NonNull EventInfo eventInfo, @NonNull SliceItem sliceItem) { //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 { Loading