From 880b8c6dbf4f0b66e95bef52520033f51eb625b0 Mon Sep 17 00:00:00 2001 From: Tom Hsu Date: Mon, 15 Apr 2024 01:50:12 +0000 Subject: [PATCH 1/8] Revert "Fixs user input nothing, but save it successfully" This reverts commit 6f27b8bca7fbd4fcf127744f2ebc4fc61d920968. Reason for revert: wrong logic Change-Id: Ic2eaaa5dd318a2eb92da1a3615590e7d132641a7 --- src/com/android/settings/network/SimOnboardingService.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/android/settings/network/SimOnboardingService.kt b/src/com/android/settings/network/SimOnboardingService.kt index a82125527a8..b99f18d9667 100644 --- a/src/com/android/settings/network/SimOnboardingService.kt +++ b/src/com/android/settings/network/SimOnboardingService.kt @@ -225,7 +225,7 @@ class SimOnboardingService { } fun addItemForRenaming(subInfo: SubscriptionInfo, newName: String) { - if (newName.isEmpty() && subInfo.displayName == newName) { + if (subInfo.displayName == newName) { return } renameMutableMap[subInfo.subscriptionId] = newName From cf292a025de9fca82bfad877fdc430c8c9d3a37a Mon Sep 17 00:00:00 2001 From: Zaiyue Xue Date: Mon, 15 Apr 2024 11:26:55 +0800 Subject: [PATCH 2/8] Support tips card directly changing settings [step-4] Add the settings name and settings value to gerrit proto. Bug: 333989261 Test: presubmit Change-Id: I169b615bb8a637614dd5b5c3eed52b4862d2e13f --- .../android/settings/fuelgauge/protos/power_anomaly_event.proto | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/com/android/settings/fuelgauge/protos/power_anomaly_event.proto b/src/com/android/settings/fuelgauge/protos/power_anomaly_event.proto index 3c0705fff24..ef0a9e09f03 100644 --- a/src/com/android/settings/fuelgauge/protos/power_anomaly_event.proto +++ b/src/com/android/settings/fuelgauge/protos/power_anomaly_event.proto @@ -57,6 +57,8 @@ message WarningBannerInfo { // Used in the SubSettingLauncher.setArguments(). optional string main_button_source_highlight_key = 6; optional string cancel_button_string = 7; + optional string main_button_config_settings_name = 8; + optional int32 main_button_config_settings_value = 9; } message WarningItemInfo { From 1ab367d3a00e9c435d1a34e59f94834166d25691 Mon Sep 17 00:00:00 2001 From: Haijie Hong Date: Mon, 15 Apr 2024 13:29:42 +0800 Subject: [PATCH 3/8] Exit bluetooth device details page when bluetooth is off Bug: 333836213 Test: atest BluetoothDeviceDetailsFragmentTest Change-Id: I4632c10a8f6f828885825e1ee46df6537a0c050c --- .../BluetoothDeviceDetailsFragment.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java index 87b2c6b65d0..e0171439198 100644 --- a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java +++ b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java @@ -19,7 +19,9 @@ package com.android.settings.bluetooth; import static android.bluetooth.BluetoothDevice.BOND_NONE; import static android.os.UserManager.DISALLOW_CONFIG_BLUETOOTH; +import android.app.Activity; import android.app.settings.SettingsEnums; +import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.content.Context; import android.content.Intent; @@ -51,6 +53,7 @@ import com.android.settings.dashboard.RestrictedDashboardFragment; import com.android.settings.inputmethod.KeyboardSettingsPreferenceController; import com.android.settings.overlay.FeatureFactory; import com.android.settings.slices.SlicePreferenceController; +import com.android.settingslib.bluetooth.BluetoothCallback; import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.core.AbstractPreferenceController; @@ -98,6 +101,20 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment private UserManager mUserManager; + private final BluetoothCallback mBluetoothCallback = + new BluetoothCallback() { + @Override + public void onBluetoothStateChanged(int bluetoothState) { + if (bluetoothState == BluetoothAdapter.STATE_OFF) { + Log.i(TAG, "Bluetooth is off, exit activity."); + Activity activity = getActivity(); + if (activity != null) { + activity.finish(); + } + } + } + }; + public BluetoothDeviceDetailsFragment() { super(DISALLOW_CONFIG_BLUETOOTH); } @@ -183,6 +200,14 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment use(BlockingPrefWithSliceController.class).setSliceUri(sliceEnabled ? featureProvider.getBluetoothDeviceSettingsUri(mCachedDevice.getDevice()) : null); + + mManager.getEventManager().registerCallback(mBluetoothCallback); + } + + @Override + public void onDetach() { + super.onDetach(); + mManager.getEventManager().unregisterCallback(mBluetoothCallback); } private void updateExtraControlUri(int viewWidth) { From 4fe887e908f21dc8356e5d71e13a9a4e0785d854 Mon Sep 17 00:00:00 2001 From: mxyyiyi Date: Thu, 11 Apr 2024 18:12:21 +0800 Subject: [PATCH 4/8] Fix failed test in BatteryTipsCardPreferenceTest. Fix: 313582999 Test: atest SettingsRoboTests:com.android.settings.fuelgauge.batteryusage.BatteryTipsCardPreferenceTest Change-Id: I31e4073332872df521cbc6811dae5e4b067e6ffa --- .../BatteryTipsCardPreferenceTest.java | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) 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 3ce3305c8fa..21840d2e686 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.util.Pair; import android.view.View; import com.android.settings.DisplaySettings; @@ -40,7 +41,6 @@ import com.android.settings.testutils.FakeFeatureFactory; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; @@ -51,6 +51,7 @@ import org.robolectric.RuntimeEnvironment; import java.util.Map; import java.util.Optional; +import java.util.TimeZone; @RunWith(RobolectricTestRunner.class) public final class BatteryTipsCardPreferenceTest { @@ -69,6 +70,7 @@ public final class BatteryTipsCardPreferenceTest { @Before public void setUp() { MockitoAnnotations.initMocks(this); + TimeZone.setDefault(TimeZone.getTimeZone("GMT+8")); mContext = spy(RuntimeEnvironment.application); mFeatureFactory = FakeFeatureFactory.setupForTest(); mBatteryTipsCardPreference = new BatteryTipsCardPreference(mContext, /* attrs= */ null); @@ -167,7 +169,6 @@ public final class BatteryTipsCardPreferenceTest { PowerAnomalyKey.KEY_SCREEN_TIMEOUT.getNumber()); } - @Ignore("b/313582999") @Test public void onClick_mainBtnOfAppsAnomaly_selectHighlightSlot() { final PowerAnomalyEvent appsAnomaly = BatteryTestUtils.createAppAnomalyEvent(); @@ -177,6 +178,7 @@ public final class BatteryTipsCardPreferenceTest { when(mPowerUsageAdvanced.findRelatedBatteryDiffEntry(any())).thenReturn(mFakeEntry); mPowerUsageAdvanced.onDisplayAnomalyEventUpdated(appsAnomaly, appsAnomaly); + assertHighlightSlotIndexPair(1, 0); mBatteryTipsCardPreference.onClick(mFakeView); assertThat(mBatteryTipsCardPreference.isVisible()).isFalse(); @@ -199,7 +201,6 @@ public final class BatteryTipsCardPreferenceTest { PowerAnomalyKey.KEY_APP_TOTAL_HIGHER_THAN_USUAL.getNumber()); } - @Ignore("b/313582999") @Test public void onClick_dismissBtnOfAppsAnomaly_keepHighlightSlotIndex() { final PowerAnomalyEvent appsAnomaly = BatteryTestUtils.createAppAnomalyEvent(); @@ -208,6 +209,7 @@ public final class BatteryTipsCardPreferenceTest { when(mPowerUsageAdvanced.findRelatedBatteryDiffEntry(any())).thenReturn(mFakeEntry); mPowerUsageAdvanced.onDisplayAnomalyEventUpdated(appsAnomaly, appsAnomaly); + assertHighlightSlotIndexPair(1, 0); mBatteryTipsCardPreference.onClick(mFakeView); assertThat(mBatteryTipsCardPreference.isVisible()).isFalse(); @@ -229,4 +231,21 @@ public final class BatteryTipsCardPreferenceTest { BatteryTipsController.ANOMALY_KEY, PowerAnomalyKey.KEY_APP_TOTAL_HIGHER_THAN_USUAL.getNumber()); } + + private void assertHighlightSlotIndexPair( + int dailyHighlightSlotIndex, int hourlyHighlightSlotIndex) { + assertThat(mPowerUsageAdvanced.mBatteryLevelData.isPresent()).isTrue(); + assertThat(mPowerUsageAdvanced.mHighlightEventWrapper.isPresent()).isTrue(); + Pair slotIndexPair = + mPowerUsageAdvanced + .mHighlightEventWrapper + .get() + .getHighlightSlotPair(mPowerUsageAdvanced.mBatteryLevelData.get()); + assertThat(slotIndexPair) + .isEqualTo(Pair.create(dailyHighlightSlotIndex, hourlyHighlightSlotIndex)); + assertThat(mPowerUsageAdvanced.mBatteryChartPreferenceController.mDailyHighlightSlotIndex) + .isEqualTo(dailyHighlightSlotIndex); + assertThat(mPowerUsageAdvanced.mBatteryChartPreferenceController.mHourlyHighlightSlotIndex) + .isEqualTo(hourlyHighlightSlotIndex); + } } From 1ee693f0edc75a6dd0af7813f3e8e5723c9682fe Mon Sep 17 00:00:00 2001 From: Zaiyue Xue Date: Mon, 15 Apr 2024 12:02:53 +0800 Subject: [PATCH 5/8] 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(); } } From 3f450dde286c4fce44fa14ece4e1e367cf4dbae3 Mon Sep 17 00:00:00 2001 From: sunnyshao Date: Tue, 2 Apr 2024 14:46:51 +0800 Subject: [PATCH 6/8] Fix talkback announce incorrect sound of the EID -- Use zero width space. Bug: 319049336 Test: manual test Change-Id: I93dd43ccf79727b8de7bba957431b77956f9b839 --- res/values/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index f695be50ebf..5d4cb63ad6c 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -3064,9 +3064,9 @@ Storage settings - EID + E​ID - EID (sim slot %1$d) + E​ID (sim slot %1$d) IMEI (sim slot %1$d) From 83f73732de74cf7c9869faa8f7d40789b031c288 Mon Sep 17 00:00:00 2001 From: josephpv Date: Mon, 15 Apr 2024 10:37:23 +0000 Subject: [PATCH 7/8] Set SKIP_FIRST_USE_HINTS setting for private space With this change the value of Secure settings SKIP_FIRST_USE_HINTS is set for private profile after creation of profile in PS setup flow. The value is set for the profile user so that first launch of an app in private space will not display introductory hints. Bug: 325596557 Test: PrivateSpaceMaintainerTest Change-Id: I63a967bba052a3dcb4742c95b89c6da19aba74d5 --- .../privatespace/PrivateSpaceMaintainer.java | 13 +++++++ .../PrivateSpaceMaintainerTest.java | 34 +++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/src/com/android/settings/privatespace/PrivateSpaceMaintainer.java b/src/com/android/settings/privatespace/PrivateSpaceMaintainer.java index 6d07305e375..3a084102ec5 100644 --- a/src/com/android/settings/privatespace/PrivateSpaceMaintainer.java +++ b/src/com/android/settings/privatespace/PrivateSpaceMaintainer.java @@ -20,6 +20,7 @@ import static android.os.UserManager.USER_TYPE_PROFILE_PRIVATE; import static android.provider.Settings.Secure.HIDE_PRIVATESPACE_ENTRY_POINT; import static android.provider.Settings.Secure.PRIVATE_SPACE_AUTO_LOCK; import static android.provider.Settings.Secure.PRIVATE_SPACE_AUTO_LOCK_AFTER_DEVICE_RESTART; +import static android.provider.Settings.Secure.SKIP_FIRST_USE_HINTS; import static android.provider.Settings.Secure.USER_SETUP_COMPLETE; import android.app.ActivityManager; @@ -122,6 +123,7 @@ public class PrivateSpaceMaintainer { Log.i(TAG, "Private space created with id: " + mUserHandle.getIdentifier()); resetPrivateSpaceSettings(); setUserSetupComplete(); + setSkipFirstUseHints(); } return true; } @@ -350,6 +352,17 @@ public class PrivateSpaceMaintainer { 1, mUserHandle.getIdentifier()); } + /** + * Sets the SKIP_FIRST_USE_HINTS for private profile so that the first launch of an app in + * private space will not display introductory hints. + */ + @GuardedBy("this") + private void setSkipFirstUseHints() { + Log.d(TAG, "setting SKIP_FIRST_USE_HINTS = 1 for private profile"); + Settings.Secure.putIntForUser(mContext.getContentResolver(), SKIP_FIRST_USE_HINTS, + 1, mUserHandle.getIdentifier()); + } + private boolean isPrivateSpaceAutoLockSupported() { return android.os.Flags.allowPrivateProfile() && android.multiuser.Flags.supportAutolockForPrivateSpace() diff --git a/tests/unit/src/com/android/settings/privatespace/PrivateSpaceMaintainerTest.java b/tests/unit/src/com/android/settings/privatespace/PrivateSpaceMaintainerTest.java index 637b4857ce5..522dcd5e242 100644 --- a/tests/unit/src/com/android/settings/privatespace/PrivateSpaceMaintainerTest.java +++ b/tests/unit/src/com/android/settings/privatespace/PrivateSpaceMaintainerTest.java @@ -421,6 +421,30 @@ public class PrivateSpaceMaintainerTest { assertThat(privateSpaceMaintainer.isPrivateSpaceEntryPointEnabled()).isFalse(); } + @Test + public void createPrivateSpace_psDoesNotExist_setsSkipFirstUseHints() { + mSetFlagsRule.enableFlags( + android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES); + assumeTrue(mContext.getSystemService(UserManager.class).canAddPrivateProfile()); + PrivateSpaceMaintainer privateSpaceMaintainer = + PrivateSpaceMaintainer.getInstance(mContext); + privateSpaceMaintainer.createPrivateSpace(); + assertThat(getSecureSkipFirstUseHints()).isEqualTo(1); + } + + @Test + public void createPrivateSpace_pSExists_doesNotChangeSkipFirstUseHints() { + mSetFlagsRule.enableFlags( + android.multiuser.Flags.FLAG_ENABLE_PRIVATE_SPACE_FEATURES); + assumeTrue(mContext.getSystemService(UserManager.class).canAddPrivateProfile()); + PrivateSpaceMaintainer privateSpaceMaintainer = + PrivateSpaceMaintainer.getInstance(mContext); + privateSpaceMaintainer.createPrivateSpace(); + assertThat(getSecureSkipFirstUseHints()).isEqualTo(1); + privateSpaceMaintainer.createPrivateSpace(); + assertThat(getSecureSkipFirstUseHints()).isEqualTo(1); + } + private int getSecureUserSetupComplete() { PrivateSpaceMaintainer privateSpaceMaintainer = PrivateSpaceMaintainer.getInstance(mContext); @@ -431,6 +455,16 @@ public class PrivateSpaceMaintainerTest { privateSpaceMaintainer.getPrivateProfileHandle().getIdentifier()); } + private int getSecureSkipFirstUseHints() { + PrivateSpaceMaintainer privateSpaceMaintainer = + PrivateSpaceMaintainer.getInstance(mContext); + return Settings.Secure.getIntForUser( + mContentResolver, + Settings.Secure.SKIP_FIRST_USE_HINTS, + 0, + privateSpaceMaintainer.getPrivateProfileHandle().getIdentifier()); + } + private int getPsSensitiveNotificationsValue(PrivateSpaceMaintainer privateSpaceMaintainer) { return Settings.Secure.getIntForUser(mContentResolver, LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, From e5d99fa93d7b7c9034bd492191d781c9f211f051 Mon Sep 17 00:00:00 2001 From: pajacechen Date: Mon, 15 Apr 2024 15:30:41 +0800 Subject: [PATCH 8/8] Fix "Free up space" not clickable issue - Adding CardPreference.java back for "Free up space" item - Rename CardPreference.kt to TipCardPreference.kt Bug: 333016642 Test: http://ab/I85800010265092964 Change-Id: I36062703b7ab5c21083459616234e3a86500719b --- res/xml/power_usage_summary.xml | 2 +- .../BatteryTipPreferenceController.java | 4 +- .../batterytip/tips/BatteryDefenderTip.java | 5 +- .../fuelgauge/batterytip/tips/BatteryTip.java | 11 +- .../tips/IncompatibleChargerTip.java | 3 +- .../settings/widget/CardPreference.java | 164 ++++++++++ ...CardPreference.kt => TipCardPreference.kt} | 2 +- .../BatteryTipPreferenceControllerTest.java | 6 +- .../tips/BatteryDefenderTipTest.java | 8 +- .../batterytip/tips/BatteryTipTest.java | 4 +- .../tips/IncompatibleChargerTipTest.java | 6 +- .../settings/widget/CardPreferenceTest.java | 293 ++++++++++++++++++ ...erenceTest.kt => TipCardPreferenceTest.kt} | 8 +- 13 files changed, 487 insertions(+), 29 deletions(-) create mode 100644 src/com/android/settings/widget/CardPreference.java rename src/com/android/settings/widget/{CardPreference.kt => TipCardPreference.kt} (99%) create mode 100644 tests/robotests/src/com/android/settings/widget/CardPreferenceTest.java rename tests/spa_unit/src/com/android/settings/widget/{CardPreferenceTest.kt => TipCardPreferenceTest.kt} (98%) diff --git a/res/xml/power_usage_summary.xml b/res/xml/power_usage_summary.xml index 1af8a8c2410..77c6b7322c2 100644 --- a/res/xml/power_usage_summary.xml +++ b/res/xml/power_usage_summary.xml @@ -33,7 +33,7 @@ android:selectable="false" settings:searchable="false" /> - diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java b/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java index 31cec6a46ba..e6f622cf00b 100644 --- a/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java +++ b/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java @@ -33,7 +33,7 @@ import com.android.settings.core.InstrumentedPreferenceFragment; import com.android.settings.fuelgauge.batterytip.actions.BatteryTipAction; import com.android.settings.fuelgauge.batterytip.tips.BatteryTip; import com.android.settings.overlay.FeatureFactory; -import com.android.settings.widget.CardPreference; +import com.android.settings.widget.TipCardPreference; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import java.util.List; @@ -55,7 +55,7 @@ public class BatteryTipPreferenceController extends BasePreferenceController { private SettingsActivity mSettingsActivity; private MetricsFeatureProvider mMetricsFeatureProvider; private boolean mNeedUpdate; - @VisibleForTesting CardPreference mCardPreference; + @VisibleForTesting TipCardPreference mCardPreference; @VisibleForTesting Context mPrefContext; InstrumentedPreferenceFragment mFragment; diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/BatteryDefenderTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/BatteryDefenderTip.java index 37162448b1b..dbe2722ebea 100644 --- a/src/com/android/settings/fuelgauge/batterytip/tips/BatteryDefenderTip.java +++ b/src/com/android/settings/fuelgauge/batterytip/tips/BatteryDefenderTip.java @@ -28,7 +28,6 @@ import androidx.preference.Preference; import com.android.settings.R; import com.android.settings.overlay.FeatureFactory; -import com.android.settings.widget.CardPreference; import com.android.settingslib.HelpUtils; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; @@ -80,9 +79,9 @@ public class BatteryDefenderTip extends BatteryTip { super.updatePreference(preference); final Context context = preference.getContext(); - CardPreference cardPreference = castToCardPreferenceSafely(preference); + var cardPreference = castToTipCardPreferenceSafely(preference); if (cardPreference == null) { - Log.e(TAG, "cast Preference to CardPreference failed"); + Log.e(TAG, "cast Preference to TipCardPreference failed"); return; } diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTip.java index 1345032d2ae..1f5374dac8a 100644 --- a/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTip.java +++ b/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTip.java @@ -23,10 +23,11 @@ import android.util.SparseIntArray; import androidx.annotation.DrawableRes; import androidx.annotation.IntDef; +import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; -import com.android.settings.widget.CardPreference; +import com.android.settings.widget.TipCardPreference; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import java.lang.annotation.Retention; @@ -165,7 +166,7 @@ public abstract class BatteryTip implements Comparable, Parcelable { preference.setTitle(getTitle(context)); preference.setSummary(getSummary(context)); preference.setIcon(getIconId()); - final CardPreference cardPreference = castToCardPreferenceSafely(preference); + final TipCardPreference cardPreference = castToTipCardPreferenceSafely(preference); if (cardPreference != null) { cardPreference.resetLayoutState(); } @@ -206,7 +207,9 @@ public abstract class BatteryTip implements Comparable, Parcelable { return "type=" + mType + " state=" + mState; } - public CardPreference castToCardPreferenceSafely(Preference preference) { - return preference instanceof CardPreference ? (CardPreference) preference : null; + /** Returns the converted {@link TipCardPreference} if it is valid. */ + @Nullable + public TipCardPreference castToTipCardPreferenceSafely(Preference preference) { + return preference instanceof TipCardPreference ? (TipCardPreference) preference : null; } } diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/IncompatibleChargerTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/IncompatibleChargerTip.java index 72c710c023f..7453dedf41c 100644 --- a/src/com/android/settings/fuelgauge/batterytip/tips/IncompatibleChargerTip.java +++ b/src/com/android/settings/fuelgauge/batterytip/tips/IncompatibleChargerTip.java @@ -26,7 +26,6 @@ import androidx.core.app.ActivityCompat; import androidx.preference.Preference; import com.android.settings.R; -import com.android.settings.widget.CardPreference; import com.android.settingslib.HelpUtils; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; @@ -74,7 +73,7 @@ public final class IncompatibleChargerTip extends BatteryTip { public void updatePreference(Preference preference) { super.updatePreference(preference); final Context context = preference.getContext(); - final CardPreference cardPreference = castToCardPreferenceSafely(preference); + final var cardPreference = castToTipCardPreferenceSafely(preference); if (cardPreference == null) { Log.e(TAG, "cast Preference to CardPreference failed"); return; diff --git a/src/com/android/settings/widget/CardPreference.java b/src/com/android/settings/widget/CardPreference.java new file mode 100644 index 00000000000..db6827efab8 --- /dev/null +++ b/src/com/android/settings/widget/CardPreference.java @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2019 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.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.widget.Button; + +import androidx.annotation.Nullable; +import androidx.preference.Preference; +import androidx.preference.PreferenceViewHolder; + +import com.android.settings.R; + +import com.google.android.material.card.MaterialCardView; + +import java.util.Optional; + +/** Preference that wrapped by {@link MaterialCardView} */ +public class CardPreference extends Preference { + @Nullable private View.OnClickListener mPrimaryBtnClickListener = null; + @Nullable private View.OnClickListener mSecondaryBtnClickListener = null; + @Nullable private String mPrimaryButtonText = null; + @Nullable private String mSecondaryButtonText = null; + private Optional