summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSFragment.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java359
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java380
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java6
6 files changed, 424 insertions, 355 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java
index fa3328417bd6..1e239b1e9ec9 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImplController.java
@@ -17,30 +17,44 @@
package com.android.systemui.qs;
import com.android.systemui.R;
+import com.android.systemui.util.ViewController;
import javax.inject.Inject;
-public class QSContainerImplController {
- private final QSContainerImpl mView;
+class QSContainerImplController extends ViewController<QSContainerImpl> {
private final QuickStatusBarHeaderController mQuickStatusBarHeaderController;
private QSContainerImplController(QSContainerImpl view,
QuickStatusBarHeaderController.Builder quickStatusBarHeaderControllerBuilder) {
- mView = view;
+ super(view);
mQuickStatusBarHeaderController = quickStatusBarHeaderControllerBuilder
.setQuickStatusBarHeader(mView.findViewById(R.id.header)).build();
}
+ @Override
+ public void init() {
+ super.init();
+ mQuickStatusBarHeaderController.init();
+ }
+
public void setListening(boolean listening) {
mQuickStatusBarHeaderController.setListening(listening);
}
- public static class Builder {
+ @Override
+ protected void onViewAttached() {
+ }
+
+ @Override
+ protected void onViewDetached() {
+ }
+
+ static class Builder {
private final QuickStatusBarHeaderController.Builder mQuickStatusBarHeaderControllerBuilder;
private QSContainerImpl mView;
@Inject
- public Builder(
+ Builder(
QuickStatusBarHeaderController.Builder quickStatusBarHeaderControllerBuilder) {
mQuickStatusBarHeaderControllerBuilder = quickStatusBarHeaderControllerBuilder;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index f1bb8996e181..3a783653a2d8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -142,7 +142,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
mQSContainerImplController = mQSContainerImplControllerBuilder
.setQSContainerImpl((QSContainerImpl) view)
.build();
-
+ mQSContainerImplController.init();
mQSDetail.setQsPanel(mQSPanel, mHeader, (View) mFooter);
mQSAnimator = new QSAnimator(this, mHeader.findViewById(R.id.quick_qs_panel), mQSPanel);
@@ -367,14 +367,13 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
if (DEBUG) Log.d(TAG, "setListening " + listening);
mListening = listening;
mQSContainerImplController.setListening(listening);
- mHeader.setListening(listening);
mFooter.setListening(listening);
mQSPanel.setListening(mListening, mQsExpanded);
}
@Override
public void setHeaderListening(boolean listening) {
- mHeader.setListening(listening);
+ mQSContainerImplController.setListening(listening);
mFooter.setListening(listening);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 544249a51b08..a9fbc744b38e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -17,27 +17,16 @@ package com.android.systemui.qs;
import static android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
-import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
-
import android.annotation.ColorInt;
-import android.app.AlarmManager;
+import android.app.AlarmManager.AlarmClockInfo;
import android.content.Context;
-import android.content.Intent;
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.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.provider.AlarmClock;
-import android.provider.Settings;
-import android.service.notification.ZenModeConfig;
-import android.text.format.DateUtils;
import android.util.AttributeSet;
-import android.util.Log;
import android.util.MathUtils;
import android.util.Pair;
import android.view.ContextThemeWrapper;
@@ -53,93 +42,48 @@ import android.widget.Space;
import android.widget.TextView;
import androidx.annotation.NonNull;
-import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LifecycleRegistry;
-import com.android.internal.logging.UiEventLogger;
import com.android.settingslib.Utils;
import com.android.systemui.BatteryMeterView;
import com.android.systemui.DualToneHandler;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.demomode.DemoMode;
-import com.android.systemui.demomode.DemoModeController;
-import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
import com.android.systemui.privacy.OngoingPrivacyChip;
-import com.android.systemui.privacy.PrivacyChipEvent;
-import com.android.systemui.privacy.PrivacyItem;
-import com.android.systemui.privacy.PrivacyItemController;
import com.android.systemui.qs.QSDetail.Callback;
-import com.android.systemui.qs.carrier.QSCarrierGroup;
-import com.android.systemui.settings.UserTracker;
-import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
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 com.android.systemui.statusbar.policy.DateView;
-import com.android.systemui.statusbar.policy.NextAlarmController;
-import com.android.systemui.statusbar.policy.ZenModeController;
-import com.android.systemui.util.RingerModeTracker;
-import java.util.ArrayList;
-import java.util.List;
import java.util.Locale;
import java.util.Objects;
-import javax.inject.Inject;
-import javax.inject.Named;
-
/**
* 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.
*/
-public class QuickStatusBarHeader extends RelativeLayout implements
- View.OnClickListener, NextAlarmController.NextAlarmChangeCallback,
- ZenModeController.Callback, LifecycleOwner {
- private static final String TAG = "QuickStatusBarHeader";
- private static final boolean DEBUG = false;
-
- /** Delay for auto fading out the long press tooltip after it's fully visible (in ms). */
- private static final long AUTO_FADE_OUT_DELAY_MS = DateUtils.SECOND_IN_MILLIS * 6;
- private static final int FADE_ANIMATION_DURATION_MS = 300;
- private static final int TOOLTIP_NOT_YET_SHOWN_COUNT = 0;
- public static final int MAX_TOOLTIP_SHOWN_COUNT = 2;
+public class QuickStatusBarHeader extends RelativeLayout implements LifecycleOwner {
- private final NextAlarmController mAlarmController;
- private final ZenModeController mZenController;
- private final StatusBarIconController mStatusBarIconController;
- private final ActivityStarter mActivityStarter;
-
- private QSPanel mQsPanel;
+ public static final int MAX_TOOLTIP_SHOWN_COUNT = 2;
private boolean mExpanded;
- private boolean mListening;
private boolean mQsDisabled;
- private QSCarrierGroup mCarrierGroup;
protected QuickQSPanel mHeaderQsPanel;
- protected QSTileHost mHost;
- private TintedIconManager mIconManager;
private TouchAnimator mStatusIconsAlphaAnimator;
private TouchAnimator mHeaderTextContainerAlphaAnimator;
private TouchAnimator mPrivacyChipAlphaAnimator;
private DualToneHandler mDualToneHandler;
- private final CommandQueue mCommandQueue;
private View mSystemIconsView;
private View mQuickQsStatusIcons;
private View mHeaderTextContainerView;
- private int mRingerMode = AudioManager.RINGER_MODE_NORMAL;
- private AlarmManager.AlarmClockInfo mNextAlarm;
-
private ImageView mNextAlarmIcon;
/** {@link TextView} containing the actual text indicating when the next alarm will go off. */
private TextView mNextAlarmTextView;
@@ -149,23 +93,13 @@ public class QuickStatusBarHeader extends RelativeLayout implements
private TextView mRingerModeTextView;
private View mRingerContainer;
private Clock mClockView;
- private DateView mDateView;
private OngoingPrivacyChip mPrivacyChip;
private Space mSpace;
private BatteryMeterView mBatteryRemainingIcon;
- private RingerModeTracker mRingerModeTracker;
- private DemoModeController mDemoModeController;
- private DemoMode mDemoModeReceiver;
- private UserTracker mUserTracker;
- private boolean mAllIndicatorsEnabled;
- private boolean mMicCameraIndicatorsEnabled;
-
- private PrivacyItemController mPrivacyItemController;
- private final UiEventLogger mUiEventLogger;
+
// Used for RingerModeTracker
private final LifecycleRegistry mLifecycle = new LifecycleRegistry(this);
- private boolean mHasTopCutout = false;
private int mStatusBarPaddingTop = 0;
private int mRoundedCornerPadding = 0;
private int mContentMarginStart;
@@ -175,59 +109,11 @@ public class QuickStatusBarHeader extends RelativeLayout implements
private int mCutOutPaddingRight;
private float mExpandedHeaderAlpha = 1.0f;
private float mKeyguardExpansionFraction;
- private boolean mPrivacyChipLogged = false;
-
- private PrivacyItemController.Callback mPICCallback = new PrivacyItemController.Callback() {
- @Override
- public void onPrivacyItemsChanged(List<PrivacyItem> privacyItems) {
- mPrivacyChip.setPrivacyList(privacyItems);
- setChipVisibility(!privacyItems.isEmpty());
- }
-
- @Override
- public void onFlagAllChanged(boolean flag) {
- if (mAllIndicatorsEnabled != flag) {
- mAllIndicatorsEnabled = flag;
- update();
- }
- }
- @Override
- public void onFlagMicCameraChanged(boolean flag) {
- if (mMicCameraIndicatorsEnabled != flag) {
- mMicCameraIndicatorsEnabled = flag;
- update();
- }
- }
-
- private void update() {
- StatusIconContainer iconContainer = requireViewById(R.id.statusIcons);
- iconContainer.setIgnoredSlots(getIgnoredIconSlots());
- setChipVisibility(!mPrivacyChip.getPrivacyList().isEmpty());
- }
- };
-
- @Inject
- public QuickStatusBarHeader(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
- NextAlarmController nextAlarmController, ZenModeController zenModeController,
- StatusBarIconController statusBarIconController,
- ActivityStarter activityStarter, PrivacyItemController privacyItemController,
- CommandQueue commandQueue, RingerModeTracker ringerModeTracker,
- UiEventLogger uiEventLogger, DemoModeController demoModeController,
- UserTracker userTracker) {
+ public QuickStatusBarHeader(Context context, AttributeSet attrs) {
super(context, attrs);
- mAlarmController = nextAlarmController;
- mZenController = zenModeController;
- mStatusBarIconController = statusBarIconController;
- mActivityStarter = activityStarter;
- mPrivacyItemController = privacyItemController;
mDualToneHandler = new DualToneHandler(
new ContextThemeWrapper(context, R.style.QSHeaderTheme));
- mCommandQueue = commandQueue;
- mRingerModeTracker = ringerModeTracker;
- mUiEventLogger = uiEventLogger;
- mDemoModeController = demoModeController;
- mUserTracker = userTracker;
}
@Override
@@ -237,11 +123,6 @@ public class QuickStatusBarHeader extends RelativeLayout implements
mHeaderQsPanel = findViewById(R.id.quick_qs_panel);
mSystemIconsView = findViewById(R.id.quick_status_bar_system_icons);
mQuickQsStatusIcons = findViewById(R.id.quick_qs_status_icons);
- StatusIconContainer iconContainer = findViewById(R.id.statusIcons);
- // Ignore privacy icons because they show in the space above QQS
- iconContainer.addIgnoredSlots(getIgnoredIconSlots());
- iconContainer.setShouldRestrictIcons(false);
- mIconManager = new TintedIconManager(iconContainer, mCommandQueue);
// Views corresponding to the header info section (e.g. ringer and next alarm).
mHeaderTextContainerView = findViewById(R.id.header_text_container);
@@ -249,36 +130,18 @@ public class QuickStatusBarHeader extends RelativeLayout implements
mNextAlarmIcon = findViewById(R.id.next_alarm_icon);
mNextAlarmTextView = findViewById(R.id.next_alarm_text);
mNextAlarmContainer = findViewById(R.id.alarm_container);
- mNextAlarmContainer.setOnClickListener(this::onClick);
mRingerModeIcon = findViewById(R.id.ringer_mode_icon);
mRingerModeTextView = findViewById(R.id.ringer_mode_text);
mRingerContainer = findViewById(R.id.ringer_container);
- mRingerContainer.setOnClickListener(this::onClick);
mPrivacyChip = findViewById(R.id.privacy_chip);
- mPrivacyChip.setOnClickListener(this::onClick);
- mCarrierGroup = findViewById(R.id.carrier_group);
-
updateResources();
Rect tintArea = new Rect(0, 0, 0, 0);
- int colorForeground = Utils.getColorAttrDefaultColor(getContext(),
- android.R.attr.colorForeground);
- float intensity = getColorIntensity(colorForeground);
- int fillColor = mDualToneHandler.getSingleColor(intensity);
-
// Set light text on the header icons because they will always be on a black background
applyDarkness(R.id.clock, tintArea, 0, DarkIconDispatcher.DEFAULT_ICON_TINT);
- // Set the correct tint for the status icons so they contrast
- mIconManager.setTint(fillColor);
- mNextAlarmIcon.setImageTintList(ColorStateList.valueOf(fillColor));
- mRingerModeIcon.setImageTintList(ColorStateList.valueOf(fillColor));
-
mClockView = findViewById(R.id.clock);
- mClockView.setOnClickListener(this);
- mDemoModeReceiver = new ClockDemoModeReceiver(mClockView);
- mDateView = findViewById(R.id.date);
mSpace = findViewById(R.id.space);
// Tint for the battery icons are handled in setupHost()
@@ -290,33 +153,28 @@ public class QuickStatusBarHeader extends RelativeLayout implements
mBatteryRemainingIcon.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE);
mRingerModeTextView.setSelected(true);
mNextAlarmTextView.setSelected(true);
+ }
- mAllIndicatorsEnabled = mPrivacyItemController.getAllIndicatorsAvailable();
- mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable();
+ void onAttach(TintedIconManager iconManager) {
+ int colorForeground = Utils.getColorAttrDefaultColor(getContext(),
+ android.R.attr.colorForeground);
+ float intensity = getColorIntensity(colorForeground);
+ int fillColor = mDualToneHandler.getSingleColor(intensity);
+
+ // Set the correct tint for the status icons so they contrast
+ iconManager.setTint(fillColor);
+ mNextAlarmIcon.setImageTintList(ColorStateList.valueOf(fillColor));
+ mRingerModeIcon.setImageTintList(ColorStateList.valueOf(fillColor));
}
public QuickQSPanel getHeaderQsPanel() {
return mHeaderQsPanel;
}
- private List<String> getIgnoredIconSlots() {
- ArrayList<String> ignored = new ArrayList<>();
- if (getChipEnabled()) {
- ignored.add(mContext.getResources().getString(
- com.android.internal.R.string.status_bar_camera));
- ignored.add(mContext.getResources().getString(
- com.android.internal.R.string.status_bar_microphone));
- if (mAllIndicatorsEnabled) {
- ignored.add(mContext.getResources().getString(
- com.android.internal.R.string.status_bar_location));
- }
- }
-
- return ignored;
- }
-
- private void updateStatusText() {
- boolean changed = updateRingerStatus() || updateAlarmStatus();
+ 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;
@@ -326,32 +184,17 @@ public class QuickStatusBarHeader extends RelativeLayout implements
}
}
- private void setChipVisibility(boolean chipVisible) {
- if (chipVisible && getChipEnabled()) {
- mPrivacyChip.setVisibility(View.VISIBLE);
- // Makes sure that the chip is logged as viewed at most once each time QS is opened
- // mListening makes sure that the callback didn't return after the user closed QS
- if (!mPrivacyChipLogged && mListening) {
- mPrivacyChipLogged = true;
- mUiEventLogger.log(PrivacyChipEvent.ONGOING_INDICATORS_CHIP_VIEW);
- }
- } else {
- mPrivacyChip.setVisibility(View.GONE);
- }
- }
-
- private boolean updateRingerStatus() {
+ private boolean updateRingerStatus(int ringerMode, boolean zenOverridingRinger) {
boolean isOriginalVisible = mRingerModeTextView.getVisibility() == View.VISIBLE;
CharSequence originalRingerText = mRingerModeTextView.getText();
boolean ringerVisible = false;
- if (!ZenModeConfig.isZenOverridingRinger(mZenController.getZen(),
- mZenController.getConsolidatedPolicy())) {
- if (mRingerMode == AudioManager.RINGER_MODE_VIBRATE) {
+ 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 (mRingerMode == AudioManager.RINGER_MODE_SILENT) {
+ } 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;
@@ -365,14 +208,14 @@ public class QuickStatusBarHeader extends RelativeLayout implements
!Objects.equals(originalRingerText, mRingerModeTextView.getText());
}
- private boolean updateAlarmStatus() {
+ private boolean updateAlarmStatus(AlarmClockInfo nextAlarm, boolean use24HourFormat) {
boolean isOriginalVisible = mNextAlarmTextView.getVisibility() == View.VISIBLE;
CharSequence originalAlarmText = mNextAlarmTextView.getText();
boolean alarmVisible = false;
- if (mNextAlarm != null) {
+ if (nextAlarm != null) {
alarmVisible = true;
- mNextAlarmTextView.setText(formatNextAlarm(mNextAlarm));
+ mNextAlarmTextView.setText(formatNextAlarm(nextAlarm, use24HourFormat));
}
mNextAlarmIcon.setVisibility(alarmVisible ? View.VISIBLE : View.GONE);
mNextAlarmTextView.setVisibility(alarmVisible ? View.VISIBLE : View.GONE);
@@ -419,7 +262,7 @@ public class QuickStatusBarHeader extends RelativeLayout implements
setMinimumHeight(sbHeight + qqsHeight);
}
- private void updateResources() {
+ void updateResources() {
Resources resources = mContext.getResources();
updateMinimumHeight();
@@ -529,18 +372,6 @@ public class QuickStatusBarHeader extends RelativeLayout implements
}
@Override
- public void onAttachedToWindow() {
- super.onAttachedToWindow();
- mRingerModeTracker.getRingerModeInternal().observe(this, ringer -> {
- mRingerMode = ringer;
- updateStatusText();
- });
- mStatusBarIconController.addIconGroup(mIconManager);
- mDemoModeController.addCallback(mDemoModeReceiver);
- requestApplyInsets();
- }
-
- @Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
// Handle padding of the clock
DisplayCutout cutout = insets.getDisplayCutout();
@@ -563,17 +394,14 @@ public class QuickStatusBarHeader extends RelativeLayout implements
if (cutout != null) {
Rect topCutout = cutout.getBoundingRectTop();
if (topCutout.isEmpty() || cornerCutout) {
- mHasTopCutout = false;
lp.width = 0;
mSpace.setVisibility(View.GONE);
} else {
- mHasTopCutout = true;
lp.width = topCutout.width();
mSpace.setVisibility(View.VISIBLE);
}
}
mSpace.setLayoutParams(lp);
- setChipVisibility(mPrivacyChip.getVisibility() == View.VISIBLE);
mCutOutPaddingLeft = padding.first;
mCutOutPaddingRight = padding.second;
mWaterfallTopInset = cutout == null ? 0 : cutout.getWaterfallInsets().top;
@@ -611,103 +439,14 @@ public class QuickStatusBarHeader extends RelativeLayout implements
0);
}
- @Override
- @VisibleForTesting
- public void onDetachedFromWindow() {
- setListening(false);
- mRingerModeTracker.getRingerModeInternal().removeObservers(this);
- mStatusBarIconController.removeIconGroup(mIconManager);
- mDemoModeController.removeCallback(mDemoModeReceiver);
- super.onDetachedFromWindow();
- }
-
- public void setListening(boolean listening) {
- if (listening == mListening) {
- return;
- }
- mHeaderQsPanel.setListening(listening);
- if (mHeaderQsPanel.switchTileLayout()) {
- updateResources();
- }
- mListening = listening;
-
- if (listening) {
- mZenController.addCallback(this);
- mAlarmController.addCallback(this);
- mLifecycle.setCurrentState(Lifecycle.State.RESUMED);
- // Get the most up to date info
- mAllIndicatorsEnabled = mPrivacyItemController.getAllIndicatorsAvailable();
- mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable();
- mPrivacyItemController.addCallback(mPICCallback);
- } else {
- mZenController.removeCallback(this);
- mAlarmController.removeCallback(this);
- mLifecycle.setCurrentState(Lifecycle.State.CREATED);
- mPrivacyItemController.removeCallback(mPICCallback);
- mPrivacyChipLogged = false;
- }
- }
-
- @Override
- public void onClick(View v) {
- 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
- Handler mUiHandler = new Handler(Looper.getMainLooper());
- mUiEventLogger.log(PrivacyChipEvent.ONGOING_INDICATORS_CHIP_CLICK);
- mUiHandler.post(() -> {
- mActivityStarter.postStartActivityDismissingKeyguard(
- new Intent(Intent.ACTION_REVIEW_ONGOING_PERMISSION_USAGE), 0);
- mHost.collapsePanels();
- });
- } else if (v == mRingerContainer && mRingerContainer.isVisibleToUser()) {
- mActivityStarter.postStartActivityDismissingKeyguard(new Intent(
- Settings.ACTION_SOUND_SETTINGS), 0);
- }
- }
-
- @Override
- public void onNextAlarmChanged(AlarmManager.AlarmClockInfo nextAlarm) {
- mNextAlarm = nextAlarm;
- updateStatusText();
- }
-
- @Override
- public void onZenChanged(int zen) {
- updateStatusText();
- }
-
- @Override
- public void onConfigChanged(ZenModeConfig config) {
- updateStatusText();
- }
-
public void updateEverything() {
post(() -> setClickable(!mExpanded));
}
public void setQSPanel(final QSPanel qsPanel) {
- mQsPanel = qsPanel;
- setupHost(qsPanel.getHost());
- }
-
- public void setupHost(final QSTileHost host) {
- mHost = host;
//host.setHeaderView(mExpandIndicator);
- mHeaderQsPanel.setQSPanelAndHeader(mQsPanel, this);
- mHeaderQsPanel.setHost(host, null /* No customization in header */);
-
+ mHeaderQsPanel.setQSPanelAndHeader(qsPanel, this);
+ mHeaderQsPanel.setHost(qsPanel.getHost(), null /* No customization in header */);
Rect tintArea = new Rect(0, 0, 0, 0);
int colorForeground = Utils.getColorAttrDefaultColor(getContext(),
@@ -721,12 +460,11 @@ public class QuickStatusBarHeader extends RelativeLayout implements
mHeaderQsPanel.setCallback(qsPanelCallback);
}
- private String formatNextAlarm(AlarmManager.AlarmClockInfo info) {
+ private String formatNextAlarm(AlarmClockInfo info, boolean use24HourFormat) {
if (info == null) {
return "";
}
- String skeleton = android.text.format.DateFormat
- .is24HourFormat(mContext, mUserTracker.getUserId()) ? "EHm" : "Ehma";
+ 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();
@@ -777,37 +515,4 @@ public class QuickStatusBarHeader extends RelativeLayout implements
updateHeaderTextContainerAlphaAnimator();
}
}
-
- private boolean getChipEnabled() {
- return mMicCameraIndicatorsEnabled || mAllIndicatorsEnabled;
- }
-
- private static class ClockDemoModeReceiver implements DemoMode {
- private Clock mClockView;
-
- @Override
- public List<String> demoCommands() {
- return List.of(COMMAND_CLOCK);
- }
-
- ClockDemoModeReceiver(Clock clockView) {
- mClockView = clockView;
- }
-
- @Override
- public void dispatchDemoCommand(String command, Bundle args) {
- mClockView.dispatchDemoCommand(command, args);
- }
-
- @Override
- public void onDemoModeStarted() {
- mClockView.onDemoModeStarted();
- }
-
- @Override
- public void onDemoModeFinished() {
- mClockView.onDemoModeFinished();
- }
- }
-
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
index d899acbade4a..676a300b0ff2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
@@ -16,36 +16,393 @@
package com.android.systemui.qs;
+import android.app.AlarmManager.AlarmClockInfo;
+import android.content.Intent;
+import android.media.AudioManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+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.logging.UiEventLogger;
import com.android.systemui.R;
+import com.android.systemui.demomode.DemoMode;
+import com.android.systemui.demomode.DemoModeController;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.privacy.OngoingPrivacyChip;
+import com.android.systemui.privacy.PrivacyChipEvent;
+import com.android.systemui.privacy.PrivacyItem;
+import com.android.systemui.privacy.PrivacyItemController;
import com.android.systemui.qs.carrier.QSCarrierGroupController;
+import com.android.systemui.settings.UserTracker;
+import com.android.systemui.statusbar.CommandQueue;
+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;
+import java.util.List;
import javax.inject.Inject;
-public class QuickStatusBarHeaderController {
- private final QuickStatusBarHeader mView;
+/**
+ * Controller for {@link QuickStatusBarHeader}.
+ */
+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 QuickQSPanel mHeaderQsPanel;
+ 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 CommandQueue mCommandQueue;
+ private final DemoModeController mDemoModeController;
+ private final UserTracker mUserTracker;
+ private final StatusIconContainer mIconContainer;
+ private final StatusBarIconController.TintedIconManager mIconManager;
+ private final DemoMode mDemoModeReceiver;
+
+ private boolean mListening;
+ private AlarmClockInfo mNextAlarm;
+ private boolean mAllIndicatorsEnabled;
+ private boolean mMicCameraIndicatorsEnabled;
+ private boolean mPrivacyChipLogged;
+ 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
+ public void onPrivacyItemsChanged(@NonNull List<PrivacyItem> privacyItems) {
+ mPrivacyChip.setPrivacyList(privacyItems);
+ setChipVisibility(!privacyItems.isEmpty());
+ }
+
+ @Override
+ public void onFlagAllChanged(boolean flag) {
+ if (mAllIndicatorsEnabled != flag) {
+ mAllIndicatorsEnabled = flag;
+ update();
+ }
+ }
+
+ @Override
+ public void onFlagMicCameraChanged(boolean flag) {
+ if (mMicCameraIndicatorsEnabled != flag) {
+ mMicCameraIndicatorsEnabled = flag;
+ update();
+ }
+ }
+
+ private void update() {
+ StatusIconContainer iconContainer = mView.requireViewById(R.id.statusIcons);
+ iconContainer.setIgnoredSlots(getIgnoredIconSlots());
+ setChipVisibility(!mPrivacyChip.getPrivacyList().isEmpty());
+ }
+ };
+
+ private View.OnClickListener mOnClickListener = new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ 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
+ Handler mUiHandler = new Handler(Looper.getMainLooper());
+ mUiEventLogger.log(PrivacyChipEvent.ONGOING_INDICATORS_CHIP_CLICK);
+ mUiHandler.post(() -> {
+ mActivityStarter.postStartActivityDismissingKeyguard(
+ new Intent(Intent.ACTION_REVIEW_ONGOING_PERMISSION_USAGE), 0);
+ mQSTileHost.collapsePanels();
+ });
+ } else if (v == mRingerContainer && mRingerContainer.isVisibleToUser()) {
+ mActivityStarter.postStartActivityDismissingKeyguard(new Intent(
+ Settings.ACTION_SOUND_SETTINGS), 0);
+ }
+ }
+ };
private QuickStatusBarHeaderController(QuickStatusBarHeader view,
+ ZenModeController zenModeController, NextAlarmController nextAlarmController,
+ PrivacyItemController privacyItemController, RingerModeTracker ringerModeTracker,
+ ActivityStarter activityStarter, UiEventLogger uiEventLogger,
+ QSTileHost qsTileHost, StatusBarIconController statusBarIconController,
+ CommandQueue commandQueue, DemoModeController demoModeController,
+ UserTracker userTracker,
QSCarrierGroupController.Builder qsCarrierGroupControllerBuilder) {
- mView = view;
+ super(view);
+ mZenModeController = zenModeController;
+ mNextAlarmController = nextAlarmController;
+ mPrivacyItemController = privacyItemController;
+ mRingerModeTracker = ringerModeTracker;
+ mActivityStarter = activityStarter;
+ mUiEventLogger = uiEventLogger;
+ mQSTileHost = qsTileHost;
+ mStatusBarIconController = statusBarIconController;
+ mCommandQueue = commandQueue;
+ mDemoModeController = demoModeController;
+ mUserTracker = userTracker;
+ mLifecycle = new LifecycleRegistry(mLifecycleOwner);
+
mQSCarrierGroupController = qsCarrierGroupControllerBuilder
.setQSCarrierGroup(mView.findViewById(R.id.carrier_group))
.build();
+
+
+ mPrivacyChip = mView.findViewById(R.id.privacy_chip);
+ mHeaderQsPanel = mView.findViewById(R.id.quick_qs_panel);
+ 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, mCommandQueue);
+ mDemoModeReceiver = new ClockDemoModeReceiver(mClockView);
+ }
+
+ @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);
+
+ // Ignore privacy icons because they show in the space above QQS
+ mIconContainer.addIgnoredSlots(getIgnoredIconSlots());
+ mIconContainer.setShouldRestrictIcons(false);
+ mStatusBarIconController.addIconGroup(mIconManager);
+
+ mAllIndicatorsEnabled = mPrivacyItemController.getAllIndicatorsAvailable();
+ mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable();
+
+ setChipVisibility(mPrivacyChip.getVisibility() == View.VISIBLE);
+
+ mView.onAttach(mIconManager);
+
+ mDemoModeController.addCallback(mDemoModeReceiver);
+ }
+
+ @Override
+ protected void onViewDetached() {
+ mRingerModeTracker.getRingerModeInternal().removeObservers(mLifecycleOwner);
+ mClockView.setOnClickListener(null);
+ mNextAlarmContainer.setOnClickListener(null);
+ mRingerContainer.setOnClickListener(null);
+ mPrivacyChip.setOnClickListener(null);
+ mStatusBarIconController.removeIconGroup(mIconManager);
+ mDemoModeController.removeCallback(mDemoModeReceiver);
+ setListening(false);
}
public void setListening(boolean listening) {
mQSCarrierGroupController.setListening(listening);
- // TODO: move mView.setListening logic into here.
- mView.setListening(listening);
+
+ if (listening == mListening) {
+ return;
+ }
+ mListening = listening;
+
+ mHeaderQsPanel.setListening(listening);
+ if (mHeaderQsPanel.switchTileLayout()) {
+ mView.updateResources();
+ }
+
+ if (listening) {
+ mZenModeController.addCallback(mZenModeControllerCallback);
+ mNextAlarmController.addCallback(mNextAlarmChangeCallback);
+ mLifecycle.setCurrentState(Lifecycle.State.RESUMED);
+ // Get the most up to date info
+ mAllIndicatorsEnabled = mPrivacyItemController.getAllIndicatorsAvailable();
+ mMicCameraIndicatorsEnabled = mPrivacyItemController.getMicCameraAvailable();
+ mPrivacyItemController.addCallback(mPICCallback);
+ } else {
+ mZenModeController.removeCallback(mZenModeControllerCallback);
+ mNextAlarmController.removeCallback(mNextAlarmChangeCallback);
+ mLifecycle.setCurrentState(Lifecycle.State.CREATED);
+ mPrivacyItemController.removeCallback(mPICCallback);
+ mPrivacyChipLogged = false;
+ }
}
+ private void setChipVisibility(boolean chipVisible) {
+ if (chipVisible && getChipEnabled()) {
+ mPrivacyChip.setVisibility(View.VISIBLE);
+ // Makes sure that the chip is logged as viewed at most once each time QS is opened
+ // mListening makes sure that the callback didn't return after the user closed QS
+ if (!mPrivacyChipLogged && mListening) {
+ mPrivacyChipLogged = true;
+ mUiEventLogger.log(PrivacyChipEvent.ONGOING_INDICATORS_CHIP_VIEW);
+ }
+ } else {
+ mPrivacyChip.setVisibility(View.GONE);
+ }
+ }
- public static class Builder {
+ private List<String> getIgnoredIconSlots() {
+ ArrayList<String> ignored = new ArrayList<>();
+ if (getChipEnabled()) {
+ ignored.add(mView.getResources().getString(
+ com.android.internal.R.string.status_bar_camera));
+ ignored.add(mView.getResources().getString(
+ com.android.internal.R.string.status_bar_microphone));
+ if (mAllIndicatorsEnabled) {
+ ignored.add(mView.getResources().getString(
+ com.android.internal.R.string.status_bar_location));
+ }
+ }
+
+ return ignored;
+ }
+
+ private boolean getChipEnabled() {
+ return mMicCameraIndicatorsEnabled || mAllIndicatorsEnabled;
+ }
+
+ private boolean isZenOverridingRinger() {
+ return ZenModeConfig.isZenOverridingRinger(mZenModeController.getZen(),
+ mZenModeController.getConsolidatedPolicy());
+ }
+
+
+ private static class ClockDemoModeReceiver implements DemoMode {
+ private Clock mClockView;
+
+ @Override
+ public List<String> demoCommands() {
+ return List.of(COMMAND_CLOCK);
+ }
+
+ ClockDemoModeReceiver(Clock clockView) {
+ mClockView = clockView;
+ }
+
+ @Override
+ public void dispatchDemoCommand(String command, Bundle args) {
+ mClockView.dispatchDemoCommand(command, args);
+ }
+
+ @Override
+ public void onDemoModeStarted() {
+ mClockView.onDemoModeStarted();
+ }
+
+ @Override
+ public void onDemoModeFinished() {
+ mClockView.onDemoModeFinished();
+ }
+ }
+
+ static class Builder {
+ 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 QSTileHost mQsTileHost;
+ private final StatusBarIconController mStatusBarIconController;
+ private final CommandQueue mCommandQueue;
+ private final DemoModeController mDemoModeController;
+ private final UserTracker mUserTracker;
private final QSCarrierGroupController.Builder mQSCarrierGroupControllerBuilder;
private QuickStatusBarHeader mView;
@Inject
- public Builder(QSCarrierGroupController.Builder qsCarrierGroupControllerBuilder) {
+ Builder(ZenModeController zenModeController, NextAlarmController nextAlarmController,
+ PrivacyItemController privacyItemController, RingerModeTracker ringerModeTracker,
+ ActivityStarter activityStarter, UiEventLogger uiEventLogger, QSTileHost qsTileHost,
+ StatusBarIconController statusBarIconController, CommandQueue commandQueue,
+ DemoModeController demoModeController, UserTracker userTracker,
+ QSCarrierGroupController.Builder qsCarrierGroupControllerBuilder) {
+ mZenModeController = zenModeController;
+ mNextAlarmController = nextAlarmController;
+ mPrivacyItemController = privacyItemController;
+ mRingerModeTracker = ringerModeTracker;
+ mActivityStarter = activityStarter;
+ mUiEventLogger = uiEventLogger;
+ mQsTileHost = qsTileHost;
+ mStatusBarIconController = statusBarIconController;
+ mCommandQueue = commandQueue;
+ mDemoModeController = demoModeController;
+ mUserTracker = userTracker;
mQSCarrierGroupControllerBuilder = qsCarrierGroupControllerBuilder;
}
@@ -54,8 +411,13 @@ public class QuickStatusBarHeaderController {
return this;
}
- public QuickStatusBarHeaderController build() {
- return new QuickStatusBarHeaderController(mView, mQSCarrierGroupControllerBuilder);
+
+ QuickStatusBarHeaderController build() {
+ return new QuickStatusBarHeaderController(mView, mZenModeController,
+ mNextAlarmController, mPrivacyItemController, mRingerModeTracker,
+ mActivityStarter, mUiEventLogger, mQsTileHost, mStatusBarIconController,
+ mCommandQueue, mDemoModeController, mUserTracker,
+ mQSCarrierGroupControllerBuilder);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
index a6cd350b33ce..344f0d2f5506 100644
--- a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
+++ b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
@@ -27,7 +27,6 @@ import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.qs.QSFooterImpl;
import com.android.systemui.qs.QSPanel;
import com.android.systemui.qs.QuickQSPanel;
-import com.android.systemui.qs.QuickStatusBarHeader;
import com.android.systemui.qs.customize.QSCustomizer;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
@@ -93,10 +92,6 @@ public class InjectionInflationController {
}
/**
- * Creates the QuickStatusBarHeader.
- */
- QuickStatusBarHeader createQsHeader();
- /**
* Creates the QSFooterImpl.
*/
QSFooterImpl createQsFooter();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
index 1c2d08402e69..e472cb22ed6b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -37,7 +37,6 @@ import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.UiEventLogger;
import com.android.keyguard.CarrierText;
import com.android.systemui.Dependency;
-import com.android.systemui.R;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.SysuiBaseFragmentTest;
import com.android.systemui.broadcast.BroadcastDispatcher;
@@ -116,11 +115,6 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
qs.setListening(false);
processAllMessages();
-
- // Manually push header through detach so it can handle standard cleanup it does on
- // removed from window.
- ((QuickStatusBarHeader) qs.getView().findViewById(R.id.header)).onDetachedFromWindow();
-
host.destroy();
processAllMessages();
}