blob: 40c60396e40dd24813d82158880bf9e61fd4351e [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;
Evan Laird4bf21df2018-10-22 14:24:32 -040018import static android.provider.Settings.System.SHOW_BATTERY_PERCENT;
Charles Hece2a7c02017-10-11 20:25:20 +010019
Jason Monkea54e8a2018-12-20 10:01:48 -050020import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
21
Rohan Shahd3cf7562018-02-23 11:12:28 -080022import android.animation.Animator;
23import android.animation.AnimatorListenerAdapter;
Amin Shaikh0e003312018-03-08 11:39:01 -050024import android.annotation.ColorInt;
Lucas Dupin1f7374a2018-02-26 18:08:33 -080025import android.app.ActivityManager;
Rohan Shahd3cf7562018-02-23 11:12:28 -080026import android.app.AlarmManager;
Fabian Kozynski12638242018-10-12 15:33:41 -040027import android.app.Dialog;
Amin Shaikh761c5662018-03-27 16:55:43 -040028import android.content.BroadcastReceiver;
Jason Monke5b770e2017-03-03 21:49:29 -050029import android.content.Context;
Evan Laird4ea2a492018-01-22 11:29:12 -050030import android.content.Intent;
Amin Shaikh761c5662018-03-27 16:55:43 -040031import android.content.IntentFilter;
Jason Monke5b770e2017-03-03 21:49:29 -050032import android.content.res.Configuration;
Rohan Shahcc3d1d82018-03-30 21:24:17 +000033import android.content.res.Resources;
Evan Laird4bf21df2018-10-22 14:24:32 -040034import android.database.ContentObserver;
Jason Monke5b770e2017-03-03 21:49:29 -050035import android.graphics.Color;
36import android.graphics.Rect;
Amin Shaikh761c5662018-03-27 16:55:43 -040037import android.media.AudioManager;
Evan Laird4bf21df2018-10-22 14:24:32 -040038import android.net.Uri;
Rohan Shahd3cf7562018-02-23 11:12:28 -080039import android.os.Handler;
Fabian Kozynski12638242018-10-12 15:33:41 -040040import android.os.Looper;
Evan Laird4ea2a492018-01-22 11:29:12 -050041import android.provider.AlarmClock;
Evan Laird4bf21df2018-10-22 14:24:32 -040042import android.provider.Settings;
Beverlyb9826dd2018-04-12 15:02:45 -040043import android.service.notification.ZenModeConfig;
Rohan Shahd3cf7562018-02-23 11:12:28 -080044import android.text.format.DateUtils;
Jason Monke5b770e2017-03-03 21:49:29 -050045import android.util.AttributeSet;
Rohan Shaha160ab12018-03-09 15:47:36 -080046import android.util.Log;
Adrian Roos13836052018-03-15 21:06:37 +010047import android.util.Pair;
Fabian Kozynski8d06c712018-11-07 10:33:02 -050048import android.view.DisplayCutout;
Jason Monk824ffff2017-04-11 15:49:06 -040049import android.view.View;
Adrian Roos13836052018-03-15 21:06:37 +010050import android.view.WindowInsets;
Fabian Kozynski12638242018-10-12 15:33:41 -040051import android.view.WindowManager;
Beverlyff2df9b2018-10-10 16:54:10 -040052import android.widget.FrameLayout;
Amin Shaikh761c5662018-03-27 16:55:43 -040053import android.widget.ImageView;
Fabian Kozynski8d06c712018-11-07 10:33:02 -050054import android.widget.LinearLayout;
Jason Monke5b770e2017-03-03 21:49:29 -050055import android.widget.RelativeLayout;
Fabian Kozynski8d06c712018-11-07 10:33:02 -050056import android.widget.Space;
Rohan Shahd3cf7562018-02-23 11:12:28 -080057import android.widget.TextView;
Jason Monke5b770e2017-03-03 21:49:29 -050058
Beverlyff2df9b2018-10-10 16:54:10 -040059import androidx.annotation.VisibleForTesting;
60
Jason Monke5b770e2017-03-03 21:49:29 -050061import com.android.settingslib.Utils;
62import com.android.systemui.BatteryMeterView;
Rohan Shahd3cf7562018-02-23 11:12:28 -080063import com.android.systemui.Prefs;
Jason Monke5b770e2017-03-03 21:49:29 -050064import com.android.systemui.R;
65import com.android.systemui.plugins.ActivityStarter;
Beverly1be62f42018-12-19 17:17:48 -050066import com.android.systemui.plugins.DarkIconDispatcher;
67import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
Fabian Kozynski12638242018-10-12 15:33:41 -040068import com.android.systemui.privacy.OngoingPrivacyChip;
69import com.android.systemui.privacy.OngoingPrivacyDialog;
Fabian Kozynski8d06c712018-11-07 10:33:02 -050070import com.android.systemui.privacy.PrivacyItem;
71import com.android.systemui.privacy.PrivacyItemController;
Jason Monke5b770e2017-03-03 21:49:29 -050072import com.android.systemui.qs.QSDetail.Callback;
Adrian Roos13836052018-03-15 21:06:37 +010073import com.android.systemui.statusbar.phone.PhoneStatusBarView;
Evan Laird95896952018-01-22 19:30:05 -050074import com.android.systemui.statusbar.phone.StatusBarIconController;
75import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager;
Evan Laird20b87bf2018-04-12 09:54:11 -040076import com.android.systemui.statusbar.phone.StatusIconContainer;
Fabian Kozynski12638242018-10-12 15:33:41 -040077import com.android.systemui.statusbar.phone.SystemUIDialog;
Evan Laird4bf21df2018-10-22 14:24:32 -040078import com.android.systemui.statusbar.policy.BatteryController;
Beverlyff2df9b2018-10-10 16:54:10 -040079import com.android.systemui.statusbar.policy.Clock;
Rohan Shahcc3d1d82018-03-30 21:24:17 +000080import com.android.systemui.statusbar.policy.DateView;
Rohan Shahd3cf7562018-02-23 11:12:28 -080081import com.android.systemui.statusbar.policy.NextAlarmController;
Beverlyb9826dd2018-04-12 15:02:45 -040082import com.android.systemui.statusbar.policy.ZenModeController;
Jason Monke5b770e2017-03-03 21:49:29 -050083
Fabian Kozynski8d06c712018-11-07 10:33:02 -050084import java.util.List;
Lucas Dupin1f7374a2018-02-26 18:08:33 -080085import java.util.Locale;
Beverlyb9826dd2018-04-12 15:02:45 -040086import java.util.Objects;
Lucas Dupin1f7374a2018-02-26 18:08:33 -080087
Jason Monkea54e8a2018-12-20 10:01:48 -050088import javax.inject.Inject;
89import javax.inject.Named;
90
Rohan Shahd3cf7562018-02-23 11:12:28 -080091/**
92 * View that contains the top-most bits of the screen (primarily the status bar with date, time, and
93 * battery) and also contains the {@link QuickQSPanel} along with some of the panel's inner
94 * contents.
95 */
Amin Shaikhf09450b2018-04-06 17:32:45 -040096public class QuickStatusBarHeader extends RelativeLayout implements
Beverlyb9826dd2018-04-12 15:02:45 -040097 View.OnClickListener, NextAlarmController.NextAlarmChangeCallback,
98 ZenModeController.Callback {
Rohan Shaha160ab12018-03-09 15:47:36 -080099 private static final String TAG = "QuickStatusBarHeader";
100 private static final boolean DEBUG = false;
Jason Monke5b770e2017-03-03 21:49:29 -0500101
Rohan Shahd3cf7562018-02-23 11:12:28 -0800102 /** Delay for auto fading out the long press tooltip after it's fully visible (in ms). */
103 private static final long AUTO_FADE_OUT_DELAY_MS = DateUtils.SECOND_IN_MILLIS * 6;
104 private static final int FADE_ANIMATION_DURATION_MS = 300;
105 private static final int TOOLTIP_NOT_YET_SHOWN_COUNT = 0;
Rohan Shahb6a915c2018-03-01 11:57:00 -0800106 public static final int MAX_TOOLTIP_SHOWN_COUNT = 2;
Rohan Shahd3cf7562018-02-23 11:12:28 -0800107
108 private final Handler mHandler = new Handler();
Jason Monkea54e8a2018-12-20 10:01:48 -0500109 private final BatteryController mBatteryController;
110 private final NextAlarmController mAlarmController;
111 private final ZenModeController mZenController;
112 private final StatusBarIconController mStatusBarIconController;
113 private final ActivityStarter mActivityStarter;
Jason Monke5b770e2017-03-03 21:49:29 -0500114
115 private QSPanel mQsPanel;
116
117 private boolean mExpanded;
118 private boolean mListening;
Charles Hece2a7c02017-10-11 20:25:20 +0100119 private boolean mQsDisabled;
Jason Monke5b770e2017-03-03 21:49:29 -0500120
121 protected QuickQSPanel mHeaderQsPanel;
122 protected QSTileHost mHost;
Evan Laird95896952018-01-22 19:30:05 -0500123 private TintedIconManager mIconManager;
Rohan Shahd3cf7562018-02-23 11:12:28 -0800124 private TouchAnimator mStatusIconsAlphaAnimator;
125 private TouchAnimator mHeaderTextContainerAlphaAnimator;
Evan Laird95896952018-01-22 19:30:05 -0500126
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000127 private View mSystemIconsView;
Evan Laird95896952018-01-22 19:30:05 -0500128 private View mQuickQsStatusIcons;
Rohan Shahd3cf7562018-02-23 11:12:28 -0800129 private View mHeaderTextContainerView;
Amin Shaikh761c5662018-03-27 16:55:43 -0400130 /** View containing the next alarm and ringer mode info. */
131 private View mStatusContainer;
Rohan Shahd3cf7562018-02-23 11:12:28 -0800132 /** Tooltip for educating users that they can long press on icons to see more details. */
133 private View mLongPressTooltipView;
Amin Shaikh761c5662018-03-27 16:55:43 -0400134
135 private int mRingerMode = AudioManager.RINGER_MODE_NORMAL;
136 private AlarmManager.AlarmClockInfo mNextAlarm;
137
138 private ImageView mNextAlarmIcon;
Rohan Shahd3cf7562018-02-23 11:12:28 -0800139 /** {@link TextView} containing the actual text indicating when the next alarm will go off. */
140 private TextView mNextAlarmTextView;
Amin Shaikh761c5662018-03-27 16:55:43 -0400141 private View mStatusSeparator;
142 private ImageView mRingerModeIcon;
143 private TextView mRingerModeTextView;
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000144 private BatteryMeterView mBatteryMeterView;
145 private Clock mClockView;
146 private DateView mDateView;
Fabian Kozynski12638242018-10-12 15:33:41 -0400147 private OngoingPrivacyChip mPrivacyChip;
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500148 private Space mSpace;
Evan Laird4bf21df2018-10-22 14:24:32 -0400149 private BatteryMeterView mBatteryRemainingIcon;
150 private TextView mBatteryRemainingText;
151 private boolean mShowBatteryPercentAndEstimate;
Rohan Shahd3cf7562018-02-23 11:12:28 -0800152
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500153 private PrivacyItemController mPrivacyItemController;
Rohan Shahd3cf7562018-02-23 11:12:28 -0800154 /** Counts how many times the long press tooltip has been shown to the user. */
155 private int mShownCount;
156
Amin Shaikh761c5662018-03-27 16:55:43 -0400157 private final BroadcastReceiver mRingerReceiver = new BroadcastReceiver() {
158 @Override
159 public void onReceive(Context context, Intent intent) {
160 mRingerMode = intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1);
161 updateStatusText();
162 }
163 };
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500164 private boolean mHasTopCutout = false;
Amin Shaikh761c5662018-03-27 16:55:43 -0400165
Evan Laird4bf21df2018-10-22 14:24:32 -0400166 private final PercentSettingObserver mPercentSettingObserver =
167 new PercentSettingObserver(new Handler(mContext.getMainLooper()));
168
Rohan Shahd3cf7562018-02-23 11:12:28 -0800169 /**
170 * Runnable for automatically fading out the long press tooltip (as if it were animating away).
171 */
172 private final Runnable mAutoFadeOutTooltipRunnable = () -> hideLongPressTooltip(false);
Evan Laird4ea2a492018-01-22 11:29:12 -0500173
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500174 private PrivacyItemController.Callback mPICCallback = new PrivacyItemController.Callback() {
175 @Override
176 public void privacyChanged(List<PrivacyItem> privacyItems) {
177 mPrivacyChip.setPrivacyList(privacyItems);
178 setChipVisibility(!privacyItems.isEmpty());
179 }
180 };
181
Jason Monkea54e8a2018-12-20 10:01:48 -0500182 @Inject
183 public QuickStatusBarHeader(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
184 NextAlarmController nextAlarmController, ZenModeController zenModeController,
185 BatteryController batteryController, StatusBarIconController statusBarIconController,
186 ActivityStarter activityStarter) {
Jason Monke5b770e2017-03-03 21:49:29 -0500187 super(context, attrs);
Jason Monkea54e8a2018-12-20 10:01:48 -0500188 mAlarmController = nextAlarmController;
189 mZenController = zenModeController;
190 mBatteryController = batteryController;
191 mStatusBarIconController = statusBarIconController;
192 mActivityStarter = activityStarter;
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500193 mPrivacyItemController = new PrivacyItemController(context, mPICCallback);
Rohan Shahd3cf7562018-02-23 11:12:28 -0800194 mShownCount = getStoredShownCount();
Jason Monke5b770e2017-03-03 21:49:29 -0500195 }
196
197 @Override
198 protected void onFinishInflate() {
199 super.onFinishInflate();
Jason Monke5b770e2017-03-03 21:49:29 -0500200
201 mHeaderQsPanel = findViewById(R.id.quick_qs_panel);
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000202 mSystemIconsView = findViewById(R.id.quick_status_bar_system_icons);
Evan Laird95896952018-01-22 19:30:05 -0500203 mQuickQsStatusIcons = findViewById(R.id.quick_qs_status_icons);
Evan Laird20b87bf2018-04-12 09:54:11 -0400204 StatusIconContainer iconContainer = findViewById(R.id.statusIcons);
205 iconContainer.setShouldRestrictIcons(false);
206 mIconManager = new TintedIconManager(iconContainer);
Jason Monke5b770e2017-03-03 21:49:29 -0500207
Rohan Shahd3cf7562018-02-23 11:12:28 -0800208 // Views corresponding to the header info section (e.g. tooltip and next alarm).
209 mHeaderTextContainerView = findViewById(R.id.header_text_container);
210 mLongPressTooltipView = findViewById(R.id.long_press_tooltip);
Amin Shaikh761c5662018-03-27 16:55:43 -0400211 mStatusContainer = findViewById(R.id.status_container);
212 mStatusSeparator = findViewById(R.id.status_separator);
213 mNextAlarmIcon = findViewById(R.id.next_alarm_icon);
Rohan Shahd3cf7562018-02-23 11:12:28 -0800214 mNextAlarmTextView = findViewById(R.id.next_alarm_text);
Amin Shaikh761c5662018-03-27 16:55:43 -0400215 mRingerModeIcon = findViewById(R.id.ringer_mode_icon);
216 mRingerModeTextView = findViewById(R.id.ringer_mode_text);
Jason Monke5b770e2017-03-03 21:49:29 -0500217
218 updateResources();
219
Jason Monk824ffff2017-04-11 15:49:06 -0400220 Rect tintArea = new Rect(0, 0, 0, 0);
Jason Changb4e879d2018-04-11 11:17:58 +0800221 int colorForeground = Utils.getColorAttrDefaultColor(getContext(),
222 android.R.attr.colorForeground);
Amin Shaikh0e003312018-03-08 11:39:01 -0500223 float intensity = getColorIntensity(colorForeground);
Evan Laird95896952018-01-22 19:30:05 -0500224 int fillColor = fillColorForIntensity(intensity, getContext());
225
226 // Set light text on the header icons because they will always be on a black background
Evan Laird39254d42018-01-18 16:05:30 -0500227 applyDarkness(R.id.clock, tintArea, 0, DarkIconDispatcher.DEFAULT_ICON_TINT);
Evan Laird95896952018-01-22 19:30:05 -0500228
229 // Set the correct tint for the status icons so they contrast
230 mIconManager.setTint(fillColor);
Jason Monke5b770e2017-03-03 21:49:29 -0500231
Evan Laird4bf21df2018-10-22 14:24:32 -0400232 mShowBatteryPercentAndEstimate = mContext.getResources().getBoolean(
233 com.android.internal.R.bool.config_battery_percentage_setting_available);
234
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000235 mBatteryMeterView = findViewById(R.id.battery);
Evan Laird4bf21df2018-10-22 14:24:32 -0400236 mBatteryMeterView.setPercentShowMode(mShowBatteryPercentAndEstimate
237 ? BatteryMeterView.MODE_ON : BatteryMeterView.MODE_OFF);
Amin Shaikh39bdc502018-05-15 23:43:34 -0400238 mBatteryMeterView.setOnClickListener(this);
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000239 mClockView = findViewById(R.id.clock);
Amin Shaikh39bdc502018-05-15 23:43:34 -0400240 mClockView.setOnClickListener(this);
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000241 mDateView = findViewById(R.id.date);
Fabian Kozynski12638242018-10-12 15:33:41 -0400242 mPrivacyChip = findViewById(R.id.privacy_chip);
243 mPrivacyChip.setOnClickListener(this);
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500244 mSpace = findViewById(R.id.space);
Evan Laird4bf21df2018-10-22 14:24:32 -0400245
246 // Tint for the battery icons are handled in setupHost()
247 mBatteryRemainingIcon = findViewById(R.id.batteryRemainingIcon);
248 mBatteryRemainingIcon.setPercentShowMode(BatteryMeterView.MODE_OFF);
Evan Laird698839b2018-12-05 15:49:12 -0500249 // Don't need to worry about tuner settings for this icon
250 mBatteryRemainingIcon.setIgnoreTunerUpdates(true);
Evan Laird4bf21df2018-10-22 14:24:32 -0400251
252 mBatteryRemainingText = findViewById(R.id.batteryRemainingText);
253 mBatteryRemainingText.setTextColor(fillColor);
254
255 updateShowPercent();
Jason Monke5b770e2017-03-03 21:49:29 -0500256 }
257
Amin Shaikh761c5662018-03-27 16:55:43 -0400258 private void updateStatusText() {
Beverlyb9826dd2018-04-12 15:02:45 -0400259 boolean changed = updateRingerStatus() || updateAlarmStatus();
260
261 if (changed) {
262 boolean alarmVisible = mNextAlarmTextView.getVisibility() == View.VISIBLE;
263 boolean ringerVisible = mRingerModeTextView.getVisibility() == View.VISIBLE;
264 mStatusSeparator.setVisibility(alarmVisible && ringerVisible ? View.VISIBLE
265 : View.GONE);
266 updateTooltipShow();
267 }
268 }
269
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500270 private void setChipVisibility(boolean chipVisible) {
271 mBatteryMeterView.setVisibility(View.VISIBLE);
272 if (chipVisible) {
273 mPrivacyChip.setVisibility(View.VISIBLE);
274 if (mHasTopCutout) mBatteryMeterView.setVisibility(View.GONE);
275 } else {
276 mPrivacyChip.setVisibility(View.GONE);
277 }
278 }
279
Beverlyb9826dd2018-04-12 15:02:45 -0400280 private boolean updateRingerStatus() {
281 boolean isOriginalVisible = mRingerModeTextView.getVisibility() == View.VISIBLE;
282 CharSequence originalRingerText = mRingerModeTextView.getText();
283
Amin Shaikh761c5662018-03-27 16:55:43 -0400284 boolean ringerVisible = false;
Beverlyb9826dd2018-04-12 15:02:45 -0400285 if (!ZenModeConfig.isZenOverridingRinger(mZenController.getZen(),
Beverlyff2df9b2018-10-10 16:54:10 -0400286 mZenController.getConsolidatedPolicy())) {
Beverlyb9826dd2018-04-12 15:02:45 -0400287 if (mRingerMode == AudioManager.RINGER_MODE_VIBRATE) {
288 mRingerModeIcon.setImageResource(R.drawable.stat_sys_ringer_vibrate);
289 mRingerModeTextView.setText(R.string.qs_status_phone_vibrate);
290 ringerVisible = true;
291 } else if (mRingerMode == AudioManager.RINGER_MODE_SILENT) {
292 mRingerModeIcon.setImageResource(R.drawable.stat_sys_ringer_silent);
293 mRingerModeTextView.setText(R.string.qs_status_phone_muted);
294 ringerVisible = true;
295 }
Amin Shaikh761c5662018-03-27 16:55:43 -0400296 }
297 mRingerModeIcon.setVisibility(ringerVisible ? View.VISIBLE : View.GONE);
298 mRingerModeTextView.setVisibility(ringerVisible ? View.VISIBLE : View.GONE);
299
Beverlyb9826dd2018-04-12 15:02:45 -0400300 return isOriginalVisible != ringerVisible ||
301 !Objects.equals(originalRingerText, mRingerModeTextView.getText());
302 }
303
304 private boolean updateAlarmStatus() {
305 boolean isOriginalVisible = mNextAlarmTextView.getVisibility() == View.VISIBLE;
306 CharSequence originalAlarmText = mNextAlarmTextView.getText();
307
Amin Shaikh761c5662018-03-27 16:55:43 -0400308 boolean alarmVisible = false;
309 if (mNextAlarm != null) {
310 alarmVisible = true;
311 mNextAlarmTextView.setText(formatNextAlarm(mNextAlarm));
312 }
313 mNextAlarmIcon.setVisibility(alarmVisible ? View.VISIBLE : View.GONE);
314 mNextAlarmTextView.setVisibility(alarmVisible ? View.VISIBLE : View.GONE);
Amin Shaikh761c5662018-03-27 16:55:43 -0400315
Beverlyb9826dd2018-04-12 15:02:45 -0400316 return isOriginalVisible != alarmVisible ||
317 !Objects.equals(originalAlarmText, mNextAlarmTextView.getText());
318 }
Amin Shaikh761c5662018-03-27 16:55:43 -0400319
Jason Monk824ffff2017-04-11 15:49:06 -0400320 private void applyDarkness(int id, Rect tintArea, float intensity, int color) {
321 View v = findViewById(id);
322 if (v instanceof DarkReceiver) {
323 ((DarkReceiver) v).onDarkChanged(tintArea, intensity, color);
324 }
325 }
326
Evan Laird95896952018-01-22 19:30:05 -0500327 private int fillColorForIntensity(float intensity, Context context) {
328 if (intensity == 0) {
Amin Shaikh9cac3382018-04-11 17:10:07 -0400329 return context.getColor(R.color.light_mode_icon_color_single_tone);
Evan Laird95896952018-01-22 19:30:05 -0500330 }
Amin Shaikh9cac3382018-04-11 17:10:07 -0400331 return context.getColor(R.color.dark_mode_icon_color_single_tone);
Evan Laird95896952018-01-22 19:30:05 -0500332 }
333
Jason Monke5b770e2017-03-03 21:49:29 -0500334 @Override
335 protected void onConfigurationChanged(Configuration newConfig) {
336 super.onConfigurationChanged(newConfig);
337 updateResources();
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000338
339 // Update color schemes in landscape to use wallpaperTextColor
340 boolean shouldUseWallpaperTextColor =
341 newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE;
342 mBatteryMeterView.useWallpaperTextColor(shouldUseWallpaperTextColor);
343 mClockView.useWallpaperTextColor(shouldUseWallpaperTextColor);
Jason Monke5b770e2017-03-03 21:49:29 -0500344 }
345
Fabian Kozynskief124492018-11-02 11:02:11 -0400346
347
Jason Monke5b770e2017-03-03 21:49:29 -0500348 @Override
349 public void onRtlPropertiesChanged(int layoutDirection) {
350 super.onRtlPropertiesChanged(layoutDirection);
351 updateResources();
352 }
353
Evan Laird84b98952018-07-02 17:43:59 -0400354 /**
355 * The height of QQS should always be the status bar height + 128dp. This is normally easy, but
356 * when there is a notch involved the status bar can remain a fixed pixel size.
357 */
358 private void updateMinimumHeight() {
359 int sbHeight = mContext.getResources().getDimensionPixelSize(
360 com.android.internal.R.dimen.status_bar_height);
361 int qqsHeight = mContext.getResources().getDimensionPixelSize(
362 R.dimen.qs_quick_header_panel_height);
363
364 setMinimumHeight(sbHeight + qqsHeight);
365 }
366
Jason Monke5b770e2017-03-03 21:49:29 -0500367 private void updateResources() {
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000368 Resources resources = mContext.getResources();
Evan Laird84b98952018-07-02 17:43:59 -0400369 updateMinimumHeight();
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000370
371 // Update height for a few views, especially due to landscape mode restricting space.
Rohan Shahd3cf7562018-02-23 11:12:28 -0800372 mHeaderTextContainerView.getLayoutParams().height =
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000373 resources.getDimensionPixelSize(R.dimen.qs_header_tooltip_height);
Rohan Shahd3cf7562018-02-23 11:12:28 -0800374 mHeaderTextContainerView.setLayoutParams(mHeaderTextContainerView.getLayoutParams());
375
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000376 mSystemIconsView.getLayoutParams().height = resources.getDimensionPixelSize(
377 com.android.internal.R.dimen.quick_qs_offset_height);
378 mSystemIconsView.setLayoutParams(mSystemIconsView.getLayoutParams());
379
Evan Laird84b98952018-07-02 17:43:59 -0400380 FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
381 if (mQsDisabled) {
382 lp.height = resources.getDimensionPixelSize(
383 com.android.internal.R.dimen.quick_qs_offset_height);
384 } else {
385 lp.height = Math.max(getMinimumHeight(),
386 resources.getDimensionPixelSize(
Evan Lairdbf3794a2018-07-17 15:55:40 -0400387 com.android.internal.R.dimen.quick_qs_total_height));
Evan Laird84b98952018-07-02 17:43:59 -0400388 }
389
390 setLayoutParams(lp);
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000391
Fabian Kozynskief124492018-11-02 11:02:11 -0400392 if (mPrivacyChip != null) {
393 MarginLayoutParams lm = (MarginLayoutParams) mPrivacyChip.getLayoutParams();
394 int sideMargins = lm.leftMargin;
395 int topBottomMargins = resources.getDimensionPixelSize(
396 R.dimen.ongoing_appops_top_chip_margin);
397 lm.setMargins(sideMargins, topBottomMargins, sideMargins, topBottomMargins);
398 mPrivacyChip.setLayoutParams(lm);
399 }
400
Rohan Shahd3cf7562018-02-23 11:12:28 -0800401 updateStatusIconAlphaAnimator();
402 updateHeaderTextContainerAlphaAnimator();
Evan Laird95896952018-01-22 19:30:05 -0500403 }
404
Rohan Shahd3cf7562018-02-23 11:12:28 -0800405 private void updateStatusIconAlphaAnimator() {
406 mStatusIconsAlphaAnimator = new TouchAnimator.Builder()
Evan Laird95896952018-01-22 19:30:05 -0500407 .addFloat(mQuickQsStatusIcons, "alpha", 1, 0)
408 .build();
Jason Monke5b770e2017-03-03 21:49:29 -0500409 }
410
Rohan Shahd3cf7562018-02-23 11:12:28 -0800411 private void updateHeaderTextContainerAlphaAnimator() {
412 mHeaderTextContainerAlphaAnimator = new TouchAnimator.Builder()
413 .addFloat(mHeaderTextContainerView, "alpha", 0, 1)
414 .setStartDelay(.5f)
415 .build();
Jason Monke5b770e2017-03-03 21:49:29 -0500416 }
417
Evan Laird4bf21df2018-10-22 14:24:32 -0400418 private void updateBatteryRemainingText() {
419 if (!mShowBatteryPercentAndEstimate) {
420 return;
421 }
Jason Monkea54e8a2018-12-20 10:01:48 -0500422 mBatteryRemainingText.setText(mBatteryController.getEstimatedTimeRemainingString());
Evan Laird4bf21df2018-10-22 14:24:32 -0400423 }
424
Jason Monke5b770e2017-03-03 21:49:29 -0500425 public void setExpanded(boolean expanded) {
426 if (mExpanded == expanded) return;
427 mExpanded = expanded;
428 mHeaderQsPanel.setExpanded(expanded);
Fabian Kozynskif3a77012019-01-09 15:37:30 +0000429 updateEverything();
Jason Monke5b770e2017-03-03 21:49:29 -0500430 }
431
Rohan Shahd3cf7562018-02-23 11:12:28 -0800432 /**
433 * Animates the inner contents based on the given expansion details.
434 *
435 * @param isKeyguardShowing whether or not we're showing the keyguard (a.k.a. lockscreen)
436 * @param expansionFraction how much the QS panel is expanded/pulled out (up to 1f)
437 * @param panelTranslationY how much the panel has physically moved down vertically (required
438 * for keyguard animations only)
439 */
440 public void setExpansion(boolean isKeyguardShowing, float expansionFraction,
441 float panelTranslationY) {
442 final float keyguardExpansionFraction = isKeyguardShowing ? 1f : expansionFraction;
443 if (mStatusIconsAlphaAnimator != null) {
444 mStatusIconsAlphaAnimator.setPosition(keyguardExpansionFraction);
Evan Laird95896952018-01-22 19:30:05 -0500445 }
Rohan Shahd3cf7562018-02-23 11:12:28 -0800446
447 if (isKeyguardShowing) {
448 // If the keyguard is showing, we want to offset the text so that it comes in at the
449 // same time as the panel as it slides down.
450 mHeaderTextContainerView.setTranslationY(panelTranslationY);
451 } else {
452 mHeaderTextContainerView.setTranslationY(0f);
453 }
454
455 if (mHeaderTextContainerAlphaAnimator != null) {
456 mHeaderTextContainerAlphaAnimator.setPosition(keyguardExpansionFraction);
457 }
458
459 // Check the original expansion fraction - we don't want to show the tooltip until the
460 // panel is pulled all the way out.
461 if (expansionFraction == 1f) {
462 // QS is fully expanded, bring in the tooltip.
463 showLongPressTooltip();
464 }
465 }
466
467 /** Returns the latest stored tooltip shown count from SharedPreferences. */
468 private int getStoredShownCount() {
469 return Prefs.getInt(
470 mContext,
471 Prefs.Key.QS_LONG_PRESS_TOOLTIP_SHOWN_COUNT,
472 TOOLTIP_NOT_YET_SHOWN_COUNT);
Jason Monke5b770e2017-03-03 21:49:29 -0500473 }
474
Charles Hece2a7c02017-10-11 20:25:20 +0100475 public void disable(int state1, int state2, boolean animate) {
476 final boolean disabled = (state2 & DISABLE2_QUICK_SETTINGS) != 0;
477 if (disabled == mQsDisabled) return;
478 mQsDisabled = disabled;
479 mHeaderQsPanel.setDisabledByPolicy(disabled);
Amin Shaikhf09450b2018-04-06 17:32:45 -0400480 mHeaderTextContainerView.setVisibility(mQsDisabled ? View.GONE : View.VISIBLE);
481 mQuickQsStatusIcons.setVisibility(mQsDisabled ? View.GONE : View.VISIBLE);
482 updateResources();
Charles Hece2a7c02017-10-11 20:25:20 +0100483 }
484
485 @Override
486 public void onAttachedToWindow() {
Amin Shaikha59215a2018-04-23 08:52:38 -0400487 super.onAttachedToWindow();
Jason Monkea54e8a2018-12-20 10:01:48 -0500488 mStatusBarIconController.addIconGroup(mIconManager);
Adrian Roos13836052018-03-15 21:06:37 +0100489 requestApplyInsets();
Evan Laird4bf21df2018-10-22 14:24:32 -0400490 mContext.getContentResolver().registerContentObserver(
491 Settings.System.getUriFor(SHOW_BATTERY_PERCENT), false, mPercentSettingObserver,
492 ActivityManager.getCurrentUser());
Adrian Roos13836052018-03-15 21:06:37 +0100493 }
494
495 @Override
496 public WindowInsets onApplyWindowInsets(WindowInsets insets) {
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500497 DisplayCutout cutout = insets.getDisplayCutout();
Adrian Roos13836052018-03-15 21:06:37 +0100498 Pair<Integer, Integer> padding = PhoneStatusBarView.cornerCutoutMargins(
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500499 cutout, getDisplay());
Adrian Roos13836052018-03-15 21:06:37 +0100500 if (padding == null) {
Amin Shaikh7d86b042018-04-16 16:00:12 -0400501 mSystemIconsView.setPaddingRelative(
502 getResources().getDimensionPixelSize(R.dimen.status_bar_padding_start), 0,
503 getResources().getDimensionPixelSize(R.dimen.status_bar_padding_end), 0);
Adrian Roos13836052018-03-15 21:06:37 +0100504 } else {
Amin Shaikh7d86b042018-04-16 16:00:12 -0400505 mSystemIconsView.setPadding(padding.first, 0, padding.second, 0);
506
Adrian Roos13836052018-03-15 21:06:37 +0100507 }
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500508 LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mSpace.getLayoutParams();
509 if (cutout != null) {
510 Rect topCutout = cutout.getBoundingRectTop();
511 if (topCutout.isEmpty()) {
512 mHasTopCutout = false;
513 lp.width = 0;
514 mSpace.setVisibility(View.GONE);
515 } else {
516 mHasTopCutout = true;
517 lp.width = topCutout.width();
518 mSpace.setVisibility(View.VISIBLE);
519 }
520 }
521 mSpace.setLayoutParams(lp);
522 // Decide whether to show BatteryMeterView
523 setChipVisibility(mPrivacyChip.getVisibility() == View.VISIBLE);
Adrian Roos13836052018-03-15 21:06:37 +0100524 return super.onApplyWindowInsets(insets);
Charles Hece2a7c02017-10-11 20:25:20 +0100525 }
526
527 @Override
Jason Monke5b770e2017-03-03 21:49:29 -0500528 @VisibleForTesting
529 public void onDetachedFromWindow() {
530 setListening(false);
Jason Monkea54e8a2018-12-20 10:01:48 -0500531 mStatusBarIconController.removeIconGroup(mIconManager);
Evan Laird4bf21df2018-10-22 14:24:32 -0400532 mContext.getContentResolver().unregisterContentObserver(mPercentSettingObserver);
Jason Monke5b770e2017-03-03 21:49:29 -0500533 super.onDetachedFromWindow();
534 }
535
536 public void setListening(boolean listening) {
537 if (listening == mListening) {
538 return;
539 }
540 mHeaderQsPanel.setListening(listening);
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500541 mPrivacyItemController.setListening(listening);
Jason Monke5b770e2017-03-03 21:49:29 -0500542 mListening = listening;
Rohan Shahd3cf7562018-02-23 11:12:28 -0800543
544 if (listening) {
Beverlyb9826dd2018-04-12 15:02:45 -0400545 mZenController.addCallback(this);
Rohan Shahd3cf7562018-02-23 11:12:28 -0800546 mAlarmController.addCallback(this);
Amin Shaikh761c5662018-03-27 16:55:43 -0400547 mContext.registerReceiver(mRingerReceiver,
548 new IntentFilter(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION));
Evan Laird4bf21df2018-10-22 14:24:32 -0400549 updateBatteryRemainingText();
Rohan Shahd3cf7562018-02-23 11:12:28 -0800550 } else {
Beverlyb9826dd2018-04-12 15:02:45 -0400551 mZenController.removeCallback(this);
Rohan Shahd3cf7562018-02-23 11:12:28 -0800552 mAlarmController.removeCallback(this);
Amin Shaikh761c5662018-03-27 16:55:43 -0400553 mContext.unregisterReceiver(mRingerReceiver);
Rohan Shahd3cf7562018-02-23 11:12:28 -0800554 }
Jason Monke5b770e2017-03-03 21:49:29 -0500555 }
556
Evan Laird95896952018-01-22 19:30:05 -0500557 @Override
558 public void onClick(View v) {
Amin Shaikh39bdc502018-05-15 23:43:34 -0400559 if (v == mClockView) {
Jason Monkea54e8a2018-12-20 10:01:48 -0500560 mActivityStarter.postStartActivityDismissingKeyguard(new Intent(
Evan Laird95896952018-01-22 19:30:05 -0500561 AlarmClock.ACTION_SHOW_ALARMS),0);
Amin Shaikh39bdc502018-05-15 23:43:34 -0400562 } else if (v == mBatteryMeterView) {
Jason Monkea54e8a2018-12-20 10:01:48 -0500563 mActivityStarter.postStartActivityDismissingKeyguard(new Intent(
Amin Shaikh39bdc502018-05-15 23:43:34 -0400564 Intent.ACTION_POWER_USAGE_SUMMARY),0);
Fabian Kozynski12638242018-10-12 15:33:41 -0400565 } else if (v == mPrivacyChip) {
566 Handler mUiHandler = new Handler(Looper.getMainLooper());
567 mUiHandler.post(() -> {
568 Dialog mDialog = new OngoingPrivacyDialog(mContext,
569 mPrivacyChip.getBuilder()).createDialog();
570 mDialog.getWindow().setType(
571 WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
572 SystemUIDialog.setShowForAllUsers(mDialog, true);
573 SystemUIDialog.registerDismissListener(mDialog);
574 SystemUIDialog.setWindowOnTop(mDialog);
575 mUiHandler.post(() -> mDialog.show());
576 mHost.collapsePanels();
577 });
Evan Laird95896952018-01-22 19:30:05 -0500578 }
579 }
580
Rohan Shahd3cf7562018-02-23 11:12:28 -0800581 @Override
582 public void onNextAlarmChanged(AlarmManager.AlarmClockInfo nextAlarm) {
Amin Shaikh761c5662018-03-27 16:55:43 -0400583 mNextAlarm = nextAlarm;
584 updateStatusText();
585 }
Rohan Shaha160ab12018-03-09 15:47:36 -0800586
Beverlyb9826dd2018-04-12 15:02:45 -0400587 @Override
588 public void onZenChanged(int zen) {
589 updateStatusText();
590
591 }
592
593 @Override
594 public void onConfigChanged(ZenModeConfig config) {
595 updateStatusText();
596 }
597
Amin Shaikh761c5662018-03-27 16:55:43 -0400598 private void updateTooltipShow() {
599 if (hasStatusText()) {
600 hideLongPressTooltip(true /* shouldShowStatusText */);
Rohan Shahd3cf7562018-02-23 11:12:28 -0800601 } else {
Amin Shaikh761c5662018-03-27 16:55:43 -0400602 hideStatusText();
Rohan Shahd3cf7562018-02-23 11:12:28 -0800603 }
604 updateHeaderTextContainerAlphaAnimator();
605 }
606
Amin Shaikh761c5662018-03-27 16:55:43 -0400607 private boolean hasStatusText() {
608 return mNextAlarmTextView.getVisibility() == View.VISIBLE
609 || mRingerModeTextView.getVisibility() == View.VISIBLE;
610 }
611
Rohan Shahd3cf7562018-02-23 11:12:28 -0800612 /**
613 * Animates in the long press tooltip (as long as the next alarm text isn't currently occupying
614 * the space).
615 */
616 public void showLongPressTooltip() {
Amin Shaikh761c5662018-03-27 16:55:43 -0400617 // If we have status text to show, don't bother fading in the tooltip.
618 if (hasStatusText()) {
Rohan Shahd3cf7562018-02-23 11:12:28 -0800619 return;
620 }
621
622 if (mShownCount < MAX_TOOLTIP_SHOWN_COUNT) {
623 mLongPressTooltipView.animate().cancel();
624 mLongPressTooltipView.setVisibility(View.VISIBLE);
625 mLongPressTooltipView.animate()
626 .alpha(1f)
627 .setDuration(FADE_ANIMATION_DURATION_MS)
628 .setListener(new AnimatorListenerAdapter() {
629 @Override
630 public void onAnimationEnd(Animator animation) {
631 mHandler.postDelayed(
632 mAutoFadeOutTooltipRunnable, AUTO_FADE_OUT_DELAY_MS);
633 }
634 })
635 .start();
636
637 // Increment and drop the shown count in prefs for the next time we're deciding to
638 // fade in the tooltip. We first sanity check that the tooltip count hasn't changed yet
639 // in prefs (say, from a long press).
640 if (getStoredShownCount() <= mShownCount) {
641 Prefs.putInt(mContext, Prefs.Key.QS_LONG_PRESS_TOOLTIP_SHOWN_COUNT, ++mShownCount);
642 }
643 }
644 }
645
646 /**
647 * Fades out the long press tooltip if it's partially visible - short circuits any running
Amin Shaikh761c5662018-03-27 16:55:43 -0400648 * animation. Additionally has the ability to fade in the status info text.
Rohan Shahd3cf7562018-02-23 11:12:28 -0800649 *
Amin Shaikh761c5662018-03-27 16:55:43 -0400650 * @param shouldShowStatusText whether we should fade in the status text
Rohan Shahd3cf7562018-02-23 11:12:28 -0800651 */
Amin Shaikh761c5662018-03-27 16:55:43 -0400652 private void hideLongPressTooltip(boolean shouldShowStatusText) {
Rohan Shahd3cf7562018-02-23 11:12:28 -0800653 mLongPressTooltipView.animate().cancel();
654 if (mLongPressTooltipView.getVisibility() == View.VISIBLE
655 && mLongPressTooltipView.getAlpha() != 0f) {
656 mHandler.removeCallbacks(mAutoFadeOutTooltipRunnable);
657 mLongPressTooltipView.animate()
658 .alpha(0f)
659 .setDuration(FADE_ANIMATION_DURATION_MS)
660 .setListener(new AnimatorListenerAdapter() {
661 @Override
662 public void onAnimationEnd(Animator animation) {
Rohan Shaha160ab12018-03-09 15:47:36 -0800663 if (DEBUG) Log.d(TAG, "hideLongPressTooltip: Hid long press tip");
Rohan Shahd3cf7562018-02-23 11:12:28 -0800664 mLongPressTooltipView.setVisibility(View.INVISIBLE);
665
Amin Shaikh761c5662018-03-27 16:55:43 -0400666 if (shouldShowStatusText) {
667 showStatus();
Rohan Shahd3cf7562018-02-23 11:12:28 -0800668 }
669 }
670 })
671 .start();
672 } else {
673 mLongPressTooltipView.setVisibility(View.INVISIBLE);
Amin Shaikh761c5662018-03-27 16:55:43 -0400674 if (shouldShowStatusText) {
675 showStatus();
Rohan Shahd3cf7562018-02-23 11:12:28 -0800676 }
677 }
678 }
679
680 /**
Amin Shaikh761c5662018-03-27 16:55:43 -0400681 * Fades in the updated status text. Note that if there's already a status showing, this will
Fabian Kozynski3f789332018-09-04 16:42:43 -0400682 * immediately fade it out and fade in the updated status.
Rohan Shahd3cf7562018-02-23 11:12:28 -0800683 */
Amin Shaikh761c5662018-03-27 16:55:43 -0400684 private void showStatus() {
685 mStatusContainer.setAlpha(0f);
Rohan Shahd3cf7562018-02-23 11:12:28 -0800686
Amin Shaikh761c5662018-03-27 16:55:43 -0400687 mStatusContainer.animate()
Rohan Shahd3cf7562018-02-23 11:12:28 -0800688 .alpha(1f)
689 .setDuration(FADE_ANIMATION_DURATION_MS)
690 .start();
691 }
692
Fabian Kozynski3f789332018-09-04 16:42:43 -0400693 /** Fades out the status text. */
Amin Shaikh761c5662018-03-27 16:55:43 -0400694 private void hideStatusText() {
Fabian Kozynski3f789332018-09-04 16:42:43 -0400695 mStatusContainer.animate()
696 .alpha(0f)
697 .setDuration(FADE_ANIMATION_DURATION_MS)
698 .start();
Rohan Shahd3cf7562018-02-23 11:12:28 -0800699 }
700
Fabian Kozynskif3a77012019-01-09 15:37:30 +0000701 public void updateEverything() {
702 post(() -> setClickable(false));
703 }
704
Jason Monke5b770e2017-03-03 21:49:29 -0500705 public void setQSPanel(final QSPanel qsPanel) {
706 mQsPanel = qsPanel;
707 setupHost(qsPanel.getHost());
708 }
709
710 public void setupHost(final QSTileHost host) {
711 mHost = host;
712 //host.setHeaderView(mExpandIndicator);
713 mHeaderQsPanel.setQSPanelAndHeader(mQsPanel, this);
714 mHeaderQsPanel.setHost(host, null /* No customization in header */);
Evan Lairdef160f22018-01-29 14:08:45 -0500715
716 // Use SystemUI context to get battery meter colors, and let it use the default tint (white)
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000717 mBatteryMeterView.setColorsFromContext(mHost.getContext());
718 mBatteryMeterView.onDarkChanged(new Rect(), 0, DarkIconDispatcher.DEFAULT_ICON_TINT);
Evan Laird4bf21df2018-10-22 14:24:32 -0400719
720 Rect tintArea = new Rect(0, 0, 0, 0);
721 int colorForeground = Utils.getColorAttrDefaultColor(getContext(),
722 android.R.attr.colorForeground);
723 float intensity = getColorIntensity(colorForeground);
724 int fillColor = fillColorForIntensity(intensity, getContext());
725 mBatteryRemainingIcon.setColorsFromContext(mHost.getContext());
726 mBatteryRemainingIcon.onDarkChanged(tintArea, intensity, fillColor);
Jason Monke5b770e2017-03-03 21:49:29 -0500727 }
728
729 public void setCallback(Callback qsPanelCallback) {
730 mHeaderQsPanel.setCallback(qsPanelCallback);
731 }
Lucas Dupin1f7374a2018-02-26 18:08:33 -0800732
733 private String formatNextAlarm(AlarmManager.AlarmClockInfo info) {
734 if (info == null) {
735 return "";
736 }
737 String skeleton = android.text.format.DateFormat
738 .is24HourFormat(mContext, ActivityManager.getCurrentUser()) ? "EHm" : "Ehma";
739 String pattern = android.text.format.DateFormat
740 .getBestDateTimePattern(Locale.getDefault(), skeleton);
741 return android.text.format.DateFormat.format(pattern, info.getTriggerTime()).toString();
742 }
Amin Shaikh0e003312018-03-08 11:39:01 -0500743
744 public static float getColorIntensity(@ColorInt int color) {
745 return color == Color.WHITE ? 0 : 1;
746 }
Amin Shaikh50d2d1e2018-04-25 14:48:13 -0400747
748 public void setMargins(int sideMargins) {
749 for (int i = 0; i < getChildCount(); i++) {
750 View v = getChildAt(i);
Fabian Kozynskief124492018-11-02 11:02:11 -0400751 if (v == mSystemIconsView || v == mQuickQsStatusIcons || v == mHeaderQsPanel
752 || v == mPrivacyChip) {
Amin Shaikh50d2d1e2018-04-25 14:48:13 -0400753 continue;
754 }
755 RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) v.getLayoutParams();
756 lp.leftMargin = sideMargins;
757 lp.rightMargin = sideMargins;
758 }
759 }
Evan Laird4bf21df2018-10-22 14:24:32 -0400760
761 private void updateShowPercent() {
762 final boolean systemSetting = 0 != Settings.System
763 .getIntForUser(getContext().getContentResolver(),
764 SHOW_BATTERY_PERCENT, 0, ActivityManager.getCurrentUser());
765
766 mShowBatteryPercentAndEstimate = systemSetting;
767
768 updateBatteryViews();
769 }
770
771 private void updateBatteryViews() {
772 if (mShowBatteryPercentAndEstimate) {
773 mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_ON);
774 mBatteryRemainingIcon.setVisibility(View.VISIBLE);
775 mBatteryRemainingText.setVisibility(View.VISIBLE);
776 updateBatteryRemainingText();
777 } else {
778 mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_OFF);
779 mBatteryRemainingIcon.setVisibility(View.GONE);
780 mBatteryRemainingText.setVisibility(View.GONE);
781 }
782 }
783
784 private final class PercentSettingObserver extends ContentObserver {
785 PercentSettingObserver(Handler handler) {
786 super(handler);
787 }
788
789 @Override
790 public void onChange(boolean selfChange, Uri uri) {
791 super.onChange(selfChange, uri);
792 updateShowPercent();
793 }
794 }
Jason Monke5b770e2017-03-03 21:49:29 -0500795}