Merge changes from topic "b168904199-qs-injection"

* changes:
  6/N Remove UserTracker from QSBarHeader
  5/N Remove DemoModecontroller from QSBarHeader
  4/N Remove ZenModeController for QSBarHeader.
  3/N Move PrivacyItemController out of QSBarHeader.
  2/N Remove SBIconCtrl and CommandQueue from QSBarHeader.
  1/N Remove Injection from QSSBHeader
This commit is contained in:
Dave Mankoff
2020-10-02 21:00:37 +00:00
committed by Android (Google) Code Review
6 changed files with 422 additions and 353 deletions

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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;
public class QuickStatusBarHeader extends RelativeLayout implements LifecycleOwner {
/** 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;
private final NextAlarmController mAlarmController;
private final ZenModeController mZenController;
private final StatusBarIconController mStatusBarIconController;
private final ActivityStarter mActivityStarter;
private QSPanel mQsPanel;
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();
@@ -528,18 +371,6 @@ public class QuickStatusBarHeader extends RelativeLayout implements
updateResources();
}
@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
@@ -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();
}
}
}

View File

@@ -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);
}
}
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());
}
public static class Builder {
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);
}
}
}

View File

@@ -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;
@@ -92,10 +91,6 @@ public class InjectionInflationController {
@BindsInstance AttributeSet attributeSet);
}
/**
* Creates the QuickStatusBarHeader.
*/
QuickStatusBarHeader createQsHeader();
/**
* Creates the QSFooterImpl.
*/

View File

@@ -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();
}