Impl dismiss action in battery tips cards.

- Use SharedPreferences to record and filter the already dimissed anomaly.

Bug: 291689623
Test: manual
Change-Id: I4fd4a39066591a4a201857f9586b6595b7d5c43b
This commit is contained in:
mxyyiyi
2023-08-17 15:30:22 +08:00
committed by Zaiyue Xue
parent c68e038508
commit d9360ec326
8 changed files with 133 additions and 7 deletions

View File

@@ -52,10 +52,10 @@ import com.google.common.base.Objects;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@@ -397,12 +397,23 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll
return true; return true;
} }
private PowerAnomalyEvent getHighestScoreAnomalyEvent(PowerAnomalyEventList anomalyEventList) { @VisibleForTesting
PowerAnomalyEvent getHighestScoreAnomalyEvent(PowerAnomalyEventList anomalyEventList) {
if (anomalyEventList == null || anomalyEventList.getPowerAnomalyEventsCount() == 0) { if (anomalyEventList == null || anomalyEventList.getPowerAnomalyEventsCount() == 0) {
return null; return null;
} }
return Collections.max(anomalyEventList.getPowerAnomalyEventsList(), final Set<String> dismissedPowerAnomalyKeys =
Comparator.comparing(PowerAnomalyEvent::getScore)); DatabaseUtils.getDismissedPowerAnomalyKeys(mContext);
Log.d(TAG, "dismissedPowerAnomalyKeys = " + dismissedPowerAnomalyKeys);
final PowerAnomalyEvent highestScoreEvent = anomalyEventList.getPowerAnomalyEventsList()
.stream()
.filter(event -> event.hasKey()
&& !dismissedPowerAnomalyKeys.contains(event.getKey().name()))
.max(Comparator.comparing(PowerAnomalyEvent::getScore))
.orElse(null);
Log.d(TAG, "highestScoreAnomalyEvent = " + highestScoreEvent);
return highestScoreEvent;
} }
private boolean refreshUiWithNoLevelDataCase() { private boolean refreshUiWithNoLevelDataCase() {

View File

@@ -50,6 +50,7 @@ public class BatteryTipsCardPreference extends Preference implements View.OnClic
private final MetricsFeatureProvider mMetricsFeatureProvider; private final MetricsFeatureProvider mMetricsFeatureProvider;
private String mAnomalyEventId; private String mAnomalyEventId;
private PowerAnomalyKey mPowerAnomalyKey;
@VisibleForTesting @VisibleForTesting
CharSequence mMainButtonLabel; CharSequence mMainButtonLabel;
@@ -69,6 +70,7 @@ public class BatteryTipsCardPreference extends Preference implements View.OnClic
final FeatureFactory featureFactory = FeatureFactory.getFeatureFactory(); final FeatureFactory featureFactory = FeatureFactory.getFeatureFactory();
mPowerUsageFeatureProvider = featureFactory.getPowerUsageFeatureProvider(); mPowerUsageFeatureProvider = featureFactory.getPowerUsageFeatureProvider();
mMetricsFeatureProvider = featureFactory.getMetricsFeatureProvider(); mMetricsFeatureProvider = featureFactory.getMetricsFeatureProvider();
mPowerAnomalyKey = null;
} }
/** /**
@@ -98,6 +100,13 @@ public class BatteryTipsCardPreference extends Preference implements View.OnClic
} }
} }
/**
* Sets the power anomaly key of battery tips card.
*/
public void setPowerAnomalyKey(final PowerAnomalyKey powerAnomalyKey) {
mPowerAnomalyKey = powerAnomalyKey;
}
/** /**
* Sets the info of target fragment launched by main button. * Sets the info of target fragment launched by main button.
*/ */
@@ -133,6 +142,9 @@ public class BatteryTipsCardPreference extends Preference implements View.OnClic
setVisible(false); setVisible(false);
mMetricsFeatureProvider.action( mMetricsFeatureProvider.action(
getContext(), SettingsEnums.ACTION_BATTERY_TIPS_CARD_DISMISS, mAnomalyEventId); getContext(), SettingsEnums.ACTION_BATTERY_TIPS_CARD_DISMISS, mAnomalyEventId);
if (mPowerAnomalyKey != null) {
DatabaseUtils.setDismissedPowerAnomalyKeys(getContext(), mPowerAnomalyKey.name());
}
} }
} }

View File

@@ -108,8 +108,9 @@ public class BatteryTipsController extends BasePreferenceController {
} }
// Get card preference strings and navigate fragment info // Get card preference strings and navigate fragment info
final int resourceIndex = powerAnomalyEvent.hasKey() final PowerAnomalyKey powerAnomalyKey = powerAnomalyEvent.hasKey()
? powerAnomalyEvent.getKey().getNumber() : -1; ? powerAnomalyEvent.getKey() : null;
final int resourceIndex = powerAnomalyKey != null ? powerAnomalyKey.getNumber() : -1;
String titleString = getString(powerAnomalyEvent, WarningBannerInfo::getTitleString, String titleString = getString(powerAnomalyEvent, WarningBannerInfo::getTitleString,
WarningItemInfo::getTitleString, R.array.power_anomaly_titles, resourceIndex); WarningItemInfo::getTitleString, R.array.power_anomaly_titles, resourceIndex);
@@ -134,6 +135,7 @@ public class BatteryTipsController extends BasePreferenceController {
// Updated card preference and main button fragment launcher // Updated card preference and main button fragment launcher
mCardPreference.setAnomalyEventId(powerAnomalyEvent.getEventId()); mCardPreference.setAnomalyEventId(powerAnomalyEvent.getEventId());
mCardPreference.setPowerAnomalyKey(powerAnomalyKey);
mCardPreference.setTitle(titleString); mCardPreference.setTitle(titleString);
mCardPreference.setMainButtonLabel(mainBtnString); mCardPreference.setMainButtonLabel(mainBtnString);
mCardPreference.setDismissButtonLabel(dismissBtnString); mCardPreference.setDismissButtonLabel(dismissBtnString);

View File

@@ -74,6 +74,7 @@ public final class BatteryUsageDataLoader {
context, DatabaseUtils.KEY_LAST_LOAD_FULL_CHARGE_TIME); context, DatabaseUtils.KEY_LAST_LOAD_FULL_CHARGE_TIME);
DatabaseUtils.sendBatteryEventData(context, ConvertUtils.convertToBatteryEvent( DatabaseUtils.sendBatteryEventData(context, ConvertUtils.convertToBatteryEvent(
currentTime, BatteryEventType.FULL_CHARGED, 100)); currentTime, BatteryEventType.FULL_CHARGED, 100));
DatabaseUtils.removeDismissedPowerAnomalyKeys(context);
} }
// Uploads the BatteryEntry data into database. // Uploads the BatteryEntry data into database.

View File

@@ -35,6 +35,7 @@ import android.os.Looper;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.SystemClock; import android.os.SystemClock;
import android.os.UserManager; import android.os.UserManager;
import android.util.ArraySet;
import android.util.Log; import android.util.Log;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
@@ -53,6 +54,7 @@ import java.util.Calendar;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -69,6 +71,7 @@ public final class DatabaseUtils {
static final String KEY_LAST_LOAD_FULL_CHARGE_TIME = "last_load_full_charge_time"; static final String KEY_LAST_LOAD_FULL_CHARGE_TIME = "last_load_full_charge_time";
static final String KEY_LAST_UPLOAD_FULL_CHARGE_TIME = "last_upload_full_charge_time"; static final String KEY_LAST_UPLOAD_FULL_CHARGE_TIME = "last_upload_full_charge_time";
static final String KEY_LAST_USAGE_SOURCE = "last_usage_source"; static final String KEY_LAST_USAGE_SOURCE = "last_usage_source";
static final String KEY_DISMISSED_POWER_ANOMALY_KEYS = "dismissed_power_anomaly_keys";
/** An authority name of the battery content provider. */ /** An authority name of the battery content provider. */
public static final String AUTHORITY = "com.android.settings.battery.usage.provider"; public static final String AUTHORITY = "com.android.settings.battery.usage.provider";
@@ -636,6 +639,8 @@ public final class DatabaseUtils {
KEY_LAST_LOAD_FULL_CHARGE_TIME); KEY_LAST_LOAD_FULL_CHARGE_TIME);
writeString(context, writer, "LastUploadFullChargeTime", writeString(context, writer, "LastUploadFullChargeTime",
KEY_LAST_UPLOAD_FULL_CHARGE_TIME); KEY_LAST_UPLOAD_FULL_CHARGE_TIME);
writeString(context, writer, "DismissedPowerAnomalyKeys",
KEY_DISMISSED_POWER_ANOMALY_KEYS);
} }
static SharedPreferences getSharedPreferences(Context context) { static SharedPreferences getSharedPreferences(Context context) {
@@ -674,6 +679,32 @@ public final class DatabaseUtils {
return usageSource; return usageSource;
} }
static void removeDismissedPowerAnomalyKeys(Context context) {
final SharedPreferences sharedPreferences = getSharedPreferences(context);
if (sharedPreferences != null
&& sharedPreferences.contains(KEY_DISMISSED_POWER_ANOMALY_KEYS)) {
sharedPreferences.edit().remove(KEY_DISMISSED_POWER_ANOMALY_KEYS).apply();
}
}
static Set<String> getDismissedPowerAnomalyKeys(Context context) {
final SharedPreferences sharedPreferences = getSharedPreferences(context);
return sharedPreferences != null
? sharedPreferences.getStringSet(KEY_DISMISSED_POWER_ANOMALY_KEYS, new ArraySet<>())
: new ArraySet<>();
}
static void setDismissedPowerAnomalyKeys(Context context, String dismissedPowerAnomalyKey) {
final SharedPreferences sharedPreferences = getSharedPreferences(context);
if (sharedPreferences != null) {
final Set<String> dismissedPowerAnomalyKeys = getDismissedPowerAnomalyKeys(context);
dismissedPowerAnomalyKeys.add(dismissedPowerAnomalyKey);
sharedPreferences.edit()
.putStringSet(KEY_DISMISSED_POWER_ANOMALY_KEYS, dismissedPowerAnomalyKeys)
.apply();
}
}
static void recordDateTime(Context context, String preferenceKey) { static void recordDateTime(Context context, String preferenceKey) {
final SharedPreferences sharedPreferences = getSharedPreferences(context); final SharedPreferences sharedPreferences = getSharedPreferences(context);
if (sharedPreferences != null) { if (sharedPreferences != null) {

View File

@@ -46,6 +46,7 @@ import android.view.ViewPropertyAnimator;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import com.android.settings.SettingsActivity; import com.android.settings.SettingsActivity;
import com.android.settings.testutils.BatteryTestUtils;
import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.FakeFeatureFactory;
import org.junit.Before; import org.junit.Before;
@@ -407,6 +408,57 @@ public final class BatteryChartPreferenceControllerTest {
assertThat(totalHour).isEqualTo(59); assertThat(totalHour).isEqualTo(59);
} }
@Test
public void getHighestScoreAnomalyEvent_withEmptyOrNullList_getNull() {
assertThat(mBatteryChartPreferenceController.getHighestScoreAnomalyEvent(null))
.isEqualTo(null);
assertThat(mBatteryChartPreferenceController.getHighestScoreAnomalyEvent(
BatteryTestUtils.createEmptyPowerAnomalyEventList()))
.isEqualTo(null);
}
@Test
public void getHighestScoreAnomalyEvent_withoutDismissed_getHighestScoreEvent() {
final PowerAnomalyEventList eventList =
BatteryTestUtils.createNonEmptyPowerAnomalyEventList();
final PowerAnomalyEvent highestScoreEvent =
mBatteryChartPreferenceController.getHighestScoreAnomalyEvent(eventList);
assertThat(highestScoreEvent)
.isEqualTo(BatteryTestUtils.createAdaptiveBrightnessAnomalyEvent());
}
@Test
public void getHighestScoreAnomalyEvent_withBrightnessDismissed_getScreenTimeout() {
final PowerAnomalyEventList eventList =
BatteryTestUtils.createNonEmptyPowerAnomalyEventList();
DatabaseUtils.removeDismissedPowerAnomalyKeys(mContext);
DatabaseUtils.setDismissedPowerAnomalyKeys(mContext, PowerAnomalyKey.KEY_BRIGHTNESS.name());
final PowerAnomalyEvent highestScoreEvent =
mBatteryChartPreferenceController.getHighestScoreAnomalyEvent(eventList);
assertThat(highestScoreEvent)
.isEqualTo(BatteryTestUtils.createScreenTimeoutAnomalyEvent());
}
@Test
public void getHighestScoreAnomalyEvent_withAllDismissed_getNull() {
final PowerAnomalyEventList eventList =
BatteryTestUtils.createNonEmptyPowerAnomalyEventList();
DatabaseUtils.removeDismissedPowerAnomalyKeys(mContext);
for (PowerAnomalyKey key : PowerAnomalyKey.values()) {
DatabaseUtils.setDismissedPowerAnomalyKeys(mContext, key.name());
}
final PowerAnomalyEvent highestScoreEvent =
mBatteryChartPreferenceController.getHighestScoreAnomalyEvent(eventList);
assertThat(highestScoreEvent).isEqualTo(null);
}
private static Long generateTimestamp(int index) { private static Long generateTimestamp(int index) {
// "2021-04-23 07:00:00 UTC" + index hours // "2021-04-23 07:00:00 UTC" + index hours
return 1619247600000L + index * DateUtils.HOUR_IN_MILLIS; return 1619247600000L + index * DateUtils.HOUR_IN_MILLIS;

View File

@@ -83,6 +83,7 @@ public final class BatteryTipsCardPreferenceTest {
mBatteryTipsController.handleBatteryTipsCardUpdated(adaptiveBrightnessAnomaly); mBatteryTipsController.handleBatteryTipsCardUpdated(adaptiveBrightnessAnomaly);
mBatteryTipsCardPreference.onClick(mFakeView); mBatteryTipsCardPreference.onClick(mFakeView);
assertThat(mBatteryTipsCardPreference.isVisible()).isEqualTo(false);
verify(mContext).startActivity(any(Intent.class)); verify(mContext).startActivity(any(Intent.class));
final Intent intent = captor.getValue(); final Intent intent = captor.getValue();
assertThat(intent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT)) assertThat(intent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT))
@@ -94,15 +95,21 @@ public final class BatteryTipsCardPreferenceTest {
} }
@Test @Test
public void onClick_dismissBtn_metricsLogged() { public void onClick_dismissBtn_cardDismissAndLogged() {
PowerAnomalyEvent screenTimeoutAnomaly = PowerAnomalyEvent screenTimeoutAnomaly =
BatteryTestUtils.createScreenTimeoutAnomalyEvent(); BatteryTestUtils.createScreenTimeoutAnomalyEvent();
DatabaseUtils.removeDismissedPowerAnomalyKeys(mContext);
when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true); when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true);
when(mFakeView.getId()).thenReturn(R.id.dismiss_button); when(mFakeView.getId()).thenReturn(R.id.dismiss_button);
mBatteryTipsController.handleBatteryTipsCardUpdated(screenTimeoutAnomaly); mBatteryTipsController.handleBatteryTipsCardUpdated(screenTimeoutAnomaly);
mBatteryTipsCardPreference.onClick(mFakeView); mBatteryTipsCardPreference.onClick(mFakeView);
assertThat(mBatteryTipsCardPreference.isVisible()).isEqualTo(false);
assertThat(DatabaseUtils.getDismissedPowerAnomalyKeys(mContext).size())
.isEqualTo(1);
assertThat(DatabaseUtils.getDismissedPowerAnomalyKeys(mContext))
.contains(PowerAnomalyKey.KEY_SCREEN_TIMEOUT.name());
verify(mFeatureFactory.metricsFeatureProvider).action( verify(mFeatureFactory.metricsFeatureProvider).action(
mContext, SettingsEnums.ACTION_BATTERY_TIPS_CARD_DISMISS, "ScreenTimeoutAnomaly"); mContext, SettingsEnums.ACTION_BATTERY_TIPS_CARD_DISMISS, "ScreenTimeoutAnomaly");
} }

View File

@@ -208,12 +208,21 @@ public class BatteryTestUtils {
return PowerAnomalyEventList.getDefaultInstance(); return PowerAnomalyEventList.getDefaultInstance();
} }
/** Create an non-empty power anomaly event list proto. */
public static PowerAnomalyEventList createNonEmptyPowerAnomalyEventList() {
return PowerAnomalyEventList.newBuilder()
.addPowerAnomalyEvents(0, createAdaptiveBrightnessAnomalyEvent())
.addPowerAnomalyEvents(1, createScreenTimeoutAnomalyEvent())
.build();
}
/** Create a power anomaly event proto of adaptive brightness. */ /** Create a power anomaly event proto of adaptive brightness. */
public static PowerAnomalyEvent createAdaptiveBrightnessAnomalyEvent() { public static PowerAnomalyEvent createAdaptiveBrightnessAnomalyEvent() {
return PowerAnomalyEvent.newBuilder() return PowerAnomalyEvent.newBuilder()
.setEventId("BrightnessAnomaly") .setEventId("BrightnessAnomaly")
.setType(PowerAnomalyType.TYPE_SETTINGS_BANNER) .setType(PowerAnomalyType.TYPE_SETTINGS_BANNER)
.setKey(PowerAnomalyKey.KEY_BRIGHTNESS) .setKey(PowerAnomalyKey.KEY_BRIGHTNESS)
.setScore(1.2f)
.setWarningBannerInfo(WarningBannerInfo.newBuilder() .setWarningBannerInfo(WarningBannerInfo.newBuilder()
.setMainButtonDestination(DisplaySettings.class.getName()) .setMainButtonDestination(DisplaySettings.class.getName())
.setMainButtonSourceMetricsCategory(SettingsEnums.DISPLAY) .setMainButtonSourceMetricsCategory(SettingsEnums.DISPLAY)
@@ -228,6 +237,7 @@ public class BatteryTestUtils {
.setEventId("ScreenTimeoutAnomaly") .setEventId("ScreenTimeoutAnomaly")
.setType(PowerAnomalyType.TYPE_SETTINGS_BANNER) .setType(PowerAnomalyType.TYPE_SETTINGS_BANNER)
.setKey(PowerAnomalyKey.KEY_SCREEN_TIMEOUT) .setKey(PowerAnomalyKey.KEY_SCREEN_TIMEOUT)
.setScore(1.1f)
.setWarningBannerInfo(WarningBannerInfo.newBuilder() .setWarningBannerInfo(WarningBannerInfo.newBuilder()
.setMainButtonDestination(ScreenTimeoutSettings.class.getName()) .setMainButtonDestination(ScreenTimeoutSettings.class.getName())
.setMainButtonSourceMetricsCategory(SettingsEnums.SCREEN_TIMEOUT) .setMainButtonSourceMetricsCategory(SettingsEnums.SCREEN_TIMEOUT)