From 4fd34aa3861c7c2c75e70aa59d0ad1c1f854aed9 Mon Sep 17 00:00:00 2001 From: Julia Reynolds Date: Wed, 3 Jul 2024 16:19:18 -0400 Subject: [PATCH 01/15] Create a new link preference for priority modes entry Test: ZenModesSummaryHelperTest Test: manual. Successfully search for both 'event' and 'priority' Flag: android.app.modes_ui Bug: 341726633 Change-Id: Ib7bd1a5c2f7b06b1728a66f7a9cef53cd45acc0b --- res/values/strings.xml | 8 ++ res/xml/configure_notification_settings.xml | 9 ++ .../modes/ZenModeSummaryHelper.java | 32 +++++ .../ZenModesLinkPreferenceController.java | 120 ++++++++++++++++++ .../zen/ZenModePreferenceController.java | 16 +-- .../modes/ZenModesSummaryHelperTest.java | 99 +++++++++++++++ 6 files changed, 269 insertions(+), 15 deletions(-) create mode 100644 src/com/android/settings/notification/modes/ZenModesLinkPreferenceController.java diff --git a/res/values/strings.xml b/res/values/strings.xml index 40b160a3915..29cbc9011e0 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -8118,6 +8118,14 @@ Additional actions + + + {count, plural, + =0 {Off} + =1 {Off / 1 mode can turn on automatically} + other {Off / # modes can turn on automatically} + } + Display settings diff --git a/res/xml/configure_notification_settings.xml b/res/xml/configure_notification_settings.xml index b673a0839b0..1e5b241ea82 100644 --- a/res/xml/configure_notification_settings.xml +++ b/res/xml/configure_notification_settings.xml @@ -135,6 +135,15 @@ settings:controller="com.android.settings.notification.zen.ZenModePreferenceController" /> + + ruleMap = config.automaticRules; + if (ruleMap != null) { + for (ZenModeConfig.ZenRule rule : ruleMap.values()) { + if (rule != null && rule.enabled) { + count++; + } + } + } + MessageFormat msgFormat = new MessageFormat( + mContext.getString(R.string.modes_sound_summary_off), + Locale.getDefault()); + Map msgArgs = new HashMap<>(); + msgArgs.put("count", count); + return msgFormat.format(msgArgs); + } + } } diff --git a/src/com/android/settings/notification/modes/ZenModesLinkPreferenceController.java b/src/com/android/settings/notification/modes/ZenModesLinkPreferenceController.java new file mode 100644 index 00000000000..f2679d7d0d0 --- /dev/null +++ b/src/com/android/settings/notification/modes/ZenModesLinkPreferenceController.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2024 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.notification.modes; + +import android.app.Flags; +import android.app.NotificationManager; +import android.content.ContentResolver; +import android.content.Context; +import android.database.ContentObserver; +import android.net.Uri; +import android.os.Handler; +import android.os.UserHandle; +import android.provider.Settings; + +import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; + +import com.android.settings.R; +import com.android.settings.core.BasePreferenceController; +import com.android.settingslib.core.lifecycle.LifecycleObserver; +import com.android.settingslib.core.lifecycle.events.OnPause; +import com.android.settingslib.core.lifecycle.events.OnResume; + +public class ZenModesLinkPreferenceController extends BasePreferenceController + implements LifecycleObserver, OnResume, OnPause { + + private SettingObserver mSettingObserver; + private ZenModeSummaryHelper mSummaryBuilder; + private NotificationManager mNm; + + public ZenModesLinkPreferenceController(Context context, String key) { + super(context, key); + mSummaryBuilder = new ZenModeSummaryHelper(context, ZenHelperBackend.getInstance(context)); + mNm = mContext.getSystemService(NotificationManager.class); + } + + @Override + @AvailabilityStatus + public int getAvailabilityStatus() { + return Flags.modesUi() ? AVAILABLE : UNSUPPORTED_ON_DEVICE; + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + Preference preference = screen.findPreference(getPreferenceKey()); + mSettingObserver = new SettingObserver(preference); + } + + @Override + public void onResume() { + if (mSettingObserver != null) { + mSettingObserver.register(mContext.getContentResolver()); + } + } + + @Override + public void onPause() { + if (mSettingObserver != null) { + mSettingObserver.unregister(mContext.getContentResolver()); + } + } + + @Override + public void updateState(Preference preference) { + preference.setSummary(mSummaryBuilder.getSoundSummary( + Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.ZEN_MODE, + Settings.Global.ZEN_MODE_OFF), + mNm.getZenModeConfig())); + } + + class SettingObserver extends ContentObserver { + private final Uri ZEN_MODE_URI = Settings.Global.getUriFor(Settings.Global.ZEN_MODE); + private final Uri ZEN_MODE_CONFIG_ETAG_URI = Settings.Global.getUriFor( + Settings.Global.ZEN_MODE_CONFIG_ETAG); + + private final Preference mPreference; + + public SettingObserver(Preference preference) { + super(new Handler()); + mPreference = preference; + } + + public void register(ContentResolver cr) { + cr.registerContentObserver(ZEN_MODE_URI, false, this, UserHandle.USER_ALL); + cr.registerContentObserver(ZEN_MODE_CONFIG_ETAG_URI, false, this, UserHandle.USER_ALL); + } + + public void unregister(ContentResolver cr) { + cr.unregisterContentObserver(this); + } + + @Override + public void onChange(boolean selfChange, Uri uri) { + super.onChange(selfChange, uri); + if (ZEN_MODE_URI.equals(uri)) { + updateState(mPreference); + } + + if (ZEN_MODE_CONFIG_ETAG_URI.equals(uri)) { + updateState(mPreference); + } + } + } +} diff --git a/src/com/android/settings/notification/zen/ZenModePreferenceController.java b/src/com/android/settings/notification/zen/ZenModePreferenceController.java index 7c36d80f8ad..c21bc3bc260 100644 --- a/src/com/android/settings/notification/zen/ZenModePreferenceController.java +++ b/src/com/android/settings/notification/zen/ZenModePreferenceController.java @@ -28,9 +28,7 @@ import android.provider.Settings; import androidx.preference.Preference; import androidx.preference.PreferenceScreen; -import com.android.settings.R; import com.android.settings.core.BasePreferenceController; -import com.android.settings.notification.modes.ZenModesListFragment; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnPause; import com.android.settingslib.core.lifecycle.events.OnResume; @@ -51,7 +49,6 @@ public class ZenModePreferenceController extends BasePreferenceController super.displayPreference(screen); Preference preference = screen.findPreference(getPreferenceKey()); mSettingObserver = new SettingObserver(preference); - maybeSetTitleAndDestination(preference); } @Override @@ -70,28 +67,17 @@ public class ZenModePreferenceController extends BasePreferenceController @Override public int getAvailabilityStatus() { - return AVAILABLE_UNSEARCHABLE; + return Flags.modesUi() ? UNSUPPORTED_ON_DEVICE : AVAILABLE_UNSEARCHABLE; } @Override public void updateState(Preference preference) { super.updateState(preference); - maybeSetTitleAndDestination(preference); if (preference.isEnabled()) { preference.setSummary(mSummaryBuilder.getSoundSummary()); } } - // Only when modes_ui is active: change title & target fragment. - private void maybeSetTitleAndDestination(Preference preference) { - if (!Flags.modesUi()) { - return; - } - - preference.setTitle(R.string.zen_modes_list_title); - preference.setFragment(ZenModesListFragment.class.getCanonicalName()); - } - class SettingObserver extends ContentObserver { private final Uri ZEN_MODE_URI = Settings.Global.getUriFor(Settings.Global.ZEN_MODE); private final Uri ZEN_MODE_CONFIG_ETAG_URI = Settings.Global.getUriFor( diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModesSummaryHelperTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModesSummaryHelperTest.java index 62b5ee02ee6..308650fe8c9 100644 --- a/tests/robotests/src/com/android/settings/notification/modes/ZenModesSummaryHelperTest.java +++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModesSummaryHelperTest.java @@ -16,6 +16,10 @@ package com.android.settings.notification.modes; +import static android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; +import static android.provider.Settings.Global.ZEN_MODE_OFF; +import static android.service.notification.Condition.SOURCE_UNKNOWN; +import static android.service.notification.Condition.STATE_TRUE; import static android.service.notification.ZenPolicy.CONVERSATION_SENDERS_ANYONE; import static android.service.notification.ZenPolicy.PEOPLE_TYPE_ANYONE; import static android.service.notification.ZenPolicy.PEOPLE_TYPE_CONTACTS; @@ -24,13 +28,21 @@ import static android.service.notification.ZenPolicy.VISUAL_EFFECT_LIGHTS; import static com.google.common.truth.Truth.assertThat; +import android.app.Flags; +import android.content.ComponentName; import android.content.Context; +import android.net.Uri; +import android.platform.test.annotations.EnableFlags; +import android.platform.test.flag.junit.SetFlagsRule; +import android.service.notification.Condition; import android.service.notification.ZenDeviceEffects; +import android.service.notification.ZenModeConfig; import android.service.notification.ZenPolicy; import com.android.settingslib.notification.modes.ZenMode; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.MockitoAnnotations; @@ -46,6 +58,10 @@ public class ZenModesSummaryHelperTest { private ZenModeSummaryHelper mSummaryHelper; + @Rule + public final SetFlagsRule mSetFlagsRule = new SetFlagsRule( + SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT); + @Before public void setup() { MockitoAnnotations.initMocks(this); @@ -351,4 +367,87 @@ public class ZenModesSummaryHelperTest { assertThat(mSummaryHelper.getAppsSummary(zenMode, apps)).isEqualTo("FifthApp, FourthApp, " + "and 4 more can interrupt"); } + + @Test + @EnableFlags(Flags.FLAG_MODES_UI) + public void getSoundSummary_off_noRules() { + ZenModeConfig config = new ZenModeConfig(); + + assertThat(mSummaryHelper.getSoundSummary(ZEN_MODE_OFF, config)).isEqualTo("Off"); + } + + @Test + @EnableFlags(Flags.FLAG_MODES_UI) + public void getSoundSummary_off_oneRule() { + ZenModeConfig config = new ZenModeConfig(); + ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule(); + rule.enabled = true; + config.automaticRules.put("key", rule); + + assertThat(mSummaryHelper.getSoundSummary(ZEN_MODE_OFF, config)) + .isEqualTo("Off / 1 mode can turn on automatically"); + } + + @Test + @EnableFlags(Flags.FLAG_MODES_UI) + public void getSoundSummary_off_twoRules() { + ZenModeConfig config = new ZenModeConfig(); + ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule(); + rule.enabled = true; + ZenModeConfig.ZenRule rule2 = new ZenModeConfig.ZenRule(); + rule2.enabled = true; + config.automaticRules.put("key", rule); + config.automaticRules.put("key2", rule2); + + assertThat(mSummaryHelper.getSoundSummary(ZEN_MODE_OFF, config)) + .isEqualTo("Off / 2 modes can turn on automatically"); + } + + @Test + @EnableFlags(Flags.FLAG_MODES_UI) + public void getSoundSummary_on_noDescription() { + ZenModeConfig config = new ZenModeConfig(); + config.manualRule.conditionId = Uri.EMPTY; + config.manualRule.pkg = "android"; + config.manualRule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS; + config.manualRule.condition = new Condition(Uri.EMPTY, "", STATE_TRUE, SOURCE_UNKNOWN); + assertThat(mSummaryHelper.getSoundSummary(ZEN_MODE_IMPORTANT_INTERRUPTIONS, config)) + .isEqualTo("On"); + } + + @Test + @EnableFlags(Flags.FLAG_MODES_UI) + public void getSoundSummary_on_manualDescription() { + ZenModeConfig config = new ZenModeConfig(); + config.manualRule.conditionId = ZenModeConfig.toCountdownConditionId( + System.currentTimeMillis() + 10000, false); + config.manualRule.pkg = "android"; + config.manualRule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS; + config.manualRule.condition = new Condition(Uri.EMPTY, "", STATE_TRUE, SOURCE_UNKNOWN); + assertThat(mSummaryHelper.getSoundSummary(ZEN_MODE_IMPORTANT_INTERRUPTIONS, config)) + .startsWith("On /"); + } + + @Test + @EnableFlags(Flags.FLAG_MODES_UI) + public void getSoundSummary_on_automatic() { + ZenModeConfig config = new ZenModeConfig(); + ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule(); + rule.configurationActivity = new ComponentName("a", "a"); + rule.component = new ComponentName("b", "b"); + rule.conditionId = new Uri.Builder().scheme("hello").build(); + rule.condition = new Condition(rule.conditionId, "", STATE_TRUE); + rule.enabled = true; + rule.creationTime = 123; + rule.id = "id"; + rule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS; + rule.modified = true; + rule.name = "name"; + rule.snoozing = false; + rule.pkg = "b"; + config.automaticRules.put("key", rule); + + assertThat(mSummaryHelper.getSoundSummary(ZEN_MODE_IMPORTANT_INTERRUPTIONS, config)) + .startsWith("On /"); + } } From 86a9e06419cc96be8e7faf306f933a15b4ee3b75 Mon Sep 17 00:00:00 2001 From: Pawan Wagh Date: Wed, 3 Jul 2024 21:37:04 +0000 Subject: [PATCH 02/15] Repost PageAgnostic mode notification when dismissed Device is in experimental mode when using 16kB developer option. When the notification is dimissed, repost it again. Bug: 351029724 Test: m Settings && adb install -r $ANDROID_PRODUCT_OUT/system_ext/priv-app/Settings/Settings.apk Flag: EXEMPT bugfix Change-Id: Ie579b6c4dd060b165c6cc8ae635d48e257d49bec --- .../development/Enable16KBootReceiver.java | 20 +++++++++---------- .../PageAgnosticNotificationService.java | 18 ++++++++++++++--- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/com/android/settings/development/Enable16KBootReceiver.java b/src/com/android/settings/development/Enable16KBootReceiver.java index 007a67b9d4f..bc2096d9452 100644 --- a/src/com/android/settings/development/Enable16KBootReceiver.java +++ b/src/com/android/settings/development/Enable16KBootReceiver.java @@ -28,17 +28,17 @@ public class Enable16KBootReceiver extends BroadcastReceiver { @Override public void onReceive(@NonNull Context context, @NonNull Intent intent) { String action = intent.getAction(); - if (!Intent.ACTION_BOOT_COMPLETED.equals(action)) { - return; - } + if (Intent.ACTION_BOOT_COMPLETED.equals(action) + || PageAgnosticNotificationService.INTENT_ACTION_DISMISSED.equals(action)) { + // Do nothing if device is not in page-agnostic mode + if (!Enable16kUtils.isPageAgnosticModeOn(context)) { + return; + } - // Do nothing if device is not in page-agnostic mode - if (!Enable16kUtils.isPageAgnosticModeOn(context)) { - return; + // start a service to post persistent notification + Intent startServiceIntent = new Intent(context, PageAgnosticNotificationService.class); + startServiceIntent.setAction(action); + context.startServiceAsUser(startServiceIntent, UserHandle.SYSTEM); } - - // start a service to post persistent notification - Intent startNotificationIntent = new Intent(context, PageAgnosticNotificationService.class); - context.startServiceAsUser(startNotificationIntent, UserHandle.SYSTEM); } } diff --git a/src/com/android/settings/development/PageAgnosticNotificationService.java b/src/com/android/settings/development/PageAgnosticNotificationService.java index 1bdda410d69..d33f1da1fc7 100644 --- a/src/com/android/settings/development/PageAgnosticNotificationService.java +++ b/src/com/android/settings/development/PageAgnosticNotificationService.java @@ -34,6 +34,8 @@ public class PageAgnosticNotificationService extends Service { private static final String NOTIFICATION_CHANNEL_ID = "com.android.settings.development.PageAgnosticNotificationService"; + public static final String INTENT_ACTION_DISMISSED = + "com.android.settings.development.NOTIFICATION_DISMISSED"; private static final int NOTIFICATION_ID = 1; static final int DISABLE_UPDATES_SETTING = 1; @@ -63,6 +65,9 @@ public class PageAgnosticNotificationService extends Service { public void onCreate() { super.onCreate(); createNotificationChannel(); + + // No updates should be allowed in page-agnostic mode + disableAutomaticUpdates(); } private Notification buildNotification() { @@ -89,6 +94,15 @@ public class PageAgnosticNotificationService extends Service { notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); + Intent dismissIntent = new Intent(this, Enable16KBootReceiver.class); + dismissIntent.setAction(INTENT_ACTION_DISMISSED); + PendingIntent dismissPendingIntent = + PendingIntent.getBroadcast( + this.getApplicationContext(), + 0, + dismissIntent, + PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); + Notification.Action action = new Notification.Action.Builder( R.drawable.empty_icon, @@ -104,6 +118,7 @@ public class PageAgnosticNotificationService extends Service { .setOngoing(true) .setSmallIcon(R.drawable.ic_settings_24dp) .setContentIntent(notifyPendingIntent) + .setDeleteIntent(dismissPendingIntent) .addAction(action); return builder.build(); @@ -131,9 +146,6 @@ public class PageAgnosticNotificationService extends Service { if (mNotificationManager != null) { mNotificationManager.notify(NOTIFICATION_ID, notification); } - - // No updates should be allowed in page-agnostic mode - disableAutomaticUpdates(); return Service.START_REDELIVER_INTENT; } } From 5d96249d6e512416edcd35181eb86514a8e20f1a Mon Sep 17 00:00:00 2001 From: Haijie Hong Date: Wed, 3 Jul 2024 11:29:41 +0800 Subject: [PATCH 03/15] Add ring indicator for battery level Bug: 343317785 Test: atest AdvancedBluetoothDetailsHeaderControllerTest Flag: com.android.settings.flags.enable_bluetooth_device_details_polish Change-Id: Ib657db60be8d377ea990674c4d2438ea8a6854d0 --- .../settings_bluetooth_declarations.aconfig | 7 ++++ res/layout/advanced_bt_entity_sub.xml | 40 ++++++++++++++----- res/values/colors.xml | 3 ++ ...ancedBluetoothDetailsHeaderController.java | 20 ++++++++++ ...dBluetoothDetailsHeaderControllerTest.java | 16 +++++++- .../stylus/StylusUsiHeaderControllerTest.java | 5 ++- 6 files changed, 78 insertions(+), 13 deletions(-) diff --git a/aconfig/settings_bluetooth_declarations.aconfig b/aconfig/settings_bluetooth_declarations.aconfig index c2684f29124..b8b9d9fe569 100644 --- a/aconfig/settings_bluetooth_declarations.aconfig +++ b/aconfig/settings_bluetooth_declarations.aconfig @@ -24,3 +24,10 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "enable_bluetooth_device_details_polish" + namespace: "cross_device_experiences" + description: "Gates whether to enable bluetooth device details polish" + bug: "343317785" +} diff --git a/res/layout/advanced_bt_entity_sub.xml b/res/layout/advanced_bt_entity_sub.xml index d29c34f590e..90ac4567176 100644 --- a/res/layout/advanced_bt_entity_sub.xml +++ b/res/layout/advanced_bt_entity_sub.xml @@ -17,21 +17,43 @@ - + + + + + + #1F1F1F1F + + + #9ED582 diff --git a/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java b/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java index 13268314fc3..11ecf8ba90d 100644 --- a/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java +++ b/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java @@ -39,6 +39,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.LinearLayout; +import android.widget.ProgressBar; import android.widget.TextView; import androidx.annotation.VisibleForTesting; @@ -46,6 +47,7 @@ import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.core.BasePreferenceController; +import com.android.settings.flags.Flags; import com.android.settings.fuelgauge.BatteryMeterView; import com.android.settingslib.bluetooth.BluetoothUtils; import com.android.settingslib.bluetooth.CachedBluetoothDevice; @@ -456,18 +458,24 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont com.android.settings.Utils.formatPercentage(batteryLevel)); batterySummaryView.setVisibility(View.VISIBLE); showBatteryIcon(linearLayout, batteryLevel, lowBatteryLevel, charging); + showBatteryRing(linearLayout, batteryLevel); } else { if (deviceId == MAIN_DEVICE_ID) { linearLayout.setVisibility(View.VISIBLE); linearLayout.findViewById(R.id.bt_battery_icon).setVisibility(View.GONE); + int level = preloadedNativeBatteryLevel.get(); if (level != BluetoothDevice.BATTERY_LEVEL_UNKNOWN && level != BluetoothDevice.BATTERY_LEVEL_BLUETOOTH_OFF) { batterySummaryView.setText( com.android.settings.Utils.formatPercentage(level)); batterySummaryView.setVisibility(View.VISIBLE); + showBatteryRing(linearLayout, level); } else { batterySummaryView.setVisibility(View.GONE); + if (Flags.enableBluetoothDeviceDetailsPolish()) { + linearLayout.findViewById(R.id.battery_ring).setVisibility(View.GONE); + } } } else { // Hide it if it doesn't have battery information @@ -481,6 +489,7 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont com.android.settings.Utils.formatPercentage(batteryLevel)); batterySummaryView.setVisibility(View.VISIBLE); showBatteryIcon(linearLayout, batteryLevel, lowBatteryLevel, charging); + showBatteryRing(linearLayout, batteryLevel); } else { batterySummaryView.setVisibility(View.GONE); } @@ -610,6 +619,14 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont imageView.setVisibility(View.VISIBLE); } + private void showBatteryRing(LinearLayout linearLayout, int level) { + if (Flags.enableBluetoothDeviceDetailsPolish()) { + ProgressBar batteryProgress = linearLayout.findViewById(R.id.battery_ring); + batteryProgress.setProgress(level); + batteryProgress.setVisibility(View.VISIBLE); + } + } + private void updateDisconnectLayout() { mLayoutPreference.findViewById(R.id.layout_left).setVisibility(View.GONE); mLayoutPreference.findViewById(R.id.layout_right).setVisibility(View.GONE); @@ -620,6 +637,9 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont linearLayout.findViewById(R.id.header_title).setVisibility(View.GONE); linearLayout.findViewById(R.id.bt_battery_summary).setVisibility(View.GONE); linearLayout.findViewById(R.id.bt_battery_icon).setVisibility(View.GONE); + if (Flags.enableBluetoothDeviceDetailsPolish()) { + linearLayout.findViewById(R.id.battery_ring).setVisibility(View.GONE); + } // Only show bluetooth icon final BluetoothDevice bluetoothDevice = mCachedDevice.getDevice(); diff --git a/tests/robotests/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderControllerTest.java index d24a83b9c4a..8d96f213446 100644 --- a/tests/robotests/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderControllerTest.java +++ b/tests/robotests/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderControllerTest.java @@ -28,16 +28,20 @@ import android.bluetooth.BluetoothDevice; import android.content.Context; import android.graphics.Bitmap; import android.graphics.drawable.Drawable; +import android.platform.test.flag.junit.SetFlagsRule; import android.provider.DeviceConfig; import android.view.LayoutInflater; import android.view.View; import android.widget.ImageView; import android.widget.LinearLayout; +import android.widget.ProgressBar; import android.widget.TextView; import com.android.settings.R; +import com.android.settings.SettingsActivity; import com.android.settings.core.BasePreferenceController; import com.android.settings.core.SettingsUIDeviceConfig; +import com.android.settings.flags.Flags; import com.android.settings.fuelgauge.BatteryMeterView; import com.android.settings.testutils.shadow.ShadowDeviceConfig; import com.android.settings.testutils.shadow.ShadowEntityHeaderController; @@ -48,12 +52,13 @@ import com.android.settingslib.widget.LayoutPreference; import org.junit.Before; import org.junit.Ignore; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import java.util.HashSet; @@ -62,6 +67,8 @@ import java.util.Set; @RunWith(RobolectricTestRunner.class) @Config(shadows = {ShadowEntityHeaderController.class, ShadowDeviceConfig.class}) public class AdvancedBluetoothDetailsHeaderControllerTest { + @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + private static final int BATTERY_LEVEL_MAIN = 30; private static final int BATTERY_LEVEL_LEFT = 25; private static final int BATTERY_LEVEL_RIGHT = 45; @@ -93,7 +100,7 @@ public class AdvancedBluetoothDetailsHeaderControllerTest { public void setUp() { MockitoAnnotations.initMocks(this); - mContext = RuntimeEnvironment.application; + mContext = Robolectric.buildActivity(SettingsActivity.class).get(); mController = new AdvancedBluetoothDetailsHeaderController(mContext, "pref_Key"); when(mCachedDevice.getDevice()).thenReturn(mBluetoothDevice); mController.init(mCachedDevice); @@ -272,6 +279,7 @@ public class AdvancedBluetoothDetailsHeaderControllerTest { View.GONE); assertThat(layout.findViewById(R.id.bt_battery_icon).getVisibility()).isEqualTo(View.GONE); assertThat(layout.findViewById(R.id.header_icon).getVisibility()).isEqualTo(View.VISIBLE); + assertThat(layout.findViewById(R.id.battery_ring).getVisibility()).isEqualTo(View.GONE); } @Ignore @@ -546,6 +554,10 @@ public class AdvancedBluetoothDetailsHeaderControllerTest { final TextView textView = linearLayout.findViewById(R.id.bt_battery_summary); assertThat(textView.getText().toString()).isEqualTo( com.android.settings.Utils.formatPercentage(batteryLevel)); + if (Flags.enableBluetoothDeviceDetailsPolish()) { + final ProgressBar bar = linearLayout.findViewById(R.id.battery_ring); + assertThat(bar.getProgress()).isEqualTo(batteryLevel); + } } private void assertBatteryIcon(LinearLayout linearLayout, int resId) { diff --git a/tests/robotests/src/com/android/settings/connecteddevice/stylus/StylusUsiHeaderControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/stylus/StylusUsiHeaderControllerTest.java index 3aad02e011a..4509c7c17ae 100644 --- a/tests/robotests/src/com/android/settings/connecteddevice/stylus/StylusUsiHeaderControllerTest.java +++ b/tests/robotests/src/com/android/settings/connecteddevice/stylus/StylusUsiHeaderControllerTest.java @@ -33,9 +33,9 @@ import android.widget.TextView; import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; -import androidx.test.core.app.ApplicationProvider; import com.android.settings.R; +import com.android.settings.SettingsActivity; import com.android.settingslib.widget.LayoutPreference; import org.junit.Before; @@ -43,6 +43,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.robolectric.Robolectric; import org.robolectric.RobolectricTestRunner; @RunWith(RobolectricTestRunner.class) @@ -72,7 +73,7 @@ public class StylusUsiHeaderControllerTest { when(mBatteryState.getCapacity()).thenReturn(1f); when(mBatteryState.isPresent()).thenReturn(true); - mContext = spy(ApplicationProvider.getApplicationContext()); + mContext = spy(Robolectric.buildActivity(SettingsActivity.class).get()); when(mContext.getSystemService(InputManager.class)).thenReturn(mInputManager); mController = new StylusUsiHeaderController(mContext, mInputDevice); From 79c69fccd187edaba3c65b39fe056107ca25ad12 Mon Sep 17 00:00:00 2001 From: Sunny Shao Date: Tue, 2 Jul 2024 21:31:30 +0800 Subject: [PATCH 04/15] Fix display problem in the freeform mode Fixes: 347373574 Flag: EXEMPT bugfix Test: manual test Change-Id: Ia1333474059988a524fc0ca49e7062b51da2cc37 --- src/com/android/settings/Utils.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java index 27a628c5308..e94769ad61a 100644 --- a/src/com/android/settings/Utils.java +++ b/src/com/android/settings/Utils.java @@ -1423,13 +1423,15 @@ public final class Utils extends com.android.settingslib.Utils { public static void setupEdgeToEdge(@NonNull FragmentActivity activity) { ViewCompat.setOnApplyWindowInsetsListener(activity.findViewById(android.R.id.content), (v, windowInsets) -> { - Insets insets = windowInsets.getInsets( + final Insets insets = windowInsets.getInsets( WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.ime() | WindowInsetsCompat.Type.displayCutout()); - int statusBarHeight = activity.getWindow().getDecorView().getRootWindowInsets() - .getInsets(WindowInsetsCompat.Type.statusBars()).top; + int newInsetsTop = activity.getWindow().getDecorView().getRootWindowInsets() + .getInsets(WindowInsetsCompat.Type.statusBars() + | WindowInsetsCompat.Type.captionBar()).top; + // Apply the insets paddings to the view. - v.setPadding(insets.left, statusBarHeight, insets.right, insets.bottom); + v.setPadding(insets.left, newInsetsTop, insets.right, insets.bottom); // Return CONSUMED if you don't want the window insets to keep being // passed down to descendant views. From 574fcaf1b2407b5996ca0529df4f9956e52035c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=ADas=20Hern=C3=A1ndez?= Date: Mon, 1 Jul 2024 18:25:54 +0200 Subject: [PATCH 05/15] Add mode: Choose name and icon for new custom modes This also unifies the "icon picker" screen with the new "add mode" screen since in both cases we want to edit name and icon together (and not save updates until the user confirms). Bug: 326442408 Bug: 346278854 Test: atest com.android.settings.notification.modes Flag: android.app.modes_ui Change-Id: I8a9d07ba0b6c55f3abc1b9884f278d51d178dc83 --- res/layout/modes_edit_done_button.xml | 32 +++ res/layout/modes_edit_name.xml | 35 +++ res/values/strings.xml | 12 + ...on_picker.xml => modes_edit_name_icon.xml} | 16 +- .../ZenModeActionsPreferenceController.java | 2 +- .../ZenModeEditDonePreferenceController.java | 60 +++++ .../modes/ZenModeEditNameIconFragment.java | 83 +++++++ .../ZenModeEditNameIconFragmentBase.java | 191 ++++++++++++++++ .../ZenModeEditNamePreferenceController.java | 87 +++++++ .../modes/ZenModeIconPickerFragment.java | 57 ----- .../modes/ZenModeNewCustomFragment.java | 68 ++++++ .../modes/ZenModesListFragment.java | 15 +- .../notification/modes/TestModeBuilder.java | 10 + ...nModeEditDonePreferenceControllerTest.java | 93 ++++++++ .../ZenModeEditNameIconFragmentTest.java | 212 ++++++++++++++++++ ...nModeEditNamePreferenceControllerTest.java | 90 ++++++++ .../modes/ZenModeNewCustomFragmentTest.java | 147 ++++++++++++ .../modes/ZenModesListFragmentTest.java | 13 ++ 18 files changed, 1154 insertions(+), 69 deletions(-) create mode 100644 res/layout/modes_edit_done_button.xml create mode 100644 res/layout/modes_edit_name.xml rename res/xml/{modes_icon_picker.xml => modes_edit_name_icon.xml} (71%) create mode 100644 src/com/android/settings/notification/modes/ZenModeEditDonePreferenceController.java create mode 100644 src/com/android/settings/notification/modes/ZenModeEditNameIconFragment.java create mode 100644 src/com/android/settings/notification/modes/ZenModeEditNameIconFragmentBase.java create mode 100644 src/com/android/settings/notification/modes/ZenModeEditNamePreferenceController.java delete mode 100644 src/com/android/settings/notification/modes/ZenModeIconPickerFragment.java create mode 100644 src/com/android/settings/notification/modes/ZenModeNewCustomFragment.java create mode 100644 tests/robotests/src/com/android/settings/notification/modes/ZenModeEditDonePreferenceControllerTest.java create mode 100644 tests/robotests/src/com/android/settings/notification/modes/ZenModeEditNameIconFragmentTest.java create mode 100644 tests/robotests/src/com/android/settings/notification/modes/ZenModeEditNamePreferenceControllerTest.java create mode 100644 tests/robotests/src/com/android/settings/notification/modes/ZenModeNewCustomFragmentTest.java diff --git a/res/layout/modes_edit_done_button.xml b/res/layout/modes_edit_done_button.xml new file mode 100644 index 00000000000..dc1f54d74ad --- /dev/null +++ b/res/layout/modes_edit_done_button.xml @@ -0,0 +1,32 @@ + + + + + +