From 1ee693f0edc75a6dd0af7813f3e8e5723c9682fe Mon Sep 17 00:00:00 2001 From: Zaiyue Xue Date: Mon, 15 Apr 2024 12:02:53 +0800 Subject: [PATCH] Support tips card directly changing settings [step-5] Support clicking tips card directly changing settings. Bug: 333989261 Test: manual Change-Id: Idc485ee7430edff7f6d7265caf8d9d5cf97548b6 --- .../batteryusage/AnomalyEventWrapper.java | 36 ++++- .../batteryusage/BatteryTipsController.java | 3 +- .../BatteryTipsCardPreferenceTest.java | 46 +++++- .../settings/testutils/BatteryTestUtils.java | 142 ++++++++---------- 4 files changed, 146 insertions(+), 81 deletions(-) diff --git a/src/com/android/settings/fuelgauge/batteryusage/AnomalyEventWrapper.java b/src/com/android/settings/fuelgauge/batteryusage/AnomalyEventWrapper.java index 8924a0b15e3..be5de06e582 100644 --- a/src/com/android/settings/fuelgauge/batteryusage/AnomalyEventWrapper.java +++ b/src/com/android/settings/fuelgauge/batteryusage/AnomalyEventWrapper.java @@ -18,9 +18,13 @@ package com.android.settings.fuelgauge.batteryusage; import android.content.Context; import android.os.Bundle; +import android.provider.Settings; import android.text.TextUtils; +import android.util.Log; import android.util.Pair; +import androidx.annotation.Nullable; + import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.core.SubSettingLauncher; @@ -49,8 +53,8 @@ final class AnomalyEventWrapper { } private T getInfo( - Function warningBannerInfoSupplier, - Function warningItemInfoSupplier) { + @Nullable Function warningBannerInfoSupplier, + @Nullable Function warningItemInfoSupplier) { if (warningBannerInfoSupplier != null && mPowerAnomalyEvent.hasWarningBannerInfo()) { return warningBannerInfoSupplier.apply(mPowerAnomalyEvent.getWarningBannerInfo()); } else if (warningItemInfoSupplier != null && mPowerAnomalyEvent.hasWarningItemInfo()) { @@ -252,4 +256,32 @@ final class AnomalyEventWrapper { mSubSettingLauncher.launch(); return true; } + + boolean updateSystemSettingsIfAvailable() { + final String settingsName = + getInfo(WarningBannerInfo::getMainButtonConfigSettingsName, null); + final Integer settingsValue = + getInfo(WarningBannerInfo::getMainButtonConfigSettingsValue, null); + if (TextUtils.isEmpty(settingsName) || settingsValue == null) { + Log.d(TAG, "Failed to update settings due to invalid key or value"); + return false; + } + + try { + Settings.System.putInt(mContext.getContentResolver(), settingsName, settingsValue); + Log.d( + TAG, + String.format( + "Update settings name=%s to value=%d", settingsName, settingsValue)); + return true; + } catch (SecurityException e) { + Log.w( + TAG, + String.format( + "Failed to update settings name=%s to value=%d", + settingsName, settingsValue), + e); + return false; + } + } } diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsController.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsController.java index e22f987c12e..821c8680522 100644 --- a/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsController.java +++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsController.java @@ -123,7 +123,8 @@ public class BatteryTipsController extends BasePreferenceController { mCardPreference.setVisible(false); if (mOnAnomalyConfirmListener != null) { mOnAnomalyConfirmListener.onAnomalyConfirm(); - } else if (mAnomalyEventWrapper.launchSubSetting()) { + } else if (mAnomalyEventWrapper.updateSystemSettingsIfAvailable() + || mAnomalyEventWrapper.launchSubSetting()) { mMetricsFeatureProvider.action( /* attribution= */ SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL, /* action= */ SettingsEnums.ACTION_BATTERY_TIPS_CARD_ACCEPT, diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsCardPreferenceTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsCardPreferenceTest.java index 21840d2e686..5f863011915 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsCardPreferenceTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryTipsCardPreferenceTest.java @@ -30,6 +30,7 @@ import static org.mockito.Mockito.when; import android.app.settings.SettingsEnums; import android.content.Context; import android.content.Intent; +import android.provider.Settings; import android.util.Pair; import android.view.View; @@ -102,10 +103,10 @@ public final class BatteryTipsCardPreferenceTest { } @Test - public void onClick_mainBtnOfSettingsAnomaly_getAdaptiveBrightnessLauncher() { + public void onClick_mainBtnOfSettingsAnomalyLaunchPage_getAdaptiveBrightnessLauncher() { final ArgumentCaptor captor = ArgumentCaptor.forClass(Intent.class); PowerAnomalyEvent adaptiveBrightnessAnomaly = - BatteryTestUtils.createAdaptiveBrightnessAnomalyEvent(); + BatteryTestUtils.createAdaptiveBrightnessAnomalyEvent(/* changeSettings= */ false); when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true); when(mFakeView.getId()).thenReturn(R.id.main_button); doNothing().when(mContext).startActivity(captor.capture()); @@ -137,6 +138,47 @@ public final class BatteryTipsCardPreferenceTest { PowerAnomalyKey.KEY_BRIGHTNESS.getNumber()); } + @Test + public void onClick_mainBtnOfSettingsAnomalyChangeSettings_settingsChanged() + throws Settings.SettingNotFoundException { + Settings.System.putInt( + mContext.getContentResolver(), + Settings.System.SCREEN_BRIGHTNESS_MODE, + Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL); + final ArgumentCaptor captor = ArgumentCaptor.forClass(Intent.class); + PowerAnomalyEvent adaptiveBrightnessAnomaly = + BatteryTestUtils.createAdaptiveBrightnessAnomalyEvent(/* changeSettings= */ true); + when(mFeatureFactory.powerUsageFeatureProvider.isBatteryTipsEnabled()).thenReturn(true); + when(mFakeView.getId()).thenReturn(R.id.main_button); + doNothing().when(mContext).startActivity(captor.capture()); + + mPowerUsageAdvanced.onDisplayAnomalyEventUpdated( + adaptiveBrightnessAnomaly, adaptiveBrightnessAnomaly); + mBatteryTipsCardPreference.onClick(mFakeView); + + assertThat(mBatteryTipsCardPreference.isVisible()).isFalse(); + assertThat( + Settings.System.getInt( + mContext.getContentResolver(), + Settings.System.SCREEN_BRIGHTNESS_MODE)) + .isEqualTo(Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC); + verify(mContext, never()).startActivity(any(Intent.class)); + verify(mFeatureFactory.metricsFeatureProvider) + .action( + SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL, + SettingsEnums.ACTION_BATTERY_TIPS_CARD_SHOW, + SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL, + BatteryTipsController.ANOMALY_KEY, + PowerAnomalyKey.KEY_BRIGHTNESS.getNumber()); + verify(mFeatureFactory.metricsFeatureProvider) + .action( + SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL, + SettingsEnums.ACTION_BATTERY_TIPS_CARD_ACCEPT, + SettingsEnums.FUELGAUGE_BATTERY_HISTORY_DETAIL, + BatteryTipsController.ANOMALY_KEY, + PowerAnomalyKey.KEY_BRIGHTNESS.getNumber()); + } + @Test public void onClick_dismissBtnOfSettingsAnomaly_cardDismissAndLogged() { final PowerAnomalyEvent screenTimeoutAnomaly = diff --git a/tests/robotests/src/com/android/settings/testutils/BatteryTestUtils.java b/tests/robotests/src/com/android/settings/testutils/BatteryTestUtils.java index 745fca70157..4bddcd1b847 100644 --- a/tests/robotests/src/com/android/settings/testutils/BatteryTestUtils.java +++ b/tests/robotests/src/com/android/settings/testutils/BatteryTestUtils.java @@ -26,6 +26,7 @@ import android.hardware.usb.UsbPort; import android.hardware.usb.UsbPortStatus; import android.os.BatteryManager; import android.os.UserManager; +import android.provider.Settings; import androidx.room.Room; @@ -71,18 +72,14 @@ public class BatteryTestUtils { BatteryManager.BATTERY_STATUS_DISCHARGING); } - /** - * Sets the work profile mode. - */ + /** Sets the work profile mode. */ public static void setWorkProfile(Context context) { final UserManager userManager = context.getSystemService(UserManager.class); Shadows.shadowOf(userManager).setManagedProfile(true); Shadows.shadowOf(userManager).setIsSystemUser(false); } - /** - * Creates and sets up the in-memory {@link BatteryStateDatabase}. - */ + /** Creates and sets up the in-memory {@link BatteryStateDatabase}. */ public static BatteryStateDatabase setUpBatteryStateDatabase(Context context) { final BatteryStateDatabase inMemoryDatabase = Room.inMemoryDatabaseBuilder(context, BatteryStateDatabase.class) @@ -92,40 +89,39 @@ public class BatteryTestUtils { return inMemoryDatabase; } - /** - * Inserts a fake data into the database for testing. - */ + /** Inserts a fake data into the database for testing. */ public static void insertDataToBatteryStateTable( Context context, long timestamp, String packageName) { insertDataToBatteryStateTable( - context, timestamp, packageName, /*multiple=*/ false, /*isFullChargeStart=*/ false); + context, + timestamp, + packageName, + /* multiple= */ false, + /* isFullChargeStart= */ false); } - /** - * Inserts a fake data into the database for testing. - */ + /** Inserts a fake data into the database for testing. */ public static void insertDataToBatteryStateTable( Context context, long timestamp, String packageName, boolean isFullChargeStart) { insertDataToBatteryStateTable( - context, timestamp, packageName, /*multiple=*/ false, isFullChargeStart); + context, timestamp, packageName, /* multiple= */ false, isFullChargeStart); } - /** - * Inserts a fake data into the database for testing. - */ + /** Inserts a fake data into the database for testing. */ public static void insertDataToBatteryStateTable( - Context context, long timestamp, String packageName, boolean multiple, + Context context, + long timestamp, + String packageName, + boolean multiple, boolean isFullChargeStart) { DeviceBatteryState deviceBatteryState = - DeviceBatteryState - .newBuilder() + DeviceBatteryState.newBuilder() .setBatteryLevel(31) .setBatteryStatus(0) .setBatteryHealth(0) .build(); BatteryInformation batteryInformation = - BatteryInformation - .newBuilder() + BatteryInformation.newBuilder() .setDeviceBatteryState(deviceBatteryState) .setIsHidden(true) .setBootTimestamp(timestamp - 1) @@ -145,16 +141,15 @@ public class BatteryTestUtils { final BatteryState state = new BatteryState( - /*uid=*/ 1001L, - /*userId=*/ 100L, + /* uid= */ 1001L, + /* userId= */ 100L, packageName, timestamp, - /*consumerType=*/ 2, + /* consumerType= */ 2, isFullChargeStart, ConvertUtils.convertBatteryInformationToString(batteryInformation), ""); - BatteryStateDao dao = - BatteryStateDatabase.getInstance(context).batteryStateDao(); + BatteryStateDao dao = BatteryStateDatabase.getInstance(context).batteryStateDao(); if (multiple) { dao.insertAll(ImmutableList.of(state)); } else { @@ -162,31 +157,26 @@ public class BatteryTestUtils { } } - /** - * Inserts a fake data into the database for testing. - */ + /** Inserts a fake data into the database for testing. */ public static void insertDataToAppUsageEventTable( Context context, long userId, long timestamp, String packageName) { insertDataToAppUsageEventTable( - context, userId, timestamp, packageName, /*multiple=*/ false); + context, userId, timestamp, packageName, /* multiple= */ false); } - /** - * Inserts a fake data into the database for testing. - */ + /** Inserts a fake data into the database for testing. */ public static void insertDataToAppUsageEventTable( Context context, long userId, long timestamp, String packageName, boolean multiple) { final AppUsageEventEntity entity = new AppUsageEventEntity( - /*uid=*/ 101L, + /* uid= */ 101L, userId, timestamp, - /*appUsageEventType=*/ 2, + /* appUsageEventType= */ 2, packageName, - /*instanceId=*/ 10001, - /*taskRootPackageName=*/ "com.android.settings"); - AppUsageEventDao dao = - BatteryStateDatabase.getInstance(context).appUsageEventDao(); + /* instanceId= */ 10001, + /* taskRootPackageName= */ "com.android.settings"); + AppUsageEventDao dao = BatteryStateDatabase.getInstance(context).appUsageEventDao(); if (multiple) { dao.insertAll(ImmutableList.of(entity)); } else { @@ -194,9 +184,7 @@ public class BatteryTestUtils { } } - /** - * Gets customized battery changed intent. - */ + /** Gets customized battery changed intent. */ public static Intent getCustomBatteryIntent(int plugged, int level, int scale, int status) { Intent intent = new Intent(); intent.putExtra(BatteryManager.EXTRA_PLUGGED, plugged); @@ -207,9 +195,7 @@ public class BatteryTestUtils { return intent; } - /** - * Configures the incompatible charger environment. - */ + /** Configures the incompatible charger environment. */ public static void setupIncompatibleEvent( UsbPort mockUsbPort, UsbManager mockUsbManager, UsbPortStatus mockUsbPortStatus) { final List usbPorts = new ArrayList<>(); @@ -219,19 +205,15 @@ public class BatteryTestUtils { when(mockUsbPort.supportsComplianceWarnings()).thenReturn(true); when(mockUsbPortStatus.isConnected()).thenReturn(true); when(mockUsbPortStatus.getComplianceWarnings()) - .thenReturn(new int[]{UsbPortStatus.COMPLIANCE_WARNING_DEBUG_ACCESSORY}); + .thenReturn(new int[] {UsbPortStatus.COMPLIANCE_WARNING_DEBUG_ACCESSORY}); } - /** - * Create an empty power anomaly event list proto. - */ + /** Create an empty power anomaly event list proto. */ public static PowerAnomalyEventList createEmptyPowerAnomalyEventList() { return PowerAnomalyEventList.getDefaultInstance(); } - /** - * Create an non-empty power anomaly event list proto. - */ + /** Create an non-empty power anomaly event list proto. */ public static PowerAnomalyEventList createNonEmptyPowerAnomalyEventList() { return PowerAnomalyEventList.newBuilder() .addPowerAnomalyEvents(0, createAdaptiveBrightnessAnomalyEvent()) @@ -239,27 +221,35 @@ public class BatteryTestUtils { .build(); } - /** - * Create a power anomaly event proto of adaptive brightness. - */ + /** Create a power anomaly event proto of adaptive brightness. */ public static PowerAnomalyEvent createAdaptiveBrightnessAnomalyEvent() { + return createAdaptiveBrightnessAnomalyEvent(false); + } + + /** Create a power anomaly event proto of adaptive brightness. */ + public static PowerAnomalyEvent createAdaptiveBrightnessAnomalyEvent(boolean changeSettings) { + WarningBannerInfo.Builder warningBannerInfoBuilder = + WarningBannerInfo.newBuilder() + .setMainButtonDestination(DisplaySettings.class.getName()) + .setMainButtonSourceMetricsCategory(SettingsEnums.DISPLAY) + .setMainButtonSourceHighlightKey("auto_brightness_entry"); + if (changeSettings) { + warningBannerInfoBuilder + .setMainButtonConfigSettingsName(Settings.System.SCREEN_BRIGHTNESS_MODE) + .setMainButtonConfigSettingsValue( + Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC); + } return PowerAnomalyEvent.newBuilder() .setEventId("BrightnessAnomaly") .setType(PowerAnomalyType.TYPE_SETTINGS_BANNER) .setKey(PowerAnomalyKey.KEY_BRIGHTNESS) .setDismissRecordKey(PowerAnomalyKey.KEY_BRIGHTNESS.name()) .setScore(1.2f) - .setWarningBannerInfo(WarningBannerInfo.newBuilder() - .setMainButtonDestination(DisplaySettings.class.getName()) - .setMainButtonSourceMetricsCategory(SettingsEnums.DISPLAY) - .setMainButtonSourceHighlightKey("auto_brightness_entry") - .build()) + .setWarningBannerInfo(warningBannerInfoBuilder.build()) .build(); } - /** - * Create a power anomaly event proto of screen timeout. - */ + /** Create a power anomaly event proto of screen timeout. */ public static PowerAnomalyEvent createScreenTimeoutAnomalyEvent() { return PowerAnomalyEvent.newBuilder() .setEventId("ScreenTimeoutAnomaly") @@ -267,17 +257,16 @@ public class BatteryTestUtils { .setKey(PowerAnomalyKey.KEY_SCREEN_TIMEOUT) .setDismissRecordKey(PowerAnomalyKey.KEY_SCREEN_TIMEOUT.name()) .setScore(1.1f) - .setWarningBannerInfo(WarningBannerInfo.newBuilder() - .setMainButtonDestination(ScreenTimeoutSettings.class.getName()) - .setMainButtonSourceMetricsCategory(SettingsEnums.SCREEN_TIMEOUT) - .setMainButtonSourceHighlightKey("60000") - .build()) + .setWarningBannerInfo( + WarningBannerInfo.newBuilder() + .setMainButtonDestination(ScreenTimeoutSettings.class.getName()) + .setMainButtonSourceMetricsCategory(SettingsEnums.SCREEN_TIMEOUT) + .setMainButtonSourceHighlightKey("60000") + .build()) .build(); } - /** - * Create a power anomaly event proto of app anomaly. - */ + /** Create a power anomaly event proto of app anomaly. */ public static PowerAnomalyEvent createAppAnomalyEvent() { return PowerAnomalyEvent.newBuilder() .setEventId("AppAnomaly") @@ -285,10 +274,11 @@ public class BatteryTestUtils { .setKey(PowerAnomalyKey.KEY_APP_TOTAL_HIGHER_THAN_USUAL) .setDismissRecordKey("KEY_APP_1") .setScore(2.0f) - .setWarningItemInfo(WarningItemInfo.newBuilder() - .setStartTimestamp(1694361600000L) // 2023-09-11 00:00:00 - .setEndTimestamp(1694368800000L) // 2023-09-11 02:00:00 - .build()) + .setWarningItemInfo( + WarningItemInfo.newBuilder() + .setStartTimestamp(1694361600000L) // 2023-09-11 00:00:00 + .setEndTimestamp(1694368800000L) // 2023-09-11 02:00:00 + .build()) .build(); } }