blob: 4862b9eddc85167f32331e779049c1ec12884809 [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
Rohan Shahd3cf7562018-02-23 11:12:28 -080021import android.animation.Animator;
22import android.animation.AnimatorListenerAdapter;
Amin Shaikh0e003312018-03-08 11:39:01 -050023import android.annotation.ColorInt;
Lucas Dupin1f7374a2018-02-26 18:08:33 -080024import android.app.ActivityManager;
Rohan Shahd3cf7562018-02-23 11:12:28 -080025import android.app.AlarmManager;
Fabian Kozynski12638242018-10-12 15:33:41 -040026import android.app.Dialog;
Amin Shaikh761c5662018-03-27 16:55:43 -040027import android.content.BroadcastReceiver;
Jason Monke5b770e2017-03-03 21:49:29 -050028import android.content.Context;
Evan Laird4ea2a492018-01-22 11:29:12 -050029import android.content.Intent;
Amin Shaikh761c5662018-03-27 16:55:43 -040030import android.content.IntentFilter;
Jason Monke5b770e2017-03-03 21:49:29 -050031import android.content.res.Configuration;
Rohan Shahcc3d1d82018-03-30 21:24:17 +000032import android.content.res.Resources;
Jason Monke5b770e2017-03-03 21:49:29 -050033import android.graphics.Color;
34import android.graphics.Rect;
Amin Shaikh761c5662018-03-27 16:55:43 -040035import android.media.AudioManager;
Rohan Shahd3cf7562018-02-23 11:12:28 -080036import android.os.Handler;
Fabian Kozynski12638242018-10-12 15:33:41 -040037import android.os.Looper;
Evan Laird4ea2a492018-01-22 11:29:12 -050038import android.provider.AlarmClock;
Beverlyb9826dd2018-04-12 15:02:45 -040039import android.service.notification.ZenModeConfig;
Rohan Shahd3cf7562018-02-23 11:12:28 -080040import android.text.format.DateUtils;
Jason Monke5b770e2017-03-03 21:49:29 -050041import android.util.AttributeSet;
Rohan Shaha160ab12018-03-09 15:47:36 -080042import android.util.Log;
Adrian Roos13836052018-03-15 21:06:37 +010043import android.util.Pair;
Fabian Kozynskibfd6d852019-02-15 15:08:16 -050044import android.util.StatsLog;
Fabian Kozynski8d06c712018-11-07 10:33:02 -050045import android.view.DisplayCutout;
Jason Monk824ffff2017-04-11 15:49:06 -040046import android.view.View;
Adrian Roos13836052018-03-15 21:06:37 +010047import android.view.WindowInsets;
Beverlyff2df9b2018-10-10 16:54:10 -040048import android.widget.FrameLayout;
Amin Shaikh761c5662018-03-27 16:55:43 -040049import android.widget.ImageView;
Fabian Kozynski8d06c712018-11-07 10:33:02 -050050import android.widget.LinearLayout;
Jason Monke5b770e2017-03-03 21:49:29 -050051import android.widget.RelativeLayout;
Fabian Kozynski8d06c712018-11-07 10:33:02 -050052import android.widget.Space;
Rohan Shahd3cf7562018-02-23 11:12:28 -080053import android.widget.TextView;
Jason Monke5b770e2017-03-03 21:49:29 -050054
Beverlyff2df9b2018-10-10 16:54:10 -040055import androidx.annotation.VisibleForTesting;
56
Jason Monke5b770e2017-03-03 21:49:29 -050057import com.android.settingslib.Utils;
58import com.android.systemui.BatteryMeterView;
Rohan Shahd3cf7562018-02-23 11:12:28 -080059import com.android.systemui.Prefs;
Jason Monke5b770e2017-03-03 21:49:29 -050060import com.android.systemui.R;
61import com.android.systemui.plugins.ActivityStarter;
Beverly1be62f42018-12-19 17:17:48 -050062import com.android.systemui.plugins.DarkIconDispatcher;
63import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
Fabian Kozynski12638242018-10-12 15:33:41 -040064import com.android.systemui.privacy.OngoingPrivacyChip;
65import com.android.systemui.privacy.OngoingPrivacyDialog;
Fabian Kozynskiafd50022019-02-05 09:41:42 -050066import com.android.systemui.privacy.PrivacyDialogBuilder;
Fabian Kozynski8d06c712018-11-07 10:33:02 -050067import com.android.systemui.privacy.PrivacyItem;
68import com.android.systemui.privacy.PrivacyItemController;
Jason Monke5b770e2017-03-03 21:49:29 -050069import com.android.systemui.qs.QSDetail.Callback;
Adrian Roos13836052018-03-15 21:06:37 +010070import com.android.systemui.statusbar.phone.PhoneStatusBarView;
Evan Laird95896952018-01-22 19:30:05 -050071import com.android.systemui.statusbar.phone.StatusBarIconController;
72import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager;
Evan Laird20b87bf2018-04-12 09:54:11 -040073import com.android.systemui.statusbar.phone.StatusIconContainer;
Fabian Kozynski12638242018-10-12 15:33:41 -040074import com.android.systemui.statusbar.phone.SystemUIDialog;
Beverlyff2df9b2018-10-10 16:54:10 -040075import com.android.systemui.statusbar.policy.Clock;
Rohan Shahcc3d1d82018-03-30 21:24:17 +000076import com.android.systemui.statusbar.policy.DateView;
Rohan Shahd3cf7562018-02-23 11:12:28 -080077import com.android.systemui.statusbar.policy.NextAlarmController;
Beverlyb9826dd2018-04-12 15:02:45 -040078import com.android.systemui.statusbar.policy.ZenModeController;
Jason Monke5b770e2017-03-03 21:49:29 -050079
Evan Lairdf435fd22019-02-15 13:35:45 -050080import java.util.ArrayList;
Fabian Kozynski8d06c712018-11-07 10:33:02 -050081import java.util.List;
Lucas Dupin1f7374a2018-02-26 18:08:33 -080082import java.util.Locale;
Beverlyb9826dd2018-04-12 15:02:45 -040083import java.util.Objects;
Lucas Dupin1f7374a2018-02-26 18:08:33 -080084
Jason Monkea54e8a2018-12-20 10:01:48 -050085import javax.inject.Inject;
86import javax.inject.Named;
87
Rohan Shahd3cf7562018-02-23 11:12:28 -080088/**
89 * View that contains the top-most bits of the screen (primarily the status bar with date, time, and
90 * battery) and also contains the {@link QuickQSPanel} along with some of the panel's inner
91 * contents.
92 */
Amin Shaikhf09450b2018-04-06 17:32:45 -040093public class QuickStatusBarHeader extends RelativeLayout implements
Beverlyb9826dd2018-04-12 15:02:45 -040094 View.OnClickListener, NextAlarmController.NextAlarmChangeCallback,
95 ZenModeController.Callback {
Rohan Shaha160ab12018-03-09 15:47:36 -080096 private static final String TAG = "QuickStatusBarHeader";
97 private static final boolean DEBUG = false;
Jason Monke5b770e2017-03-03 21:49:29 -050098
Rohan Shahd3cf7562018-02-23 11:12:28 -080099 /** Delay for auto fading out the long press tooltip after it's fully visible (in ms). */
100 private static final long AUTO_FADE_OUT_DELAY_MS = DateUtils.SECOND_IN_MILLIS * 6;
101 private static final int FADE_ANIMATION_DURATION_MS = 300;
102 private static final int TOOLTIP_NOT_YET_SHOWN_COUNT = 0;
Rohan Shahb6a915c2018-03-01 11:57:00 -0800103 public static final int MAX_TOOLTIP_SHOWN_COUNT = 2;
Rohan Shahd3cf7562018-02-23 11:12:28 -0800104
105 private final Handler mHandler = new Handler();
Jason Monkea54e8a2018-12-20 10:01:48 -0500106 private final NextAlarmController mAlarmController;
107 private final ZenModeController mZenController;
108 private final StatusBarIconController mStatusBarIconController;
109 private final ActivityStarter mActivityStarter;
Jason Monke5b770e2017-03-03 21:49:29 -0500110
111 private QSPanel mQsPanel;
112
113 private boolean mExpanded;
114 private boolean mListening;
Charles Hece2a7c02017-10-11 20:25:20 +0100115 private boolean mQsDisabled;
Jason Monke5b770e2017-03-03 21:49:29 -0500116
Fabian Kozynski4e76d1f2019-02-25 16:30:04 -0500117 private QSCarrierGroup mCarrierGroup;
Jason Monke5b770e2017-03-03 21:49:29 -0500118 protected QuickQSPanel mHeaderQsPanel;
119 protected QSTileHost mHost;
Evan Laird95896952018-01-22 19:30:05 -0500120 private TintedIconManager mIconManager;
Rohan Shahd3cf7562018-02-23 11:12:28 -0800121 private TouchAnimator mStatusIconsAlphaAnimator;
122 private TouchAnimator mHeaderTextContainerAlphaAnimator;
Fabian Kozynski216812e2019-02-01 13:49:00 -0500123 private TouchAnimator mPrivacyChipAlphaAnimator;
Evan Laird95896952018-01-22 19:30:05 -0500124
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000125 private View mSystemIconsView;
Evan Laird95896952018-01-22 19:30:05 -0500126 private View mQuickQsStatusIcons;
Rohan Shahd3cf7562018-02-23 11:12:28 -0800127 private View mHeaderTextContainerView;
Amin Shaikh761c5662018-03-27 16:55:43 -0400128 /** View containing the next alarm and ringer mode info. */
129 private View mStatusContainer;
Rohan Shahd3cf7562018-02-23 11:12:28 -0800130 /** Tooltip for educating users that they can long press on icons to see more details. */
131 private View mLongPressTooltipView;
Amin Shaikh761c5662018-03-27 16:55:43 -0400132
133 private int mRingerMode = AudioManager.RINGER_MODE_NORMAL;
134 private AlarmManager.AlarmClockInfo mNextAlarm;
135
136 private ImageView mNextAlarmIcon;
Rohan Shahd3cf7562018-02-23 11:12:28 -0800137 /** {@link TextView} containing the actual text indicating when the next alarm will go off. */
138 private TextView mNextAlarmTextView;
Amin Shaikh761c5662018-03-27 16:55:43 -0400139 private View mStatusSeparator;
140 private ImageView mRingerModeIcon;
141 private TextView mRingerModeTextView;
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000142 private Clock mClockView;
143 private DateView mDateView;
Fabian Kozynski12638242018-10-12 15:33:41 -0400144 private OngoingPrivacyChip mPrivacyChip;
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500145 private Space mSpace;
Evan Laird4bf21df2018-10-22 14:24:32 -0400146 private BatteryMeterView mBatteryRemainingIcon;
Rohan Shahd3cf7562018-02-23 11:12:28 -0800147
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500148 private PrivacyItemController mPrivacyItemController;
Rohan Shahd3cf7562018-02-23 11:12:28 -0800149 /** Counts how many times the long press tooltip has been shown to the user. */
150 private int mShownCount;
151
Amin Shaikh761c5662018-03-27 16:55:43 -0400152 private final BroadcastReceiver mRingerReceiver = new BroadcastReceiver() {
153 @Override
154 public void onReceive(Context context, Intent intent) {
155 mRingerMode = intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1);
156 updateStatusText();
157 }
158 };
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500159 private boolean mHasTopCutout = false;
Fabian Kozynskibfd6d852019-02-15 15:08:16 -0500160 private boolean mPrivacyChipLogged = false;
Amin Shaikh761c5662018-03-27 16:55:43 -0400161
Rohan Shahd3cf7562018-02-23 11:12:28 -0800162 /**
163 * Runnable for automatically fading out the long press tooltip (as if it were animating away).
164 */
165 private final Runnable mAutoFadeOutTooltipRunnable = () -> hideLongPressTooltip(false);
Evan Laird4ea2a492018-01-22 11:29:12 -0500166
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500167 private PrivacyItemController.Callback mPICCallback = new PrivacyItemController.Callback() {
168 @Override
169 public void privacyChanged(List<PrivacyItem> privacyItems) {
170 mPrivacyChip.setPrivacyList(privacyItems);
171 setChipVisibility(!privacyItems.isEmpty());
172 }
173 };
174
Jason Monkea54e8a2018-12-20 10:01:48 -0500175 @Inject
176 public QuickStatusBarHeader(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
177 NextAlarmController nextAlarmController, ZenModeController zenModeController,
Evan Laird85ee4a32019-03-06 18:09:20 -0500178 StatusBarIconController statusBarIconController,
Fabian Kozynski04f83eb2019-01-22 10:38:40 -0500179 ActivityStarter activityStarter, PrivacyItemController privacyItemController) {
Jason Monke5b770e2017-03-03 21:49:29 -0500180 super(context, attrs);
Jason Monkea54e8a2018-12-20 10:01:48 -0500181 mAlarmController = nextAlarmController;
182 mZenController = zenModeController;
Jason Monkea54e8a2018-12-20 10:01:48 -0500183 mStatusBarIconController = statusBarIconController;
184 mActivityStarter = activityStarter;
Fabian Kozynski04f83eb2019-01-22 10:38:40 -0500185 mPrivacyItemController = privacyItemController;
Rohan Shahd3cf7562018-02-23 11:12:28 -0800186 mShownCount = getStoredShownCount();
Jason Monke5b770e2017-03-03 21:49:29 -0500187 }
188
189 @Override
190 protected void onFinishInflate() {
191 super.onFinishInflate();
Jason Monke5b770e2017-03-03 21:49:29 -0500192
193 mHeaderQsPanel = findViewById(R.id.quick_qs_panel);
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000194 mSystemIconsView = findViewById(R.id.quick_status_bar_system_icons);
Evan Laird95896952018-01-22 19:30:05 -0500195 mQuickQsStatusIcons = findViewById(R.id.quick_qs_status_icons);
Evan Laird20b87bf2018-04-12 09:54:11 -0400196 StatusIconContainer iconContainer = findViewById(R.id.statusIcons);
Evan Lairdf435fd22019-02-15 13:35:45 -0500197 // Ignore privacy icons because they show in the space above QQS
198 iconContainer.addIgnoredSlots(getIgnoredIconSlots());
Evan Laird20b87bf2018-04-12 09:54:11 -0400199 iconContainer.setShouldRestrictIcons(false);
200 mIconManager = new TintedIconManager(iconContainer);
Jason Monke5b770e2017-03-03 21:49:29 -0500201
Rohan Shahd3cf7562018-02-23 11:12:28 -0800202 // Views corresponding to the header info section (e.g. tooltip and next alarm).
203 mHeaderTextContainerView = findViewById(R.id.header_text_container);
204 mLongPressTooltipView = findViewById(R.id.long_press_tooltip);
Amin Shaikh761c5662018-03-27 16:55:43 -0400205 mStatusContainer = findViewById(R.id.status_container);
206 mStatusSeparator = findViewById(R.id.status_separator);
207 mNextAlarmIcon = findViewById(R.id.next_alarm_icon);
Rohan Shahd3cf7562018-02-23 11:12:28 -0800208 mNextAlarmTextView = findViewById(R.id.next_alarm_text);
Amin Shaikh761c5662018-03-27 16:55:43 -0400209 mRingerModeIcon = findViewById(R.id.ringer_mode_icon);
210 mRingerModeTextView = findViewById(R.id.ringer_mode_text);
Fabian Kozynski216812e2019-02-01 13:49:00 -0500211 mPrivacyChip = findViewById(R.id.privacy_chip);
212 mPrivacyChip.setOnClickListener(this);
Fabian Kozynski4e76d1f2019-02-25 16:30:04 -0500213 mCarrierGroup = findViewById(R.id.carrier_group);
Jason Monke5b770e2017-03-03 21:49:29 -0500214
Fabian Kozynskibfd6d852019-02-15 15:08:16 -0500215
Jason Monke5b770e2017-03-03 21:49:29 -0500216 updateResources();
217
Jason Monk824ffff2017-04-11 15:49:06 -0400218 Rect tintArea = new Rect(0, 0, 0, 0);
Jason Changb4e879d2018-04-11 11:17:58 +0800219 int colorForeground = Utils.getColorAttrDefaultColor(getContext(),
220 android.R.attr.colorForeground);
Amin Shaikh0e003312018-03-08 11:39:01 -0500221 float intensity = getColorIntensity(colorForeground);
Evan Laird95896952018-01-22 19:30:05 -0500222 int fillColor = fillColorForIntensity(intensity, getContext());
223
224 // Set light text on the header icons because they will always be on a black background
Evan Laird39254d42018-01-18 16:05:30 -0500225 applyDarkness(R.id.clock, tintArea, 0, DarkIconDispatcher.DEFAULT_ICON_TINT);
Evan Laird95896952018-01-22 19:30:05 -0500226
227 // Set the correct tint for the status icons so they contrast
228 mIconManager.setTint(fillColor);
Jason Monke5b770e2017-03-03 21:49:29 -0500229
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000230 mClockView = findViewById(R.id.clock);
Amin Shaikh39bdc502018-05-15 23:43:34 -0400231 mClockView.setOnClickListener(this);
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000232 mDateView = findViewById(R.id.date);
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500233 mSpace = findViewById(R.id.space);
Evan Laird4bf21df2018-10-22 14:24:32 -0400234
235 // Tint for the battery icons are handled in setupHost()
236 mBatteryRemainingIcon = findViewById(R.id.batteryRemainingIcon);
Evan Laird698839b2018-12-05 15:49:12 -0500237 // Don't need to worry about tuner settings for this icon
238 mBatteryRemainingIcon.setIgnoreTunerUpdates(true);
Evan Laird85ee4a32019-03-06 18:09:20 -0500239 // QS will always show the estimate, and BatteryMeterView handles the case where
240 // it's unavailable or charging
241 mBatteryRemainingIcon.setPercentShowMode(BatteryMeterView.MODE_ESTIMATE);
Jason Monke5b770e2017-03-03 21:49:29 -0500242 }
243
Evan Lairdf435fd22019-02-15 13:35:45 -0500244 private List<String> getIgnoredIconSlots() {
245 ArrayList<String> ignored = new ArrayList<>();
246 ignored.add(mContext.getResources().getString(
247 com.android.internal.R.string.status_bar_camera));
248 ignored.add(mContext.getResources().getString(
249 com.android.internal.R.string.status_bar_microphone));
250 ignored.add(mContext.getResources().getString(
251 com.android.internal.R.string.status_bar_location));
252
253 return ignored;
254 }
255
Amin Shaikh761c5662018-03-27 16:55:43 -0400256 private void updateStatusText() {
Beverlyb9826dd2018-04-12 15:02:45 -0400257 boolean changed = updateRingerStatus() || updateAlarmStatus();
258
259 if (changed) {
260 boolean alarmVisible = mNextAlarmTextView.getVisibility() == View.VISIBLE;
261 boolean ringerVisible = mRingerModeTextView.getVisibility() == View.VISIBLE;
262 mStatusSeparator.setVisibility(alarmVisible && ringerVisible ? View.VISIBLE
263 : View.GONE);
264 updateTooltipShow();
265 }
266 }
267
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500268 private void setChipVisibility(boolean chipVisible) {
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500269 if (chipVisible) {
270 mPrivacyChip.setVisibility(View.VISIBLE);
Fabian Kozynskibfd6d852019-02-15 15:08:16 -0500271 // Makes sure that the chip is logged as viewed at most once each time QS is opened
272 // mListening makes sure that the callback didn't return after the user closed QS
273 if (!mPrivacyChipLogged && mListening) {
274 mPrivacyChipLogged = true;
275 StatsLog.write(StatsLog.PRIVACY_INDICATORS_INTERACTED,
276 StatsLog.PRIVACY_INDICATORS_INTERACTED__TYPE__CHIP_VIEWED);
277 }
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500278 } else {
279 mPrivacyChip.setVisibility(View.GONE);
280 }
281 }
282
Beverlyb9826dd2018-04-12 15:02:45 -0400283 private boolean updateRingerStatus() {
284 boolean isOriginalVisible = mRingerModeTextView.getVisibility() == View.VISIBLE;
285 CharSequence originalRingerText = mRingerModeTextView.getText();
286
Amin Shaikh761c5662018-03-27 16:55:43 -0400287 boolean ringerVisible = false;
Beverlyb9826dd2018-04-12 15:02:45 -0400288 if (!ZenModeConfig.isZenOverridingRinger(mZenController.getZen(),
Beverlyff2df9b2018-10-10 16:54:10 -0400289 mZenController.getConsolidatedPolicy())) {
Beverlyb9826dd2018-04-12 15:02:45 -0400290 if (mRingerMode == AudioManager.RINGER_MODE_VIBRATE) {
291 mRingerModeIcon.setImageResource(R.drawable.stat_sys_ringer_vibrate);
292 mRingerModeTextView.setText(R.string.qs_status_phone_vibrate);
293 ringerVisible = true;
294 } else if (mRingerMode == AudioManager.RINGER_MODE_SILENT) {
295 mRingerModeIcon.setImageResource(R.drawable.stat_sys_ringer_silent);
296 mRingerModeTextView.setText(R.string.qs_status_phone_muted);
297 ringerVisible = true;
298 }
Amin Shaikh761c5662018-03-27 16:55:43 -0400299 }
300 mRingerModeIcon.setVisibility(ringerVisible ? View.VISIBLE : View.GONE);
301 mRingerModeTextView.setVisibility(ringerVisible ? View.VISIBLE : View.GONE);
302
Beverlyb9826dd2018-04-12 15:02:45 -0400303 return isOriginalVisible != ringerVisible ||
304 !Objects.equals(originalRingerText, mRingerModeTextView.getText());
305 }
306
307 private boolean updateAlarmStatus() {
308 boolean isOriginalVisible = mNextAlarmTextView.getVisibility() == View.VISIBLE;
309 CharSequence originalAlarmText = mNextAlarmTextView.getText();
310
Amin Shaikh761c5662018-03-27 16:55:43 -0400311 boolean alarmVisible = false;
312 if (mNextAlarm != null) {
313 alarmVisible = true;
314 mNextAlarmTextView.setText(formatNextAlarm(mNextAlarm));
315 }
316 mNextAlarmIcon.setVisibility(alarmVisible ? View.VISIBLE : View.GONE);
317 mNextAlarmTextView.setVisibility(alarmVisible ? View.VISIBLE : View.GONE);
Amin Shaikh761c5662018-03-27 16:55:43 -0400318
Beverlyb9826dd2018-04-12 15:02:45 -0400319 return isOriginalVisible != alarmVisible ||
320 !Objects.equals(originalAlarmText, mNextAlarmTextView.getText());
321 }
Amin Shaikh761c5662018-03-27 16:55:43 -0400322
Jason Monk824ffff2017-04-11 15:49:06 -0400323 private void applyDarkness(int id, Rect tintArea, float intensity, int color) {
324 View v = findViewById(id);
325 if (v instanceof DarkReceiver) {
326 ((DarkReceiver) v).onDarkChanged(tintArea, intensity, color);
327 }
328 }
329
Evan Laird95896952018-01-22 19:30:05 -0500330 private int fillColorForIntensity(float intensity, Context context) {
331 if (intensity == 0) {
Amin Shaikh9cac3382018-04-11 17:10:07 -0400332 return context.getColor(R.color.light_mode_icon_color_single_tone);
Evan Laird95896952018-01-22 19:30:05 -0500333 }
Amin Shaikh9cac3382018-04-11 17:10:07 -0400334 return context.getColor(R.color.dark_mode_icon_color_single_tone);
Evan Laird95896952018-01-22 19:30:05 -0500335 }
336
Jason Monke5b770e2017-03-03 21:49:29 -0500337 @Override
338 protected void onConfigurationChanged(Configuration newConfig) {
339 super.onConfigurationChanged(newConfig);
340 updateResources();
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000341
342 // Update color schemes in landscape to use wallpaperTextColor
343 boolean shouldUseWallpaperTextColor =
344 newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE;
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000345 mClockView.useWallpaperTextColor(shouldUseWallpaperTextColor);
Jason Monke5b770e2017-03-03 21:49:29 -0500346 }
347
Fabian Kozynskief124492018-11-02 11:02:11 -0400348
349
Jason Monke5b770e2017-03-03 21:49:29 -0500350 @Override
351 public void onRtlPropertiesChanged(int layoutDirection) {
352 super.onRtlPropertiesChanged(layoutDirection);
353 updateResources();
354 }
355
Evan Laird84b98952018-07-02 17:43:59 -0400356 /**
357 * The height of QQS should always be the status bar height + 128dp. This is normally easy, but
358 * when there is a notch involved the status bar can remain a fixed pixel size.
359 */
360 private void updateMinimumHeight() {
361 int sbHeight = mContext.getResources().getDimensionPixelSize(
362 com.android.internal.R.dimen.status_bar_height);
363 int qqsHeight = mContext.getResources().getDimensionPixelSize(
364 R.dimen.qs_quick_header_panel_height);
365
366 setMinimumHeight(sbHeight + qqsHeight);
367 }
368
Jason Monke5b770e2017-03-03 21:49:29 -0500369 private void updateResources() {
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000370 Resources resources = mContext.getResources();
Evan Laird84b98952018-07-02 17:43:59 -0400371 updateMinimumHeight();
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000372
373 // Update height for a few views, especially due to landscape mode restricting space.
Rohan Shahd3cf7562018-02-23 11:12:28 -0800374 mHeaderTextContainerView.getLayoutParams().height =
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000375 resources.getDimensionPixelSize(R.dimen.qs_header_tooltip_height);
Rohan Shahd3cf7562018-02-23 11:12:28 -0800376 mHeaderTextContainerView.setLayoutParams(mHeaderTextContainerView.getLayoutParams());
377
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000378 mSystemIconsView.getLayoutParams().height = resources.getDimensionPixelSize(
379 com.android.internal.R.dimen.quick_qs_offset_height);
380 mSystemIconsView.setLayoutParams(mSystemIconsView.getLayoutParams());
381
Evan Laird84b98952018-07-02 17:43:59 -0400382 FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
383 if (mQsDisabled) {
384 lp.height = resources.getDimensionPixelSize(
385 com.android.internal.R.dimen.quick_qs_offset_height);
386 } else {
387 lp.height = Math.max(getMinimumHeight(),
388 resources.getDimensionPixelSize(
Evan Lairdbf3794a2018-07-17 15:55:40 -0400389 com.android.internal.R.dimen.quick_qs_total_height));
Evan Laird84b98952018-07-02 17:43:59 -0400390 }
391
392 setLayoutParams(lp);
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000393
Rohan Shahd3cf7562018-02-23 11:12:28 -0800394 updateStatusIconAlphaAnimator();
395 updateHeaderTextContainerAlphaAnimator();
Fabian Kozynski216812e2019-02-01 13:49:00 -0500396 updatePrivacyChipAlphaAnimator();
Evan Laird95896952018-01-22 19:30:05 -0500397 }
398
Rohan Shahd3cf7562018-02-23 11:12:28 -0800399 private void updateStatusIconAlphaAnimator() {
400 mStatusIconsAlphaAnimator = new TouchAnimator.Builder()
Evan Laird95896952018-01-22 19:30:05 -0500401 .addFloat(mQuickQsStatusIcons, "alpha", 1, 0)
402 .build();
Jason Monke5b770e2017-03-03 21:49:29 -0500403 }
404
Rohan Shahd3cf7562018-02-23 11:12:28 -0800405 private void updateHeaderTextContainerAlphaAnimator() {
406 mHeaderTextContainerAlphaAnimator = new TouchAnimator.Builder()
407 .addFloat(mHeaderTextContainerView, "alpha", 0, 1)
408 .setStartDelay(.5f)
409 .build();
Jason Monke5b770e2017-03-03 21:49:29 -0500410 }
411
Fabian Kozynski216812e2019-02-01 13:49:00 -0500412 private void updatePrivacyChipAlphaAnimator() {
413 mPrivacyChipAlphaAnimator = new TouchAnimator.Builder()
414 .addFloat(mPrivacyChip, "alpha", 1, 0, 1)
415 .build();
416 }
417
Jason Monke5b770e2017-03-03 21:49:29 -0500418 public void setExpanded(boolean expanded) {
419 if (mExpanded == expanded) return;
420 mExpanded = expanded;
421 mHeaderQsPanel.setExpanded(expanded);
Fabian Kozynskif3a77012019-01-09 15:37:30 +0000422 updateEverything();
Jason Monke5b770e2017-03-03 21:49:29 -0500423 }
424
Rohan Shahd3cf7562018-02-23 11:12:28 -0800425 /**
426 * Animates the inner contents based on the given expansion details.
427 *
428 * @param isKeyguardShowing whether or not we're showing the keyguard (a.k.a. lockscreen)
429 * @param expansionFraction how much the QS panel is expanded/pulled out (up to 1f)
430 * @param panelTranslationY how much the panel has physically moved down vertically (required
431 * for keyguard animations only)
432 */
433 public void setExpansion(boolean isKeyguardShowing, float expansionFraction,
434 float panelTranslationY) {
435 final float keyguardExpansionFraction = isKeyguardShowing ? 1f : expansionFraction;
436 if (mStatusIconsAlphaAnimator != null) {
437 mStatusIconsAlphaAnimator.setPosition(keyguardExpansionFraction);
Evan Laird95896952018-01-22 19:30:05 -0500438 }
Rohan Shahd3cf7562018-02-23 11:12:28 -0800439
440 if (isKeyguardShowing) {
441 // If the keyguard is showing, we want to offset the text so that it comes in at the
442 // same time as the panel as it slides down.
443 mHeaderTextContainerView.setTranslationY(panelTranslationY);
444 } else {
445 mHeaderTextContainerView.setTranslationY(0f);
446 }
447
448 if (mHeaderTextContainerAlphaAnimator != null) {
449 mHeaderTextContainerAlphaAnimator.setPosition(keyguardExpansionFraction);
450 }
Fabian Kozynski216812e2019-02-01 13:49:00 -0500451 if (mPrivacyChipAlphaAnimator != null) {
452 mPrivacyChip.setExpanded(expansionFraction > 0.5);
453 mPrivacyChipAlphaAnimator.setPosition(keyguardExpansionFraction);
454 }
Rohan Shahd3cf7562018-02-23 11:12:28 -0800455
456 // Check the original expansion fraction - we don't want to show the tooltip until the
457 // panel is pulled all the way out.
458 if (expansionFraction == 1f) {
459 // QS is fully expanded, bring in the tooltip.
460 showLongPressTooltip();
461 }
462 }
463
464 /** Returns the latest stored tooltip shown count from SharedPreferences. */
465 private int getStoredShownCount() {
466 return Prefs.getInt(
467 mContext,
468 Prefs.Key.QS_LONG_PRESS_TOOLTIP_SHOWN_COUNT,
469 TOOLTIP_NOT_YET_SHOWN_COUNT);
Jason Monke5b770e2017-03-03 21:49:29 -0500470 }
471
Charles Hece2a7c02017-10-11 20:25:20 +0100472 public void disable(int state1, int state2, boolean animate) {
473 final boolean disabled = (state2 & DISABLE2_QUICK_SETTINGS) != 0;
474 if (disabled == mQsDisabled) return;
475 mQsDisabled = disabled;
476 mHeaderQsPanel.setDisabledByPolicy(disabled);
Amin Shaikhf09450b2018-04-06 17:32:45 -0400477 mHeaderTextContainerView.setVisibility(mQsDisabled ? View.GONE : View.VISIBLE);
478 mQuickQsStatusIcons.setVisibility(mQsDisabled ? View.GONE : View.VISIBLE);
479 updateResources();
Charles Hece2a7c02017-10-11 20:25:20 +0100480 }
481
482 @Override
483 public void onAttachedToWindow() {
Amin Shaikha59215a2018-04-23 08:52:38 -0400484 super.onAttachedToWindow();
Jason Monkea54e8a2018-12-20 10:01:48 -0500485 mStatusBarIconController.addIconGroup(mIconManager);
Adrian Roos13836052018-03-15 21:06:37 +0100486 requestApplyInsets();
487 }
488
489 @Override
490 public WindowInsets onApplyWindowInsets(WindowInsets insets) {
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500491 DisplayCutout cutout = insets.getDisplayCutout();
Adrian Roos13836052018-03-15 21:06:37 +0100492 Pair<Integer, Integer> padding = PhoneStatusBarView.cornerCutoutMargins(
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500493 cutout, getDisplay());
Adrian Roos13836052018-03-15 21:06:37 +0100494 if (padding == null) {
Amin Shaikh7d86b042018-04-16 16:00:12 -0400495 mSystemIconsView.setPaddingRelative(
496 getResources().getDimensionPixelSize(R.dimen.status_bar_padding_start), 0,
497 getResources().getDimensionPixelSize(R.dimen.status_bar_padding_end), 0);
Adrian Roos13836052018-03-15 21:06:37 +0100498 } else {
Amin Shaikh7d86b042018-04-16 16:00:12 -0400499 mSystemIconsView.setPadding(padding.first, 0, padding.second, 0);
500
Adrian Roos13836052018-03-15 21:06:37 +0100501 }
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500502 LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mSpace.getLayoutParams();
503 if (cutout != null) {
504 Rect topCutout = cutout.getBoundingRectTop();
505 if (topCutout.isEmpty()) {
506 mHasTopCutout = false;
507 lp.width = 0;
508 mSpace.setVisibility(View.GONE);
509 } else {
510 mHasTopCutout = true;
511 lp.width = topCutout.width();
512 mSpace.setVisibility(View.VISIBLE);
513 }
514 }
515 mSpace.setLayoutParams(lp);
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500516 setChipVisibility(mPrivacyChip.getVisibility() == View.VISIBLE);
Adrian Roos13836052018-03-15 21:06:37 +0100517 return super.onApplyWindowInsets(insets);
Charles Hece2a7c02017-10-11 20:25:20 +0100518 }
519
520 @Override
Jason Monke5b770e2017-03-03 21:49:29 -0500521 @VisibleForTesting
522 public void onDetachedFromWindow() {
523 setListening(false);
Jason Monkea54e8a2018-12-20 10:01:48 -0500524 mStatusBarIconController.removeIconGroup(mIconManager);
Jason Monke5b770e2017-03-03 21:49:29 -0500525 super.onDetachedFromWindow();
526 }
527
528 public void setListening(boolean listening) {
529 if (listening == mListening) {
530 return;
531 }
532 mHeaderQsPanel.setListening(listening);
533 mListening = listening;
Fabian Kozynski4e76d1f2019-02-25 16:30:04 -0500534 mCarrierGroup.setListening(mListening);
Rohan Shahd3cf7562018-02-23 11:12:28 -0800535
536 if (listening) {
Beverlyb9826dd2018-04-12 15:02:45 -0400537 mZenController.addCallback(this);
Rohan Shahd3cf7562018-02-23 11:12:28 -0800538 mAlarmController.addCallback(this);
Amin Shaikh761c5662018-03-27 16:55:43 -0400539 mContext.registerReceiver(mRingerReceiver,
540 new IntentFilter(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION));
Fabian Kozynski04f83eb2019-01-22 10:38:40 -0500541 mPrivacyItemController.addCallback(mPICCallback);
Rohan Shahd3cf7562018-02-23 11:12:28 -0800542 } else {
Beverlyb9826dd2018-04-12 15:02:45 -0400543 mZenController.removeCallback(this);
Rohan Shahd3cf7562018-02-23 11:12:28 -0800544 mAlarmController.removeCallback(this);
Fabian Kozynski04f83eb2019-01-22 10:38:40 -0500545 mPrivacyItemController.removeCallback(mPICCallback);
Amin Shaikh761c5662018-03-27 16:55:43 -0400546 mContext.unregisterReceiver(mRingerReceiver);
Fabian Kozynskibfd6d852019-02-15 15:08:16 -0500547 mPrivacyChipLogged = false;
Rohan Shahd3cf7562018-02-23 11:12:28 -0800548 }
Jason Monke5b770e2017-03-03 21:49:29 -0500549 }
550
Evan Laird95896952018-01-22 19:30:05 -0500551 @Override
552 public void onClick(View v) {
Amin Shaikh39bdc502018-05-15 23:43:34 -0400553 if (v == mClockView) {
Jason Monkea54e8a2018-12-20 10:01:48 -0500554 mActivityStarter.postStartActivityDismissingKeyguard(new Intent(
Evan Laird95896952018-01-22 19:30:05 -0500555 AlarmClock.ACTION_SHOW_ALARMS),0);
Fabian Kozynski12638242018-10-12 15:33:41 -0400556 } else if (v == mPrivacyChip) {
Fabian Kozynskiafd50022019-02-05 09:41:42 -0500557 // Makes sure that the builder is grabbed as soon as the chip is pressed
558 PrivacyDialogBuilder builder = mPrivacyChip.getBuilder();
559 if (builder.getAppsAndTypes().size() == 0) return;
Fabian Kozynski12638242018-10-12 15:33:41 -0400560 Handler mUiHandler = new Handler(Looper.getMainLooper());
Fabian Kozynskibfd6d852019-02-15 15:08:16 -0500561 StatsLog.write(StatsLog.PRIVACY_INDICATORS_INTERACTED,
562 StatsLog.PRIVACY_INDICATORS_INTERACTED__TYPE__CHIP_CLICKED);
Fabian Kozynski12638242018-10-12 15:33:41 -0400563 mUiHandler.post(() -> {
Fabian Kozynskiafd50022019-02-05 09:41:42 -0500564 Dialog mDialog = new OngoingPrivacyDialog(mContext, builder).createDialog();
Fabian Kozynski8f3660e2019-02-11 11:02:11 -0500565 SystemUIDialog.setShowForAllUsers(mDialog, false);
Fabian Kozynski12638242018-10-12 15:33:41 -0400566 SystemUIDialog.registerDismissListener(mDialog);
567 SystemUIDialog.setWindowOnTop(mDialog);
Fabian Kozynski8f3660e2019-02-11 11:02:11 -0500568 mActivityStarter.postQSRunnableDismissingKeyguard(() -> mDialog.show());
Fabian Kozynski12638242018-10-12 15:33:41 -0400569 mHost.collapsePanels();
570 });
Evan Laird95896952018-01-22 19:30:05 -0500571 }
572 }
573
Rohan Shahd3cf7562018-02-23 11:12:28 -0800574 @Override
575 public void onNextAlarmChanged(AlarmManager.AlarmClockInfo nextAlarm) {
Amin Shaikh761c5662018-03-27 16:55:43 -0400576 mNextAlarm = nextAlarm;
577 updateStatusText();
578 }
Rohan Shaha160ab12018-03-09 15:47:36 -0800579
Beverlyb9826dd2018-04-12 15:02:45 -0400580 @Override
581 public void onZenChanged(int zen) {
582 updateStatusText();
583
584 }
585
586 @Override
587 public void onConfigChanged(ZenModeConfig config) {
588 updateStatusText();
589 }
590
Amin Shaikh761c5662018-03-27 16:55:43 -0400591 private void updateTooltipShow() {
592 if (hasStatusText()) {
593 hideLongPressTooltip(true /* shouldShowStatusText */);
Rohan Shahd3cf7562018-02-23 11:12:28 -0800594 } else {
Amin Shaikh761c5662018-03-27 16:55:43 -0400595 hideStatusText();
Rohan Shahd3cf7562018-02-23 11:12:28 -0800596 }
597 updateHeaderTextContainerAlphaAnimator();
598 }
599
Amin Shaikh761c5662018-03-27 16:55:43 -0400600 private boolean hasStatusText() {
601 return mNextAlarmTextView.getVisibility() == View.VISIBLE
602 || mRingerModeTextView.getVisibility() == View.VISIBLE;
603 }
604
Rohan Shahd3cf7562018-02-23 11:12:28 -0800605 /**
606 * Animates in the long press tooltip (as long as the next alarm text isn't currently occupying
607 * the space).
608 */
609 public void showLongPressTooltip() {
Amin Shaikh761c5662018-03-27 16:55:43 -0400610 // If we have status text to show, don't bother fading in the tooltip.
611 if (hasStatusText()) {
Rohan Shahd3cf7562018-02-23 11:12:28 -0800612 return;
613 }
614
615 if (mShownCount < MAX_TOOLTIP_SHOWN_COUNT) {
616 mLongPressTooltipView.animate().cancel();
617 mLongPressTooltipView.setVisibility(View.VISIBLE);
618 mLongPressTooltipView.animate()
619 .alpha(1f)
620 .setDuration(FADE_ANIMATION_DURATION_MS)
621 .setListener(new AnimatorListenerAdapter() {
622 @Override
623 public void onAnimationEnd(Animator animation) {
624 mHandler.postDelayed(
625 mAutoFadeOutTooltipRunnable, AUTO_FADE_OUT_DELAY_MS);
626 }
627 })
628 .start();
629
630 // Increment and drop the shown count in prefs for the next time we're deciding to
631 // fade in the tooltip. We first sanity check that the tooltip count hasn't changed yet
632 // in prefs (say, from a long press).
633 if (getStoredShownCount() <= mShownCount) {
634 Prefs.putInt(mContext, Prefs.Key.QS_LONG_PRESS_TOOLTIP_SHOWN_COUNT, ++mShownCount);
635 }
636 }
637 }
638
639 /**
640 * Fades out the long press tooltip if it's partially visible - short circuits any running
Amin Shaikh761c5662018-03-27 16:55:43 -0400641 * animation. Additionally has the ability to fade in the status info text.
Rohan Shahd3cf7562018-02-23 11:12:28 -0800642 *
Amin Shaikh761c5662018-03-27 16:55:43 -0400643 * @param shouldShowStatusText whether we should fade in the status text
Rohan Shahd3cf7562018-02-23 11:12:28 -0800644 */
Amin Shaikh761c5662018-03-27 16:55:43 -0400645 private void hideLongPressTooltip(boolean shouldShowStatusText) {
Rohan Shahd3cf7562018-02-23 11:12:28 -0800646 mLongPressTooltipView.animate().cancel();
647 if (mLongPressTooltipView.getVisibility() == View.VISIBLE
648 && mLongPressTooltipView.getAlpha() != 0f) {
649 mHandler.removeCallbacks(mAutoFadeOutTooltipRunnable);
650 mLongPressTooltipView.animate()
651 .alpha(0f)
652 .setDuration(FADE_ANIMATION_DURATION_MS)
653 .setListener(new AnimatorListenerAdapter() {
654 @Override
655 public void onAnimationEnd(Animator animation) {
Rohan Shaha160ab12018-03-09 15:47:36 -0800656 if (DEBUG) Log.d(TAG, "hideLongPressTooltip: Hid long press tip");
Rohan Shahd3cf7562018-02-23 11:12:28 -0800657 mLongPressTooltipView.setVisibility(View.INVISIBLE);
658
Amin Shaikh761c5662018-03-27 16:55:43 -0400659 if (shouldShowStatusText) {
660 showStatus();
Rohan Shahd3cf7562018-02-23 11:12:28 -0800661 }
662 }
663 })
664 .start();
665 } else {
666 mLongPressTooltipView.setVisibility(View.INVISIBLE);
Amin Shaikh761c5662018-03-27 16:55:43 -0400667 if (shouldShowStatusText) {
668 showStatus();
Rohan Shahd3cf7562018-02-23 11:12:28 -0800669 }
670 }
671 }
672
673 /**
Amin Shaikh761c5662018-03-27 16:55:43 -0400674 * Fades in the updated status text. Note that if there's already a status showing, this will
Fabian Kozynski3f789332018-09-04 16:42:43 -0400675 * immediately fade it out and fade in the updated status.
Rohan Shahd3cf7562018-02-23 11:12:28 -0800676 */
Amin Shaikh761c5662018-03-27 16:55:43 -0400677 private void showStatus() {
678 mStatusContainer.setAlpha(0f);
Rohan Shahd3cf7562018-02-23 11:12:28 -0800679
Amin Shaikh761c5662018-03-27 16:55:43 -0400680 mStatusContainer.animate()
Rohan Shahd3cf7562018-02-23 11:12:28 -0800681 .alpha(1f)
682 .setDuration(FADE_ANIMATION_DURATION_MS)
683 .start();
684 }
685
Fabian Kozynski3f789332018-09-04 16:42:43 -0400686 /** Fades out the status text. */
Amin Shaikh761c5662018-03-27 16:55:43 -0400687 private void hideStatusText() {
Fabian Kozynski3f789332018-09-04 16:42:43 -0400688 mStatusContainer.animate()
689 .alpha(0f)
690 .setDuration(FADE_ANIMATION_DURATION_MS)
691 .start();
Rohan Shahd3cf7562018-02-23 11:12:28 -0800692 }
693
Fabian Kozynskif3a77012019-01-09 15:37:30 +0000694 public void updateEverything() {
Fabian Kozynski9a15b7c2019-01-10 11:13:27 -0500695 post(() -> setClickable(!mExpanded));
Fabian Kozynskif3a77012019-01-09 15:37:30 +0000696 }
697
Jason Monke5b770e2017-03-03 21:49:29 -0500698 public void setQSPanel(final QSPanel qsPanel) {
699 mQsPanel = qsPanel;
700 setupHost(qsPanel.getHost());
701 }
702
703 public void setupHost(final QSTileHost host) {
704 mHost = host;
705 //host.setHeaderView(mExpandIndicator);
706 mHeaderQsPanel.setQSPanelAndHeader(mQsPanel, this);
707 mHeaderQsPanel.setHost(host, null /* No customization in header */);
Evan Lairdef160f22018-01-29 14:08:45 -0500708
Evan Laird4bf21df2018-10-22 14:24:32 -0400709
710 Rect tintArea = new Rect(0, 0, 0, 0);
711 int colorForeground = Utils.getColorAttrDefaultColor(getContext(),
712 android.R.attr.colorForeground);
713 float intensity = getColorIntensity(colorForeground);
714 int fillColor = fillColorForIntensity(intensity, getContext());
715 mBatteryRemainingIcon.setColorsFromContext(mHost.getContext());
716 mBatteryRemainingIcon.onDarkChanged(tintArea, intensity, fillColor);
Jason Monke5b770e2017-03-03 21:49:29 -0500717 }
718
719 public void setCallback(Callback qsPanelCallback) {
720 mHeaderQsPanel.setCallback(qsPanelCallback);
721 }
Lucas Dupin1f7374a2018-02-26 18:08:33 -0800722
723 private String formatNextAlarm(AlarmManager.AlarmClockInfo info) {
724 if (info == null) {
725 return "";
726 }
727 String skeleton = android.text.format.DateFormat
728 .is24HourFormat(mContext, ActivityManager.getCurrentUser()) ? "EHm" : "Ehma";
729 String pattern = android.text.format.DateFormat
730 .getBestDateTimePattern(Locale.getDefault(), skeleton);
731 return android.text.format.DateFormat.format(pattern, info.getTriggerTime()).toString();
732 }
Amin Shaikh0e003312018-03-08 11:39:01 -0500733
734 public static float getColorIntensity(@ColorInt int color) {
735 return color == Color.WHITE ? 0 : 1;
736 }
Amin Shaikh50d2d1e2018-04-25 14:48:13 -0400737
738 public void setMargins(int sideMargins) {
739 for (int i = 0; i < getChildCount(); i++) {
740 View v = getChildAt(i);
Fabian Kozynskief124492018-11-02 11:02:11 -0400741 if (v == mSystemIconsView || v == mQuickQsStatusIcons || v == mHeaderQsPanel
742 || v == mPrivacyChip) {
Amin Shaikh50d2d1e2018-04-25 14:48:13 -0400743 continue;
744 }
745 RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) v.getLayoutParams();
746 lp.leftMargin = sideMargins;
747 lp.rightMargin = sideMargins;
748 }
749 }
Jason Monke5b770e2017-03-03 21:49:29 -0500750}