blob: a28b60dbe13c75c416c0b398feb61f06f7a4b113 [file] [log] [blame]
Jason Monke5b770e2017-03-03 21:49:29 -05001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5 * except in compliance with the License. You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under the
10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11 * KIND, either express or implied. See the License for the specific language governing
12 * permissions and limitations under the License.
13 */
14
15package com.android.systemui.qs;
16
Charles Hece2a7c02017-10-11 20:25:20 +010017import static android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS;
Charles Hece2a7c02017-10-11 20:25:20 +010018
Jason Monkea54e8a2018-12-20 10:01:48 -050019import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
20
Amin Shaikh0e003312018-03-08 11:39:01 -050021import android.annotation.ColorInt;
Lucas Dupin1f7374a2018-02-26 18:08:33 -080022import android.app.ActivityManager;
Rohan Shahd3cf7562018-02-23 11:12:28 -080023import android.app.AlarmManager;
Amin Shaikh761c5662018-03-27 16:55:43 -040024import android.content.BroadcastReceiver;
Jason Monke5b770e2017-03-03 21:49:29 -050025import android.content.Context;
Evan Laird4ea2a492018-01-22 11:29:12 -050026import android.content.Intent;
Amin Shaikh761c5662018-03-27 16:55:43 -040027import android.content.IntentFilter;
Fabian Kozynskif86df992019-04-22 14:23:47 -040028import android.content.res.ColorStateList;
Jason Monke5b770e2017-03-03 21:49:29 -050029import android.content.res.Configuration;
Rohan Shahcc3d1d82018-03-30 21:24:17 +000030import android.content.res.Resources;
Jason Monke5b770e2017-03-03 21:49:29 -050031import android.graphics.Color;
32import android.graphics.Rect;
Amin Shaikh761c5662018-03-27 16:55:43 -040033import android.media.AudioManager;
Rohan Shahd3cf7562018-02-23 11:12:28 -080034import android.os.Handler;
Evan Laird4ea2a492018-01-22 11:29:12 -050035import android.provider.AlarmClock;
Fabian Kozynskib1aee812019-04-04 14:17:48 -040036import android.provider.Settings;
Beverlyb9826dd2018-04-12 15:02:45 -040037import android.service.notification.ZenModeConfig;
Rohan Shahd3cf7562018-02-23 11:12:28 -080038import android.text.format.DateUtils;
Jason Monke5b770e2017-03-03 21:49:29 -050039import android.util.AttributeSet;
Fabian Kozynskia3544712019-04-25 17:05:21 -040040import android.util.Log;
Adrian Roos13836052018-03-15 21:06:37 +010041import android.util.Pair;
Fabian Kozynskif86df992019-04-22 14:23:47 -040042import android.view.ContextThemeWrapper;
Fabian Kozynski8d06c712018-11-07 10:33:02 -050043import android.view.DisplayCutout;
Jason Monk824ffff2017-04-11 15:49:06 -040044import android.view.View;
Adrian Roos13836052018-03-15 21:06:37 +010045import android.view.WindowInsets;
Beverlyff2df9b2018-10-10 16:54:10 -040046import android.widget.FrameLayout;
Amin Shaikh761c5662018-03-27 16:55:43 -040047import android.widget.ImageView;
Jason Monke5b770e2017-03-03 21:49:29 -050048import android.widget.RelativeLayout;
Rohan Shahd3cf7562018-02-23 11:12:28 -080049import android.widget.TextView;
Jason Monke5b770e2017-03-03 21:49:29 -050050
Beverlyff2df9b2018-10-10 16:54:10 -040051import androidx.annotation.VisibleForTesting;
52
Jason Monke5b770e2017-03-03 21:49:29 -050053import com.android.settingslib.Utils;
54import com.android.systemui.BatteryMeterView;
Fabian Kozynskif86df992019-04-22 14:23:47 -040055import com.android.systemui.DualToneHandler;
Jason Monke5b770e2017-03-03 21:49:29 -050056import com.android.systemui.R;
57import com.android.systemui.plugins.ActivityStarter;
Beverly1be62f42018-12-19 17:17:48 -050058import com.android.systemui.plugins.DarkIconDispatcher;
59import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
Jason Monke5b770e2017-03-03 21:49:29 -050060import com.android.systemui.qs.QSDetail.Callback;
Adrian Roos13836052018-03-15 21:06:37 +010061import com.android.systemui.statusbar.phone.PhoneStatusBarView;
Evan Laird95896952018-01-22 19:30:05 -050062import com.android.systemui.statusbar.phone.StatusBarIconController;
63import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager;
Evan Laird20b87bf2018-04-12 09:54:11 -040064import com.android.systemui.statusbar.phone.StatusIconContainer;
Beverlyff2df9b2018-10-10 16:54:10 -040065import com.android.systemui.statusbar.policy.Clock;
Rohan Shahcc3d1d82018-03-30 21:24:17 +000066import com.android.systemui.statusbar.policy.DateView;
Rohan Shahd3cf7562018-02-23 11:12:28 -080067import com.android.systemui.statusbar.policy.NextAlarmController;
Beverlyb9826dd2018-04-12 15:02:45 -040068import com.android.systemui.statusbar.policy.ZenModeController;
Jason Monke5b770e2017-03-03 21:49:29 -050069
Lucas Dupin1f7374a2018-02-26 18:08:33 -080070import java.util.Locale;
Beverlyb9826dd2018-04-12 15:02:45 -040071import java.util.Objects;
Lucas Dupin1f7374a2018-02-26 18:08:33 -080072
Jason Monkea54e8a2018-12-20 10:01:48 -050073import javax.inject.Inject;
74import javax.inject.Named;
75
Rohan Shahd3cf7562018-02-23 11:12:28 -080076/**
77 * View that contains the top-most bits of the screen (primarily the status bar with date, time, and
78 * battery) and also contains the {@link QuickQSPanel} along with some of the panel's inner
79 * contents.
80 */
Amin Shaikhf09450b2018-04-06 17:32:45 -040081public class QuickStatusBarHeader extends RelativeLayout implements
Beverlyb9826dd2018-04-12 15:02:45 -040082 View.OnClickListener, NextAlarmController.NextAlarmChangeCallback,
83 ZenModeController.Callback {
Rohan Shaha160ab12018-03-09 15:47:36 -080084 private static final String TAG = "QuickStatusBarHeader";
85 private static final boolean DEBUG = false;
Jason Monke5b770e2017-03-03 21:49:29 -050086
Rohan Shahd3cf7562018-02-23 11:12:28 -080087 /** Delay for auto fading out the long press tooltip after it's fully visible (in ms). */
88 private static final long AUTO_FADE_OUT_DELAY_MS = DateUtils.SECOND_IN_MILLIS * 6;
89 private static final int FADE_ANIMATION_DURATION_MS = 300;
90 private static final int TOOLTIP_NOT_YET_SHOWN_COUNT = 0;
Rohan Shahb6a915c2018-03-01 11:57:00 -080091 public static final int MAX_TOOLTIP_SHOWN_COUNT = 2;
Rohan Shahd3cf7562018-02-23 11:12:28 -080092
93 private final Handler mHandler = new Handler();
Jason Monkea54e8a2018-12-20 10:01:48 -050094 private final NextAlarmController mAlarmController;
95 private final ZenModeController mZenController;
96 private final StatusBarIconController mStatusBarIconController;
97 private final ActivityStarter mActivityStarter;
Jason Monke5b770e2017-03-03 21:49:29 -050098
99 private QSPanel mQsPanel;
100
101 private boolean mExpanded;
102 private boolean mListening;
Charles Hece2a7c02017-10-11 20:25:20 +0100103 private boolean mQsDisabled;
Jason Monke5b770e2017-03-03 21:49:29 -0500104
Fabian Kozynski4e76d1f2019-02-25 16:30:04 -0500105 private QSCarrierGroup mCarrierGroup;
Jason Monke5b770e2017-03-03 21:49:29 -0500106 protected QuickQSPanel mHeaderQsPanel;
107 protected QSTileHost mHost;
Evan Laird95896952018-01-22 19:30:05 -0500108 private TintedIconManager mIconManager;
Rohan Shahd3cf7562018-02-23 11:12:28 -0800109 private TouchAnimator mStatusIconsAlphaAnimator;
110 private TouchAnimator mHeaderTextContainerAlphaAnimator;
Fabian Kozynskif86df992019-04-22 14:23:47 -0400111 private DualToneHandler mDualToneHandler;
Evan Laird95896952018-01-22 19:30:05 -0500112
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000113 private View mSystemIconsView;
Evan Laird95896952018-01-22 19:30:05 -0500114 private View mQuickQsStatusIcons;
Rohan Shahd3cf7562018-02-23 11:12:28 -0800115 private View mHeaderTextContainerView;
Amin Shaikh761c5662018-03-27 16:55:43 -0400116
117 private int mRingerMode = AudioManager.RINGER_MODE_NORMAL;
118 private AlarmManager.AlarmClockInfo mNextAlarm;
119
120 private ImageView mNextAlarmIcon;
Rohan Shahd3cf7562018-02-23 11:12:28 -0800121 /** {@link TextView} containing the actual text indicating when the next alarm will go off. */
122 private TextView mNextAlarmTextView;
Fabian Kozynskib1aee812019-04-04 14:17:48 -0400123 private View mNextAlarmContainer;
Amin Shaikh761c5662018-03-27 16:55:43 -0400124 private View mStatusSeparator;
125 private ImageView mRingerModeIcon;
126 private TextView mRingerModeTextView;
Fabian Kozynskib1aee812019-04-04 14:17:48 -0400127 private View mRingerContainer;
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000128 private Clock mClockView;
129 private DateView mDateView;
Evan Laird4bf21df2018-10-22 14:24:32 -0400130 private BatteryMeterView mBatteryRemainingIcon;
Rohan Shahd3cf7562018-02-23 11:12:28 -0800131
Amin Shaikh761c5662018-03-27 16:55:43 -0400132 private final BroadcastReceiver mRingerReceiver = new BroadcastReceiver() {
133 @Override
134 public void onReceive(Context context, Intent intent) {
135 mRingerMode = intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1);
136 updateStatusText();
137 }
138 };
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500139 private boolean mHasTopCutout = false;
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500140
Jason Monkea54e8a2018-12-20 10:01:48 -0500141 @Inject
142 public QuickStatusBarHeader(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
143 NextAlarmController nextAlarmController, ZenModeController zenModeController,
Evan Laird85ee4a32019-03-06 18:09:20 -0500144 StatusBarIconController statusBarIconController,
Fabian Kozynski5c837102019-06-13 10:54:40 -0400145 ActivityStarter activityStarter) {
Jason Monke5b770e2017-03-03 21:49:29 -0500146 super(context, attrs);
Jason Monkea54e8a2018-12-20 10:01:48 -0500147 mAlarmController = nextAlarmController;
148 mZenController = zenModeController;
Jason Monkea54e8a2018-12-20 10:01:48 -0500149 mStatusBarIconController = statusBarIconController;
150 mActivityStarter = activityStarter;
Fabian Kozynskif86df992019-04-22 14:23:47 -0400151 mDualToneHandler = new DualToneHandler(
152 new ContextThemeWrapper(context, R.style.QSHeaderTheme));
Jason Monke5b770e2017-03-03 21:49:29 -0500153 }
154
155 @Override
156 protected void onFinishInflate() {
157 super.onFinishInflate();
Jason Monke5b770e2017-03-03 21:49:29 -0500158
159 mHeaderQsPanel = findViewById(R.id.quick_qs_panel);
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000160 mSystemIconsView = findViewById(R.id.quick_status_bar_system_icons);
Evan Laird95896952018-01-22 19:30:05 -0500161 mQuickQsStatusIcons = findViewById(R.id.quick_qs_status_icons);
Evan Laird20b87bf2018-04-12 09:54:11 -0400162 StatusIconContainer iconContainer = findViewById(R.id.statusIcons);
163 iconContainer.setShouldRestrictIcons(false);
164 mIconManager = new TintedIconManager(iconContainer);
Jason Monke5b770e2017-03-03 21:49:29 -0500165
Fabian Kozynski121adb42019-04-22 15:10:43 -0400166 // Views corresponding to the header info section (e.g. ringer and next alarm).
Rohan Shahd3cf7562018-02-23 11:12:28 -0800167 mHeaderTextContainerView = findViewById(R.id.header_text_container);
Amin Shaikh761c5662018-03-27 16:55:43 -0400168 mStatusSeparator = findViewById(R.id.status_separator);
169 mNextAlarmIcon = findViewById(R.id.next_alarm_icon);
Rohan Shahd3cf7562018-02-23 11:12:28 -0800170 mNextAlarmTextView = findViewById(R.id.next_alarm_text);
Fabian Kozynskib1aee812019-04-04 14:17:48 -0400171 mNextAlarmContainer = findViewById(R.id.alarm_container);
172 mNextAlarmContainer.setOnClickListener(this::onClick);
Amin Shaikh761c5662018-03-27 16:55:43 -0400173 mRingerModeIcon = findViewById(R.id.ringer_mode_icon);
174 mRingerModeTextView = findViewById(R.id.ringer_mode_text);
Fabian Kozynskib1aee812019-04-04 14:17:48 -0400175 mRingerContainer = findViewById(R.id.ringer_container);
Fabian Kozynski4e76d1f2019-02-25 16:30:04 -0500176 mCarrierGroup = findViewById(R.id.carrier_group);
Jason Monke5b770e2017-03-03 21:49:29 -0500177
Fabian Kozynskibfd6d852019-02-15 15:08:16 -0500178
Jason Monke5b770e2017-03-03 21:49:29 -0500179 updateResources();
180
Jason Monk824ffff2017-04-11 15:49:06 -0400181 Rect tintArea = new Rect(0, 0, 0, 0);
Jason Changb4e879d2018-04-11 11:17:58 +0800182 int colorForeground = Utils.getColorAttrDefaultColor(getContext(),
183 android.R.attr.colorForeground);
Amin Shaikh0e003312018-03-08 11:39:01 -0500184 float intensity = getColorIntensity(colorForeground);
Fabian Kozynskif86df992019-04-22 14:23:47 -0400185 int fillColor = mDualToneHandler.getSingleColor(intensity);
Evan Laird95896952018-01-22 19:30:05 -0500186
187 // Set light text on the header icons because they will always be on a black background
Evan Laird39254d42018-01-18 16:05:30 -0500188 applyDarkness(R.id.clock, tintArea, 0, DarkIconDispatcher.DEFAULT_ICON_TINT);
Evan Laird95896952018-01-22 19:30:05 -0500189
190 // Set the correct tint for the status icons so they contrast
191 mIconManager.setTint(fillColor);
Fabian Kozynskif86df992019-04-22 14:23:47 -0400192 mNextAlarmIcon.setImageTintList(ColorStateList.valueOf(fillColor));
193 mRingerModeIcon.setImageTintList(ColorStateList.valueOf(fillColor));
Jason Monke5b770e2017-03-03 21:49:29 -0500194
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000195 mClockView = findViewById(R.id.clock);
Amin Shaikh39bdc502018-05-15 23:43:34 -0400196 mClockView.setOnClickListener(this);
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000197 mDateView = findViewById(R.id.date);
Evan Laird4bf21df2018-10-22 14:24:32 -0400198
199 // Tint for the battery icons are handled in setupHost()
200 mBatteryRemainingIcon = findViewById(R.id.batteryRemainingIcon);
Evan Laird698839b2018-12-05 15:49:12 -0500201 // Don't need to worry about tuner settings for this icon
202 mBatteryRemainingIcon.setIgnoreTunerUpdates(true);
Evan Laird85ee4a32019-03-06 18:09:20 -0500203 // QS will always show the estimate, and BatteryMeterView handles the case where
204 // it's unavailable or charging
205 mBatteryRemainingIcon.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE);
Fabian Kozynskib1aee812019-04-04 14:17:48 -0400206 mRingerModeTextView.setSelected(true);
207 mNextAlarmTextView.setSelected(true);
Evan Lairdf435fd22019-02-15 13:35:45 -0500208 }
209
Amin Shaikh761c5662018-03-27 16:55:43 -0400210 private void updateStatusText() {
Beverlyb9826dd2018-04-12 15:02:45 -0400211 boolean changed = updateRingerStatus() || updateAlarmStatus();
212
213 if (changed) {
214 boolean alarmVisible = mNextAlarmTextView.getVisibility() == View.VISIBLE;
215 boolean ringerVisible = mRingerModeTextView.getVisibility() == View.VISIBLE;
216 mStatusSeparator.setVisibility(alarmVisible && ringerVisible ? View.VISIBLE
217 : View.GONE);
Beverlyb9826dd2018-04-12 15:02:45 -0400218 }
219 }
220
221 private boolean updateRingerStatus() {
222 boolean isOriginalVisible = mRingerModeTextView.getVisibility() == View.VISIBLE;
223 CharSequence originalRingerText = mRingerModeTextView.getText();
224
Amin Shaikh761c5662018-03-27 16:55:43 -0400225 boolean ringerVisible = false;
Beverlyb9826dd2018-04-12 15:02:45 -0400226 if (!ZenModeConfig.isZenOverridingRinger(mZenController.getZen(),
Beverlyff2df9b2018-10-10 16:54:10 -0400227 mZenController.getConsolidatedPolicy())) {
Beverlyb9826dd2018-04-12 15:02:45 -0400228 if (mRingerMode == AudioManager.RINGER_MODE_VIBRATE) {
Fabian Kozynskib1aee812019-04-04 14:17:48 -0400229 mRingerModeIcon.setImageResource(R.drawable.ic_volume_ringer_vibrate);
Beverlyb9826dd2018-04-12 15:02:45 -0400230 mRingerModeTextView.setText(R.string.qs_status_phone_vibrate);
231 ringerVisible = true;
232 } else if (mRingerMode == AudioManager.RINGER_MODE_SILENT) {
Fabian Kozynskib1aee812019-04-04 14:17:48 -0400233 mRingerModeIcon.setImageResource(R.drawable.ic_volume_ringer_mute);
Beverlyb9826dd2018-04-12 15:02:45 -0400234 mRingerModeTextView.setText(R.string.qs_status_phone_muted);
235 ringerVisible = true;
236 }
Amin Shaikh761c5662018-03-27 16:55:43 -0400237 }
238 mRingerModeIcon.setVisibility(ringerVisible ? View.VISIBLE : View.GONE);
239 mRingerModeTextView.setVisibility(ringerVisible ? View.VISIBLE : View.GONE);
Fabian Kozynskiceb057b2019-05-17 14:06:38 -0400240 mRingerContainer.setVisibility(ringerVisible ? View.VISIBLE : View.GONE);
Amin Shaikh761c5662018-03-27 16:55:43 -0400241
Beverlyb9826dd2018-04-12 15:02:45 -0400242 return isOriginalVisible != ringerVisible ||
243 !Objects.equals(originalRingerText, mRingerModeTextView.getText());
244 }
245
246 private boolean updateAlarmStatus() {
247 boolean isOriginalVisible = mNextAlarmTextView.getVisibility() == View.VISIBLE;
248 CharSequence originalAlarmText = mNextAlarmTextView.getText();
249
Amin Shaikh761c5662018-03-27 16:55:43 -0400250 boolean alarmVisible = false;
251 if (mNextAlarm != null) {
252 alarmVisible = true;
253 mNextAlarmTextView.setText(formatNextAlarm(mNextAlarm));
254 }
255 mNextAlarmIcon.setVisibility(alarmVisible ? View.VISIBLE : View.GONE);
256 mNextAlarmTextView.setVisibility(alarmVisible ? View.VISIBLE : View.GONE);
Fabian Kozynskiceb057b2019-05-17 14:06:38 -0400257 mNextAlarmContainer.setVisibility(alarmVisible ? View.VISIBLE : View.GONE);
Amin Shaikh761c5662018-03-27 16:55:43 -0400258
Beverlyb9826dd2018-04-12 15:02:45 -0400259 return isOriginalVisible != alarmVisible ||
260 !Objects.equals(originalAlarmText, mNextAlarmTextView.getText());
261 }
Amin Shaikh761c5662018-03-27 16:55:43 -0400262
Jason Monk824ffff2017-04-11 15:49:06 -0400263 private void applyDarkness(int id, Rect tintArea, float intensity, int color) {
264 View v = findViewById(id);
265 if (v instanceof DarkReceiver) {
266 ((DarkReceiver) v).onDarkChanged(tintArea, intensity, color);
267 }
268 }
269
Jason Monke5b770e2017-03-03 21:49:29 -0500270 @Override
271 protected void onConfigurationChanged(Configuration newConfig) {
272 super.onConfigurationChanged(newConfig);
273 updateResources();
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000274
275 // Update color schemes in landscape to use wallpaperTextColor
276 boolean shouldUseWallpaperTextColor =
277 newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE;
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000278 mClockView.useWallpaperTextColor(shouldUseWallpaperTextColor);
Jason Monke5b770e2017-03-03 21:49:29 -0500279 }
280
281 @Override
282 public void onRtlPropertiesChanged(int layoutDirection) {
283 super.onRtlPropertiesChanged(layoutDirection);
284 updateResources();
285 }
286
Evan Laird84b98952018-07-02 17:43:59 -0400287 /**
288 * The height of QQS should always be the status bar height + 128dp. This is normally easy, but
289 * when there is a notch involved the status bar can remain a fixed pixel size.
290 */
291 private void updateMinimumHeight() {
292 int sbHeight = mContext.getResources().getDimensionPixelSize(
293 com.android.internal.R.dimen.status_bar_height);
294 int qqsHeight = mContext.getResources().getDimensionPixelSize(
295 R.dimen.qs_quick_header_panel_height);
296
297 setMinimumHeight(sbHeight + qqsHeight);
298 }
299
Jason Monke5b770e2017-03-03 21:49:29 -0500300 private void updateResources() {
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000301 Resources resources = mContext.getResources();
Evan Laird84b98952018-07-02 17:43:59 -0400302 updateMinimumHeight();
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000303
304 // Update height for a few views, especially due to landscape mode restricting space.
Rohan Shahd3cf7562018-02-23 11:12:28 -0800305 mHeaderTextContainerView.getLayoutParams().height =
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000306 resources.getDimensionPixelSize(R.dimen.qs_header_tooltip_height);
Rohan Shahd3cf7562018-02-23 11:12:28 -0800307 mHeaderTextContainerView.setLayoutParams(mHeaderTextContainerView.getLayoutParams());
308
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000309 mSystemIconsView.getLayoutParams().height = resources.getDimensionPixelSize(
310 com.android.internal.R.dimen.quick_qs_offset_height);
311 mSystemIconsView.setLayoutParams(mSystemIconsView.getLayoutParams());
312
Evan Laird84b98952018-07-02 17:43:59 -0400313 FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
314 if (mQsDisabled) {
315 lp.height = resources.getDimensionPixelSize(
316 com.android.internal.R.dimen.quick_qs_offset_height);
317 } else {
318 lp.height = Math.max(getMinimumHeight(),
319 resources.getDimensionPixelSize(
Evan Lairdbf3794a2018-07-17 15:55:40 -0400320 com.android.internal.R.dimen.quick_qs_total_height));
Evan Laird84b98952018-07-02 17:43:59 -0400321 }
322
323 setLayoutParams(lp);
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000324
Rohan Shahd3cf7562018-02-23 11:12:28 -0800325 updateStatusIconAlphaAnimator();
326 updateHeaderTextContainerAlphaAnimator();
Evan Laird95896952018-01-22 19:30:05 -0500327 }
328
Rohan Shahd3cf7562018-02-23 11:12:28 -0800329 private void updateStatusIconAlphaAnimator() {
330 mStatusIconsAlphaAnimator = new TouchAnimator.Builder()
Fabian Kozynski0e8449f2019-03-14 15:03:48 -0400331 .addFloat(mQuickQsStatusIcons, "alpha", 1, 0, 0)
Evan Laird95896952018-01-22 19:30:05 -0500332 .build();
Jason Monke5b770e2017-03-03 21:49:29 -0500333 }
334
Rohan Shahd3cf7562018-02-23 11:12:28 -0800335 private void updateHeaderTextContainerAlphaAnimator() {
336 mHeaderTextContainerAlphaAnimator = new TouchAnimator.Builder()
Fabian Kozynski0e8449f2019-03-14 15:03:48 -0400337 .addFloat(mHeaderTextContainerView, "alpha", 0, 0, 1)
Rohan Shahd3cf7562018-02-23 11:12:28 -0800338 .build();
Jason Monke5b770e2017-03-03 21:49:29 -0500339 }
340
341 public void setExpanded(boolean expanded) {
342 if (mExpanded == expanded) return;
343 mExpanded = expanded;
344 mHeaderQsPanel.setExpanded(expanded);
Fabian Kozynskif3a77012019-01-09 15:37:30 +0000345 updateEverything();
Jason Monke5b770e2017-03-03 21:49:29 -0500346 }
347
Rohan Shahd3cf7562018-02-23 11:12:28 -0800348 /**
349 * Animates the inner contents based on the given expansion details.
350 *
Selim Cinekb0fada62019-06-17 19:03:59 -0700351 * @param forceExpanded whether we should show the state expanded forcibly
Rohan Shahd3cf7562018-02-23 11:12:28 -0800352 * @param expansionFraction how much the QS panel is expanded/pulled out (up to 1f)
353 * @param panelTranslationY how much the panel has physically moved down vertically (required
354 * for keyguard animations only)
355 */
Selim Cinekb0fada62019-06-17 19:03:59 -0700356 public void setExpansion(boolean forceExpanded, float expansionFraction,
Rohan Shahd3cf7562018-02-23 11:12:28 -0800357 float panelTranslationY) {
Selim Cinekb0fada62019-06-17 19:03:59 -0700358 final float keyguardExpansionFraction = forceExpanded ? 1f : expansionFraction;
Rohan Shahd3cf7562018-02-23 11:12:28 -0800359 if (mStatusIconsAlphaAnimator != null) {
360 mStatusIconsAlphaAnimator.setPosition(keyguardExpansionFraction);
Evan Laird95896952018-01-22 19:30:05 -0500361 }
Rohan Shahd3cf7562018-02-23 11:12:28 -0800362
Selim Cinekb0fada62019-06-17 19:03:59 -0700363 if (forceExpanded) {
Rohan Shahd3cf7562018-02-23 11:12:28 -0800364 // If the keyguard is showing, we want to offset the text so that it comes in at the
365 // same time as the panel as it slides down.
366 mHeaderTextContainerView.setTranslationY(panelTranslationY);
367 } else {
368 mHeaderTextContainerView.setTranslationY(0f);
369 }
370
371 if (mHeaderTextContainerAlphaAnimator != null) {
372 mHeaderTextContainerAlphaAnimator.setPosition(keyguardExpansionFraction);
Aran Ink7dd05dc2019-05-31 11:47:23 -0400373 if (keyguardExpansionFraction > 0) {
374 mHeaderTextContainerView.setVisibility(VISIBLE);
375 } else {
376 mHeaderTextContainerView.setVisibility(INVISIBLE);
377 }
Rohan Shahd3cf7562018-02-23 11:12:28 -0800378 }
Jason Monke5b770e2017-03-03 21:49:29 -0500379 }
380
Charles Hece2a7c02017-10-11 20:25:20 +0100381 public void disable(int state1, int state2, boolean animate) {
382 final boolean disabled = (state2 & DISABLE2_QUICK_SETTINGS) != 0;
383 if (disabled == mQsDisabled) return;
384 mQsDisabled = disabled;
385 mHeaderQsPanel.setDisabledByPolicy(disabled);
Amin Shaikhf09450b2018-04-06 17:32:45 -0400386 mHeaderTextContainerView.setVisibility(mQsDisabled ? View.GONE : View.VISIBLE);
387 mQuickQsStatusIcons.setVisibility(mQsDisabled ? View.GONE : View.VISIBLE);
388 updateResources();
Charles Hece2a7c02017-10-11 20:25:20 +0100389 }
390
391 @Override
392 public void onAttachedToWindow() {
Amin Shaikha59215a2018-04-23 08:52:38 -0400393 super.onAttachedToWindow();
Jason Monkea54e8a2018-12-20 10:01:48 -0500394 mStatusBarIconController.addIconGroup(mIconManager);
Adrian Roos13836052018-03-15 21:06:37 +0100395 requestApplyInsets();
396 }
397
398 @Override
399 public WindowInsets onApplyWindowInsets(WindowInsets insets) {
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500400 DisplayCutout cutout = insets.getDisplayCutout();
Adrian Roos13836052018-03-15 21:06:37 +0100401 Pair<Integer, Integer> padding = PhoneStatusBarView.cornerCutoutMargins(
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500402 cutout, getDisplay());
Adrian Roos13836052018-03-15 21:06:37 +0100403 if (padding == null) {
Amin Shaikh7d86b042018-04-16 16:00:12 -0400404 mSystemIconsView.setPaddingRelative(
405 getResources().getDimensionPixelSize(R.dimen.status_bar_padding_start), 0,
406 getResources().getDimensionPixelSize(R.dimen.status_bar_padding_end), 0);
Adrian Roos13836052018-03-15 21:06:37 +0100407 } else {
Amin Shaikh7d86b042018-04-16 16:00:12 -0400408 mSystemIconsView.setPadding(padding.first, 0, padding.second, 0);
409
Adrian Roos13836052018-03-15 21:06:37 +0100410 }
411 return super.onApplyWindowInsets(insets);
Charles Hece2a7c02017-10-11 20:25:20 +0100412 }
413
414 @Override
Jason Monke5b770e2017-03-03 21:49:29 -0500415 @VisibleForTesting
416 public void onDetachedFromWindow() {
417 setListening(false);
Jason Monkea54e8a2018-12-20 10:01:48 -0500418 mStatusBarIconController.removeIconGroup(mIconManager);
Jason Monke5b770e2017-03-03 21:49:29 -0500419 super.onDetachedFromWindow();
420 }
421
422 public void setListening(boolean listening) {
423 if (listening == mListening) {
424 return;
425 }
426 mHeaderQsPanel.setListening(listening);
427 mListening = listening;
Fabian Kozynski4e76d1f2019-02-25 16:30:04 -0500428 mCarrierGroup.setListening(mListening);
Rohan Shahd3cf7562018-02-23 11:12:28 -0800429
430 if (listening) {
Beverlyb9826dd2018-04-12 15:02:45 -0400431 mZenController.addCallback(this);
Rohan Shahd3cf7562018-02-23 11:12:28 -0800432 mAlarmController.addCallback(this);
Amin Shaikh761c5662018-03-27 16:55:43 -0400433 mContext.registerReceiver(mRingerReceiver,
434 new IntentFilter(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION));
Rohan Shahd3cf7562018-02-23 11:12:28 -0800435 } else {
Beverlyb9826dd2018-04-12 15:02:45 -0400436 mZenController.removeCallback(this);
Rohan Shahd3cf7562018-02-23 11:12:28 -0800437 mAlarmController.removeCallback(this);
Amin Shaikh761c5662018-03-27 16:55:43 -0400438 mContext.unregisterReceiver(mRingerReceiver);
Rohan Shahd3cf7562018-02-23 11:12:28 -0800439 }
Jason Monke5b770e2017-03-03 21:49:29 -0500440 }
441
Evan Laird95896952018-01-22 19:30:05 -0500442 @Override
443 public void onClick(View v) {
Fabian Kozynskif3db35c2019-04-24 14:37:35 -0400444 if (v == mClockView) {
Jason Monkea54e8a2018-12-20 10:01:48 -0500445 mActivityStarter.postStartActivityDismissingKeyguard(new Intent(
Fabian Kozynskif3db35c2019-04-24 14:37:35 -0400446 AlarmClock.ACTION_SHOW_ALARMS), 0);
Fabian Kozynski1bdb0b92019-04-26 10:25:30 -0400447 } else if (v == mNextAlarmContainer && mNextAlarmContainer.isVisibleToUser()) {
Fabian Kozynskia3544712019-04-25 17:05:21 -0400448 if (mNextAlarm.getShowIntent() != null) {
Fabian Kozynskif3db35c2019-04-24 14:37:35 -0400449 mActivityStarter.postStartActivityDismissingKeyguard(
Fabian Kozynskia3544712019-04-25 17:05:21 -0400450 mNextAlarm.getShowIntent());
Fabian Kozynskif3db35c2019-04-24 14:37:35 -0400451 } else {
Fabian Kozynskia3544712019-04-25 17:05:21 -0400452 Log.d(TAG, "No PendingIntent for next alarm. Using default intent");
Fabian Kozynskif3db35c2019-04-24 14:37:35 -0400453 mActivityStarter.postStartActivityDismissingKeyguard(new Intent(
454 AlarmClock.ACTION_SHOW_ALARMS), 0);
455 }
Fabian Kozynski1bdb0b92019-04-26 10:25:30 -0400456 } else if (v == mRingerContainer && mRingerContainer.isVisibleToUser()) {
Fabian Kozynskib1aee812019-04-04 14:17:48 -0400457 mActivityStarter.postStartActivityDismissingKeyguard(new Intent(
458 Settings.ACTION_SOUND_SETTINGS), 0);
Evan Laird95896952018-01-22 19:30:05 -0500459 }
460 }
461
Rohan Shahd3cf7562018-02-23 11:12:28 -0800462 @Override
463 public void onNextAlarmChanged(AlarmManager.AlarmClockInfo nextAlarm) {
Amin Shaikh761c5662018-03-27 16:55:43 -0400464 mNextAlarm = nextAlarm;
465 updateStatusText();
466 }
Rohan Shaha160ab12018-03-09 15:47:36 -0800467
Beverlyb9826dd2018-04-12 15:02:45 -0400468 @Override
469 public void onZenChanged(int zen) {
470 updateStatusText();
Beverlyb9826dd2018-04-12 15:02:45 -0400471 }
472
473 @Override
474 public void onConfigChanged(ZenModeConfig config) {
475 updateStatusText();
476 }
477
Fabian Kozynskif3a77012019-01-09 15:37:30 +0000478 public void updateEverything() {
Fabian Kozynski9a15b7c2019-01-10 11:13:27 -0500479 post(() -> setClickable(!mExpanded));
Fabian Kozynskif3a77012019-01-09 15:37:30 +0000480 }
481
Jason Monke5b770e2017-03-03 21:49:29 -0500482 public void setQSPanel(final QSPanel qsPanel) {
483 mQsPanel = qsPanel;
484 setupHost(qsPanel.getHost());
485 }
486
487 public void setupHost(final QSTileHost host) {
488 mHost = host;
489 //host.setHeaderView(mExpandIndicator);
490 mHeaderQsPanel.setQSPanelAndHeader(mQsPanel, this);
491 mHeaderQsPanel.setHost(host, null /* No customization in header */);
Evan Lairdef160f22018-01-29 14:08:45 -0500492
Evan Laird4bf21df2018-10-22 14:24:32 -0400493
494 Rect tintArea = new Rect(0, 0, 0, 0);
495 int colorForeground = Utils.getColorAttrDefaultColor(getContext(),
496 android.R.attr.colorForeground);
497 float intensity = getColorIntensity(colorForeground);
Fabian Kozynskif86df992019-04-22 14:23:47 -0400498 int fillColor = mDualToneHandler.getSingleColor(intensity);
Evan Laird4bf21df2018-10-22 14:24:32 -0400499 mBatteryRemainingIcon.onDarkChanged(tintArea, intensity, fillColor);
Jason Monke5b770e2017-03-03 21:49:29 -0500500 }
501
502 public void setCallback(Callback qsPanelCallback) {
503 mHeaderQsPanel.setCallback(qsPanelCallback);
504 }
Lucas Dupin1f7374a2018-02-26 18:08:33 -0800505
506 private String formatNextAlarm(AlarmManager.AlarmClockInfo info) {
507 if (info == null) {
508 return "";
509 }
510 String skeleton = android.text.format.DateFormat
511 .is24HourFormat(mContext, ActivityManager.getCurrentUser()) ? "EHm" : "Ehma";
512 String pattern = android.text.format.DateFormat
513 .getBestDateTimePattern(Locale.getDefault(), skeleton);
514 return android.text.format.DateFormat.format(pattern, info.getTriggerTime()).toString();
515 }
Amin Shaikh0e003312018-03-08 11:39:01 -0500516
517 public static float getColorIntensity(@ColorInt int color) {
518 return color == Color.WHITE ? 0 : 1;
519 }
Amin Shaikh50d2d1e2018-04-25 14:48:13 -0400520
521 public void setMargins(int sideMargins) {
522 for (int i = 0; i < getChildCount(); i++) {
523 View v = getChildAt(i);
Fabian Kozynskib1aee812019-04-04 14:17:48 -0400524 // Prevents these views from getting set a margin.
525 // The Icon views all have the same padding set in XML to be aligned.
Fabian Kozynskief124492018-11-02 11:02:11 -0400526 if (v == mSystemIconsView || v == mQuickQsStatusIcons || v == mHeaderQsPanel
Fabian Kozynskib1aee812019-04-04 14:17:48 -0400527 || v == mHeaderTextContainerView) {
Amin Shaikh50d2d1e2018-04-25 14:48:13 -0400528 continue;
529 }
530 RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) v.getLayoutParams();
531 lp.leftMargin = sideMargins;
532 lp.rightMargin = sideMargins;
533 }
534 }
Jason Monke5b770e2017-03-03 21:49:29 -0500535}