Merge "Implement new QQS/QS headers" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
ec012bc426
@@ -30,9 +30,7 @@
|
||||
<!-- Height of the status bar -->
|
||||
<dimen name="status_bar_height">@dimen/status_bar_height_landscape</dimen>
|
||||
<!-- Height of area above QQS where battery/time go -->
|
||||
<dimen name="quick_qs_offset_height">@dimen/status_bar_height_landscape</dimen>
|
||||
<!-- Total height of QQS in landscape, this is effectively status_bar_height_landscape + 128 -->
|
||||
<dimen name="quick_qs_total_height">152dp</dimen>
|
||||
<dimen name="quick_qs_offset_height">48dp</dimen>
|
||||
<!-- Default height of an action bar. -->
|
||||
<dimen name="action_bar_default_height">40dip</dimen>
|
||||
<!-- Vertical padding around action bar icons. -->
|
||||
|
||||
@@ -47,10 +47,6 @@
|
||||
<dimen name="status_bar_height_landscape">@dimen/status_bar_height_portrait</dimen>
|
||||
<!-- Height of area above QQS where battery/time go -->
|
||||
<dimen name="quick_qs_offset_height">48dp</dimen>
|
||||
<!-- Total height of QQS (quick_qs_offset_height + 128) -->
|
||||
<dimen name="quick_qs_total_height">176dp</dimen>
|
||||
<!-- Total height of QQS with two rows to fit media player (quick_qs_offset_height + 176) -->
|
||||
<dimen name="quick_qs_total_height_with_media">224dp</dimen>
|
||||
<!-- Height of the bottom navigation / system bar. -->
|
||||
<dimen name="navigation_bar_height">48dp</dimen>
|
||||
<!-- Height of the bottom navigation bar in portrait; often the same as @dimen/navigation_bar_height -->
|
||||
|
||||
@@ -1716,8 +1716,6 @@
|
||||
<java-symbol type="dimen" name="status_bar_height" />
|
||||
<java-symbol type="dimen" name="display_cutout_touchable_region_size" />
|
||||
<java-symbol type="dimen" name="quick_qs_offset_height" />
|
||||
<java-symbol type="dimen" name="quick_qs_total_height" />
|
||||
<java-symbol type="dimen" name="quick_qs_total_height_with_media" />
|
||||
<java-symbol type="drawable" name="ic_jog_dial_sound_off" />
|
||||
<java-symbol type="drawable" name="ic_jog_dial_sound_on" />
|
||||
<java-symbol type="drawable" name="ic_jog_dial_unlock" />
|
||||
|
||||
@@ -18,32 +18,52 @@
|
||||
xmlns:systemui="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/quick_qs_status_icons"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="@dimen/qs_header_top_padding"
|
||||
android:paddingBottom="@dimen/qs_header_bottom_padding"
|
||||
android:layout_below="@id/quick_status_bar_system_icons"
|
||||
android:layout_height="@*android:dimen/quick_qs_offset_height"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:minHeight="20dp"
|
||||
android:minHeight="48dp"
|
||||
android:clickable="false"
|
||||
android:focusable="true"
|
||||
android:theme="@style/QSHeaderTheme">
|
||||
|
||||
<com.android.systemui.statusbar.policy.DateView
|
||||
android:id="@+id/date"
|
||||
<com.android.systemui.statusbar.policy.Clock
|
||||
android:id="@+id/clock"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start|center_vertical"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_height="match_parent"
|
||||
android:minWidth="48dp"
|
||||
android:minHeight="48dp"
|
||||
android:gravity="center_vertical|start"
|
||||
android:paddingStart="@dimen/status_bar_left_clock_starting_padding"
|
||||
android:paddingEnd="@dimen/status_bar_left_clock_end_padding"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/TextAppearance.QS.Status"
|
||||
systemui:datePattern="@string/abbrev_wday_month_day_no_year_alarm" />
|
||||
android:textAppearance="@style/TextAppearance.StatusBar.Clock" />
|
||||
|
||||
<View
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
/>
|
||||
|
||||
<!-- Will hold security footer in landscape with media -->
|
||||
<FrameLayout
|
||||
android:id="@+id/header_text_container"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="wrap_content"
|
||||
android:gravity="center"
|
||||
/>
|
||||
|
||||
<include layout="@layout/qs_carrier_group"
|
||||
android:id="@+id/carrier_group"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:minHeight="48dp"
|
||||
android:layout_gravity="end|center_vertical"
|
||||
android:focusable="false"/>
|
||||
|
||||
<com.android.systemui.statusbar.phone.StatusIconContainer
|
||||
android:id="@+id/statusIcons"
|
||||
android:layout_width="0dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:paddingEnd="@dimen/signal_cluster_battery_padding" />
|
||||
|
||||
<com.android.systemui.BatteryMeterView
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2018 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
|
||||
-->
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/header_text_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/qs_header_tooltip_height"
|
||||
android:layout_below="@id/quick_status_bar_system_icons"
|
||||
android:visibility="invisible"
|
||||
android:theme="@style/QSHeaderTheme"
|
||||
android:forceHasOverlappingRendering="false">
|
||||
|
||||
<com.android.systemui.qs.QSHeaderInfoLayout
|
||||
android:id="@+id/status_container"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:id = "@+id/alarm_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_vertical"
|
||||
android:focusable="true"
|
||||
android:clickable="true">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/next_alarm_icon"
|
||||
android:layout_width="@dimen/qs_header_alarm_icon_size"
|
||||
android:layout_height="@dimen/qs_header_alarm_icon_size"
|
||||
android:src="@drawable/ic_alarm"
|
||||
android:contentDescription="@string/accessibility_quick_settings_alarm_set"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<com.android.systemui.util.AutoMarqueeTextView
|
||||
android:id="@+id/next_alarm_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="marquee"
|
||||
android:marqueeRepeatLimit="marquee_forever"
|
||||
android:layout_marginStart="@dimen/qs_header_alarm_text_margin_start"
|
||||
android:textAppearance="@style/TextAppearance.QS.Status"
|
||||
android:visibility="gone"/>
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/status_separator"
|
||||
android:layout_width="@dimen/qs_header_separator_width"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id = "@+id/ringer_container"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_vertical"
|
||||
android:focusable="true"
|
||||
android:clickable="true">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ringer_mode_icon"
|
||||
android:layout_width="@dimen/qs_header_alarm_icon_size"
|
||||
android:layout_height="@dimen/qs_header_alarm_icon_size"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<com.android.systemui.util.AutoMarqueeTextView
|
||||
android:id="@+id/ringer_mode_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="marquee"
|
||||
android:marqueeRepeatLimit="marquee_forever"
|
||||
android:layout_marginStart="@dimen/qs_header_alarm_text_margin_start"
|
||||
android:textAppearance="@style/TextAppearance.QS.Status"
|
||||
android:visibility="gone"/>
|
||||
</LinearLayout>
|
||||
</com.android.systemui.qs.QSHeaderInfoLayout>
|
||||
|
||||
<include layout="@layout/qs_carrier_group"
|
||||
android:id="@+id/carrier_group"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="@dimen/qs_status_separator"
|
||||
android:layout_gravity="end|center_vertical"
|
||||
android:focusable="false"/>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -32,26 +32,32 @@
|
||||
android:paddingStart="0dp"
|
||||
android:elevation="4dp" >
|
||||
|
||||
<!-- The clock -->
|
||||
<include layout="@layout/quick_status_bar_header_system_icons" />
|
||||
<!-- Date and privacy. Only visible in QS -->
|
||||
<include layout="@layout/quick_status_bar_header_date_privacy"/>
|
||||
|
||||
<!-- Status icons within the panel itself (and not in the top-most status bar) -->
|
||||
<include layout="@layout/quick_qs_status_icons" />
|
||||
|
||||
<!-- Layout containing tooltips, alarm text, etc. -->
|
||||
<include layout="@layout/quick_settings_header_info" />
|
||||
<RelativeLayout
|
||||
android:id="@+id/container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false">
|
||||
<!-- Time, icons and Carrier (only in QS) -->
|
||||
<include layout="@layout/quick_qs_status_icons"/>
|
||||
|
||||
<com.android.systemui.qs.QuickQSPanel
|
||||
android:id="@+id/quick_qs_panel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/quick_qs_status_icons"
|
||||
android:accessibilityTraversalAfter="@+id/date_time_group"
|
||||
android:layout_marginTop="8dp"
|
||||
android:accessibilityTraversalAfter="@id/quick_qs_status_icons"
|
||||
android:accessibilityTraversalBefore="@id/expand_indicator"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:focusable="true"
|
||||
android:paddingBottom="10dp"
|
||||
android:importantForAccessibility="yes" />
|
||||
</RelativeLayout>
|
||||
|
||||
</com.android.systemui.qs.QuickStatusBarHeader>
|
||||
|
||||
@@ -17,33 +17,35 @@
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:systemui="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/quick_status_bar_system_icons"
|
||||
android:id="@+id/quick_status_bar_date_privacy"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@*android:dimen/quick_qs_offset_height"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:gravity="center"
|
||||
android:layout_gravity="top"
|
||||
android:orientation="horizontal"
|
||||
android:clickable="true"
|
||||
android:paddingTop="@dimen/status_bar_padding_top" >
|
||||
android:paddingTop="@dimen/status_bar_padding_top"
|
||||
android:minHeight="48dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:minHeight="48dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical|start" >
|
||||
|
||||
<com.android.systemui.statusbar.policy.Clock
|
||||
android:id="@+id/clock"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:minWidth="48dp"
|
||||
android:gravity="center_vertical|start"
|
||||
android:paddingStart="@dimen/status_bar_left_clock_starting_padding"
|
||||
android:paddingEnd="@dimen/status_bar_left_clock_end_padding"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/TextAppearance.StatusBar.Clock" />
|
||||
<com.android.systemui.statusbar.policy.DateView
|
||||
android:id="@+id/date"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start|center_vertical"
|
||||
android:gravity="center_vertical"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="@style/TextAppearance.QS.Status"
|
||||
systemui:datePattern="@string/abbrev_wday_month_day_no_year_alarm" />
|
||||
</LinearLayout>
|
||||
|
||||
<android.widget.Space
|
||||
@@ -56,6 +58,7 @@
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:minHeight="48dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical|end" >
|
||||
@@ -65,12 +65,14 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
|
||||
private final QuickQSPanel mQuickQsPanel;
|
||||
private final QSPanelController mQsPanelController;
|
||||
private final QuickQSPanelController mQuickQSPanelController;
|
||||
private final QuickStatusBarHeader mQuickStatusBarHeader;
|
||||
private final QSSecurityFooter mSecurityFooter;
|
||||
private final QS mQs;
|
||||
|
||||
private PagedTileLayout mPagedLayout;
|
||||
|
||||
private boolean mOnFirstPage = true;
|
||||
private QSExpansionPathInterpolator mQSExpansionPathInterpolator;
|
||||
private TouchAnimator mFirstPageAnimator;
|
||||
private TouchAnimator mFirstPageDelayedAnimator;
|
||||
private TouchAnimator mTranslationXAnimator;
|
||||
@@ -98,19 +100,22 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
|
||||
private final FeatureFlags mFeatureFlags;
|
||||
|
||||
@Inject
|
||||
public QSAnimator(QS qs, QuickQSPanel quickPanel, QSPanelController qsPanelController,
|
||||
public QSAnimator(QS qs, QuickQSPanel quickPanel, QuickStatusBarHeader quickStatusBarHeader,
|
||||
QSPanelController qsPanelController,
|
||||
QuickQSPanelController quickQSPanelController, QSTileHost qsTileHost,
|
||||
QSSecurityFooter securityFooter, @Main Executor executor, TunerService tunerService,
|
||||
FeatureFlags featureFlags) {
|
||||
FeatureFlags featureFlags, QSExpansionPathInterpolator qsExpansionPathInterpolator) {
|
||||
mQs = qs;
|
||||
mQuickQsPanel = quickPanel;
|
||||
mQsPanelController = qsPanelController;
|
||||
mQuickQSPanelController = quickQSPanelController;
|
||||
mQuickStatusBarHeader = quickStatusBarHeader;
|
||||
mSecurityFooter = securityFooter;
|
||||
mHost = qsTileHost;
|
||||
mExecutor = executor;
|
||||
mTunerService = tunerService;
|
||||
mFeatureFlags = featureFlags;
|
||||
mQSExpansionPathInterpolator = qsExpansionPathInterpolator;
|
||||
mHost.addCallback(this);
|
||||
mQsPanelController.addOnAttachStateChangeListener(this);
|
||||
qs.getView().addOnLayoutChangeListener(this);
|
||||
@@ -252,7 +257,9 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
|
||||
if (count < tileLayout.getNumVisibleTiles()) {
|
||||
getRelativePosition(loc1, quickTileView, view);
|
||||
getRelativePosition(loc2, tileView, view);
|
||||
int yOffset = qsSideLabelsEnabled ? loc2[1] - loc1[1] : 0;
|
||||
int yOffset = qsSideLabelsEnabled
|
||||
? loc2[1] - loc1[1]
|
||||
: mQuickStatusBarHeader.getOffsetTranslation();
|
||||
// Move the quick tile right from its location to the new one.
|
||||
View v = qsSideLabelsEnabled ? quickTileView.getIcon() : quickTileView;
|
||||
translationXBuilder.addFloat(v, "translationX", 0, xDiff);
|
||||
@@ -266,8 +273,14 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
|
||||
translationYBuilder.addFloat(v, "translationY", -yDiff + yOffset, 0);
|
||||
|
||||
if (qsSideLabelsEnabled) {
|
||||
translationYBuilder.addFloat(quickTileView, "translationY", 0, yOffset);
|
||||
translationYBuilder.addFloat(tileView, "translationY", -yOffset, 0);
|
||||
// Offset the translation animation on the views
|
||||
// (that goes from 0 to getOffsetTranslation)
|
||||
int offsetWithQSBHTranslation =
|
||||
yOffset - mQuickStatusBarHeader.getOffsetTranslation();
|
||||
translationYBuilder.addFloat(quickTileView, "translationY", 0,
|
||||
offsetWithQSBHTranslation);
|
||||
translationYBuilder.addFloat(tileView, "translationY",
|
||||
-offsetWithQSBHTranslation, 0);
|
||||
|
||||
if (mQQSTileHeightAnimator == null) {
|
||||
mQQSTileHeightAnimator = new HeightExpansionAnimator(this,
|
||||
@@ -375,22 +388,23 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha
|
||||
}
|
||||
|
||||
float px = 0;
|
||||
float py = 1;
|
||||
if (tiles.size() <= 3) {
|
||||
px = 1;
|
||||
} else if (tiles.size() <= 6) {
|
||||
px = .4f;
|
||||
}
|
||||
PathInterpolatorBuilder interpolatorBuilder = new PathInterpolatorBuilder(0, 0, px, py);
|
||||
translationXBuilder.setInterpolator(interpolatorBuilder.getXInterpolator());
|
||||
translationYBuilder.setInterpolator(interpolatorBuilder.getYInterpolator());
|
||||
mQSExpansionPathInterpolator.setControlX2(px);
|
||||
translationXBuilder.setInterpolator(mQSExpansionPathInterpolator.getXInterpolator());
|
||||
translationYBuilder.setInterpolator(mQSExpansionPathInterpolator.getYInterpolator());
|
||||
mTranslationXAnimator = translationXBuilder.build();
|
||||
mTranslationYAnimator = translationYBuilder.build();
|
||||
if (mQQSTileHeightAnimator != null) {
|
||||
mQQSTileHeightAnimator.setInterpolator(interpolatorBuilder.getYInterpolator());
|
||||
mQQSTileHeightAnimator.setInterpolator(
|
||||
mQSExpansionPathInterpolator.getYInterpolator());
|
||||
}
|
||||
if (mOtherTilesExpandAnimator != null) {
|
||||
mOtherTilesExpandAnimator.setInterpolator(interpolatorBuilder.getYInterpolator());
|
||||
mOtherTilesExpandAnimator.setInterpolator(
|
||||
mQSExpansionPathInterpolator.getYInterpolator());
|
||||
}
|
||||
}
|
||||
mNonfirstPageAnimator = new TouchAnimator.Builder()
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.systemui.qs
|
||||
|
||||
import android.view.animation.Interpolator
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Singleton
|
||||
class QSExpansionPathInterpolator @Inject constructor() {
|
||||
|
||||
private var pathInterpolatorBuilder = PathInterpolatorBuilder(0f, 0f, 0f, 1f)
|
||||
private var lastX = 0f
|
||||
val xInterpolator: Interpolator
|
||||
get() = pathInterpolatorBuilder.xInterpolator
|
||||
|
||||
val yInterpolator: Interpolator
|
||||
get() = pathInterpolatorBuilder.yInterpolator
|
||||
|
||||
fun setControlX2(value: Float) {
|
||||
if (value != lastX) {
|
||||
lastX = value
|
||||
pathInterpolatorBuilder = PathInterpolatorBuilder(0f, 0f, lastX, 1f)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
package com.android.systemui.qs
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import android.widget.FrameLayout
|
||||
import com.android.systemui.R
|
||||
|
||||
/**
|
||||
* Container for the Next Alarm and Ringer status texts in [QuickStatusBarHeader].
|
||||
*
|
||||
* If both elements are visible, it splits the available space according to the following rules:
|
||||
* * If both views add up to less than the total space, they take all the space they need.
|
||||
* * If both views are larger than half the space, each view takes half the space.
|
||||
* * Otherwise, the smaller view takes the space it needs and the larger one takes all remaining
|
||||
* space.
|
||||
*/
|
||||
class QSHeaderInfoLayout @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyle: Int = 0,
|
||||
defStyleRes: Int = 0
|
||||
) : FrameLayout(context, attrs, defStyle, defStyleRes) {
|
||||
|
||||
private lateinit var alarmContainer: View
|
||||
private lateinit var ringerContainer: View
|
||||
private lateinit var statusSeparator: View
|
||||
private val location = Location(0, 0)
|
||||
|
||||
override fun onFinishInflate() {
|
||||
super.onFinishInflate()
|
||||
alarmContainer = findViewById(R.id.alarm_container)
|
||||
ringerContainer = findViewById(R.id.ringer_container)
|
||||
statusSeparator = findViewById(R.id.status_separator)
|
||||
}
|
||||
|
||||
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
|
||||
// At most one view is there
|
||||
if (statusSeparator.visibility == View.GONE) super.onLayout(changed, l, t, r, b)
|
||||
else {
|
||||
val layoutRTL = isLayoutRtl
|
||||
val width = r - l
|
||||
val height = b - t
|
||||
var offset = 0
|
||||
|
||||
offset += alarmContainer.layoutView(width, height, offset, layoutRTL)
|
||||
offset += statusSeparator.layoutView(width, height, offset, layoutRTL)
|
||||
ringerContainer.layoutView(width, height, offset, layoutRTL)
|
||||
}
|
||||
}
|
||||
|
||||
private fun View.layoutView(pWidth: Int, pHeight: Int, offset: Int, RTL: Boolean): Int {
|
||||
location.setLocationFromOffset(pWidth, offset, this.measuredWidth, RTL)
|
||||
layout(location.left, 0, location.right, pHeight)
|
||||
return this.measuredWidth
|
||||
}
|
||||
|
||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||
super.onMeasure(
|
||||
MeasureSpec.makeMeasureSpec(
|
||||
MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.AT_MOST),
|
||||
heightMeasureSpec)
|
||||
val width = MeasureSpec.getSize(widthMeasureSpec)
|
||||
// Once we measure the views, using as much space as they need, we need to remeasure them
|
||||
// assigning them their final width. This is because TextViews decide whether to MARQUEE
|
||||
// after onMeasure.
|
||||
if (statusSeparator.visibility != View.GONE) {
|
||||
val alarmWidth = alarmContainer.measuredWidth
|
||||
val separatorWidth = statusSeparator.measuredWidth
|
||||
val ringerWidth = ringerContainer.measuredWidth
|
||||
val availableSpace = MeasureSpec.getSize(width) - separatorWidth
|
||||
if (alarmWidth < availableSpace / 2) {
|
||||
measureChild(
|
||||
ringerContainer,
|
||||
MeasureSpec.makeMeasureSpec(
|
||||
Math.min(ringerWidth, availableSpace - alarmWidth),
|
||||
MeasureSpec.AT_MOST),
|
||||
heightMeasureSpec)
|
||||
} else if (ringerWidth < availableSpace / 2) {
|
||||
measureChild(alarmContainer,
|
||||
MeasureSpec.makeMeasureSpec(
|
||||
Math.min(alarmWidth, availableSpace - ringerWidth),
|
||||
MeasureSpec.AT_MOST),
|
||||
heightMeasureSpec)
|
||||
} else {
|
||||
measureChild(
|
||||
alarmContainer,
|
||||
MeasureSpec.makeMeasureSpec(availableSpace / 2, MeasureSpec.AT_MOST),
|
||||
heightMeasureSpec)
|
||||
measureChild(
|
||||
ringerContainer,
|
||||
MeasureSpec.makeMeasureSpec(availableSpace / 2, MeasureSpec.AT_MOST),
|
||||
heightMeasureSpec)
|
||||
}
|
||||
}
|
||||
setMeasuredDimension(width, measuredHeight)
|
||||
}
|
||||
|
||||
private data class Location(var left: Int, var right: Int) {
|
||||
/**
|
||||
* Sets the [left] and [right] with the correct values for laying out the child, respecting
|
||||
* RTL. Only set the variable through here to prevent concurrency issues.
|
||||
* This is done to prevent allocation of [Pair] in [onLayout].
|
||||
*/
|
||||
fun setLocationFromOffset(parentWidth: Int, offset: Int, width: Int, RTL: Boolean) {
|
||||
if (RTL) {
|
||||
left = parentWidth - offset - width
|
||||
right = parentWidth - offset
|
||||
} else {
|
||||
left = offset
|
||||
right = offset + width
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -391,20 +391,13 @@ public class QSPanel extends LinearLayout implements Tunable {
|
||||
index++;
|
||||
|
||||
if (mSecurityFooter != null) {
|
||||
LinearLayout.LayoutParams layoutParams =
|
||||
(LayoutParams) mSecurityFooter.getLayoutParams();
|
||||
if (mUsingHorizontalLayout && mHeaderContainer != null) {
|
||||
// Adding the security view to the header, that enables us to avoid scrolling
|
||||
layoutParams.width = 0;
|
||||
layoutParams.weight = 1.6f;
|
||||
switchToParent(mSecurityFooter, mHeaderContainer, 1 /* always in second place */);
|
||||
switchToParent(mSecurityFooter, mHeaderContainer, 0);
|
||||
} else {
|
||||
layoutParams.width = LayoutParams.WRAP_CONTENT;
|
||||
layoutParams.weight = 0;
|
||||
switchToParent(mSecurityFooter, parent, index);
|
||||
index++;
|
||||
}
|
||||
mSecurityFooter.setLayoutParams(layoutParams);
|
||||
}
|
||||
|
||||
if (mFooter != null) {
|
||||
|
||||
@@ -17,15 +17,14 @@ package com.android.systemui.qs;
|
||||
import static android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS;
|
||||
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
|
||||
import android.annotation.ColorInt;
|
||||
import android.app.AlarmManager.AlarmClockInfo;
|
||||
import static com.android.systemui.statusbar.StatusBarIconView.STATE_HIDDEN;
|
||||
import static com.android.systemui.statusbar.StatusBarIconView.STATE_ICON;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Rect;
|
||||
import android.media.AudioManager;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.MathUtils;
|
||||
import android.util.Pair;
|
||||
@@ -34,66 +33,46 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowInsets;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.Space;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.lifecycle.LifecycleRegistry;
|
||||
|
||||
import com.android.settingslib.Utils;
|
||||
import com.android.systemui.BatteryMeterView;
|
||||
import com.android.systemui.Interpolators;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.privacy.OngoingPrivacyChip;
|
||||
import com.android.systemui.qs.QSDetail.Callback;
|
||||
import com.android.systemui.statusbar.StatusBarMobileView;
|
||||
import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager;
|
||||
import com.android.systemui.statusbar.phone.StatusBarWindowView;
|
||||
import com.android.systemui.statusbar.phone.StatusIconContainer;
|
||||
import com.android.systemui.statusbar.policy.Clock;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* View that contains the top-most bits of the screen (primarily the status bar with date, time, and
|
||||
* battery) and also contains the {@link QuickQSPanel} along with some of the panel's inner
|
||||
* contents.
|
||||
* View that contains the top-most bits of the QS panel (primarily the status bar with date, time,
|
||||
* battery, carrier info and privacy icons) and also contains the {@link QuickQSPanel}.
|
||||
*/
|
||||
public class QuickStatusBarHeader extends RelativeLayout implements LifecycleOwner {
|
||||
|
||||
public static final int MAX_TOOLTIP_SHOWN_COUNT = 2;
|
||||
public class QuickStatusBarHeader extends FrameLayout {
|
||||
|
||||
private boolean mExpanded;
|
||||
private boolean mQsDisabled;
|
||||
|
||||
private TouchAnimator mAlphaAnimator;
|
||||
private TouchAnimator mTranslationAnimator;
|
||||
|
||||
protected QuickQSPanel mHeaderQsPanel;
|
||||
private TouchAnimator mStatusIconsAlphaAnimator;
|
||||
private TouchAnimator mHeaderTextContainerAlphaAnimator;
|
||||
private View mDatePrivacyView;
|
||||
private View mClockIconsView;
|
||||
private View mContainer;
|
||||
|
||||
private View mSystemIconsView;
|
||||
private View mQuickQsStatusIcons;
|
||||
private View mHeaderTextContainerView;
|
||||
|
||||
private ImageView mNextAlarmIcon;
|
||||
/** {@link TextView} containing the actual text indicating when the next alarm will go off. */
|
||||
private TextView mNextAlarmTextView;
|
||||
private View mNextAlarmContainer;
|
||||
private View mStatusSeparator;
|
||||
private ImageView mRingerModeIcon;
|
||||
private TextView mRingerModeTextView;
|
||||
private View mRingerContainer;
|
||||
private View mQSCarriers;
|
||||
private Clock mClockView;
|
||||
private OngoingPrivacyChip mPrivacyChip;
|
||||
private Space mSpace;
|
||||
private BatteryMeterView mBatteryRemainingIcon;
|
||||
private TintedIconManager mTintedIconManager;
|
||||
private StatusIconContainer mIconContainer;
|
||||
|
||||
// Used for RingerModeTracker
|
||||
private final LifecycleRegistry mLifecycle = new LifecycleRegistry(this);
|
||||
|
||||
private TintedIconManager mTintedIconManager;
|
||||
private QSExpansionPathInterpolator mQSExpansionPathInterpolator;
|
||||
|
||||
private int mStatusBarPaddingTop = 0;
|
||||
private int mRoundedCornerPadding = 0;
|
||||
@@ -102,12 +81,26 @@ public class QuickStatusBarHeader extends RelativeLayout implements LifecycleOwn
|
||||
private int mWaterfallTopInset;
|
||||
private int mCutOutPaddingLeft;
|
||||
private int mCutOutPaddingRight;
|
||||
private float mExpandedHeaderAlpha = 1.0f;
|
||||
private float mClockIconsAlpha = 1.0f;
|
||||
private float mDatePrivacyAlpha = 1.0f;
|
||||
private float mKeyguardExpansionFraction;
|
||||
private int mTextColorPrimary = Color.TRANSPARENT;
|
||||
private int mTopViewMeasureHeight;
|
||||
|
||||
private final String mMobileSlotName;
|
||||
|
||||
public QuickStatusBarHeader(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mMobileSlotName = context.getString(com.android.internal.R.string.status_bar_mobile);
|
||||
}
|
||||
|
||||
/**
|
||||
* How much the view containing the clock and QQS will translate down when QS is fully expanded.
|
||||
*
|
||||
* This matches the measured height of the view containing the date and privacy icons.
|
||||
*/
|
||||
public int getOffsetTranslation() {
|
||||
return mTopViewMeasureHeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -115,19 +108,12 @@ public class QuickStatusBarHeader extends RelativeLayout implements LifecycleOwn
|
||||
super.onFinishInflate();
|
||||
|
||||
mHeaderQsPanel = findViewById(R.id.quick_qs_panel);
|
||||
mSystemIconsView = findViewById(R.id.quick_status_bar_system_icons);
|
||||
mQuickQsStatusIcons = findViewById(R.id.quick_qs_status_icons);
|
||||
mDatePrivacyView = findViewById(R.id.quick_status_bar_date_privacy);
|
||||
mClockIconsView = findViewById(R.id.quick_qs_status_icons);
|
||||
mQSCarriers = findViewById(R.id.carrier_group);
|
||||
mContainer = findViewById(R.id.container);
|
||||
mIconContainer = findViewById(R.id.statusIcons);
|
||||
|
||||
// Views corresponding to the header info section (e.g. ringer and next alarm).
|
||||
mHeaderTextContainerView = findViewById(R.id.header_text_container);
|
||||
mStatusSeparator = findViewById(R.id.status_separator);
|
||||
mNextAlarmIcon = findViewById(R.id.next_alarm_icon);
|
||||
mNextAlarmTextView = findViewById(R.id.next_alarm_text);
|
||||
mNextAlarmContainer = findViewById(R.id.alarm_container);
|
||||
mRingerModeIcon = findViewById(R.id.ringer_mode_icon);
|
||||
mRingerModeTextView = findViewById(R.id.ringer_mode_text);
|
||||
mRingerContainer = findViewById(R.id.ringer_container);
|
||||
mPrivacyChip = findViewById(R.id.privacy_chip);
|
||||
mClockView = findViewById(R.id.clock);
|
||||
mSpace = findViewById(R.id.space);
|
||||
// Tint for the battery icons are handled in setupHost()
|
||||
@@ -140,79 +126,34 @@ public class QuickStatusBarHeader extends RelativeLayout implements LifecycleOwn
|
||||
// QS will always show the estimate, and BatteryMeterView handles the case where
|
||||
// it's unavailable or charging
|
||||
mBatteryRemainingIcon.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE);
|
||||
mRingerModeTextView.setSelected(true);
|
||||
mNextAlarmTextView.setSelected(true);
|
||||
}
|
||||
|
||||
void onAttach(TintedIconManager iconManager) {
|
||||
void onAttach(TintedIconManager iconManager,
|
||||
QSExpansionPathInterpolator qsExpansionPathInterpolator) {
|
||||
mTintedIconManager = iconManager;
|
||||
int fillColor = Utils.getColorAttrDefaultColor(getContext(),
|
||||
android.R.attr.textColorPrimary);
|
||||
|
||||
// Set the correct tint for the status icons so they contrast
|
||||
iconManager.setTint(fillColor);
|
||||
mNextAlarmIcon.setImageTintList(ColorStateList.valueOf(fillColor));
|
||||
mRingerModeIcon.setImageTintList(ColorStateList.valueOf(fillColor));
|
||||
|
||||
mQSExpansionPathInterpolator = qsExpansionPathInterpolator;
|
||||
updateAnimators();
|
||||
}
|
||||
|
||||
public QuickQSPanel getHeaderQsPanel() {
|
||||
return mHeaderQsPanel;
|
||||
}
|
||||
|
||||
void updateStatusText(int ringerMode, AlarmClockInfo nextAlarm, boolean zenOverridingRinger,
|
||||
boolean use24HourFormat) {
|
||||
boolean changed = updateRingerStatus(ringerMode, zenOverridingRinger)
|
||||
|| updateAlarmStatus(nextAlarm, use24HourFormat);
|
||||
|
||||
if (changed) {
|
||||
boolean alarmVisible = mNextAlarmTextView.getVisibility() == View.VISIBLE;
|
||||
boolean ringerVisible = mRingerModeTextView.getVisibility() == View.VISIBLE;
|
||||
mStatusSeparator.setVisibility(alarmVisible && ringerVisible ? View.VISIBLE
|
||||
: View.GONE);
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
if (mDatePrivacyView.getMeasuredHeight() != mTopViewMeasureHeight) {
|
||||
mTopViewMeasureHeight = mDatePrivacyView.getMeasuredHeight();
|
||||
updateAnimators();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean updateRingerStatus(int ringerMode, boolean zenOverridingRinger) {
|
||||
boolean isOriginalVisible = mRingerModeTextView.getVisibility() == View.VISIBLE;
|
||||
CharSequence originalRingerText = mRingerModeTextView.getText();
|
||||
|
||||
boolean ringerVisible = false;
|
||||
if (!zenOverridingRinger) {
|
||||
if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
|
||||
mRingerModeIcon.setImageResource(R.drawable.ic_volume_ringer_vibrate);
|
||||
mRingerModeTextView.setText(R.string.qs_status_phone_vibrate);
|
||||
ringerVisible = true;
|
||||
} else if (ringerMode == AudioManager.RINGER_MODE_SILENT) {
|
||||
mRingerModeIcon.setImageResource(R.drawable.ic_volume_ringer_mute);
|
||||
mRingerModeTextView.setText(R.string.qs_status_phone_muted);
|
||||
ringerVisible = true;
|
||||
}
|
||||
}
|
||||
mRingerModeIcon.setVisibility(ringerVisible ? View.VISIBLE : View.GONE);
|
||||
mRingerModeTextView.setVisibility(ringerVisible ? View.VISIBLE : View.GONE);
|
||||
mRingerContainer.setVisibility(ringerVisible ? View.VISIBLE : View.GONE);
|
||||
|
||||
return isOriginalVisible != ringerVisible ||
|
||||
!Objects.equals(originalRingerText, mRingerModeTextView.getText());
|
||||
}
|
||||
|
||||
private boolean updateAlarmStatus(AlarmClockInfo nextAlarm, boolean use24HourFormat) {
|
||||
boolean isOriginalVisible = mNextAlarmTextView.getVisibility() == View.VISIBLE;
|
||||
CharSequence originalAlarmText = mNextAlarmTextView.getText();
|
||||
|
||||
boolean alarmVisible = false;
|
||||
if (nextAlarm != null) {
|
||||
alarmVisible = true;
|
||||
mNextAlarmTextView.setText(formatNextAlarm(nextAlarm, use24HourFormat));
|
||||
}
|
||||
mNextAlarmIcon.setVisibility(alarmVisible ? View.VISIBLE : View.GONE);
|
||||
mNextAlarmTextView.setVisibility(alarmVisible ? View.VISIBLE : View.GONE);
|
||||
mNextAlarmContainer.setVisibility(alarmVisible ? View.VISIBLE : View.GONE);
|
||||
|
||||
return isOriginalVisible != alarmVisible ||
|
||||
!Objects.equals(originalAlarmText, mNextAlarmTextView.getText());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onConfigurationChanged(Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
@@ -225,40 +166,27 @@ public class QuickStatusBarHeader extends RelativeLayout implements LifecycleOwn
|
||||
updateResources();
|
||||
}
|
||||
|
||||
/**
|
||||
* The height of QQS should always be the status bar height + 128dp. This is normally easy, but
|
||||
* when there is a notch involved the status bar can remain a fixed pixel size.
|
||||
*/
|
||||
private void updateMinimumHeight() {
|
||||
int sbHeight = mContext.getResources().getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.status_bar_height);
|
||||
int qqsHeight = mContext.getResources().getDimensionPixelSize(
|
||||
R.dimen.qs_quick_header_panel_height);
|
||||
|
||||
setMinimumHeight(sbHeight + qqsHeight);
|
||||
}
|
||||
|
||||
void updateResources() {
|
||||
Resources resources = mContext.getResources();
|
||||
updateMinimumHeight();
|
||||
|
||||
mRoundedCornerPadding = resources.getDimensionPixelSize(
|
||||
R.dimen.rounded_corner_content_padding);
|
||||
mStatusBarPaddingTop = resources.getDimensionPixelSize(R.dimen.status_bar_padding_top);
|
||||
|
||||
// Update height for a few views, especially due to landscape mode restricting space.
|
||||
mHeaderTextContainerView.getLayoutParams().height =
|
||||
resources.getDimensionPixelSize(R.dimen.qs_header_tooltip_height);
|
||||
mHeaderTextContainerView.setLayoutParams(mHeaderTextContainerView.getLayoutParams());
|
||||
|
||||
mSystemIconsView.getLayoutParams().height = resources.getDimensionPixelSize(
|
||||
int qsOffsetHeight = resources.getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.quick_qs_offset_height);
|
||||
mSystemIconsView.setLayoutParams(mSystemIconsView.getLayoutParams());
|
||||
|
||||
mDatePrivacyView.getLayoutParams().height =
|
||||
Math.max(qsOffsetHeight, mDatePrivacyView.getMinimumHeight());
|
||||
mDatePrivacyView.setLayoutParams(mDatePrivacyView.getLayoutParams());
|
||||
|
||||
mClockIconsView.getLayoutParams().height =
|
||||
Math.max(qsOffsetHeight, mClockIconsView.getMinimumHeight());
|
||||
mClockIconsView.setLayoutParams(mClockIconsView.getLayoutParams());
|
||||
|
||||
ViewGroup.LayoutParams lp = getLayoutParams();
|
||||
if (mQsDisabled) {
|
||||
lp.height = resources.getDimensionPixelSize(
|
||||
com.android.internal.R.dimen.quick_qs_offset_height);
|
||||
lp.height = mClockIconsView.getLayoutParams().height;
|
||||
} else {
|
||||
lp.height = WRAP_CONTENT;
|
||||
}
|
||||
@@ -276,21 +204,45 @@ public class QuickStatusBarHeader extends RelativeLayout implements LifecycleOwn
|
||||
mBatteryRemainingIcon.updateColors(mTextColorPrimary, textColorSecondary,
|
||||
mTextColorPrimary);
|
||||
}
|
||||
|
||||
updateStatusIconAlphaAnimator();
|
||||
updateHeaderTextContainerAlphaAnimator();
|
||||
updateHeadersPadding();
|
||||
updateAnimators();
|
||||
}
|
||||
|
||||
private void updateStatusIconAlphaAnimator() {
|
||||
mStatusIconsAlphaAnimator = new TouchAnimator.Builder()
|
||||
.addFloat(mQuickQsStatusIcons, "alpha", 1, 0, 0)
|
||||
private void updateAnimators() {
|
||||
updateAlphaAnimator();
|
||||
int offset = mTopViewMeasureHeight;
|
||||
|
||||
mTranslationAnimator = new TouchAnimator.Builder()
|
||||
.addFloat(mContainer, "translationY", 0, offset)
|
||||
.setInterpolator(mQSExpansionPathInterpolator != null
|
||||
? mQSExpansionPathInterpolator.getYInterpolator()
|
||||
: null)
|
||||
.build();
|
||||
}
|
||||
|
||||
private void updateHeaderTextContainerAlphaAnimator() {
|
||||
mHeaderTextContainerAlphaAnimator = new TouchAnimator.Builder()
|
||||
.addFloat(mHeaderTextContainerView, "alpha", 0, 0, mExpandedHeaderAlpha)
|
||||
.build();
|
||||
private void updateAlphaAnimator() {
|
||||
StatusBarMobileView icon =
|
||||
((StatusBarMobileView) mIconContainer.getViewForSlot(mMobileSlotName));
|
||||
TouchAnimator.Builder builder = new TouchAnimator.Builder()
|
||||
.addFloat(mQSCarriers, "alpha", 0, 1)
|
||||
.addFloat(mDatePrivacyView, "alpha", 0, mDatePrivacyAlpha);
|
||||
if (icon != null) {
|
||||
builder.addFloat(icon, "alpha", 1, 0);
|
||||
builder.setListener(new TouchAnimator.ListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationAtEnd() {
|
||||
icon.forceHidden(true);
|
||||
icon.setVisibleState(STATE_HIDDEN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationStarted() {
|
||||
icon.forceHidden(false);
|
||||
icon.setVisibleState(STATE_ICON);
|
||||
}
|
||||
});
|
||||
}
|
||||
mAlphaAnimator = builder.build();
|
||||
}
|
||||
|
||||
/** */
|
||||
@@ -312,25 +264,19 @@ public class QuickStatusBarHeader extends RelativeLayout implements LifecycleOwn
|
||||
public void setExpansion(boolean forceExpanded, float expansionFraction,
|
||||
float panelTranslationY) {
|
||||
final float keyguardExpansionFraction = forceExpanded ? 1f : expansionFraction;
|
||||
if (mStatusIconsAlphaAnimator != null) {
|
||||
mStatusIconsAlphaAnimator.setPosition(keyguardExpansionFraction);
|
||||
}
|
||||
|
||||
if (mAlphaAnimator != null) {
|
||||
mAlphaAnimator.setPosition(keyguardExpansionFraction);
|
||||
}
|
||||
if (mTranslationAnimator != null) {
|
||||
mTranslationAnimator.setPosition(keyguardExpansionFraction);
|
||||
}
|
||||
// If forceExpanded (we are opening QS from lockscreen), the animators have been set to
|
||||
// position = 1f.
|
||||
if (forceExpanded) {
|
||||
// If the keyguard is showing, we want to offset the text so that it comes in at the
|
||||
// same time as the panel as it slides down.
|
||||
mHeaderTextContainerView.setTranslationY(panelTranslationY);
|
||||
setTranslationY(panelTranslationY);
|
||||
} else {
|
||||
mHeaderTextContainerView.setTranslationY(0f);
|
||||
}
|
||||
|
||||
if (mHeaderTextContainerAlphaAnimator != null) {
|
||||
mHeaderTextContainerAlphaAnimator.setPosition(keyguardExpansionFraction);
|
||||
if (keyguardExpansionFraction > 0) {
|
||||
mHeaderTextContainerView.setVisibility(VISIBLE);
|
||||
} else {
|
||||
mHeaderTextContainerView.setVisibility(INVISIBLE);
|
||||
}
|
||||
setTranslationY(0);
|
||||
}
|
||||
|
||||
mKeyguardExpansionFraction = keyguardExpansionFraction;
|
||||
@@ -341,28 +287,21 @@ public class QuickStatusBarHeader extends RelativeLayout implements LifecycleOwn
|
||||
if (disabled == mQsDisabled) return;
|
||||
mQsDisabled = disabled;
|
||||
mHeaderQsPanel.setDisabledByPolicy(disabled);
|
||||
mHeaderTextContainerView.setVisibility(mQsDisabled ? View.GONE : View.VISIBLE);
|
||||
mQuickQsStatusIcons.setVisibility(mQsDisabled ? View.GONE : View.VISIBLE);
|
||||
mClockIconsView.setVisibility(mQsDisabled ? View.GONE : View.VISIBLE);
|
||||
updateResources();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
|
||||
// Handle padding of the clock
|
||||
// Handle padding of the views
|
||||
DisplayCutout cutout = insets.getDisplayCutout();
|
||||
Pair<Integer, Integer> cornerCutoutPadding = StatusBarWindowView.cornerCutoutMargins(
|
||||
cutout, getDisplay());
|
||||
Pair<Integer, Integer> padding =
|
||||
StatusBarWindowView.paddingNeededForCutoutAndRoundedCorner(
|
||||
cutout, cornerCutoutPadding, -1);
|
||||
if (padding == null) {
|
||||
mSystemIconsView.setPaddingRelative(
|
||||
getResources().getDimensionPixelSize(R.dimen.status_bar_padding_start), 0,
|
||||
getResources().getDimensionPixelSize(R.dimen.status_bar_padding_end), 0);
|
||||
} else {
|
||||
mSystemIconsView.setPadding(padding.first, 0, padding.second, 0);
|
||||
|
||||
}
|
||||
mDatePrivacyView.setPadding(padding.first, 0, padding.second, 0);
|
||||
mClockIconsView.setPadding(padding.first, 0, padding.second, 0);
|
||||
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mSpace.getLayoutParams();
|
||||
boolean cornerCutout = cornerCutoutPadding != null
|
||||
&& (cornerCutoutPadding.first == 0 || cornerCutoutPadding.second == 0);
|
||||
@@ -380,13 +319,13 @@ public class QuickStatusBarHeader extends RelativeLayout implements LifecycleOwn
|
||||
mCutOutPaddingLeft = padding.first;
|
||||
mCutOutPaddingRight = padding.second;
|
||||
mWaterfallTopInset = cutout == null ? 0 : cutout.getWaterfallInsets().top;
|
||||
updateClockPadding();
|
||||
updateHeadersPadding();
|
||||
return super.onApplyWindowInsets(insets);
|
||||
}
|
||||
|
||||
private void updateClockPadding() {
|
||||
int clockPaddingLeft = 0;
|
||||
int clockPaddingRight = 0;
|
||||
private void updateHeadersPadding() {
|
||||
int paddingLeft = 0;
|
||||
int paddingRight = 0;
|
||||
|
||||
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
|
||||
int leftMargin = lp.leftMargin;
|
||||
@@ -399,18 +338,22 @@ public class QuickStatusBarHeader extends RelativeLayout implements LifecycleOwn
|
||||
// if there's a cutout, let's use at least the rounded corner inset
|
||||
int cutoutPadding = Math.max(mCutOutPaddingLeft, mRoundedCornerPadding);
|
||||
int contentMarginLeft = isLayoutRtl() ? mContentMarginEnd : mContentMarginStart;
|
||||
clockPaddingLeft = Math.max(cutoutPadding - contentMarginLeft - leftMargin, 0);
|
||||
paddingLeft = Math.max(cutoutPadding - contentMarginLeft - leftMargin, 0);
|
||||
}
|
||||
if (mCutOutPaddingRight > 0) {
|
||||
// if there's a cutout, let's use at least the rounded corner inset
|
||||
int cutoutPadding = Math.max(mCutOutPaddingRight, mRoundedCornerPadding);
|
||||
int contentMarginRight = isLayoutRtl() ? mContentMarginStart : mContentMarginEnd;
|
||||
clockPaddingRight = Math.max(cutoutPadding - contentMarginRight - rightMargin, 0);
|
||||
paddingRight = Math.max(cutoutPadding - contentMarginRight - rightMargin, 0);
|
||||
}
|
||||
|
||||
mSystemIconsView.setPadding(clockPaddingLeft,
|
||||
mDatePrivacyView.setPadding(paddingLeft,
|
||||
mWaterfallTopInset + mStatusBarPaddingTop,
|
||||
clockPaddingRight,
|
||||
paddingRight,
|
||||
0);
|
||||
mClockIconsView.setPadding(paddingLeft,
|
||||
mWaterfallTopInset + mStatusBarPaddingTop,
|
||||
paddingRight,
|
||||
0);
|
||||
}
|
||||
|
||||
@@ -422,26 +365,6 @@ public class QuickStatusBarHeader extends RelativeLayout implements LifecycleOwn
|
||||
mHeaderQsPanel.setCallback(qsPanelCallback);
|
||||
}
|
||||
|
||||
private String formatNextAlarm(AlarmClockInfo info, boolean use24HourFormat) {
|
||||
if (info == null) {
|
||||
return "";
|
||||
}
|
||||
String skeleton = use24HourFormat ? "EHm" : "Ehma";
|
||||
String pattern = android.text.format.DateFormat
|
||||
.getBestDateTimePattern(Locale.getDefault(), skeleton);
|
||||
return android.text.format.DateFormat.format(pattern, info.getTriggerTime()).toString();
|
||||
}
|
||||
|
||||
public static float getColorIntensity(@ColorInt int color) {
|
||||
return color == Color.WHITE ? 0 : 1;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Lifecycle getLifecycle() {
|
||||
return mLifecycle;
|
||||
}
|
||||
|
||||
/** */
|
||||
public void setContentMargins(int marginStart, int marginEnd,
|
||||
QuickQSPanelController quickQSPanelController) {
|
||||
@@ -459,24 +382,39 @@ public class QuickStatusBarHeader extends RelativeLayout implements LifecycleOwn
|
||||
view.setLayoutParams(lp);
|
||||
}
|
||||
}
|
||||
updateClockPadding();
|
||||
updateHeadersPadding();
|
||||
}
|
||||
|
||||
/**
|
||||
* When QS is scrolling, mClockIconsAlpha should scroll away and fade out.
|
||||
*
|
||||
* For a given scroll level, this method does the following:
|
||||
* <ol>
|
||||
* <li>Determine the alpha that {@code mClockIconsView} should have when the panel is fully
|
||||
* expanded.</li>
|
||||
* <li>Set the scroll of {@code mClockIconsView} to the same of {@code QSPanel}.</li>
|
||||
* <li>Set the alpha of {@code mClockIconsView} to that determined by the expansion of
|
||||
* the panel, interpolated between 1 (no expansion) and {@code mClockIconsAlpha} (fully
|
||||
* expanded), matching the animator.</li>
|
||||
* </ol>
|
||||
*
|
||||
* @param scrollY the scroll of the QSPanel container
|
||||
*/
|
||||
public void setExpandedScrollAmount(int scrollY) {
|
||||
// The scrolling of the expanded qs has changed. Since the header text isn't part of it,
|
||||
// but would overlap content, we're fading it out.
|
||||
float newAlpha = 1.0f;
|
||||
if (mHeaderTextContainerView.getHeight() > 0) {
|
||||
newAlpha = MathUtils.map(0, mHeaderTextContainerView.getHeight() / 2.0f, 1.0f, 0.0f,
|
||||
if (mClockIconsView.getHeight() > 0) {
|
||||
newAlpha = MathUtils.map(0, mClockIconsView.getHeight() / 2.0f, 1.0f, 0.0f,
|
||||
scrollY);
|
||||
newAlpha = Interpolators.ALPHA_OUT.getInterpolation(newAlpha);
|
||||
}
|
||||
mHeaderTextContainerView.setScrollY(scrollY);
|
||||
if (newAlpha != mExpandedHeaderAlpha) {
|
||||
mExpandedHeaderAlpha = newAlpha;
|
||||
mHeaderTextContainerView.setAlpha(MathUtils.lerp(0.0f, mExpandedHeaderAlpha,
|
||||
mClockIconsView.setScrollY(scrollY);
|
||||
if (newAlpha != mClockIconsAlpha) {
|
||||
mClockIconsAlpha = newAlpha;
|
||||
mClockIconsView.setAlpha(MathUtils.lerp(1.0f, mClockIconsAlpha,
|
||||
mKeyguardExpansionFraction));
|
||||
updateHeaderTextContainerAlphaAnimator();
|
||||
updateAlphaAnimator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,21 +16,13 @@
|
||||
|
||||
package com.android.systemui.qs;
|
||||
|
||||
import android.app.AlarmManager.AlarmClockInfo;
|
||||
import android.content.Intent;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Bundle;
|
||||
import android.provider.AlarmClock;
|
||||
import android.provider.Settings;
|
||||
import android.service.notification.ZenModeConfig;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.lifecycle.LifecycleRegistry;
|
||||
|
||||
import com.android.internal.colorextraction.ColorExtractor;
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
@@ -47,15 +39,9 @@ import com.android.systemui.privacy.PrivacyItemController;
|
||||
import com.android.systemui.privacy.logging.PrivacyLogger;
|
||||
import com.android.systemui.qs.carrier.QSCarrierGroupController;
|
||||
import com.android.systemui.qs.dagger.QSScope;
|
||||
import com.android.systemui.settings.UserTracker;
|
||||
import com.android.systemui.statusbar.phone.StatusBarIconController;
|
||||
import com.android.systemui.statusbar.phone.StatusIconContainer;
|
||||
import com.android.systemui.statusbar.policy.Clock;
|
||||
import com.android.systemui.statusbar.policy.NextAlarmController;
|
||||
import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback;
|
||||
import com.android.systemui.statusbar.policy.ZenModeController;
|
||||
import com.android.systemui.statusbar.policy.ZenModeController.Callback;
|
||||
import com.android.systemui.util.RingerModeTracker;
|
||||
import com.android.systemui.util.ViewController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -70,75 +56,29 @@ import javax.inject.Inject;
|
||||
class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader> {
|
||||
private static final String TAG = "QuickStatusBarHeader";
|
||||
|
||||
private final ZenModeController mZenModeController;
|
||||
private final NextAlarmController mNextAlarmController;
|
||||
private final PrivacyItemController mPrivacyItemController;
|
||||
private final RingerModeTracker mRingerModeTracker;
|
||||
private final ActivityStarter mActivityStarter;
|
||||
private final UiEventLogger mUiEventLogger;
|
||||
private final QSCarrierGroupController mQSCarrierGroupController;
|
||||
private final QuickQSPanelController mHeaderQsPanelController;
|
||||
private final LifecycleRegistry mLifecycle;
|
||||
private final OngoingPrivacyChip mPrivacyChip;
|
||||
private final Clock mClockView;
|
||||
private final View mNextAlarmContainer;
|
||||
private final View mRingerContainer;
|
||||
private final QSTileHost mQSTileHost;
|
||||
private final StatusBarIconController mStatusBarIconController;
|
||||
private final DemoModeController mDemoModeController;
|
||||
private final UserTracker mUserTracker;
|
||||
private final StatusIconContainer mIconContainer;
|
||||
private final StatusBarIconController.TintedIconManager mIconManager;
|
||||
private final DemoMode mDemoModeReceiver;
|
||||
private final PrivacyLogger mPrivacyLogger;
|
||||
private final PrivacyDialogController mPrivacyDialogController;
|
||||
private final QSExpansionPathInterpolator mQSExpansionPathInterpolator;
|
||||
|
||||
private boolean mListening;
|
||||
private AlarmClockInfo mNextAlarm;
|
||||
private boolean mMicCameraIndicatorsEnabled;
|
||||
private boolean mLocationIndicatorsEnabled;
|
||||
private boolean mPrivacyChipLogged;
|
||||
|
||||
private SysuiColorExtractor mColorExtractor;
|
||||
private ColorExtractor.OnColorsChangedListener mOnColorsChangedListener;
|
||||
private int mRingerMode = AudioManager.RINGER_MODE_NORMAL;
|
||||
|
||||
private final ZenModeController.Callback mZenModeControllerCallback = new Callback() {
|
||||
@Override
|
||||
public void onZenChanged(int zen) {
|
||||
mView.updateStatusText(mRingerMode, mNextAlarm, isZenOverridingRinger(),
|
||||
use24HourFormat());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigChanged(ZenModeConfig config) {
|
||||
mView.updateStatusText(mRingerMode, mNextAlarm, isZenOverridingRinger(),
|
||||
use24HourFormat());
|
||||
}
|
||||
};
|
||||
|
||||
private boolean use24HourFormat() {
|
||||
return android.text.format.DateFormat.is24HourFormat(
|
||||
mView.getContext(), mUserTracker.getUserId());
|
||||
|
||||
}
|
||||
|
||||
private final NextAlarmChangeCallback mNextAlarmChangeCallback = new NextAlarmChangeCallback() {
|
||||
@Override
|
||||
public void onNextAlarmChanged(AlarmClockInfo nextAlarm) {
|
||||
mNextAlarm = nextAlarm;
|
||||
mView.updateStatusText(mRingerMode, mNextAlarm, isZenOverridingRinger(),
|
||||
use24HourFormat());
|
||||
}
|
||||
};
|
||||
|
||||
private final LifecycleOwner mLifecycleOwner = new LifecycleOwner() {
|
||||
@NonNull
|
||||
@Override
|
||||
public Lifecycle getLifecycle() {
|
||||
return mLifecycle;
|
||||
}
|
||||
};
|
||||
|
||||
private PrivacyItemController.Callback mPICCallback = new PrivacyItemController.Callback() {
|
||||
@Override
|
||||
@@ -176,63 +116,43 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
|
||||
if (v == mClockView) {
|
||||
mActivityStarter.postStartActivityDismissingKeyguard(new Intent(
|
||||
AlarmClock.ACTION_SHOW_ALARMS), 0);
|
||||
} else if (v == mNextAlarmContainer && mNextAlarmContainer.isVisibleToUser()) {
|
||||
if (mNextAlarm.getShowIntent() != null) {
|
||||
mActivityStarter.postStartActivityDismissingKeyguard(
|
||||
mNextAlarm.getShowIntent());
|
||||
} else {
|
||||
Log.d(TAG, "No PendingIntent for next alarm. Using default intent");
|
||||
mActivityStarter.postStartActivityDismissingKeyguard(new Intent(
|
||||
AlarmClock.ACTION_SHOW_ALARMS), 0);
|
||||
}
|
||||
} else if (v == mPrivacyChip) {
|
||||
// If the privacy chip is visible, it means there were some indicators
|
||||
mUiEventLogger.log(PrivacyChipEvent.ONGOING_INDICATORS_CHIP_CLICK);
|
||||
mPrivacyDialogController.showDialog(getContext());
|
||||
} else if (v == mRingerContainer && mRingerContainer.isVisibleToUser()) {
|
||||
mActivityStarter.postStartActivityDismissingKeyguard(new Intent(
|
||||
Settings.ACTION_SOUND_SETTINGS), 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Inject
|
||||
QuickStatusBarHeaderController(QuickStatusBarHeader view,
|
||||
ZenModeController zenModeController, NextAlarmController nextAlarmController,
|
||||
PrivacyItemController privacyItemController, RingerModeTracker ringerModeTracker,
|
||||
PrivacyItemController privacyItemController,
|
||||
ActivityStarter activityStarter, UiEventLogger uiEventLogger,
|
||||
QSTileHost qsTileHost, StatusBarIconController statusBarIconController,
|
||||
StatusBarIconController statusBarIconController,
|
||||
DemoModeController demoModeController,
|
||||
UserTracker userTracker, QuickQSPanelController quickQSPanelController,
|
||||
QuickQSPanelController quickQSPanelController,
|
||||
QSCarrierGroupController.Builder qsCarrierGroupControllerBuilder,
|
||||
PrivacyLogger privacyLogger,
|
||||
SysuiColorExtractor colorExtractor,
|
||||
PrivacyDialogController privacyDialogController) {
|
||||
PrivacyDialogController privacyDialogController,
|
||||
QSExpansionPathInterpolator qsExpansionPathInterpolator) {
|
||||
super(view);
|
||||
mZenModeController = zenModeController;
|
||||
mNextAlarmController = nextAlarmController;
|
||||
mPrivacyItemController = privacyItemController;
|
||||
mRingerModeTracker = ringerModeTracker;
|
||||
mActivityStarter = activityStarter;
|
||||
mUiEventLogger = uiEventLogger;
|
||||
mQSTileHost = qsTileHost;
|
||||
mStatusBarIconController = statusBarIconController;
|
||||
mDemoModeController = demoModeController;
|
||||
mUserTracker = userTracker;
|
||||
mLifecycle = new LifecycleRegistry(mLifecycleOwner);
|
||||
mHeaderQsPanelController = quickQSPanelController;
|
||||
mPrivacyLogger = privacyLogger;
|
||||
mPrivacyDialogController = privacyDialogController;
|
||||
mQSExpansionPathInterpolator = qsExpansionPathInterpolator;
|
||||
|
||||
mQSCarrierGroupController = qsCarrierGroupControllerBuilder
|
||||
.setQSCarrierGroup(mView.findViewById(R.id.carrier_group))
|
||||
.build();
|
||||
|
||||
|
||||
mPrivacyChip = mView.findViewById(R.id.privacy_chip);
|
||||
mNextAlarmContainer = mView.findViewById(R.id.alarm_container);
|
||||
mClockView = mView.findViewById(R.id.clock);
|
||||
mRingerContainer = mView.findViewById(R.id.ringer_container);
|
||||
mIconContainer = mView.findViewById(R.id.statusIcons);
|
||||
|
||||
mIconManager = new StatusBarIconController.TintedIconManager(mIconContainer);
|
||||
@@ -247,15 +167,7 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
|
||||
|
||||
@Override
|
||||
protected void onViewAttached() {
|
||||
mRingerModeTracker.getRingerModeInternal().observe(mLifecycleOwner, ringer -> {
|
||||
mRingerMode = ringer;
|
||||
mView.updateStatusText(mRingerMode, mNextAlarm, isZenOverridingRinger(),
|
||||
use24HourFormat());
|
||||
});
|
||||
|
||||
mClockView.setOnClickListener(mOnClickListener);
|
||||
mNextAlarmContainer.setOnClickListener(mOnClickListener);
|
||||
mRingerContainer.setOnClickListener(mOnClickListener);
|
||||
mPrivacyChip.setOnClickListener(mOnClickListener);
|
||||
|
||||
mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable();
|
||||
@@ -268,18 +180,15 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
|
||||
|
||||
setChipVisibility(mPrivacyChip.getVisibility() == View.VISIBLE);
|
||||
|
||||
mView.onAttach(mIconManager);
|
||||
mView.onAttach(mIconManager, mQSExpansionPathInterpolator);
|
||||
|
||||
mDemoModeController.addCallback(mDemoModeReceiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onViewDetached() {
|
||||
mRingerModeTracker.getRingerModeInternal().removeObservers(mLifecycleOwner);
|
||||
mClockView.setOnClickListener(null);
|
||||
mColorExtractor.removeOnColorsChangedListener(mOnColorsChangedListener);
|
||||
mNextAlarmContainer.setOnClickListener(null);
|
||||
mRingerContainer.setOnClickListener(null);
|
||||
mPrivacyChip.setOnClickListener(null);
|
||||
mStatusBarIconController.removeIconGroup(mIconManager);
|
||||
mDemoModeController.removeCallback(mDemoModeReceiver);
|
||||
@@ -304,17 +213,11 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
|
||||
}
|
||||
|
||||
if (listening) {
|
||||
mZenModeController.addCallback(mZenModeControllerCallback);
|
||||
mNextAlarmController.addCallback(mNextAlarmChangeCallback);
|
||||
mLifecycle.setCurrentState(Lifecycle.State.RESUMED);
|
||||
// Get the most up to date info
|
||||
mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable();
|
||||
mLocationIndicatorsEnabled = mPrivacyItemController.getLocationAvailable();
|
||||
mPrivacyItemController.addCallback(mPICCallback);
|
||||
} else {
|
||||
mZenModeController.removeCallback(mZenModeControllerCallback);
|
||||
mNextAlarmController.removeCallback(mNextAlarmChangeCallback);
|
||||
mLifecycle.setCurrentState(Lifecycle.State.CREATED);
|
||||
mPrivacyItemController.removeCallback(mPICCallback);
|
||||
mPrivacyChipLogged = false;
|
||||
}
|
||||
@@ -357,11 +260,6 @@ class QuickStatusBarHeaderController extends ViewController<QuickStatusBarHeader
|
||||
return mMicCameraIndicatorsEnabled || mLocationIndicatorsEnabled;
|
||||
}
|
||||
|
||||
private boolean isZenOverridingRinger() {
|
||||
return ZenModeConfig.isZenOverridingRinger(mZenModeController.getZen(),
|
||||
mZenModeController.getConsolidatedPolicy());
|
||||
}
|
||||
|
||||
public void setContentMargins(int contentPaddingStart, int contentPaddingEnd) {
|
||||
mView.setContentMargins(contentPaddingStart, contentPaddingEnd, mHeaderQsPanelController);
|
||||
}
|
||||
|
||||
@@ -56,7 +56,6 @@ import com.android.settingslib.RestrictedLockUtils;
|
||||
import com.android.settingslib.RestrictedLockUtilsInternal;
|
||||
import com.android.settingslib.Utils;
|
||||
import com.android.systemui.Dumpable;
|
||||
import com.android.systemui.Prefs;
|
||||
import com.android.systemui.plugins.ActivityStarter;
|
||||
import com.android.systemui.plugins.FalsingManager;
|
||||
import com.android.systemui.plugins.qs.DetailAdapter;
|
||||
@@ -67,7 +66,6 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController;
|
||||
import com.android.systemui.qs.PagedTileLayout.TilePage;
|
||||
import com.android.systemui.qs.QSEvent;
|
||||
import com.android.systemui.qs.QSHost;
|
||||
import com.android.systemui.qs.QuickStatusBarHeader;
|
||||
import com.android.systemui.qs.logging.QSLogger;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
@@ -300,11 +298,6 @@ public abstract class QSTileImpl<TState extends State> implements QSTile, Lifecy
|
||||
getInstanceId());
|
||||
mQSLogger.logTileLongClick(mTileSpec, mStatusBarStateController.getState(), mState.state);
|
||||
mHandler.sendEmptyMessage(H.LONG_CLICK);
|
||||
|
||||
Prefs.putInt(
|
||||
mContext,
|
||||
Prefs.Key.QS_LONG_PRESS_TOOLTIP_SHOWN_COUNT,
|
||||
QuickStatusBarHeader.MAX_TOOLTIP_SHOWN_COUNT);
|
||||
}
|
||||
|
||||
public LogMaker populate(LogMaker logMaker) {
|
||||
|
||||
@@ -59,6 +59,7 @@ public class StatusBarMobileView extends FrameLayout implements DarkReceiver,
|
||||
private View mMobileRoamingSpace;
|
||||
private int mVisibleState = -1;
|
||||
private DualToneHandler mDualToneHandler;
|
||||
private boolean mForceHidden;
|
||||
|
||||
public static StatusBarMobileView fromContext(Context context, String slot) {
|
||||
LayoutInflater inflater = LayoutInflater.from(context);
|
||||
@@ -150,7 +151,7 @@ public class StatusBarMobileView extends FrameLayout implements DarkReceiver,
|
||||
|
||||
private void initViewState() {
|
||||
setContentDescription(mState.contentDescription);
|
||||
if (!mState.visible) {
|
||||
if (!mState.visible || mForceHidden) {
|
||||
mMobileGroup.setVisibility(View.GONE);
|
||||
} else {
|
||||
mMobileGroup.setVisibility(View.VISIBLE);
|
||||
@@ -176,8 +177,9 @@ public class StatusBarMobileView extends FrameLayout implements DarkReceiver,
|
||||
boolean needsLayout = false;
|
||||
|
||||
setContentDescription(state.contentDescription);
|
||||
if (mState.visible != state.visible) {
|
||||
mMobileGroup.setVisibility(state.visible ? View.VISIBLE : View.GONE);
|
||||
int newVisibility = state.visible && !mForceHidden ? View.VISIBLE : View.GONE;
|
||||
if (newVisibility != mMobileGroup.getVisibility()) {
|
||||
mMobileGroup.setVisibility(newVisibility);
|
||||
needsLayout = true;
|
||||
}
|
||||
if (mState.strengthId != state.strengthId) {
|
||||
@@ -252,7 +254,7 @@ public class StatusBarMobileView extends FrameLayout implements DarkReceiver,
|
||||
|
||||
@Override
|
||||
public boolean isIconVisible() {
|
||||
return mState.visible;
|
||||
return mState.visible && !mForceHidden;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -279,6 +281,23 @@ public class StatusBarMobileView extends FrameLayout implements DarkReceiver,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Forces the state to be hidden (views will be GONE) and if necessary updates the layout.
|
||||
*
|
||||
* Makes sure that the {@link StatusBarIconController} cannot make it visible while this flag
|
||||
* is enabled.
|
||||
* @param forceHidden {@code true} if the icon should be GONE in its view regardless of its
|
||||
* state.
|
||||
* {@code false} if the icon should show as determined by its controller.
|
||||
*/
|
||||
public void forceHidden(boolean forceHidden) {
|
||||
if (mForceHidden != forceHidden) {
|
||||
mForceHidden = forceHidden;
|
||||
updateState(mState);
|
||||
requestLayout();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVisibleState() {
|
||||
return mVisibleState;
|
||||
|
||||
@@ -33,6 +33,8 @@ import android.view.View;
|
||||
import android.view.WindowInsets;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.systemui.util.leak.RotationUtils;
|
||||
|
||||
/**
|
||||
@@ -91,6 +93,7 @@ public class StatusBarWindowView extends FrameLayout {
|
||||
* @param roundedCornerContentPadding
|
||||
* @return
|
||||
*/
|
||||
@NonNull
|
||||
public static Pair<Integer, Integer> paddingNeededForCutoutAndRoundedCorner(
|
||||
DisplayCutout cutout, Pair<Integer, Integer> cornerCutoutPadding,
|
||||
int roundedCornerContentPadding) {
|
||||
|
||||
@@ -261,6 +261,25 @@ public class StatusIconContainer extends AlphaOptimizedLinearLayout {
|
||||
addIgnoredSlots(slots);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the view corresponding to a particular slot.
|
||||
*
|
||||
* Use it solely to manipulate how it is presented.
|
||||
* @param slot name of the slot to find. Names are defined in
|
||||
* {@link com.android.internal.R.config_statusBarIcons}
|
||||
* @return a view for the slot if this container has it, else {@code null}
|
||||
*/
|
||||
public View getViewForSlot(String slot) {
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
View child = getChildAt(i);
|
||||
if (child instanceof StatusIconDisplayable
|
||||
&& ((StatusIconDisplayable) child).getSlot().equals(slot)) {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Layout is happening from end -> start
|
||||
*/
|
||||
|
||||
@@ -21,9 +21,9 @@ import android.testing.AndroidTestingRunner
|
||||
import android.view.View
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.internal.logging.UiEventLogger
|
||||
import com.android.systemui.colorextraction.SysuiColorExtractor
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.colorextraction.SysuiColorExtractor
|
||||
import com.android.systemui.demomode.DemoModeController
|
||||
import com.android.systemui.plugins.ActivityStarter
|
||||
import com.android.systemui.privacy.OngoingPrivacyChip
|
||||
@@ -32,16 +32,12 @@ import com.android.systemui.privacy.PrivacyItemController
|
||||
import com.android.systemui.privacy.logging.PrivacyLogger
|
||||
import com.android.systemui.qs.carrier.QSCarrierGroup
|
||||
import com.android.systemui.qs.carrier.QSCarrierGroupController
|
||||
import com.android.systemui.settings.UserTracker
|
||||
import com.android.systemui.statusbar.phone.StatusBarIconController
|
||||
import com.android.systemui.statusbar.phone.StatusIconContainer
|
||||
import com.android.systemui.statusbar.policy.Clock
|
||||
import com.android.systemui.statusbar.policy.NextAlarmController
|
||||
import com.android.systemui.util.RingerModeTracker
|
||||
import com.android.systemui.util.mockito.any
|
||||
import com.android.systemui.util.mockito.argumentCaptor
|
||||
import com.android.systemui.util.mockito.capture
|
||||
import com.android.systemui.utils.leaks.FakeZenModeController
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
@@ -61,26 +57,16 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() {
|
||||
@Mock
|
||||
private lateinit var view: QuickStatusBarHeader
|
||||
@Mock
|
||||
private lateinit var zenModeController: FakeZenModeController
|
||||
@Mock
|
||||
private lateinit var nextAlarmController: NextAlarmController
|
||||
@Mock
|
||||
private lateinit var privacyItemController: PrivacyItemController
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
private lateinit var ringerModeTracker: RingerModeTracker
|
||||
@Mock
|
||||
private lateinit var activityStarter: ActivityStarter
|
||||
@Mock
|
||||
private lateinit var uiEventLogger: UiEventLogger
|
||||
@Mock
|
||||
private lateinit var qsTileHost: QSTileHost
|
||||
@Mock
|
||||
private lateinit var statusBarIconController: StatusBarIconController
|
||||
@Mock
|
||||
private lateinit var demoModeController: DemoModeController
|
||||
@Mock
|
||||
private lateinit var userTracker: UserTracker
|
||||
@Mock
|
||||
private lateinit var quickQSPanelController: QuickQSPanelController
|
||||
@Mock(answer = Answers.RETURNS_SELF)
|
||||
private lateinit var qsCarrierGroupControllerBuilder: QSCarrierGroupController.Builder
|
||||
@@ -105,6 +91,8 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() {
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
private lateinit var context: Context
|
||||
|
||||
private val qsExpansionPathInterpolator = QSExpansionPathInterpolator()
|
||||
|
||||
private lateinit var controller: QuickStatusBarHeaderController
|
||||
|
||||
@Before
|
||||
@@ -119,21 +107,17 @@ class QuickStatusBarHeaderControllerTest : SysuiTestCase() {
|
||||
|
||||
controller = QuickStatusBarHeaderController(
|
||||
view,
|
||||
zenModeController,
|
||||
nextAlarmController,
|
||||
privacyItemController,
|
||||
ringerModeTracker,
|
||||
activityStarter,
|
||||
uiEventLogger,
|
||||
qsTileHost,
|
||||
statusBarIconController,
|
||||
demoModeController,
|
||||
userTracker,
|
||||
quickQSPanelController,
|
||||
qsCarrierGroupControllerBuilder,
|
||||
privacyLogger,
|
||||
colorExtractor,
|
||||
privacyDialogController
|
||||
privacyDialogController,
|
||||
qsExpansionPathInterpolator
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user