diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 2aa1a6ea7798..9407acc56f97 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -6149,6 +6149,10 @@ public static void setShowGTalkServiceStatusForUser(ContentResolver cr, boolean
*/
public static final String QQS_LAYOUT = "qqs_layout";
+ /**
+ * @hide
+ */
+ public static final String QS_UI_STYLE = "qs_ui_style";
/**
* Whether to enable PULSE Edge lights
* @hide
diff --git a/core/java/com/android/internal/util/octavi/OctaviUtils.java b/core/java/com/android/internal/util/octavi/OctaviUtils.java
index dd8a2d4e2cdf..2c8f04072e0e 100644
--- a/core/java/com/android/internal/util/octavi/OctaviUtils.java
+++ b/core/java/com/android/internal/util/octavi/OctaviUtils.java
@@ -240,6 +240,12 @@ public static boolean getQSTileVerticalLayout(Context context) {
0, UserHandle.USER_CURRENT) == 1;
}
+ public static int getQsUiStyle(Context context) {
+ return Settings.System.getIntForUser(context.getContentResolver(),
+ Settings.System.QS_UI_STYLE,
+ 0, UserHandle.USER_CURRENT);
+ }
+
public static boolean updateLayout(Context context) {
final IOverlayManager overlayManager = IOverlayManager.Stub.asInterface(ServiceManager.getService(
Context.OVERLAY_SERVICE));
diff --git a/packages/SettingsLib/src/com/android/settingslib/display/BrightnessUtils.java b/packages/SettingsLib/src/com/android/settingslib/display/BrightnessUtils.java
index 4f86afaa995c..e108ceedea03 100644
--- a/packages/SettingsLib/src/com/android/settingslib/display/BrightnessUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/display/BrightnessUtils.java
@@ -16,12 +16,18 @@
package com.android.settingslib.display;
+import android.os.SystemProperties;
import android.util.MathUtils;
+import com.android.internal.display.BrightnessSynchronizer;
+
public class BrightnessUtils {
+ public static final boolean sysUseLowGamma = Boolean.parseBoolean(
+ SystemProperties.get("persist.sys.brightness.low.gamma", "false"));
+
public static final int GAMMA_SPACE_MIN = 0;
- public static final int GAMMA_SPACE_MAX = 65535;
+ public static final int GAMMA_SPACE_MAX = sysUseLowGamma ? 255 : 65535;
// Hybrid Log Gamma constant values
private static final float R = 0.5f;
@@ -87,9 +93,8 @@ public static final float convertGammaToLinearFloat(int val, float min, float ma
// it shouldn't be out of bounds.
final float normalizedRet = MathUtils.constrain(ret, 0, 12);
- // Re-normalize to the range [0, 1]
- // in order to derive the correct setting value.
- return MathUtils.lerp(min, max, normalizedRet / 12);
+ return sysUseLowGamma ? MathUtils.constrain(BrightnessSynchronizer.brightnessIntToFloat(val),
+ min, max) : MathUtils.lerp(min, max, normalizedRet / 12);
}
/**
@@ -136,6 +141,7 @@ public static final int convertLinearToGammaFloat(float val, float min, float ma
ret = A * MathUtils.log(normalizedVal - B) + C;
}
- return Math.round(MathUtils.lerp(GAMMA_SPACE_MIN, GAMMA_SPACE_MAX, ret));
+ return sysUseLowGamma ? BrightnessSynchronizer.brightnessFloatToInt(
+ MathUtils.constrain(val, min, max)) : Math.round(MathUtils.lerp(GAMMA_SPACE_MIN, GAMMA_SPACE_MAX, ret));
}
-}
+}
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/qs_tile_background_no_mask.xml b/packages/SystemUI/res/drawable/qs_tile_background_no_mask.xml
new file mode 100644
index 000000000000..7edc4c8531b8
--- /dev/null
+++ b/packages/SystemUI/res/drawable/qs_tile_background_no_mask.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/qs_tile_background_shape_a11.xml b/packages/SystemUI/res/drawable/qs_tile_background_shape_a11.xml
new file mode 100644
index 000000000000..c37fa5196e8d
--- /dev/null
+++ b/packages/SystemUI/res/drawable/qs_tile_background_shape_a11.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_panel.xml b/packages/SystemUI/res/layout/qs_panel.xml
index 1eb05bfd602d..894ea465c671 100644
--- a/packages/SystemUI/res/layout/qs_panel.xml
+++ b/packages/SystemUI/res/layout/qs_panel.xml
@@ -38,6 +38,7 @@
android:background="@android:color/transparent"
android:focusable="true"
android:accessibilityTraversalBefore="@android:id/edit"
+ android:paddingTop="@dimen/custom_qs_panel_padding_top"
android:clipToPadding="false"
android:clipChildren="false">
diff --git a/packages/SystemUI/res/layout/qs_tile_label_a11.xml b/packages/SystemUI/res/layout/qs_tile_label_a11.xml
new file mode 100644
index 000000000000..5a6a0cc66128
--- /dev/null
+++ b/packages/SystemUI/res/layout/qs_tile_label_a11.xml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_tile_side_icon_a11.xml b/packages/SystemUI/res/layout/qs_tile_side_icon_a11.xml
new file mode 100644
index 000000000000..aee802146aec
--- /dev/null
+++ b/packages/SystemUI/res/layout/qs_tile_side_icon_a11.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
index 1749ed403c09..8915d87caf2f 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
@@ -41,6 +41,7 @@
android:clipChildren="false"
android:clipToPadding="false"
android:focusable="true"
+ android:paddingTop="@dimen/custom_qs_panel_padding_top"
android:paddingBottom="@dimen/qqs_layout_padding_bottom"
android:importantForAccessibility="no">
diff --git a/packages/SystemUI/res/layout/status_bar_notification_footer.xml b/packages/SystemUI/res/layout/status_bar_notification_footer.xml
index db94c92738f2..c1df2e8291d4 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_footer.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_footer.xml
@@ -19,8 +19,8 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingStart="16dp"
- android:paddingEnd="16dp"
+ android:paddingStart="@dimen/custom_notification_row_padding"
+ android:paddingEnd="@dimen/custom_notification_row_padding"
android:visibility="gone">
+
+
+
+ 6
+ 4
+
+
+ 6
+ 4
+
\ No newline at end of file
diff --git a/packages/SystemUI/res/values/qsUIStyle_dimens.xml b/packages/SystemUI/res/values/qsUIStyle_dimens.xml
new file mode 100644
index 000000000000..738c345e2717
--- /dev/null
+++ b/packages/SystemUI/res/values/qsUIStyle_dimens.xml
@@ -0,0 +1,18 @@
+
+
+
+
+ 0dp
+ 16dp
+
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index c453b7df1495..ae01ec6b6cc3 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -106,6 +106,7 @@
import com.android.internal.policy.ScreenDecorationsUtils;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.LatencyTracker;
+import com.android.internal.util.octavi.udfps.UdfpsUtils;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardConstants;
import com.android.keyguard.KeyguardDisplayManager;
@@ -1435,8 +1436,10 @@ public void onStartedGoingToSleep(@WindowManagerPolicyConstants.OffReason int of
// explicitly DO NOT want to call
// mKeyguardViewControllerLazy.get().setKeyguardGoingAwayState(false)
// here, since that will mess with the device lock state.
- mUpdateMonitor.dispatchKeyguardGoingAway(false);
-
+ boolean isUdfps = deviceHasUdfps();
+ if (!isUdfps) {
+ mUpdateMonitor.dispatchKeyguardGoingAway(false);
+ }
notifyStartedGoingToSleep();
}
@@ -3454,4 +3457,8 @@ public void onAnimationCancelled(boolean isKeyguardOccluded) throws RemoteExcept
mInteractionJankMonitor.cancel(CUJ_LOCKSCREEN_OCCLUSION);
}
}
-}
+
+ private boolean deviceHasUdfps() {
+ return UdfpsUtils.hasUdfpsSupport(mContext);
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index 9a201e7ca03c..55d9643bdaf1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -143,6 +143,7 @@ public class QSAnimator implements QSHost.Callback, PagedTileLayout.PageListener
private final TunerService mTunerService;
private boolean mShowCollapsedOnKeyguard;
private int mQQSTop;
+ private boolean isA11Style;
private int[] mTmpLoc1 = new int[2];
private int[] mTmpLoc2 = new int[2];
@@ -180,6 +181,8 @@ public QSAnimator(QS qs, QuickQSPanel quickPanel, QuickStatusBarHeader quickStat
Log.w(TAG, "QS Not using page layout");
}
mQsPanelController.setPageListener(this);
+ isA11Style = mTunerService.getValue(QSPanel.QS_UI_STYLE, 0) == 1;
+
}
public void onRtlChanged() {
@@ -358,8 +361,8 @@ private void updateAnimators() {
// Icons
translateContent(
- quickTileView.getIcon(),
- tileView.getIcon(),
+ isA11Style ? quickTileView.getIconWithBackground() : quickTileView.getIcon(),
+ isA11Style ? tileView.getIconWithBackground() : tileView.getIcon(),
view,
xOffset,
yOffset,
@@ -401,13 +404,13 @@ private void updateAnimators() {
// Therefore, we use a quadratic interpolator animator to animate the alpha
// for tiles in QQS to match.
quadraticInterpolatorBuilder
- .addFloat(quickTileView.getSecondaryLabel(), "alpha", 0, 1);
+ .addFloat(isA11Style ? quickTileView.getLabelContainer() : quickTileView.getSecondaryLabel(), "alpha", 0, 1);
nonFirstPageAlphaBuilder
- .addFloat(quickTileView.getSecondaryLabel(), "alpha", 0, 0);
+ .addFloat(isA11Style ? quickTileView.getLabelContainer() : quickTileView.getSecondaryLabel(), "alpha", 0, 0);
mAnimatedQsViews.add(tileView);
mAllViews.add(quickTileView);
- mAllViews.add(quickTileView.getSecondaryLabel());
+ mAllViews.add(isA11Style ? quickTileView.getLabelContainer() : quickTileView.getSecondaryLabel());
} else if (!isIconInAnimatedRow(count)) {
// Pretend there's a corresponding QQS tile (for the position) that we are
// expanding from.
@@ -426,8 +429,8 @@ private void updateAnimators() {
mOtherFirstPageTilesHeightAnimator.addView(tileView);
tileView.setClipChildren(true);
tileView.setClipToPadding(true);
- firstPageBuilder.addFloat(tileView.getSecondaryLabel(), "alpha", 0, 1);
- mAllViews.add(tileView.getSecondaryLabel());
+ firstPageBuilder.addFloat(isA11Style ? tileView.getLabelContainer() : tileView.getSecondaryLabel(), "alpha", 0, 1);
+ mAllViews.add(isA11Style ? tileView.getLabelContainer() : tileView.getSecondaryLabel());
}
QSTileView quickTileView = mQuickQSPanelController.getTileView(tile);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index b7f9f6bc0e4a..d36560acaf4e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -19,6 +19,7 @@
import static android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS;
import android.content.Context;
+import android.content.res.Configuration;
import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.PointF;
@@ -30,6 +31,7 @@
import com.android.systemui.R;
import com.android.systemui.qs.customize.QSCustomizer;
import com.android.systemui.util.LargeScreenUtils;
+import com.android.internal.util.systemui.qs.QSLayoutUtils;
import java.io.PrintWriter;
@@ -83,11 +85,19 @@ public boolean performClick() {
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// QSPanel will show as many rows as it can (up to TileLayout.MAX_ROWS) such that the
// bottom and footer are inside the screen.
+ Configuration config = getResources().getConfiguration();
+ boolean navBelow = config.smallestScreenWidthDp >= 600
+ || config.orientation != Configuration.ORIENTATION_LANDSCAPE;
MarginLayoutParams layoutParams = (MarginLayoutParams) mQSPanelContainer.getLayoutParams();
+ // The footer is pinned to the bottom of QSPanel (same bottoms), therefore we don't need to
+ // subtract its height. We do not care if the collapsed notifications fit in the screen.
int availableHeight = View.MeasureSpec.getSize(heightMeasureSpec);
int maxQs = availableHeight - layoutParams.topMargin - layoutParams.bottomMargin
- getPaddingBottom();
+ if (navBelow && QSLayoutUtils.getQsUiStyle(mContext) == 1) {
+ maxQs -= getResources().getDimensionPixelSize(R.dimen.navigation_bar_height);
+ }
int padding = mPaddingLeft + mPaddingRight + layoutParams.leftMargin
+ layoutParams.rightMargin;
final int qsPanelWidthSpec = getChildMeasureSpec(widthMeasureSpec, padding,
@@ -95,6 +105,8 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
mQSPanelContainer.measure(qsPanelWidthSpec,
MeasureSpec.makeMeasureSpec(maxQs, MeasureSpec.AT_MOST));
int width = mQSPanelContainer.getMeasuredWidth() + padding;
+ int height = layoutParams.topMargin + layoutParams.bottomMargin
+ + mQSPanelContainer.getMeasuredHeight() + getPaddingBottom();
super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(availableHeight, MeasureSpec.EXACTLY));
// QSCustomizer will always be the height of the screen, but do this after
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 29e18b4686aa..b234de2d70d8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -28,6 +28,7 @@
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Trace;
+import android.provider.Settings;
import android.util.IndentingPrintWriter;
import android.util.Log;
import android.view.ContextThemeWrapper;
@@ -70,6 +71,7 @@
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
+import com.android.systemui.tuner.TunerService;
import com.android.systemui.statusbar.policy.SecureLockscreenQSDisabler;
import com.android.systemui.util.LifecycleFragment;
import com.android.systemui.util.Utils;
@@ -82,13 +84,16 @@
import javax.inject.Named;
public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Callbacks,
- StatusBarStateController.StateListener, Dumpable {
+ StatusBarStateController.StateListener, Dumpable, TunerService.Tunable {
private static final String TAG = "QS";
private static final boolean DEBUG = false;
private static final String EXTRA_EXPANDED = "expanded";
private static final String EXTRA_LISTENING = "listening";
private static final String EXTRA_VISIBLE = "visible";
+ private static final String QS_UI_STYLE =
+ "system:" + Settings.System.QS_UI_STYLE;
+
private final Rect mQsBounds = new Rect();
private final SysuiStatusBarStateController mStatusBarStateController;
private final KeyguardBypassController mBypassController;
@@ -110,6 +115,8 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
private float mSquishinessFraction = 1;
private boolean mQsDisabled;
private int[] mLocationTemp = new int[2];
+ private int mQSPanelScrollY = 0;
+ private boolean isA11Style;
private final RemoteInputQuickSettingsDisabler mRemoteInputQuickSettingsDisabler;
private final MediaHost mQsMediaHost;
@@ -167,6 +174,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
private boolean mQsVisible;
private boolean mIsSmallScreen;
+ private final TunerService mTunerService;
@Inject
public QSFragment(RemoteInputQuickSettingsDisabler remoteInputQsDisabler,
@@ -181,7 +189,8 @@ public QSFragment(RemoteInputQuickSettingsDisabler remoteInputQsDisabler,
FooterActionsViewModel.Factory footerActionsViewModelFactory,
SecureLockscreenQSDisabler secureLockscreenQSDisabler,
LargeScreenShadeInterpolator largeScreenShadeInterpolator,
- FeatureFlags featureFlags) {
+ FeatureFlags featureFlags,
+ TunerService tunerService) {
mRemoteInputQuickSettingsDisabler = remoteInputQsDisabler;
mQsMediaHost = qsMediaHost;
mQqsMediaHost = qqsMediaHost;
@@ -198,6 +207,8 @@ public QSFragment(RemoteInputQuickSettingsDisabler remoteInputQsDisabler,
mFooterActionsViewModelFactory = footerActionsViewModelFactory;
mListeningAndVisibilityLifecycleOwner = new ListeningAndVisibilityLifecycleOwner();
mSecureLockscreenQSDisabler = secureLockscreenQSDisabler;
+ mTunerService = tunerService;
+
}
@Override
@@ -235,6 +246,9 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
mQSPanelScrollView.setOnScrollChangeListener(
(v, scrollX, scrollY, oldScrollX, oldScrollY) -> {
// Lazily update animators whenever the scrolling changes
+ if (isA11Style) {
+ mQSPanelScrollY = scrollY;
+ }
mQSAnimator.requestAnimatorUpdate();
if (mScrollListener != null) {
mScrollListener.onQsPanelScrollChanged(scrollY);
@@ -282,6 +296,8 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
mQSPanelController.getMediaHost().getHostView().setAlpha(1.0f);
mQSAnimator.requestAnimatorUpdate();
});
+ mTunerService.addTunable(this, QS_UI_STYLE);
+
}
private void bindFooterActionsView(View root) {
@@ -413,6 +429,17 @@ public void setCollapsedMediaVisibilityChangedListener(Consumer listene
mQuickQSPanelController.setMediaVisibilityChangedListener(listener);
}
+ @Override
+ public void onTuningChanged(String key, String newValue) {
+ switch (key) {
+ case QS_UI_STYLE:
+ isA11Style = TunerService.parseInteger(newValue, 0) == 1;
+ break;
+ default:
+ break;
+ }
+ }
+
private void setEditLocation(View view) {
View edit = view.findViewById(android.R.id.edit);
int[] loc = edit.getLocationOnScreen();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index ac2039b09b17..95436a591fdd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -62,6 +62,9 @@ public class QSPanel extends LinearLayout implements Tunable {
public static final String QS_BRIGHTNESS_SLIDER_POSITION =
Settings.Secure.QS_BRIGHTNESS_SLIDER_POSITION;
+ public static final String QS_UI_STYLE =
+ "system:" + Settings.System.QS_UI_STYLE;
+
private static final String TAG = "QSPanel";
protected final Context mContext;
@@ -103,7 +106,7 @@ public class QSPanel extends LinearLayout implements Tunable {
private PageIndicator mFooterPageIndicator;
private int mContentMarginStart;
private int mContentMarginEnd;
- private boolean mUsingHorizontalLayout;
+ protected boolean mUsingHorizontalLayout;
@Nullable
private LinearLayout mHorizontalLinearLayout;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
index 00a1e6f617ba..4d557988ef99 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
@@ -151,7 +151,9 @@ protected void onViewDetached() {
@Override
protected void onConfigurationChanged() {
- mView.updateResources();
+ if (mView != null) {
+ mView.updateResources();
+ }
if (mView.isListening()) {
refreshAllTiles();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileView.kt b/packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileView.kt
index a316e6aa5f1b..8db674f276dc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileView.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/CustomizeTileView.kt
@@ -18,6 +18,10 @@ package com.android.systemui.qs.customize
import android.content.Context
import android.text.TextUtils
+
+import android.os.UserHandle
+import android.provider.Settings
+
import com.android.systemui.plugins.qs.QSIconView
import com.android.systemui.plugins.qs.QSTile
import com.android.systemui.qs.tileimpl.QSTileViewImpl
@@ -42,6 +46,9 @@ class CustomizeTileView(
if (!showSideView) sideView.visibility = GONE
}
+ private fun isA11Style(): Boolean = Settings.System.getIntForUser(context.contentResolver,
+ Settings.System.QS_UI_STYLE, 0, UserHandle.USER_CURRENT) == 1
+
override fun handleStateChanged(state: QSTile.State) {
super.handleStateChanged(state)
showRippleEffect = false
@@ -53,7 +60,7 @@ class CustomizeTileView(
return if (showAppLabel && !TextUtils.isEmpty(text)) {
VISIBLE
} else {
- GONE
+ if (isA11Style()) INVISIBLE else GONE
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
index 13a0fbeb6f59..8e6da4ed2c1f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
@@ -16,6 +16,7 @@
package com.android.systemui.qs.tileimpl
+import android.animation.AnimatorSet
import android.animation.ArgbEvaluator
import android.animation.PropertyValuesHolder
import android.animation.ValueAnimator
@@ -25,6 +26,7 @@ import android.content.res.Configuration
import android.content.res.Resources.ID_NULL
import android.graphics.drawable.Drawable
import android.graphics.drawable.RippleDrawable
+import android.graphics.drawable.GradientDrawable
import android.os.Trace
import android.os.UserHandle
import android.provider.Settings
@@ -48,6 +50,7 @@ import com.android.systemui.FontSizeUtils
import com.android.systemui.R
import com.android.systemui.animation.LaunchableView
import com.android.systemui.animation.LaunchableViewDelegate
+import com.android.systemui.animation.Interpolators
import com.android.systemui.plugins.qs.QSIconView
import com.android.systemui.plugins.qs.QSTile
import com.android.systemui.plugins.qs.QSTile.BooleanState
@@ -72,6 +75,10 @@ open class QSTileViewImpl @JvmOverloads constructor(
private const val SECONDARY_LABEL_NAME = "secondaryLabel"
private const val CHEVRON_NAME = "chevron"
const val UNAVAILABLE_ALPHA = 0.3f
+ const val INACTIVE_ALPHA = 0.8f
+ const val TILE_ALPHA = 0.2f
+
+
@VisibleForTesting
internal const val TILE_STATE_RES_PREFIX = "tile_states_"
}
@@ -96,25 +103,31 @@ open class QSTileViewImpl @JvmOverloads constructor(
updateHeight()
}
+ private val isA11Style: Boolean = System.getIntForUser(
+ context.contentResolver,
+ System.QS_UI_STYLE, 0, UserHandle.USER_CURRENT
+ ) == 1
+
private val colorActive = Utils.getColorAttrDefaultColor(context,
android.R.attr.colorAccent)
- private val colorInactive = Utils.getColorAttrDefaultColor(context, R.attr.offStateColor)
- private val colorUnavailable = Utils.applyAlpha(UNAVAILABLE_ALPHA, colorInactive)
+ private val colorOffstate = Utils.getColorAttrDefaultColor(context, R.attr.offStateColor)
+ private val colorInactive = if (isA11Style) Utils.applyAlpha(INACTIVE_ALPHA, colorOffstate) else Utils.getColorAttrDefaultColor(context, R.attr.offStateColor) private val colorUnavailable = Utils.applyAlpha(UNAVAILABLE_ALPHA, colorInactive)
private val colorLabelActive = Utils.getColorAttrDefaultColor(context,
- com.android.internal.R.attr.textColorPrimaryInverse)
+ if (isA11Style) com.android.internal.R.attr.textColorPrimary else com.android.internal.R.attr.textColorPrimaryInverse)
private val colorLabelInactive =
- Utils.getColorAttrDefaultColor(context, android.R.attr.textColorPrimary)
+ Utils.getColorAttrDefaultColor(context, if (isA11Style) android.R.attr.textColorSecondary else android.R.attr.textColorPrimary)
private val colorLabelUnavailable =
Utils.getColorAttrDefaultColor(context, com.android.internal.R.attr.textColorTertiary)
private val colorSecondaryLabelActive =
- Utils.getColorAttrDefaultColor(context, android.R.attr.textColorSecondaryInverse)
+ Utils.getColorAttrDefaultColor(context, if (isA11Style) android.R.attr.textColorSecondary else android.R.attr.textColorSecondaryInverse)
private val colorSecondaryLabelInactive =
- Utils.getColorAttrDefaultColor(context, android.R.attr.textColorSecondary)
+ Utils.getColorAttrDefaultColor(context, if (isA11Style) com.android.internal.R.attr.textColorTertiary else android.R.attr.textColorSecondary)
private val colorSecondaryLabelUnavailable =
Utils.getColorAttrDefaultColor(context, com.android.internal.R.attr.textColorTertiary)
+ private lateinit var iconContainer: LinearLayout
private lateinit var label: TextView
protected lateinit var secondaryLabel: TextView
private lateinit var labelContainer: IgnorableChildLinearLayout
@@ -127,8 +140,17 @@ open class QSTileViewImpl @JvmOverloads constructor(
private lateinit var ripple: RippleDrawable
private lateinit var colorBackgroundDrawable: Drawable
private var paintColor: Int = 0
+ private var radiusActive: Float = 0f
+ private var radiusInactive: Float = 0f
+ private val shapeAnimator: ValueAnimator = ValueAnimator.ofFloat(0f, 1f).apply {
+ duration = QS_ANIM_LENGTH
+ interpolator = Interpolators.FAST_OUT_SLOW_IN
+ addUpdateListener { animation ->
+ setCornerRadius(animation.animatedValue as Float)
+ }
+ }
private val singleAnimator: ValueAnimator = ValueAnimator().apply {
- setDuration(QS_ANIM_LENGTH)
+ duration = QS_ANIM_LENGTH
addUpdateListener { animation ->
setAllColors(
// These casts will throw an exception if some property is missing. We should
@@ -141,6 +163,9 @@ open class QSTileViewImpl @JvmOverloads constructor(
}
}
+ private val tileAnimator = AnimatorSet().apply {
+ playTogether(singleAnimator, shapeAnimator)
+ }
private var accessibilityClass: String? = null
private var stateDescriptionDeltas: CharSequence? = null
private var lastStateDescription: CharSequence? = null
@@ -161,34 +186,58 @@ open class QSTileViewImpl @JvmOverloads constructor(
init {
setId(generateViewId())
vertical = QSLayoutUtils.getQSTileVerticalLayout(context)
- if (vertical) {
+ if (isA11Style) {
orientation = LinearLayout.VERTICAL
gravity = Gravity.CENTER_HORIZONTAL
} else {
orientation = LinearLayout.HORIZONTAL
- gravity = Gravity.CENTER_VERTICAL or Gravity.START
- }
+ orientation = if (vertical) LinearLayout.VERTICAL else LinearLayout.HORIZONTAL
+ gravity = if (vertical) Gravity.CENTER_HORIZONTAL or Gravity.CENTER_VERTICAL else Gravity.CENTER_VERTICAL or Gravity.START
+ }
labelHide = QSLayoutUtils.getQSTileLabelHide(context)
if (labelHide)
- gravity = Gravity.CENTER_HORIZONTAL or Gravity.CENTER_VERTICAL
+ gravity = Gravity.CENTER
importantForAccessibility = IMPORTANT_FOR_ACCESSIBILITY_YES
clipChildren = false
clipToPadding = false
isFocusable = true
background = createTileBackground()
+ background = if (isA11Style) null else createTileBackground()
+
+ if (isA11Style) {
+ val iconContainerSize = context.resources.getDimensionPixelSize(R.dimen.qs_quick_tile_size)
+ radiusActive = iconContainerSize / 2f
+ radiusInactive = iconContainerSize / 4f
+ iconContainer = LinearLayout(context)
+ iconContainer.layoutParams = LayoutParams(iconContainerSize, iconContainerSize)
+ iconContainer.clipChildren = false
+ iconContainer.clipToPadding = false
+ iconContainer.orientation = LinearLayout.VERTICAL
+ iconContainer.gravity = Gravity.CENTER
+ iconContainer.background = createTileBackground()
+ }
+
setColor(getBackgroundColorForState(QSTile.State.DEFAULT_STATE))
- val padding = resources.getDimensionPixelSize(R.dimen.qs_tile_padding)
- val startPadding = if (vertical) padding else resources.getDimensionPixelSize(R.dimen.qs_tile_start_padding)
- setPaddingRelative(startPadding, padding, padding, padding)
+ val iconSize = context.resources.getDimensionPixelSize(R.dimen.qs_icon_size)
- val iconSize = resources.getDimensionPixelSize(R.dimen.qs_icon_size)
- addView(_icon, LayoutParams(iconSize, iconSize))
+ if (isA11Style) {
+ setCornerRadius(getCornerRadiusForState(QSTile.State.DEFAULT_STATE))
+ iconContainer.addView(_icon, LayoutParams(iconSize, iconSize))
+ addView(iconContainer, 0)
+ } else {
+ val padding = resources.getDimensionPixelSize(R.dimen.qs_tile_padding)
+ val startPadding = if (vertical) padding else resources.getDimensionPixelSize(R.dimen.qs_tile_start_padding)
+ setPaddingRelative(startPadding, padding, padding, padding)
+ addView(_icon, LayoutParams(iconSize, iconSize))
+ }
createAndAddLabels()
createAndAddSideView()
+ updateResources()
+
}
override fun onConfigurationChanged(newConfig: Configuration?) {
@@ -215,6 +264,14 @@ open class QSTileViewImpl @JvmOverloads constructor(
FontSizeUtils.updateFontSize(label, R.dimen.qs_tile_text_size)
FontSizeUtils.updateFontSize(secondaryLabel, R.dimen.qs_tile_text_size)
+
+ if (isA11Style) {
+ updateA11StyleResources()
+ } else {
+ updateDefaultResources()
+ }
+ }
+
val iconSize = context.resources.getDimensionPixelSize(R.dimen.qs_icon_size)
_icon.layoutParams.apply {
height = iconSize
@@ -222,12 +279,12 @@ open class QSTileViewImpl @JvmOverloads constructor(
}
vertical = QSLayoutUtils.getQSTileVerticalLayout(context)
- if (vertical) {
+ if (isA11Style) {
orientation = LinearLayout.VERTICAL
- gravity = Gravity.CENTER_HORIZONTAL
+ gravity = Gravity.CENTER
} else {
- orientation = LinearLayout.HORIZONTAL
- gravity = Gravity.CENTER_VERTICAL or Gravity.START
+ orientation = if (vertical) LinearLayout.VERTICAL else LinearLayout.HORIZONTAL
+ gravity = if (vertical) Gravity.CENTER_HORIZONTAL or Gravity.CENTER_VERTICAL else Gravity.CENTER_VERTICAL or Gravity.START
}
if (labelHide)
@@ -235,7 +292,7 @@ open class QSTileViewImpl @JvmOverloads constructor(
val padding = resources.getDimensionPixelSize(R.dimen.qs_tile_padding)
val startPadding = if (vertical) padding else resources.getDimensionPixelSize(R.dimen.qs_tile_start_padding)
- setPaddingRelative(startPadding, padding, padding, padding)
+ setPaddingRelative(startPadding, padding, padding, padding)
val labelMargin = if (vertical) 0 else resources.getDimensionPixelSize(R.dimen.qs_label_container_margin)
(labelContainer.layoutParams as MarginLayoutParams).apply {
@@ -257,19 +314,56 @@ open class QSTileViewImpl @JvmOverloads constructor(
}
}
+ fun updateA11StyleResources() {
+ labelContainer.invalidate()
+ labelContainer.apply {
+ ignoreLastView = collapsed
+ forceUnspecifiedMeasure = collapsed
+ }
+ secondaryLabel.alpha = if (collapsed) 0f else 1f
+
+ orientation = LinearLayout.VERTICAL
+ gravity = Gravity.CENTER
+
+ val iconContainerSize = context.resources.getDimensionPixelSize(R.dimen.qs_quick_tile_size)
+ iconContainer.layoutParams.apply {
+ height = iconContainerSize
+ width = iconContainerSize
+ }
+ val padding = resources.getDimensionPixelSize(R.dimen.qs_tile_padding)
+ val iconSize = context.resources.getDimensionPixelSize(R.dimen.qs_icon_size)
+ _icon.layoutParams.apply {
+ height = iconSize
+ width = iconSize
+ }
+ iconContainer.setPaddingRelative(padding, padding, padding, padding)
+ (labelContainer.layoutParams as MarginLayoutParams).apply {
+ topMargin = padding / 2
+ }
+ }
private fun createAndAddLabels() {
labelContainer = LayoutInflater.from(context)
- .inflate(if (vertical) R.layout.qs_tile_label_vertical else R.layout.qs_tile_label, this, false) as IgnorableChildLinearLayout
- label = labelContainer.requireViewById(R.id.tile_label)
+ .inflate(if (isA11Style) R.layout.qs_tile_label_a11 else (if (vertical) R.layout.qs_tile_label_vertical else R.layout.qs_tile_label), this, false) as
+ IgnorableChildLinearLayout
+ label = labelContainer.requireViewById(R.id.tile_label)
secondaryLabel = labelContainer.requireViewById(R.id.app_label)
- if (collapsed) {
- labelContainer.ignoreLastView = true
- // Ideally, it'd be great if the parent could set this up when measuring just this child
- // instead of the View class having to support this. However, due to the mysteries of
- // LinearLayout's double measure pass, we cannot overwrite `measureChild` or any of its
- // sibling methods to have special behavior for labelContainer.
- labelContainer.forceUnspecifiedMeasure = true
- secondaryLabel.alpha = 0f
+ if (isA11Style) {
+ if (collapsed) {
+ labelContainer.ignoreLastView = true
+ // Ideally, it'd be great if the parent could set this up when measuring just this child
+ // instead of the View class having to support this. However, due to the mysteries of
+ // LinearLayout's double measure pass, we cannot overwrite `measureChild` or any of its
+ // sibling methods to have special behavior for labelContainer.
+ labelContainer.forceUnspecifiedMeasure = true
+ secondaryLabel.alpha = 0f
+ }
+ } else {
+ labelContainer.invalidate()
+ labelContainer.apply {
+ ignoreLastView = collapsed
+ forceUnspecifiedMeasure = collapsed
+ }
+ secondaryLabel.alpha = if (collapsed) 0f else 1f
}
setLabelColor(getLabelColorForState(QSTile.State.DEFAULT_STATE))
setSecondaryLabelColor(getSecondaryLabelColorForState(QSTile.State.DEFAULT_STATE))
@@ -280,7 +374,7 @@ open class QSTileViewImpl @JvmOverloads constructor(
private fun createAndAddSideView() {
sideView = LayoutInflater.from(context)
- .inflate(R.layout.qs_tile_side_icon, this, false) as ViewGroup
+ .inflate(if (isA11Style) R.layout.qs_tile_side_icon else R.layout.qs_tile_side_icon_a11, this, false) as ViewGroup
customDrawableView = sideView.requireViewById(R.id.customDrawable)
chevronView = sideView.requireViewById(R.id.chevron)
setChevronColor(getChevronColorForState(QSTile.State.DEFAULT_STATE))
@@ -288,7 +382,7 @@ open class QSTileViewImpl @JvmOverloads constructor(
}
fun createTileBackground(): Drawable {
- ripple = mContext.getDrawable(R.drawable.qs_tile_background) as RippleDrawable
+ ripple = mContext.getDrawable(if (isA11Style) R.drawable.qs_tile_background_no_mask else R.drawable.qs_tile_background).mutate() as RippleDrawable
colorBackgroundDrawable = ripple.findDrawableByLayerId(R.id.background)
return ripple
}
@@ -321,7 +415,7 @@ open class QSTileViewImpl @JvmOverloads constructor(
}
override fun getIconWithBackground(): View {
- return icon
+ return if (isA11Style) iconContainer else icon
}
override fun init(tile: QSTile) {
@@ -359,15 +453,26 @@ open class QSTileViewImpl @JvmOverloads constructor(
override fun setClickable(clickable: Boolean) {
super.setClickable(clickable)
- background = if (clickable && showRippleEffect) {
- ripple.also {
- // In case that the colorBackgroundDrawable was used as the background, make sure
- // it has the correct callback instead of null
- colorBackgroundDrawable.callback = it
+ if (isA11Style) {
+ iconContainer.background = if (clickable && showRippleEffect) {
+ ripple.also {
+ // In case that the colorBackgroundDrawable was used as the background, make sure
+ // it has the correct callback instead of null
+ colorBackgroundDrawable.callback = it
+ }
+ } else {
+ colorBackgroundDrawable
}
} else {
- colorBackgroundDrawable
- }
+ background = if (clickable && showRippleEffect) {
+ ripple.also {
+ // In case that the colorBackgroundDrawable was used as the background, make sure
+ // it has the correct callback instead of null
+ colorBackgroundDrawable.callback = it
+ }
+ } else {
+ colorBackgroundDrawable
+ } }
}
override fun getLabelContainer(): View {
@@ -516,7 +621,7 @@ open class QSTileViewImpl @JvmOverloads constructor(
if (!Objects.equals(secondaryLabel.text, state.secondaryLabel)) {
secondaryLabel.text = state.secondaryLabel
secondaryLabel.visibility = if (TextUtils.isEmpty(state.secondaryLabel)) {
- GONE
+ if (isA11Style) View.INVISIBLE else View.GONE
} else {
VISIBLE
}
@@ -524,13 +629,23 @@ open class QSTileViewImpl @JvmOverloads constructor(
// Colors
if (state.state != lastState || state.disabledByPolicy || lastDisabledByPolicy) {
- singleAnimator.cancel()
+ if (isA11Style) {
+ tileAnimator.cancel()
+ } else {
+ singleAnimator.cancel()
+ }
mQsLogger?.logTileBackgroundColorUpdateIfInternetTile(
state.spec,
state.state,
state.disabledByPolicy,
getBackgroundColorForState(state.state, state.disabledByPolicy))
if (allowAnimations) {
+ if (isA11Style) {
+ shapeAnimator.setFloatValues(
+ (colorBackgroundDrawable as GradientDrawable).cornerRadius,
+ getCornerRadiusForState(state.state)
+ )
+ }
singleAnimator.setValues(
colorValuesHolder(
BACKGROUND_NAME,
@@ -554,6 +669,11 @@ open class QSTileViewImpl @JvmOverloads constructor(
)
)
singleAnimator.start()
+ if (isA11Style) {
+ tileAnimator.start()
+ } else {
+ singleAnimator.start()
+ }
} else {
setAllColors(
getBackgroundColorForState(state.state, state.disabledByPolicy),
@@ -561,6 +681,9 @@ open class QSTileViewImpl @JvmOverloads constructor(
getSecondaryLabelColorForState(state.state, state.disabledByPolicy),
getChevronColorForState(state.state, state.disabledByPolicy)
)
+ if (isA11Style) {
+ setCornerRadius(getCornerRadiusForState(state.state))
+ }
}
}
@@ -623,6 +746,21 @@ open class QSTileViewImpl @JvmOverloads constructor(
return resources.getStringArray(arrayResId)[Tile.STATE_UNAVAILABLE]
}
+ private fun setCornerRadius(cornerRadius: Float) {
+ val mBg = ripple.findDrawableByLayerId(R.id.background) as GradientDrawable
+ mBg.cornerRadius = cornerRadius
+ }
+
+ private fun getCornerRadiusForState(state: Int): Float {
+ return when (state) {
+ Tile.STATE_ACTIVE -> radiusActive
+ Tile.STATE_INACTIVE -> radiusInactive
+ Tile.STATE_UNAVAILABLE -> radiusInactive
+ else -> radiusInactive
+ }
+ }
+
+
/*
* The view should not be animated if it's not on screen and no part of it is visible.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index e01a0e84bd83..e26af8926a8e 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -329,6 +329,8 @@ public final class NotificationPanelViewController implements Dumpable {
"system:" + Settings.System.RETICKER_STATUS;
private static final String RETICKER_COLORED =
"system:" + Settings.System.RETICKER_COLORED;
+ private static final String QS_UI_STYLE =
+ "system:" + Settings.System.QS_UI_STYLE;
private static final String KEYGUARD_QUICK_TOGGLES_NEW =
"system:" + Settings.System.KEYGUARD_QUICK_TOGGLES_NEW;
@@ -733,6 +735,9 @@ public void onTransitionEnd(Transition transition) {
private boolean mBlockedGesturalNavigation = false;
+ private boolean mIsA11Style;
+
+
@Inject
public NotificationPanelViewController(NotificationPanelView view,
@Main Handler handler,
@@ -4697,6 +4702,7 @@ public void onViewAttachedToWindow(View v) {
mConfigurationController.addCallback(mConfigurationListener);
mTunerService.addTunable(this, RETICKER_STATUS);
mTunerService.addTunable(this, RETICKER_COLORED);
+ mTunerService.addTunable(this, QS_UI_STYLE);
mTunerService.addTunable(this, KEYGUARD_QUICK_TOGGLES_NEW);
// Theme might have changed between inflating this view and attaching it to the
// window, so
@@ -4729,6 +4735,9 @@ public void onTuningChanged(String key, String newValue) {
mReTickerColored =
TunerService.parseIntegerSwitch(newValue, false);
break;
+ case QS_UI_STYLE:
+ mIsA11Style = TunerService.parseInteger(newValue, 0) == 1;
+ break;
case KEYGUARD_QUICK_TOGGLES_NEW:
mKeyguardBottomAreaViewModel.updateSettings();
break;
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
index 3a9fc166cd62..e31448ee024e 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
@@ -450,6 +450,18 @@ public void onChange(boolean selfChange, Collection collection, int flags,
}
},
UserHandle.USER_ALL);
+ mSystemSettings.registerContentObserverForUser(
+ Settings.System.getUriFor(Settings.System.QS_UI_STYLE),
+ false,
+ new ContentObserver(mBgHandler) {
+ @Override
+ public void onChange(boolean selfChange, Collection collection, int flags,
+ int userId) {
+ reevaluateSystemTheme(true /* forceReload */);
+ }
+ },
+ UserHandle.USER_ALL);
+
mSecureSettings.registerContentObserverForUser(
Settings.Secure.getUriFor(Settings.Secure.SYSTEM_CUSTOM_THEME),
false,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java
index 35c8cc70953d..ebf8b50adaf8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/TileLayoutTest.java
@@ -157,7 +157,7 @@ public void testMeasureLayout_CallsLayoutOnTilesWithNeighboredBounds() {
.layout(left2.capture(), top2.capture(), right2.capture(), bottom2.capture());
// We assume two tiles will always fit side-by-side.
- assertTrue(mContext.getResources().getInteger(R.integer.quick_settings_num_columns) > 1);
+ assertTrue(mContext.getResources().getInteger(R.integer.quick_qs_panel_max_tiles) > 1);
// left <= right, top <= bottom
assertTrue(left1.getValue() <= right1.getValue());