From b79d962c93d6cbd12b06d747a7b240f754b60980 Mon Sep 17 00:00:00 2001 From: shaoweishen Date: Thu, 13 Jun 2024 09:28:34 +0000 Subject: [PATCH 1/5] [Physical Keyboard] Add flag for keyboard a11y new page features Bug: 345399212 Test: N/A Flags: com.android.settings.keyboard.keyboard_and_touchpad_a11y_new_page_enabled Change-Id: I03a6c7bbb042f90761838724a0097f35b008449c --- Android.bp | 1 + aconfig/Android.bp | 12 ++++++++++++ .../settings_physical_keyboard_a11y_features.aconfig | 9 +++++++++ 3 files changed, 22 insertions(+) create mode 100644 aconfig/keyboard/settings_physical_keyboard_a11y_features.aconfig diff --git a/Android.bp b/Android.bp index 4c472c8c411..6dc1e9a43ec 100644 --- a/Android.bp +++ b/Android.bp @@ -113,6 +113,7 @@ android_library { "telephony_flags_core_java_lib", "setupdesign-lottie-loading-layout", "device_policy_aconfig_flags_lib", + "keyboard_flags_lib", ], plugins: ["androidx.room_room-compiler-plugin"], diff --git a/aconfig/Android.bp b/aconfig/Android.bp index 549ccc712e7..198c24d3c48 100644 --- a/aconfig/Android.bp +++ b/aconfig/Android.bp @@ -66,3 +66,15 @@ java_aconfig_library { name: "development_settings_flag_lib", aconfig_declarations: "development_settings_flags", } + +aconfig_declarations { + name: "keyboard_flags", + package: "com.android.settings.keyboard", + container: "system_ext", + srcs: ["keyboard/*.aconfig"], +} + +java_aconfig_library { + name: "keyboard_flags_lib", + aconfig_declarations: "keyboard_flags", +} \ No newline at end of file diff --git a/aconfig/keyboard/settings_physical_keyboard_a11y_features.aconfig b/aconfig/keyboard/settings_physical_keyboard_a11y_features.aconfig new file mode 100644 index 00000000000..ca5cb8d7739 --- /dev/null +++ b/aconfig/keyboard/settings_physical_keyboard_a11y_features.aconfig @@ -0,0 +1,9 @@ +package: "com.android.settings.keyboard" +container: "system_ext" + +flag { + name: "keyboard_and_touchpad_a11y_new_page_enabled" + namespace: "input" + description: "This flag enables or disables new page for physical keyboard and touchpad a11y features" + bug: "345399212" +} \ No newline at end of file From 115d29e851d6c4f6b593591a578bf5653d1f7e35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=ADas=20Hern=C3=A1ndez?= Date: Tue, 13 Aug 2024 19:13:46 +0200 Subject: [PATCH 2/5] Animate the color transition (active<->inactive) in the mode header icon Also, don't apply the layout params, etc on each call to updateState - once per displayPreference is enough. Fixes: 356399449 Bug: 357861830 Test: manual Flag: android.app.modes_ui Change-Id: I6967ea1745377d0f514ca0f68101043f017a8fd7 --- .../AbstractZenModeHeaderController.java | 62 +++++++++++-------- .../settings/notification/modes/IconUtil.java | 46 ++++++++++---- .../modes/ZenModeHeaderController.java | 11 +++- ...odeIconPickerIconPreferenceController.java | 12 +++- 4 files changed, 88 insertions(+), 43 deletions(-) diff --git a/src/com/android/settings/notification/modes/AbstractZenModeHeaderController.java b/src/com/android/settings/notification/modes/AbstractZenModeHeaderController.java index 06a30fa30f5..81b53cc3d3e 100644 --- a/src/com/android/settings/notification/modes/AbstractZenModeHeaderController.java +++ b/src/com/android/settings/notification/modes/AbstractZenModeHeaderController.java @@ -15,6 +15,8 @@ */ package com.android.settings.notification.modes; +import static com.google.common.base.Preconditions.checkNotNull; + import android.app.Flags; import android.content.Context; import android.graphics.drawable.Drawable; @@ -22,8 +24,8 @@ import android.view.ViewGroup; import android.widget.ImageView; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; @@ -32,13 +34,15 @@ import com.android.settingslib.notification.modes.ZenIconLoader; import com.android.settingslib.notification.modes.ZenMode; import com.android.settingslib.widget.LayoutPreference; -import java.util.function.Consumer; +import com.google.common.base.Objects; + import java.util.function.Function; abstract class AbstractZenModeHeaderController extends AbstractZenModePreferenceController { private final DashboardFragment mFragment; private EntityHeaderController mHeaderController; + private String mCurrentIconKey; AbstractZenModeHeaderController( @NonNull Context context, @@ -53,40 +57,44 @@ abstract class AbstractZenModeHeaderController extends AbstractZenModePreference return Flags.modesApi() && Flags.modesUi(); } - protected void updateIcon(Preference preference, @NonNull ZenMode zenMode, int iconSizePx, - Function modeIconStylist, - @Nullable Consumer iconViewCustomizer) { - if (mFragment == null) { - return; - } + protected void setUpHeader(PreferenceScreen screen, int iconSizePx) { + LayoutPreference preference = checkNotNull(screen.findPreference(getPreferenceKey())); preference.setSelectable(false); if (mHeaderController == null) { - final LayoutPreference pref = (LayoutPreference) preference; mHeaderController = EntityHeaderController.newInstance( mFragment.getActivity(), mFragment, - pref.findViewById(R.id.entity_header)); + preference.findViewById(R.id.entity_header)); } - ImageView iconView = ((LayoutPreference) preference).findViewById(R.id.entity_header_icon); - if (iconView != null) { - if (iconViewCustomizer != null) { - iconViewCustomizer.accept(iconView); - } - ViewGroup.LayoutParams layoutParams = iconView.getLayoutParams(); - if (layoutParams.width != iconSizePx || layoutParams.height != iconSizePx) { - layoutParams.width = iconSizePx; - layoutParams.height = iconSizePx; - iconView.setLayoutParams(layoutParams); - } + ImageView iconView = checkNotNull(preference.findViewById(R.id.entity_header_icon)); + ViewGroup.LayoutParams layoutParams = iconView.getLayoutParams(); + if (layoutParams.width != iconSizePx || layoutParams.height != iconSizePx) { + layoutParams.width = iconSizePx; + layoutParams.height = iconSizePx; + iconView.setLayoutParams(layoutParams); } + } - FutureUtil.whenDone( - zenMode.getIcon(mContext, ZenIconLoader.getInstance()), - icon -> mHeaderController - .setIcon(modeIconStylist.apply(icon)) - .done(/* rebindActions= */ false), - mContext.getMainExecutor()); + protected void updateIcon(Preference preference, @NonNull ZenMode zenMode, + Function iconStylist, boolean isSelected) { + + ImageView iconView = checkNotNull( + ((LayoutPreference) preference).findViewById(R.id.entity_header_icon)); + iconView.setSelected(isSelected); + + if (!Objects.equal(mCurrentIconKey, zenMode.getIconKey())) { + mCurrentIconKey = zenMode.getIconKey(); + FutureUtil.whenDone( + zenMode.getIcon(mContext, ZenIconLoader.getInstance()), + icon -> { + checkNotNull(mHeaderController) + .setIcon(iconStylist.apply(icon)) + .done(/* rebindActions= */ false); + iconView.jumpDrawablesToCurrentState(); // Skip animation on first load. + }, + mContext.getMainExecutor()); + } } } diff --git a/src/com/android/settings/notification/modes/IconUtil.java b/src/com/android/settings/notification/modes/IconUtil.java index 43161ce085d..dc4d875869e 100644 --- a/src/com/android/settings/notification/modes/IconUtil.java +++ b/src/com/android/settings/notification/modes/IconUtil.java @@ -30,7 +30,9 @@ import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.LayerDrawable; import android.graphics.drawable.ShapeDrawable; +import android.graphics.drawable.StateListDrawable; import android.graphics.drawable.shapes.OvalShape; +import android.util.StateSet; import android.view.Gravity; import androidx.annotation.AttrRes; @@ -65,20 +67,42 @@ class IconUtil { /** * Returns a variant of the supplied mode icon to be used as the header in the mode page. The - * inner icon is 64x64 dp and it's contained in a 12-sided-cookie of 136dp diameter. It's - * tinted with the "material secondary" color combination and the "selected" color variant - * should be used for modes currently active. + * mode icon is contained in a 12-sided-cookie. The color combination is "material secondary" + * when unselected and "material primary" when selected; the switch between these two color sets + * is animated with a cross-fade. The selected colors should be used when the mode is currently + * active. */ static Drawable makeModeHeader(@NonNull Context context, Drawable modeIcon) { - return composeIcons( - checkNotNull(context.getDrawable(R.drawable.ic_zen_mode_icon_cookie)), - context.getColorStateList(R.color.modes_icon_selectable_background), - context.getResources().getDimensionPixelSize( - R.dimen.zen_mode_header_size), + Resources res = context.getResources(); + Drawable background = checkNotNull(context.getDrawable(R.drawable.ic_zen_mode_icon_cookie)); + @Px int outerSizePx = res.getDimensionPixelSize(R.dimen.zen_mode_header_size); + @Px int innerSizePx = res.getDimensionPixelSize(R.dimen.zen_mode_header_inner_icon_size); + + Drawable base = composeIcons( + background, + Utils.getColorAttr(context, + com.android.internal.R.attr.materialColorSecondaryContainer), + outerSizePx, modeIcon, - context.getColorStateList(R.color.modes_icon_selectable_icon), - context.getResources().getDimensionPixelSize( - R.dimen.zen_mode_header_inner_icon_size)); + Utils.getColorAttr(context, + com.android.internal.R.attr.materialColorOnSecondaryContainer), + innerSizePx); + + Drawable selected = composeIcons( + background, + Utils.getColorAttr(context, com.android.internal.R.attr.materialColorPrimary), + outerSizePx, + modeIcon, + Utils.getColorAttr(context, com.android.internal.R.attr.materialColorOnPrimary), + innerSizePx); + + StateListDrawable result = new StateListDrawable(); + result.setEnterFadeDuration(res.getInteger(android.R.integer.config_mediumAnimTime)); + result.setExitFadeDuration(res.getInteger(android.R.integer.config_mediumAnimTime)); + result.addState(new int[] { android.R.attr.state_selected }, selected); + result.addState(StateSet.WILD_CARD, base); + result.setBounds(0, 0, outerSizePx, outerSizePx); + return result; } /** diff --git a/src/com/android/settings/notification/modes/ZenModeHeaderController.java b/src/com/android/settings/notification/modes/ZenModeHeaderController.java index c4f3dd188ba..ae6eacc52da 100644 --- a/src/com/android/settings/notification/modes/ZenModeHeaderController.java +++ b/src/com/android/settings/notification/modes/ZenModeHeaderController.java @@ -19,6 +19,7 @@ import android.content.Context; import androidx.annotation.NonNull; import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; @@ -33,11 +34,17 @@ class ZenModeHeaderController extends AbstractZenModeHeaderController { super(context, key, fragment); } + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + setUpHeader(screen, + mContext.getResources().getDimensionPixelSize(R.dimen.zen_mode_header_size)); + } + @Override public void updateState(Preference preference, @NonNull ZenMode zenMode) { updateIcon(preference, zenMode, - mContext.getResources().getDimensionPixelSize(R.dimen.zen_mode_header_size), icon -> IconUtil.makeModeHeader(mContext, icon), - iconView -> iconView.setSelected(zenMode.isActive())); + /* isSelected= */ zenMode.isActive()); } } diff --git a/src/com/android/settings/notification/modes/ZenModeIconPickerIconPreferenceController.java b/src/com/android/settings/notification/modes/ZenModeIconPickerIconPreferenceController.java index a7adf6c27f9..6c8d41f591a 100644 --- a/src/com/android/settings/notification/modes/ZenModeIconPickerIconPreferenceController.java +++ b/src/com/android/settings/notification/modes/ZenModeIconPickerIconPreferenceController.java @@ -20,6 +20,7 @@ import android.content.Context; import androidx.annotation.NonNull; import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; @@ -33,12 +34,17 @@ class ZenModeIconPickerIconPreferenceController extends AbstractZenModeHeaderCon super(context, key, fragment); } + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + setUpHeader(screen, mContext.getResources().getDimensionPixelSize( + R.dimen.zen_mode_icon_list_header_circle_diameter)); + } + @Override void updateState(Preference preference, @NonNull ZenMode zenMode) { updateIcon(preference, zenMode, - mContext.getResources().getDimensionPixelSize( - R.dimen.zen_mode_icon_list_header_circle_diameter), icon -> IconUtil.makeIconPickerHeader(mContext, icon), - null); + /* isSelected= */ false); } } From 24ba675fe406c32e07a03be9483a8a71ffd98177 Mon Sep 17 00:00:00 2001 From: Yuri Lin Date: Mon, 12 Aug 2024 17:45:49 -0400 Subject: [PATCH 3/5] Add images for interstitial pages. This change removes the custom rounding of corners, as the provided images already have rounded corners. Bug: 332730534 Test: manual (light & dark mode, various font/display sizes) Flag: android.app.modes_ui Change-Id: I71d0707554e5bc638add6a2907874e18e833da08 --- .../modes_interstitial_bedtime.xml | 62 +++++++++ .../modes_interstitial_driving.xml | 81 +++++++++++ .../modes_interstitial_immersive.xml | 83 +++++++++++ .../modes_interstitial_managed.xml | 56 ++++++++ .../modes_interstitial_other.xml | 118 ++++++++++++++++ .../modes_interstitial_theater.xml | 69 ++++++++++ .../modes_interstitial_unknown.xml | 65 +++++++++ res/drawable/modes_interstitial_bedtime.xml | 62 +++++++++ res/drawable/modes_interstitial_driving.xml | 81 +++++++++++ res/drawable/modes_interstitial_immersive.xml | 83 +++++++++++ res/drawable/modes_interstitial_managed.xml | 57 ++++++++ res/drawable/modes_interstitial_other.xml | 118 ++++++++++++++++ res/drawable/modes_interstitial_theater.xml | 77 +++++++++++ res/drawable/modes_interstitial_unknown.xml | 65 +++++++++ res/layout-land/mode_interstitial_layout.xml | 2 +- res/layout/mode_interstitial_layout.xml | 4 +- res/values/dimens.xml | 2 - .../modes/SetupInterstitialActivity.java | 109 +++------------ .../modes/SetupInterstitialActivityTest.java | 130 ------------------ 19 files changed, 1096 insertions(+), 228 deletions(-) create mode 100644 res/drawable-night/modes_interstitial_bedtime.xml create mode 100644 res/drawable-night/modes_interstitial_driving.xml create mode 100644 res/drawable-night/modes_interstitial_immersive.xml create mode 100644 res/drawable-night/modes_interstitial_managed.xml create mode 100644 res/drawable-night/modes_interstitial_other.xml create mode 100644 res/drawable-night/modes_interstitial_theater.xml create mode 100644 res/drawable-night/modes_interstitial_unknown.xml create mode 100644 res/drawable/modes_interstitial_bedtime.xml create mode 100644 res/drawable/modes_interstitial_driving.xml create mode 100644 res/drawable/modes_interstitial_immersive.xml create mode 100644 res/drawable/modes_interstitial_managed.xml create mode 100644 res/drawable/modes_interstitial_other.xml create mode 100644 res/drawable/modes_interstitial_theater.xml create mode 100644 res/drawable/modes_interstitial_unknown.xml diff --git a/res/drawable-night/modes_interstitial_bedtime.xml b/res/drawable-night/modes_interstitial_bedtime.xml new file mode 100644 index 00000000000..f28bb017170 --- /dev/null +++ b/res/drawable-night/modes_interstitial_bedtime.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + diff --git a/res/drawable-night/modes_interstitial_driving.xml b/res/drawable-night/modes_interstitial_driving.xml new file mode 100644 index 00000000000..6edbfe51aad --- /dev/null +++ b/res/drawable-night/modes_interstitial_driving.xml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/drawable-night/modes_interstitial_immersive.xml b/res/drawable-night/modes_interstitial_immersive.xml new file mode 100644 index 00000000000..a29c4743174 --- /dev/null +++ b/res/drawable-night/modes_interstitial_immersive.xml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/res/drawable-night/modes_interstitial_managed.xml b/res/drawable-night/modes_interstitial_managed.xml new file mode 100644 index 00000000000..05f8f6a3ceb --- /dev/null +++ b/res/drawable-night/modes_interstitial_managed.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + diff --git a/res/drawable-night/modes_interstitial_other.xml b/res/drawable-night/modes_interstitial_other.xml new file mode 100644 index 00000000000..2bbed99d5ff --- /dev/null +++ b/res/drawable-night/modes_interstitial_other.xml @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/drawable-night/modes_interstitial_theater.xml b/res/drawable-night/modes_interstitial_theater.xml new file mode 100644 index 00000000000..d17b167d2b0 --- /dev/null +++ b/res/drawable-night/modes_interstitial_theater.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + diff --git a/res/drawable-night/modes_interstitial_unknown.xml b/res/drawable-night/modes_interstitial_unknown.xml new file mode 100644 index 00000000000..4047e13c7e3 --- /dev/null +++ b/res/drawable-night/modes_interstitial_unknown.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + diff --git a/res/drawable/modes_interstitial_bedtime.xml b/res/drawable/modes_interstitial_bedtime.xml new file mode 100644 index 00000000000..24061ca85cc --- /dev/null +++ b/res/drawable/modes_interstitial_bedtime.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + diff --git a/res/drawable/modes_interstitial_driving.xml b/res/drawable/modes_interstitial_driving.xml new file mode 100644 index 00000000000..eba51f476bf --- /dev/null +++ b/res/drawable/modes_interstitial_driving.xml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/drawable/modes_interstitial_immersive.xml b/res/drawable/modes_interstitial_immersive.xml new file mode 100644 index 00000000000..d901e232226 --- /dev/null +++ b/res/drawable/modes_interstitial_immersive.xml @@ -0,0 +1,83 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/res/drawable/modes_interstitial_managed.xml b/res/drawable/modes_interstitial_managed.xml new file mode 100644 index 00000000000..c54aeaec4d9 --- /dev/null +++ b/res/drawable/modes_interstitial_managed.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + diff --git a/res/drawable/modes_interstitial_other.xml b/res/drawable/modes_interstitial_other.xml new file mode 100644 index 00000000000..096de3918c7 --- /dev/null +++ b/res/drawable/modes_interstitial_other.xml @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/res/drawable/modes_interstitial_theater.xml b/res/drawable/modes_interstitial_theater.xml new file mode 100644 index 00000000000..78356b47803 --- /dev/null +++ b/res/drawable/modes_interstitial_theater.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + diff --git a/res/drawable/modes_interstitial_unknown.xml b/res/drawable/modes_interstitial_unknown.xml new file mode 100644 index 00000000000..a68f71a8ca1 --- /dev/null +++ b/res/drawable/modes_interstitial_unknown.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + diff --git a/res/layout-land/mode_interstitial_layout.xml b/res/layout-land/mode_interstitial_layout.xml index 14201853c88..597196cbb8d 100644 --- a/res/layout-land/mode_interstitial_layout.xml +++ b/res/layout-land/mode_interstitial_layout.xml @@ -114,7 +114,7 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:adjustViewBounds="true" - android:scaleType="centerCrop" + android:scaleType="fitCenter" android:layout_gravity="center" /> diff --git a/res/layout/mode_interstitial_layout.xml b/res/layout/mode_interstitial_layout.xml index d0f80a77af7..2deaf9f6321 100644 --- a/res/layout/mode_interstitial_layout.xml +++ b/res/layout/mode_interstitial_layout.xml @@ -56,7 +56,7 @@ android:layout_height="match_parent" android:adjustViewBounds="true" android:clickable="false" - android:scaleType="centerCrop" + android:scaleType="fitCenter" android:layout_gravity="center" /> @@ -78,7 +78,7 @@ android:clickable="false" android:text="@string/zen_mode_setup_page_summary" android:textSize="18sp" - android:paddingBottom="12dp" + android:paddingBottom="18dp" android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Body1" app:layout_constraintBottom_toTopOf="@+id/enable_mode_button" /> diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 3a327c98a12..689262fa3e8 100755 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -519,6 +519,4 @@ 4dp 8dp 18dp - - 30dp diff --git a/src/com/android/settings/notification/modes/SetupInterstitialActivity.java b/src/com/android/settings/notification/modes/SetupInterstitialActivity.java index 225ded0632b..f26de76844b 100644 --- a/src/com/android/settings/notification/modes/SetupInterstitialActivity.java +++ b/src/com/android/settings/notification/modes/SetupInterstitialActivity.java @@ -16,25 +16,21 @@ package com.android.settings.notification.modes; -import static android.graphics.drawable.GradientDrawable.LINEAR_GRADIENT; -import static android.graphics.drawable.GradientDrawable.Orientation.BL_TR; +import static android.app.AutomaticZenRule.TYPE_BEDTIME; +import static android.app.AutomaticZenRule.TYPE_DRIVING; +import static android.app.AutomaticZenRule.TYPE_IMMERSIVE; +import static android.app.AutomaticZenRule.TYPE_MANAGED; +import static android.app.AutomaticZenRule.TYPE_OTHER; +import static android.app.AutomaticZenRule.TYPE_THEATER; import static android.provider.Settings.EXTRA_AUTOMATIC_ZEN_RULE_ID; import android.app.ActionBar; import android.content.Context; import android.content.Intent; -import android.graphics.Color; -import android.graphics.Outline; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.GradientDrawable; import android.os.Bundle; import android.util.Log; import android.view.View; -import android.view.ViewGroup; -import android.view.ViewOutlineProvider; -import android.view.ViewTreeObserver; import android.widget.Button; -import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; @@ -58,17 +54,6 @@ public class SetupInterstitialActivity extends FragmentActivity { private static final String TAG = "ModeSetupInterstitial"; private ZenModesBackend mBackend; - private final ViewOutlineProvider mOutlineProvider = new ViewOutlineProvider() { - @Override - public void getOutline(View view, Outline outline) { - // Provides a rounded rectangle outline whose width & height matches the View. - float cornerRadius = getResources().getDimensionPixelSize( - R.dimen.zen_mode_interstitial_corner_radius); - outline.setRoundRect(0, 0, view.getMeasuredWidth(), view.getMeasuredHeight(), - cornerRadius); - } - }; - /** * Returns an intent leading to this page for the given mode and context. */ @@ -150,79 +135,17 @@ public class SetupInterstitialActivity extends FragmentActivity { } private void setImage(@NonNull ImageView img, @NonNull ZenMode mode) { - img.setImageDrawable(getModeDrawable(mode)); - img.setClipToOutline(true); - img.setOutlineProvider(mOutlineProvider); + int drawableRes = switch (mode.getType()) { + case TYPE_BEDTIME -> R.drawable.modes_interstitial_bedtime; + case TYPE_DRIVING -> R.drawable.modes_interstitial_driving; + case TYPE_IMMERSIVE -> R.drawable.modes_interstitial_immersive; + case TYPE_THEATER -> R.drawable.modes_interstitial_theater; + case TYPE_MANAGED -> R.drawable.modes_interstitial_managed; + case TYPE_OTHER -> R.drawable.modes_interstitial_other; + default -> R.drawable.modes_interstitial_unknown; + }; - FrameLayout frame = findViewById(R.id.image_frame); - if (frame == null) { - return; - } - if (img.getMeasuredWidth() == 0) { - // set up to resize after the global layout occurs - img.getViewTreeObserver().addOnGlobalLayoutListener( - new ViewTreeObserver.OnGlobalLayoutListener() { - @Override - public void onGlobalLayout() { - img.getViewTreeObserver().removeOnGlobalLayoutListener(this); - sizeImageToFrame(img, frame); - } - }); - } else { - // measured already, resize it now - sizeImageToFrame(img, frame); - } - } - - private Drawable getModeDrawable(@NonNull ZenMode mode) { - // TODO: b/332730534 - set actual images depending on mode type (asynchronously?) - GradientDrawable placeholder = new GradientDrawable(); - placeholder.setSize(40, 60); // 4x6 rectangle, slightly taller than wide - placeholder.setGradientType(LINEAR_GRADIENT); - placeholder.setOrientation(BL_TR); - placeholder.setColors(new int[]{Color.BLACK, Color.WHITE}); - return placeholder; - } - - @VisibleForTesting - protected void sizeImageToFrame(ImageView img, FrameLayout frame) { - // width of the space we have available = overall size of frame - relevant padding - int frameHeight = - frame.getMeasuredHeight() - frame.getPaddingTop() - frame.getPaddingBottom(); - int frameWidth = - frame.getMeasuredWidth() - frame.getPaddingLeft() - frame.getPaddingRight(); - - int imgHeight = img.getDrawable().getIntrinsicHeight(); - int imgWidth = img.getDrawable().getIntrinsicWidth(); - - // if any of these are 0, give up because we won't be able to do the relevant math (and - // we probably don't have the relevant data set up) - if (frameHeight == 0 || frameWidth == 0 || imgHeight == 0 || imgWidth == 0) { - Log.w(TAG, "image or frame has invalid size parameters"); - return; - } - float frameHWRatio = ((float) frameHeight) / frameWidth; - float imgHWRatio = ((float) imgHeight) / imgWidth; - - // fit horizontal dimension if the frame has a taller ratio (height/width) than the image; - // otherwise, fit the vertical direction - boolean fitHorizontal = frameHWRatio > imgHWRatio; - - ViewGroup.LayoutParams layoutParams = img.getLayoutParams(); - if (layoutParams == null) { - Log.w(TAG, "image has null LayoutParams"); - return; - } - if (fitHorizontal) { - layoutParams.width = frameWidth; - float scaledHeight = imgHWRatio * frameWidth; - layoutParams.height = (int) scaledHeight; - } else { - layoutParams.height = frameHeight; - float scaledWidth = /* w/h ratio */ (1 / imgHWRatio) * frameHeight; - layoutParams.width = (int) scaledWidth; - } - img.setLayoutParams(layoutParams); + img.setImageResource(drawableRes); } private void setupButton(Button button, @NonNull ZenMode mode) { diff --git a/tests/robotests/src/com/android/settings/notification/modes/SetupInterstitialActivityTest.java b/tests/robotests/src/com/android/settings/notification/modes/SetupInterstitialActivityTest.java index 129e56e548c..40bf1c725e9 100644 --- a/tests/robotests/src/com/android/settings/notification/modes/SetupInterstitialActivityTest.java +++ b/tests/robotests/src/com/android/settings/notification/modes/SetupInterstitialActivityTest.java @@ -150,134 +150,4 @@ public class SetupInterstitialActivityTest { }); scenario.close(); } - - @Test - public void setImageToFrame_sizeZero() { - ActivityScenario scenario = - ActivityScenario.launch(new Intent(Intent.ACTION_MAIN) - .setClass(RuntimeEnvironment.getApplication(), - SetupInterstitialActivity.class) - .putExtra(EXTRA_AUTOMATIC_ZEN_RULE_ID, MODE_ID)); - scenario.onActivity(activity -> { - // when either the image or the frame has a size 0, we do nothing - when(mDrawable.getIntrinsicWidth()).thenReturn(0); - when(mDrawable.getIntrinsicHeight()).thenReturn(25); - when(mFrame.getMeasuredWidth()).thenReturn(40); - when(mFrame.getMeasuredHeight()).thenReturn(50); - - activity.sizeImageToFrame(mImage, mFrame); - verify(mImage, never()).setLayoutParams(any()); - }); - scenario.close(); - } - - @Test - public void setImageToFrame_imageLargerThanFrame() { - ActivityScenario scenario = - ActivityScenario.launch(new Intent(Intent.ACTION_MAIN) - .setClass(RuntimeEnvironment.getApplication(), - SetupInterstitialActivity.class) - .putExtra(EXTRA_AUTOMATIC_ZEN_RULE_ID, MODE_ID)); - scenario.onActivity(activity -> { - // image: 900(w)x1500(h); frame: 600(w)x500(h) - // image expected to be scaled down to match the height of the frame -> 300(w)x500(h) - when(mDrawable.getIntrinsicWidth()).thenReturn(900); - when(mDrawable.getIntrinsicHeight()).thenReturn(1500); - when(mFrame.getMeasuredWidth()).thenReturn(600); - when(mFrame.getMeasuredHeight()).thenReturn(500); - - ArgumentCaptor captor = ArgumentCaptor.forClass( - ViewGroup.LayoutParams.class); - activity.sizeImageToFrame(mImage, mFrame); - verify(mImage).setLayoutParams(captor.capture()); - ViewGroup.LayoutParams out = captor.getValue(); - assertThat(out.width).isEqualTo(300); - assertThat(out.height).isEqualTo(500); - }); - scenario.close(); - } - - @Test - public void setImageToFrame_imageSmallerThanFrame() { - ActivityScenario scenario = - ActivityScenario.launch(new Intent(Intent.ACTION_MAIN) - .setClass(RuntimeEnvironment.getApplication(), - SetupInterstitialActivity.class) - .putExtra(EXTRA_AUTOMATIC_ZEN_RULE_ID, MODE_ID)); - scenario.onActivity(activity -> { - // image: 300(w)x200(h); frame: 900(w)x1200(h) - // image expected to be scaled up to match the width of the frame -> 900(w)x600(h) - when(mDrawable.getIntrinsicWidth()).thenReturn(300); - when(mDrawable.getIntrinsicHeight()).thenReturn(200); - when(mFrame.getMeasuredWidth()).thenReturn(900); - when(mFrame.getMeasuredHeight()).thenReturn(1200); - - ArgumentCaptor captor = ArgumentCaptor.forClass( - ViewGroup.LayoutParams.class); - activity.sizeImageToFrame(mImage, mFrame); - verify(mImage).setLayoutParams(captor.capture()); - ViewGroup.LayoutParams out = captor.getValue(); - assertThat(out.width).isEqualTo(900); - assertThat(out.height).isEqualTo(600); - }); - scenario.close(); - } - - @Test - public void setImageToFrame_horizontalImageNarrowerThanFrame() { - ActivityScenario scenario = - ActivityScenario.launch(new Intent(Intent.ACTION_MAIN) - .setClass(RuntimeEnvironment.getApplication(), - SetupInterstitialActivity.class) - .putExtra(EXTRA_AUTOMATIC_ZEN_RULE_ID, MODE_ID)); - scenario.onActivity(activity -> { - // image: 600(w)x400(h); frame: 1000(w)x100(h) - // both image and frame are wider than tall, but frame is much narrower - // so should fit image to height of frame -> 150(w)x100(h) - when(mDrawable.getIntrinsicWidth()).thenReturn(600); - when(mDrawable.getIntrinsicHeight()).thenReturn(400); - when(mFrame.getMeasuredWidth()).thenReturn(1000); - when(mFrame.getMeasuredHeight()).thenReturn(100); - - ArgumentCaptor captor = ArgumentCaptor.forClass( - ViewGroup.LayoutParams.class); - activity.sizeImageToFrame(mImage, mFrame); - verify(mImage).setLayoutParams(captor.capture()); - ViewGroup.LayoutParams out = captor.getValue(); - assertThat(out.width).isEqualTo(150); - assertThat(out.height).isEqualTo(100); - }); - scenario.close(); - } - - @Test - public void setImageToFrame_accountsForPadding() { - ActivityScenario scenario = - ActivityScenario.launch(new Intent(Intent.ACTION_MAIN) - .setClass(RuntimeEnvironment.getApplication(), - SetupInterstitialActivity.class) - .putExtra(EXTRA_AUTOMATIC_ZEN_RULE_ID, MODE_ID)); - scenario.onActivity(activity -> { - // image: 200(w)x300(h); frame: 1000(w)x1000(h), 50 top/bottom padding, 100 l/r padding - // effective size of frame is therefore 800(w)x900(h) - // scale image to the height of the effective frame -> 600(w)x900(h) - when(mDrawable.getIntrinsicWidth()).thenReturn(200); - when(mDrawable.getIntrinsicHeight()).thenReturn(300); - when(mFrame.getMeasuredWidth()).thenReturn(1000); - when(mFrame.getMeasuredHeight()).thenReturn(1000); - when(mFrame.getPaddingTop()).thenReturn(50); - when(mFrame.getPaddingBottom()).thenReturn(50); - when(mFrame.getPaddingLeft()).thenReturn(100); - when(mFrame.getPaddingRight()).thenReturn(100); - - ArgumentCaptor captor = ArgumentCaptor.forClass( - ViewGroup.LayoutParams.class); - activity.sizeImageToFrame(mImage, mFrame); - verify(mImage).setLayoutParams(captor.capture()); - ViewGroup.LayoutParams out = captor.getValue(); - assertThat(out.width).isEqualTo(600); - assertThat(out.height).isEqualTo(900); - }); - scenario.close(); - } } From 6c2158edefebf86c10de2a2746c2f785665c7071 Mon Sep 17 00:00:00 2001 From: Weng Su Date: Wed, 14 Aug 2024 17:01:27 +0800 Subject: [PATCH 4/5] Get available channels allowed by Hotspot - Use getAllowedChannels API instead of getUsableChannels API to avoid corner cases Bug: 352267181 Flag: EXEMPT bugfix Test: Manual testing atest -c WifiHotspotRepositoryTest Change-Id: I5ae4a4d429924ac2b8676bbbb27016a93ccd9a1b --- .../wifi/repository/WifiHotspotRepository.java | 2 +- .../wifi/repository/WifiHotspotRepositoryTest.java | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/com/android/settings/wifi/repository/WifiHotspotRepository.java b/src/com/android/settings/wifi/repository/WifiHotspotRepository.java index 7a001caedc6..e523831d229 100644 --- a/src/com/android/settings/wifi/repository/WifiHotspotRepository.java +++ b/src/com/android/settings/wifi/repository/WifiHotspotRepository.java @@ -473,7 +473,7 @@ public class WifiHotspotRepository { boolean isChannelAvailable(SapBand sapBand) { try { List channels = - mWifiManager.getUsableChannels(sapBand.band, OP_MODE_SAP); + mWifiManager.getAllowedChannels(sapBand.band, OP_MODE_SAP); log("isChannelAvailable(), band:" + sapBand.band + ", channels:" + channels); sapBand.hasUsableChannels = (channels != null && channels.size() > 0); sapBand.isUsableChannelsUnsupported = false; diff --git a/tests/unit/src/com/android/settings/wifi/repository/WifiHotspotRepositoryTest.java b/tests/unit/src/com/android/settings/wifi/repository/WifiHotspotRepositoryTest.java index a97b1a04e68..3571a36bde7 100644 --- a/tests/unit/src/com/android/settings/wifi/repository/WifiHotspotRepositoryTest.java +++ b/tests/unit/src/com/android/settings/wifi/repository/WifiHotspotRepositoryTest.java @@ -109,10 +109,10 @@ public class WifiHotspotRepositoryTest { doReturn(SPEED_6GHZ).when(mSpeedType).getValue(); doReturn(true).when(mWifiManager).is5GHzBandSupported(); doReturn(Arrays.asList(new WifiAvailableChannel(FREQ_5GHZ, OP_MODE_SAP))).when(mWifiManager) - .getUsableChannels(WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS, OP_MODE_SAP); + .getAllowedChannels(WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS, OP_MODE_SAP); doReturn(true).when(mWifiManager).is6GHzBandSupported(); doReturn(Arrays.asList(new WifiAvailableChannel(FREQ_6GHZ, OP_MODE_SAP))).when(mWifiManager) - .getUsableChannels(WifiScanner.WIFI_BAND_6_GHZ, OP_MODE_SAP); + .getAllowedChannels(WifiScanner.WIFI_BAND_6_GHZ, OP_MODE_SAP); mRepository = new WifiHotspotRepository(mContext, mWifiManager, mTetheringManager); mRepository.mSecurityType = mSecurityType; @@ -575,7 +575,7 @@ public class WifiHotspotRepositoryTest { mRepository.mIs5gBandSupported = true; // Reset m5gBand to trigger an update mRepository.mBand5g.isUsableChannelsReady = false; - when(mWifiManager.getUsableChannels(WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS, OP_MODE_SAP)) + when(mWifiManager.getAllowedChannels(WifiScanner.WIFI_BAND_5_GHZ_WITH_DFS, OP_MODE_SAP)) .thenReturn(null); assertThat(mRepository.is5gAvailable()).isFalse(); @@ -619,7 +619,7 @@ public class WifiHotspotRepositoryTest { mRepository.mIs6gBandSupported = true; // Reset m6gBand to trigger an update mRepository.mBand6g.isUsableChannelsReady = false; - when(mWifiManager.getUsableChannels(WifiScanner.WIFI_BAND_6_GHZ, OP_MODE_SAP)) + when(mWifiManager.getAllowedChannels(WifiScanner.WIFI_BAND_6_GHZ, OP_MODE_SAP)) .thenReturn(null); assertThat(mRepository.is6gAvailable()).isFalse(); @@ -660,7 +660,7 @@ public class WifiHotspotRepositoryTest { @Test public void isChannelAvailable_throwIllegalArgumentException_hasUsableChannelsFalse() { doThrow(IllegalArgumentException.class).when(mWifiManager) - .getUsableChannels(WifiScanner.WIFI_BAND_6_GHZ, OP_MODE_SAP); + .getAllowedChannels(WifiScanner.WIFI_BAND_6_GHZ, OP_MODE_SAP); mRepository.isChannelAvailable(mRepository.mBand6g); @@ -671,7 +671,7 @@ public class WifiHotspotRepositoryTest { @Test public void isChannelAvailable_throwUnsupportedOperationException_hasUsableChannelsFalse() { doThrow(UnsupportedOperationException.class).when(mWifiManager) - .getUsableChannels(WifiScanner.WIFI_BAND_6_GHZ, OP_MODE_SAP); + .getAllowedChannels(WifiScanner.WIFI_BAND_6_GHZ, OP_MODE_SAP); mRepository.isChannelAvailable(mRepository.mBand6g); From 6f38de49328a0bb9a359fd5a94bb35ea35f45b5a Mon Sep 17 00:00:00 2001 From: Haijie Hong Date: Wed, 14 Aug 2024 09:42:21 +0000 Subject: [PATCH 5/5] Add owners for bluetooth settings test folder Change-Id: I1503db974eb271890486581d173c1bde8457f7df --- tests/robotests/src/com/android/settings/bluetooth/OWNERS | 1 + tests/robotests/src/com/android/settings/connecteddevice/OWNERS | 1 + 2 files changed, 2 insertions(+) create mode 100644 tests/robotests/src/com/android/settings/bluetooth/OWNERS create mode 100644 tests/robotests/src/com/android/settings/connecteddevice/OWNERS diff --git a/tests/robotests/src/com/android/settings/bluetooth/OWNERS b/tests/robotests/src/com/android/settings/bluetooth/OWNERS new file mode 100644 index 00000000000..6f0add6c07b --- /dev/null +++ b/tests/robotests/src/com/android/settings/bluetooth/OWNERS @@ -0,0 +1 @@ +include /src/com/android/settings/bluetooth/OWNERS diff --git a/tests/robotests/src/com/android/settings/connecteddevice/OWNERS b/tests/robotests/src/com/android/settings/connecteddevice/OWNERS new file mode 100644 index 00000000000..faa848d7d1e --- /dev/null +++ b/tests/robotests/src/com/android/settings/connecteddevice/OWNERS @@ -0,0 +1 @@ +include /src/com/android/settings/connecteddevice/OWNERS