blob: 3cecff033c911de39c4c823da31da2266c56e2f0 [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
Rohan Shahd3cf7562018-02-23 11:12:28 -080020import android.animation.Animator;
21import android.animation.AnimatorListenerAdapter;
Amin Shaikh0e003312018-03-08 11:39:01 -050022import android.annotation.ColorInt;
Lucas Dupin1f7374a2018-02-26 18:08:33 -080023import android.app.ActivityManager;
Rohan Shahd3cf7562018-02-23 11:12:28 -080024import android.app.AlarmManager;
Fabian Kozynski12638242018-10-12 15:33:41 -040025import android.app.Dialog;
Amin Shaikh761c5662018-03-27 16:55:43 -040026import android.content.BroadcastReceiver;
Jason Monke5b770e2017-03-03 21:49:29 -050027import android.content.Context;
Evan Laird4ea2a492018-01-22 11:29:12 -050028import android.content.Intent;
Amin Shaikh761c5662018-03-27 16:55:43 -040029import android.content.IntentFilter;
Jason Monke5b770e2017-03-03 21:49:29 -050030import android.content.res.Configuration;
Rohan Shahcc3d1d82018-03-30 21:24:17 +000031import android.content.res.Resources;
Evan Laird4bf21df2018-10-22 14:24:32 -040032import android.database.ContentObserver;
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;
Evan Laird4bf21df2018-10-22 14:24:32 -040036import android.net.Uri;
Rohan Shahd3cf7562018-02-23 11:12:28 -080037import android.os.Handler;
Fabian Kozynski12638242018-10-12 15:33:41 -040038import android.os.Looper;
Evan Laird4ea2a492018-01-22 11:29:12 -050039import android.provider.AlarmClock;
Evan Laird4bf21df2018-10-22 14:24:32 -040040import android.provider.Settings;
Beverlyb9826dd2018-04-12 15:02:45 -040041import android.service.notification.ZenModeConfig;
Rohan Shahd3cf7562018-02-23 11:12:28 -080042import android.text.format.DateUtils;
Jason Monke5b770e2017-03-03 21:49:29 -050043import android.util.AttributeSet;
Rohan Shaha160ab12018-03-09 15:47:36 -080044import android.util.Log;
Adrian Roos13836052018-03-15 21:06:37 +010045import android.util.Pair;
Fabian Kozynski8d06c712018-11-07 10:33:02 -050046import android.view.DisplayCutout;
Jason Monk824ffff2017-04-11 15:49:06 -040047import android.view.View;
Adrian Roos13836052018-03-15 21:06:37 +010048import android.view.WindowInsets;
Fabian Kozynski12638242018-10-12 15:33:41 -040049import android.view.WindowManager;
Beverlyff2df9b2018-10-10 16:54:10 -040050import android.widget.FrameLayout;
Amin Shaikh761c5662018-03-27 16:55:43 -040051import android.widget.ImageView;
Fabian Kozynski8d06c712018-11-07 10:33:02 -050052import android.widget.LinearLayout;
Jason Monke5b770e2017-03-03 21:49:29 -050053import android.widget.RelativeLayout;
Fabian Kozynski8d06c712018-11-07 10:33:02 -050054import android.widget.Space;
Rohan Shahd3cf7562018-02-23 11:12:28 -080055import android.widget.TextView;
Jason Monke5b770e2017-03-03 21:49:29 -050056
Beverlyff2df9b2018-10-10 16:54:10 -040057import androidx.annotation.VisibleForTesting;
58
Jason Monke5b770e2017-03-03 21:49:29 -050059import com.android.settingslib.Utils;
60import com.android.systemui.BatteryMeterView;
61import com.android.systemui.Dependency;
Rohan Shahd3cf7562018-02-23 11:12:28 -080062import com.android.systemui.Prefs;
Jason Monke5b770e2017-03-03 21:49:29 -050063import com.android.systemui.R;
64import com.android.systemui.plugins.ActivityStarter;
Fabian Kozynski12638242018-10-12 15:33:41 -040065import com.android.systemui.privacy.OngoingPrivacyChip;
66import com.android.systemui.privacy.OngoingPrivacyDialog;
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;
Evan Laird4bf21df2018-10-22 14:24:32 -040075import com.android.systemui.statusbar.policy.BatteryController;
Beverlyff2df9b2018-10-10 16:54:10 -040076import com.android.systemui.statusbar.policy.Clock;
Evan Laird39254d42018-01-18 16:05:30 -050077import com.android.systemui.statusbar.policy.DarkIconDispatcher;
Jason Monk824ffff2017-04-11 15:49:06 -040078import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
Rohan Shahcc3d1d82018-03-30 21:24:17 +000079import com.android.systemui.statusbar.policy.DateView;
Rohan Shahd3cf7562018-02-23 11:12:28 -080080import com.android.systemui.statusbar.policy.NextAlarmController;
Beverlyb9826dd2018-04-12 15:02:45 -040081import com.android.systemui.statusbar.policy.ZenModeController;
Jason Monke5b770e2017-03-03 21:49:29 -050082
Fabian Kozynski8d06c712018-11-07 10:33:02 -050083import java.util.List;
Lucas Dupin1f7374a2018-02-26 18:08:33 -080084import java.util.Locale;
Beverlyb9826dd2018-04-12 15:02:45 -040085import java.util.Objects;
Lucas Dupin1f7374a2018-02-26 18:08:33 -080086
Rohan Shahd3cf7562018-02-23 11:12:28 -080087/**
88 * View that contains the top-most bits of the screen (primarily the status bar with date, time, and
89 * battery) and also contains the {@link QuickQSPanel} along with some of the panel's inner
90 * contents.
91 */
Amin Shaikhf09450b2018-04-06 17:32:45 -040092public class QuickStatusBarHeader extends RelativeLayout implements
Beverlyb9826dd2018-04-12 15:02:45 -040093 View.OnClickListener, NextAlarmController.NextAlarmChangeCallback,
94 ZenModeController.Callback {
Rohan Shaha160ab12018-03-09 15:47:36 -080095 private static final String TAG = "QuickStatusBarHeader";
96 private static final boolean DEBUG = false;
Jason Monke5b770e2017-03-03 21:49:29 -050097
Rohan Shahd3cf7562018-02-23 11:12:28 -080098 /** Delay for auto fading out the long press tooltip after it's fully visible (in ms). */
99 private static final long AUTO_FADE_OUT_DELAY_MS = DateUtils.SECOND_IN_MILLIS * 6;
100 private static final int FADE_ANIMATION_DURATION_MS = 300;
101 private static final int TOOLTIP_NOT_YET_SHOWN_COUNT = 0;
Rohan Shahb6a915c2018-03-01 11:57:00 -0800102 public static final int MAX_TOOLTIP_SHOWN_COUNT = 2;
Rohan Shahd3cf7562018-02-23 11:12:28 -0800103
104 private final Handler mHandler = new Handler();
Jason Monke5b770e2017-03-03 21:49:29 -0500105
106 private QSPanel mQsPanel;
107
108 private boolean mExpanded;
109 private boolean mListening;
Charles Hece2a7c02017-10-11 20:25:20 +0100110 private boolean mQsDisabled;
Jason Monke5b770e2017-03-03 21:49:29 -0500111
112 protected QuickQSPanel mHeaderQsPanel;
113 protected QSTileHost mHost;
Evan Laird95896952018-01-22 19:30:05 -0500114 private TintedIconManager mIconManager;
Rohan Shahd3cf7562018-02-23 11:12:28 -0800115 private TouchAnimator mStatusIconsAlphaAnimator;
116 private TouchAnimator mHeaderTextContainerAlphaAnimator;
Evan Laird95896952018-01-22 19:30:05 -0500117
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000118 private View mSystemIconsView;
Evan Laird95896952018-01-22 19:30:05 -0500119 private View mQuickQsStatusIcons;
Rohan Shahd3cf7562018-02-23 11:12:28 -0800120 private View mHeaderTextContainerView;
Amin Shaikh761c5662018-03-27 16:55:43 -0400121 /** View containing the next alarm and ringer mode info. */
122 private View mStatusContainer;
Rohan Shahd3cf7562018-02-23 11:12:28 -0800123 /** Tooltip for educating users that they can long press on icons to see more details. */
124 private View mLongPressTooltipView;
Amin Shaikh761c5662018-03-27 16:55:43 -0400125
126 private int mRingerMode = AudioManager.RINGER_MODE_NORMAL;
127 private AlarmManager.AlarmClockInfo mNextAlarm;
128
129 private ImageView mNextAlarmIcon;
Rohan Shahd3cf7562018-02-23 11:12:28 -0800130 /** {@link TextView} containing the actual text indicating when the next alarm will go off. */
131 private TextView mNextAlarmTextView;
Amin Shaikh761c5662018-03-27 16:55:43 -0400132 private View mStatusSeparator;
133 private ImageView mRingerModeIcon;
134 private TextView mRingerModeTextView;
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000135 private BatteryMeterView mBatteryMeterView;
136 private Clock mClockView;
137 private DateView mDateView;
Fabian Kozynski12638242018-10-12 15:33:41 -0400138 private OngoingPrivacyChip mPrivacyChip;
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500139 private Space mSpace;
Evan Laird4bf21df2018-10-22 14:24:32 -0400140 private BatteryMeterView mBatteryRemainingIcon;
141 private TextView mBatteryRemainingText;
142 private boolean mShowBatteryPercentAndEstimate;
Rohan Shahd3cf7562018-02-23 11:12:28 -0800143
144 private NextAlarmController mAlarmController;
Beverlyb9826dd2018-04-12 15:02:45 -0400145 private ZenModeController mZenController;
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500146 private PrivacyItemController mPrivacyItemController;
Rohan Shahd3cf7562018-02-23 11:12:28 -0800147 /** Counts how many times the long press tooltip has been shown to the user. */
148 private int mShownCount;
149
Amin Shaikh761c5662018-03-27 16:55:43 -0400150 private final BroadcastReceiver mRingerReceiver = new BroadcastReceiver() {
151 @Override
152 public void onReceive(Context context, Intent intent) {
153 mRingerMode = intent.getIntExtra(AudioManager.EXTRA_RINGER_MODE, -1);
154 updateStatusText();
155 }
156 };
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500157 private boolean mHasTopCutout = false;
Amin Shaikh761c5662018-03-27 16:55:43 -0400158
Evan Laird4bf21df2018-10-22 14:24:32 -0400159 private final PercentSettingObserver mPercentSettingObserver =
160 new PercentSettingObserver(new Handler(mContext.getMainLooper()));
161
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 Monke5b770e2017-03-03 21:49:29 -0500175 public QuickStatusBarHeader(Context context, AttributeSet attrs) {
176 super(context, attrs);
Rohan Shahd3cf7562018-02-23 11:12:28 -0800177 mAlarmController = Dependency.get(NextAlarmController.class);
Beverlyb9826dd2018-04-12 15:02:45 -0400178 mZenController = Dependency.get(ZenModeController.class);
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500179 mPrivacyItemController = new PrivacyItemController(context, mPICCallback);
Rohan Shahd3cf7562018-02-23 11:12:28 -0800180 mShownCount = getStoredShownCount();
Jason Monke5b770e2017-03-03 21:49:29 -0500181 }
182
183 @Override
184 protected void onFinishInflate() {
185 super.onFinishInflate();
Jason Monke5b770e2017-03-03 21:49:29 -0500186
187 mHeaderQsPanel = findViewById(R.id.quick_qs_panel);
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000188 mSystemIconsView = findViewById(R.id.quick_status_bar_system_icons);
Evan Laird95896952018-01-22 19:30:05 -0500189 mQuickQsStatusIcons = findViewById(R.id.quick_qs_status_icons);
Evan Laird20b87bf2018-04-12 09:54:11 -0400190 StatusIconContainer iconContainer = findViewById(R.id.statusIcons);
191 iconContainer.setShouldRestrictIcons(false);
192 mIconManager = new TintedIconManager(iconContainer);
Jason Monke5b770e2017-03-03 21:49:29 -0500193
Rohan Shahd3cf7562018-02-23 11:12:28 -0800194 // Views corresponding to the header info section (e.g. tooltip and next alarm).
195 mHeaderTextContainerView = findViewById(R.id.header_text_container);
196 mLongPressTooltipView = findViewById(R.id.long_press_tooltip);
Amin Shaikh761c5662018-03-27 16:55:43 -0400197 mStatusContainer = findViewById(R.id.status_container);
198 mStatusSeparator = findViewById(R.id.status_separator);
199 mNextAlarmIcon = findViewById(R.id.next_alarm_icon);
Rohan Shahd3cf7562018-02-23 11:12:28 -0800200 mNextAlarmTextView = findViewById(R.id.next_alarm_text);
Amin Shaikh761c5662018-03-27 16:55:43 -0400201 mRingerModeIcon = findViewById(R.id.ringer_mode_icon);
202 mRingerModeTextView = findViewById(R.id.ringer_mode_text);
Jason Monke5b770e2017-03-03 21:49:29 -0500203
204 updateResources();
205
Jason Monk824ffff2017-04-11 15:49:06 -0400206 Rect tintArea = new Rect(0, 0, 0, 0);
Jason Changb4e879d2018-04-11 11:17:58 +0800207 int colorForeground = Utils.getColorAttrDefaultColor(getContext(),
208 android.R.attr.colorForeground);
Amin Shaikh0e003312018-03-08 11:39:01 -0500209 float intensity = getColorIntensity(colorForeground);
Evan Laird95896952018-01-22 19:30:05 -0500210 int fillColor = fillColorForIntensity(intensity, getContext());
211
212 // Set light text on the header icons because they will always be on a black background
Evan Laird39254d42018-01-18 16:05:30 -0500213 applyDarkness(R.id.clock, tintArea, 0, DarkIconDispatcher.DEFAULT_ICON_TINT);
Evan Laird95896952018-01-22 19:30:05 -0500214
215 // Set the correct tint for the status icons so they contrast
216 mIconManager.setTint(fillColor);
Jason Monke5b770e2017-03-03 21:49:29 -0500217
Evan Laird4bf21df2018-10-22 14:24:32 -0400218 mShowBatteryPercentAndEstimate = mContext.getResources().getBoolean(
219 com.android.internal.R.bool.config_battery_percentage_setting_available);
220
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000221 mBatteryMeterView = findViewById(R.id.battery);
Evan Laird4bf21df2018-10-22 14:24:32 -0400222 mBatteryMeterView.setPercentShowMode(mShowBatteryPercentAndEstimate
223 ? BatteryMeterView.MODE_ON : BatteryMeterView.MODE_OFF);
Amin Shaikh39bdc502018-05-15 23:43:34 -0400224 mBatteryMeterView.setOnClickListener(this);
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000225 mClockView = findViewById(R.id.clock);
Amin Shaikh39bdc502018-05-15 23:43:34 -0400226 mClockView.setOnClickListener(this);
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000227 mDateView = findViewById(R.id.date);
Fabian Kozynski12638242018-10-12 15:33:41 -0400228 mPrivacyChip = findViewById(R.id.privacy_chip);
229 mPrivacyChip.setOnClickListener(this);
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500230 mSpace = findViewById(R.id.space);
Evan Laird4bf21df2018-10-22 14:24:32 -0400231
232 // Tint for the battery icons are handled in setupHost()
233 mBatteryRemainingIcon = findViewById(R.id.batteryRemainingIcon);
234 mBatteryRemainingIcon.setPercentShowMode(BatteryMeterView.MODE_OFF);
Evan Laird698839b2018-12-05 15:49:12 -0500235 // Don't need to worry about tuner settings for this icon
236 mBatteryRemainingIcon.setIgnoreTunerUpdates(true);
Evan Laird4bf21df2018-10-22 14:24:32 -0400237
238 mBatteryRemainingText = findViewById(R.id.batteryRemainingText);
239 mBatteryRemainingText.setTextColor(fillColor);
240
241 updateShowPercent();
Jason Monke5b770e2017-03-03 21:49:29 -0500242 }
243
Amin Shaikh761c5662018-03-27 16:55:43 -0400244 private void updateStatusText() {
Beverlyb9826dd2018-04-12 15:02:45 -0400245 boolean changed = updateRingerStatus() || updateAlarmStatus();
246
247 if (changed) {
248 boolean alarmVisible = mNextAlarmTextView.getVisibility() == View.VISIBLE;
249 boolean ringerVisible = mRingerModeTextView.getVisibility() == View.VISIBLE;
250 mStatusSeparator.setVisibility(alarmVisible && ringerVisible ? View.VISIBLE
251 : View.GONE);
252 updateTooltipShow();
253 }
254 }
255
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500256 private void setChipVisibility(boolean chipVisible) {
257 mBatteryMeterView.setVisibility(View.VISIBLE);
258 if (chipVisible) {
259 mPrivacyChip.setVisibility(View.VISIBLE);
260 if (mHasTopCutout) mBatteryMeterView.setVisibility(View.GONE);
261 } else {
262 mPrivacyChip.setVisibility(View.GONE);
263 }
264 }
265
Beverlyb9826dd2018-04-12 15:02:45 -0400266 private boolean updateRingerStatus() {
267 boolean isOriginalVisible = mRingerModeTextView.getVisibility() == View.VISIBLE;
268 CharSequence originalRingerText = mRingerModeTextView.getText();
269
Amin Shaikh761c5662018-03-27 16:55:43 -0400270 boolean ringerVisible = false;
Beverlyb9826dd2018-04-12 15:02:45 -0400271 if (!ZenModeConfig.isZenOverridingRinger(mZenController.getZen(),
Beverlyff2df9b2018-10-10 16:54:10 -0400272 mZenController.getConsolidatedPolicy())) {
Beverlyb9826dd2018-04-12 15:02:45 -0400273 if (mRingerMode == AudioManager.RINGER_MODE_VIBRATE) {
274 mRingerModeIcon.setImageResource(R.drawable.stat_sys_ringer_vibrate);
275 mRingerModeTextView.setText(R.string.qs_status_phone_vibrate);
276 ringerVisible = true;
277 } else if (mRingerMode == AudioManager.RINGER_MODE_SILENT) {
278 mRingerModeIcon.setImageResource(R.drawable.stat_sys_ringer_silent);
279 mRingerModeTextView.setText(R.string.qs_status_phone_muted);
280 ringerVisible = true;
281 }
Amin Shaikh761c5662018-03-27 16:55:43 -0400282 }
283 mRingerModeIcon.setVisibility(ringerVisible ? View.VISIBLE : View.GONE);
284 mRingerModeTextView.setVisibility(ringerVisible ? View.VISIBLE : View.GONE);
285
Beverlyb9826dd2018-04-12 15:02:45 -0400286 return isOriginalVisible != ringerVisible ||
287 !Objects.equals(originalRingerText, mRingerModeTextView.getText());
288 }
289
290 private boolean updateAlarmStatus() {
291 boolean isOriginalVisible = mNextAlarmTextView.getVisibility() == View.VISIBLE;
292 CharSequence originalAlarmText = mNextAlarmTextView.getText();
293
Amin Shaikh761c5662018-03-27 16:55:43 -0400294 boolean alarmVisible = false;
295 if (mNextAlarm != null) {
296 alarmVisible = true;
297 mNextAlarmTextView.setText(formatNextAlarm(mNextAlarm));
298 }
299 mNextAlarmIcon.setVisibility(alarmVisible ? View.VISIBLE : View.GONE);
300 mNextAlarmTextView.setVisibility(alarmVisible ? View.VISIBLE : View.GONE);
Amin Shaikh761c5662018-03-27 16:55:43 -0400301
Beverlyb9826dd2018-04-12 15:02:45 -0400302 return isOriginalVisible != alarmVisible ||
303 !Objects.equals(originalAlarmText, mNextAlarmTextView.getText());
304 }
Amin Shaikh761c5662018-03-27 16:55:43 -0400305
Jason Monk824ffff2017-04-11 15:49:06 -0400306 private void applyDarkness(int id, Rect tintArea, float intensity, int color) {
307 View v = findViewById(id);
308 if (v instanceof DarkReceiver) {
309 ((DarkReceiver) v).onDarkChanged(tintArea, intensity, color);
310 }
311 }
312
Evan Laird95896952018-01-22 19:30:05 -0500313 private int fillColorForIntensity(float intensity, Context context) {
314 if (intensity == 0) {
Amin Shaikh9cac3382018-04-11 17:10:07 -0400315 return context.getColor(R.color.light_mode_icon_color_single_tone);
Evan Laird95896952018-01-22 19:30:05 -0500316 }
Amin Shaikh9cac3382018-04-11 17:10:07 -0400317 return context.getColor(R.color.dark_mode_icon_color_single_tone);
Evan Laird95896952018-01-22 19:30:05 -0500318 }
319
Jason Monke5b770e2017-03-03 21:49:29 -0500320 @Override
321 protected void onConfigurationChanged(Configuration newConfig) {
322 super.onConfigurationChanged(newConfig);
323 updateResources();
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000324
325 // Update color schemes in landscape to use wallpaperTextColor
326 boolean shouldUseWallpaperTextColor =
327 newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE;
328 mBatteryMeterView.useWallpaperTextColor(shouldUseWallpaperTextColor);
329 mClockView.useWallpaperTextColor(shouldUseWallpaperTextColor);
Jason Monke5b770e2017-03-03 21:49:29 -0500330 }
331
Fabian Kozynskief124492018-11-02 11:02:11 -0400332
333
Jason Monke5b770e2017-03-03 21:49:29 -0500334 @Override
335 public void onRtlPropertiesChanged(int layoutDirection) {
336 super.onRtlPropertiesChanged(layoutDirection);
337 updateResources();
338 }
339
Evan Laird84b98952018-07-02 17:43:59 -0400340 /**
341 * The height of QQS should always be the status bar height + 128dp. This is normally easy, but
342 * when there is a notch involved the status bar can remain a fixed pixel size.
343 */
344 private void updateMinimumHeight() {
345 int sbHeight = mContext.getResources().getDimensionPixelSize(
346 com.android.internal.R.dimen.status_bar_height);
347 int qqsHeight = mContext.getResources().getDimensionPixelSize(
348 R.dimen.qs_quick_header_panel_height);
349
350 setMinimumHeight(sbHeight + qqsHeight);
351 }
352
Jason Monke5b770e2017-03-03 21:49:29 -0500353 private void updateResources() {
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000354 Resources resources = mContext.getResources();
Evan Laird84b98952018-07-02 17:43:59 -0400355 updateMinimumHeight();
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000356
357 // Update height for a few views, especially due to landscape mode restricting space.
Rohan Shahd3cf7562018-02-23 11:12:28 -0800358 mHeaderTextContainerView.getLayoutParams().height =
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000359 resources.getDimensionPixelSize(R.dimen.qs_header_tooltip_height);
Rohan Shahd3cf7562018-02-23 11:12:28 -0800360 mHeaderTextContainerView.setLayoutParams(mHeaderTextContainerView.getLayoutParams());
361
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000362 mSystemIconsView.getLayoutParams().height = resources.getDimensionPixelSize(
363 com.android.internal.R.dimen.quick_qs_offset_height);
364 mSystemIconsView.setLayoutParams(mSystemIconsView.getLayoutParams());
365
Evan Laird84b98952018-07-02 17:43:59 -0400366 FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
367 if (mQsDisabled) {
368 lp.height = resources.getDimensionPixelSize(
369 com.android.internal.R.dimen.quick_qs_offset_height);
370 } else {
371 lp.height = Math.max(getMinimumHeight(),
372 resources.getDimensionPixelSize(
Evan Lairdbf3794a2018-07-17 15:55:40 -0400373 com.android.internal.R.dimen.quick_qs_total_height));
Evan Laird84b98952018-07-02 17:43:59 -0400374 }
375
376 setLayoutParams(lp);
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000377
Fabian Kozynskief124492018-11-02 11:02:11 -0400378 if (mPrivacyChip != null) {
379 MarginLayoutParams lm = (MarginLayoutParams) mPrivacyChip.getLayoutParams();
380 int sideMargins = lm.leftMargin;
381 int topBottomMargins = resources.getDimensionPixelSize(
382 R.dimen.ongoing_appops_top_chip_margin);
383 lm.setMargins(sideMargins, topBottomMargins, sideMargins, topBottomMargins);
384 mPrivacyChip.setLayoutParams(lm);
385 }
386
Rohan Shahd3cf7562018-02-23 11:12:28 -0800387 updateStatusIconAlphaAnimator();
388 updateHeaderTextContainerAlphaAnimator();
Evan Laird95896952018-01-22 19:30:05 -0500389 }
390
Rohan Shahd3cf7562018-02-23 11:12:28 -0800391 private void updateStatusIconAlphaAnimator() {
392 mStatusIconsAlphaAnimator = new TouchAnimator.Builder()
Evan Laird95896952018-01-22 19:30:05 -0500393 .addFloat(mQuickQsStatusIcons, "alpha", 1, 0)
394 .build();
Jason Monke5b770e2017-03-03 21:49:29 -0500395 }
396
Rohan Shahd3cf7562018-02-23 11:12:28 -0800397 private void updateHeaderTextContainerAlphaAnimator() {
398 mHeaderTextContainerAlphaAnimator = new TouchAnimator.Builder()
399 .addFloat(mHeaderTextContainerView, "alpha", 0, 1)
400 .setStartDelay(.5f)
401 .build();
Jason Monke5b770e2017-03-03 21:49:29 -0500402 }
403
Evan Laird4bf21df2018-10-22 14:24:32 -0400404 private void updateBatteryRemainingText() {
405 if (!mShowBatteryPercentAndEstimate) {
406 return;
407 }
408 mBatteryRemainingText.setText(
409 Dependency.get(BatteryController.class).getEstimatedTimeRemainingString());
410 }
411
Jason Monke5b770e2017-03-03 21:49:29 -0500412 public void setExpanded(boolean expanded) {
413 if (mExpanded == expanded) return;
414 mExpanded = expanded;
415 mHeaderQsPanel.setExpanded(expanded);
Fabian Kozynskif3a77012019-01-09 15:37:30 +0000416 updateEverything();
Jason Monke5b770e2017-03-03 21:49:29 -0500417 }
418
Rohan Shahd3cf7562018-02-23 11:12:28 -0800419 /**
420 * Animates the inner contents based on the given expansion details.
421 *
422 * @param isKeyguardShowing whether or not we're showing the keyguard (a.k.a. lockscreen)
423 * @param expansionFraction how much the QS panel is expanded/pulled out (up to 1f)
424 * @param panelTranslationY how much the panel has physically moved down vertically (required
425 * for keyguard animations only)
426 */
427 public void setExpansion(boolean isKeyguardShowing, float expansionFraction,
428 float panelTranslationY) {
429 final float keyguardExpansionFraction = isKeyguardShowing ? 1f : expansionFraction;
430 if (mStatusIconsAlphaAnimator != null) {
431 mStatusIconsAlphaAnimator.setPosition(keyguardExpansionFraction);
Evan Laird95896952018-01-22 19:30:05 -0500432 }
Rohan Shahd3cf7562018-02-23 11:12:28 -0800433
434 if (isKeyguardShowing) {
435 // If the keyguard is showing, we want to offset the text so that it comes in at the
436 // same time as the panel as it slides down.
437 mHeaderTextContainerView.setTranslationY(panelTranslationY);
438 } else {
439 mHeaderTextContainerView.setTranslationY(0f);
440 }
441
442 if (mHeaderTextContainerAlphaAnimator != null) {
443 mHeaderTextContainerAlphaAnimator.setPosition(keyguardExpansionFraction);
444 }
445
446 // Check the original expansion fraction - we don't want to show the tooltip until the
447 // panel is pulled all the way out.
448 if (expansionFraction == 1f) {
449 // QS is fully expanded, bring in the tooltip.
450 showLongPressTooltip();
451 }
452 }
453
454 /** Returns the latest stored tooltip shown count from SharedPreferences. */
455 private int getStoredShownCount() {
456 return Prefs.getInt(
457 mContext,
458 Prefs.Key.QS_LONG_PRESS_TOOLTIP_SHOWN_COUNT,
459 TOOLTIP_NOT_YET_SHOWN_COUNT);
Jason Monke5b770e2017-03-03 21:49:29 -0500460 }
461
Charles Hece2a7c02017-10-11 20:25:20 +0100462 public void disable(int state1, int state2, boolean animate) {
463 final boolean disabled = (state2 & DISABLE2_QUICK_SETTINGS) != 0;
464 if (disabled == mQsDisabled) return;
465 mQsDisabled = disabled;
466 mHeaderQsPanel.setDisabledByPolicy(disabled);
Amin Shaikhf09450b2018-04-06 17:32:45 -0400467 mHeaderTextContainerView.setVisibility(mQsDisabled ? View.GONE : View.VISIBLE);
468 mQuickQsStatusIcons.setVisibility(mQsDisabled ? View.GONE : View.VISIBLE);
469 updateResources();
Charles Hece2a7c02017-10-11 20:25:20 +0100470 }
471
472 @Override
473 public void onAttachedToWindow() {
Amin Shaikha59215a2018-04-23 08:52:38 -0400474 super.onAttachedToWindow();
Evan Laird95896952018-01-22 19:30:05 -0500475 Dependency.get(StatusBarIconController.class).addIconGroup(mIconManager);
Adrian Roos13836052018-03-15 21:06:37 +0100476 requestApplyInsets();
Evan Laird4bf21df2018-10-22 14:24:32 -0400477 mContext.getContentResolver().registerContentObserver(
478 Settings.System.getUriFor(SHOW_BATTERY_PERCENT), false, mPercentSettingObserver,
479 ActivityManager.getCurrentUser());
Adrian Roos13836052018-03-15 21:06:37 +0100480 }
481
482 @Override
483 public WindowInsets onApplyWindowInsets(WindowInsets insets) {
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500484 DisplayCutout cutout = insets.getDisplayCutout();
Adrian Roos13836052018-03-15 21:06:37 +0100485 Pair<Integer, Integer> padding = PhoneStatusBarView.cornerCutoutMargins(
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500486 cutout, getDisplay());
Adrian Roos13836052018-03-15 21:06:37 +0100487 if (padding == null) {
Amin Shaikh7d86b042018-04-16 16:00:12 -0400488 mSystemIconsView.setPaddingRelative(
489 getResources().getDimensionPixelSize(R.dimen.status_bar_padding_start), 0,
490 getResources().getDimensionPixelSize(R.dimen.status_bar_padding_end), 0);
Adrian Roos13836052018-03-15 21:06:37 +0100491 } else {
Amin Shaikh7d86b042018-04-16 16:00:12 -0400492 mSystemIconsView.setPadding(padding.first, 0, padding.second, 0);
493
Adrian Roos13836052018-03-15 21:06:37 +0100494 }
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500495 LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mSpace.getLayoutParams();
496 if (cutout != null) {
497 Rect topCutout = cutout.getBoundingRectTop();
498 if (topCutout.isEmpty()) {
499 mHasTopCutout = false;
500 lp.width = 0;
501 mSpace.setVisibility(View.GONE);
502 } else {
503 mHasTopCutout = true;
504 lp.width = topCutout.width();
505 mSpace.setVisibility(View.VISIBLE);
506 }
507 }
508 mSpace.setLayoutParams(lp);
509 // Decide whether to show BatteryMeterView
510 setChipVisibility(mPrivacyChip.getVisibility() == View.VISIBLE);
Adrian Roos13836052018-03-15 21:06:37 +0100511 return super.onApplyWindowInsets(insets);
Charles Hece2a7c02017-10-11 20:25:20 +0100512 }
513
514 @Override
Jason Monke5b770e2017-03-03 21:49:29 -0500515 @VisibleForTesting
516 public void onDetachedFromWindow() {
517 setListening(false);
Evan Laird95896952018-01-22 19:30:05 -0500518 Dependency.get(StatusBarIconController.class).removeIconGroup(mIconManager);
Evan Laird4bf21df2018-10-22 14:24:32 -0400519 mContext.getContentResolver().unregisterContentObserver(mPercentSettingObserver);
Jason Monke5b770e2017-03-03 21:49:29 -0500520 super.onDetachedFromWindow();
521 }
522
523 public void setListening(boolean listening) {
524 if (listening == mListening) {
525 return;
526 }
527 mHeaderQsPanel.setListening(listening);
Fabian Kozynski8d06c712018-11-07 10:33:02 -0500528 mPrivacyItemController.setListening(listening);
Jason Monke5b770e2017-03-03 21:49:29 -0500529 mListening = listening;
Rohan Shahd3cf7562018-02-23 11:12:28 -0800530
531 if (listening) {
Beverlyb9826dd2018-04-12 15:02:45 -0400532 mZenController.addCallback(this);
Rohan Shahd3cf7562018-02-23 11:12:28 -0800533 mAlarmController.addCallback(this);
Amin Shaikh761c5662018-03-27 16:55:43 -0400534 mContext.registerReceiver(mRingerReceiver,
535 new IntentFilter(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION));
Evan Laird4bf21df2018-10-22 14:24:32 -0400536 updateBatteryRemainingText();
Rohan Shahd3cf7562018-02-23 11:12:28 -0800537 } else {
Beverlyb9826dd2018-04-12 15:02:45 -0400538 mZenController.removeCallback(this);
Rohan Shahd3cf7562018-02-23 11:12:28 -0800539 mAlarmController.removeCallback(this);
Amin Shaikh761c5662018-03-27 16:55:43 -0400540 mContext.unregisterReceiver(mRingerReceiver);
Rohan Shahd3cf7562018-02-23 11:12:28 -0800541 }
Jason Monke5b770e2017-03-03 21:49:29 -0500542 }
543
Evan Laird95896952018-01-22 19:30:05 -0500544 @Override
545 public void onClick(View v) {
Amin Shaikh39bdc502018-05-15 23:43:34 -0400546 if (v == mClockView) {
Evan Laird95896952018-01-22 19:30:05 -0500547 Dependency.get(ActivityStarter.class).postStartActivityDismissingKeyguard(new Intent(
548 AlarmClock.ACTION_SHOW_ALARMS),0);
Amin Shaikh39bdc502018-05-15 23:43:34 -0400549 } else if (v == mBatteryMeterView) {
550 Dependency.get(ActivityStarter.class).postStartActivityDismissingKeyguard(new Intent(
551 Intent.ACTION_POWER_USAGE_SUMMARY),0);
Fabian Kozynski12638242018-10-12 15:33:41 -0400552 } else if (v == mPrivacyChip) {
553 Handler mUiHandler = new Handler(Looper.getMainLooper());
554 mUiHandler.post(() -> {
555 Dialog mDialog = new OngoingPrivacyDialog(mContext,
556 mPrivacyChip.getBuilder()).createDialog();
557 mDialog.getWindow().setType(
558 WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
559 SystemUIDialog.setShowForAllUsers(mDialog, true);
560 SystemUIDialog.registerDismissListener(mDialog);
561 SystemUIDialog.setWindowOnTop(mDialog);
562 mUiHandler.post(() -> mDialog.show());
563 mHost.collapsePanels();
564 });
Evan Laird95896952018-01-22 19:30:05 -0500565 }
566 }
567
Rohan Shahd3cf7562018-02-23 11:12:28 -0800568 @Override
569 public void onNextAlarmChanged(AlarmManager.AlarmClockInfo nextAlarm) {
Amin Shaikh761c5662018-03-27 16:55:43 -0400570 mNextAlarm = nextAlarm;
571 updateStatusText();
572 }
Rohan Shaha160ab12018-03-09 15:47:36 -0800573
Beverlyb9826dd2018-04-12 15:02:45 -0400574 @Override
575 public void onZenChanged(int zen) {
576 updateStatusText();
577
578 }
579
580 @Override
581 public void onConfigChanged(ZenModeConfig config) {
582 updateStatusText();
583 }
584
Amin Shaikh761c5662018-03-27 16:55:43 -0400585 private void updateTooltipShow() {
586 if (hasStatusText()) {
587 hideLongPressTooltip(true /* shouldShowStatusText */);
Rohan Shahd3cf7562018-02-23 11:12:28 -0800588 } else {
Amin Shaikh761c5662018-03-27 16:55:43 -0400589 hideStatusText();
Rohan Shahd3cf7562018-02-23 11:12:28 -0800590 }
591 updateHeaderTextContainerAlphaAnimator();
592 }
593
Amin Shaikh761c5662018-03-27 16:55:43 -0400594 private boolean hasStatusText() {
595 return mNextAlarmTextView.getVisibility() == View.VISIBLE
596 || mRingerModeTextView.getVisibility() == View.VISIBLE;
597 }
598
Rohan Shahd3cf7562018-02-23 11:12:28 -0800599 /**
600 * Animates in the long press tooltip (as long as the next alarm text isn't currently occupying
601 * the space).
602 */
603 public void showLongPressTooltip() {
Amin Shaikh761c5662018-03-27 16:55:43 -0400604 // If we have status text to show, don't bother fading in the tooltip.
605 if (hasStatusText()) {
Rohan Shahd3cf7562018-02-23 11:12:28 -0800606 return;
607 }
608
609 if (mShownCount < MAX_TOOLTIP_SHOWN_COUNT) {
610 mLongPressTooltipView.animate().cancel();
611 mLongPressTooltipView.setVisibility(View.VISIBLE);
612 mLongPressTooltipView.animate()
613 .alpha(1f)
614 .setDuration(FADE_ANIMATION_DURATION_MS)
615 .setListener(new AnimatorListenerAdapter() {
616 @Override
617 public void onAnimationEnd(Animator animation) {
618 mHandler.postDelayed(
619 mAutoFadeOutTooltipRunnable, AUTO_FADE_OUT_DELAY_MS);
620 }
621 })
622 .start();
623
624 // Increment and drop the shown count in prefs for the next time we're deciding to
625 // fade in the tooltip. We first sanity check that the tooltip count hasn't changed yet
626 // in prefs (say, from a long press).
627 if (getStoredShownCount() <= mShownCount) {
628 Prefs.putInt(mContext, Prefs.Key.QS_LONG_PRESS_TOOLTIP_SHOWN_COUNT, ++mShownCount);
629 }
630 }
631 }
632
633 /**
634 * Fades out the long press tooltip if it's partially visible - short circuits any running
Amin Shaikh761c5662018-03-27 16:55:43 -0400635 * animation. Additionally has the ability to fade in the status info text.
Rohan Shahd3cf7562018-02-23 11:12:28 -0800636 *
Amin Shaikh761c5662018-03-27 16:55:43 -0400637 * @param shouldShowStatusText whether we should fade in the status text
Rohan Shahd3cf7562018-02-23 11:12:28 -0800638 */
Amin Shaikh761c5662018-03-27 16:55:43 -0400639 private void hideLongPressTooltip(boolean shouldShowStatusText) {
Rohan Shahd3cf7562018-02-23 11:12:28 -0800640 mLongPressTooltipView.animate().cancel();
641 if (mLongPressTooltipView.getVisibility() == View.VISIBLE
642 && mLongPressTooltipView.getAlpha() != 0f) {
643 mHandler.removeCallbacks(mAutoFadeOutTooltipRunnable);
644 mLongPressTooltipView.animate()
645 .alpha(0f)
646 .setDuration(FADE_ANIMATION_DURATION_MS)
647 .setListener(new AnimatorListenerAdapter() {
648 @Override
649 public void onAnimationEnd(Animator animation) {
Rohan Shaha160ab12018-03-09 15:47:36 -0800650 if (DEBUG) Log.d(TAG, "hideLongPressTooltip: Hid long press tip");
Rohan Shahd3cf7562018-02-23 11:12:28 -0800651 mLongPressTooltipView.setVisibility(View.INVISIBLE);
652
Amin Shaikh761c5662018-03-27 16:55:43 -0400653 if (shouldShowStatusText) {
654 showStatus();
Rohan Shahd3cf7562018-02-23 11:12:28 -0800655 }
656 }
657 })
658 .start();
659 } else {
660 mLongPressTooltipView.setVisibility(View.INVISIBLE);
Amin Shaikh761c5662018-03-27 16:55:43 -0400661 if (shouldShowStatusText) {
662 showStatus();
Rohan Shahd3cf7562018-02-23 11:12:28 -0800663 }
664 }
665 }
666
667 /**
Amin Shaikh761c5662018-03-27 16:55:43 -0400668 * Fades in the updated status text. Note that if there's already a status showing, this will
Fabian Kozynski3f789332018-09-04 16:42:43 -0400669 * immediately fade it out and fade in the updated status.
Rohan Shahd3cf7562018-02-23 11:12:28 -0800670 */
Amin Shaikh761c5662018-03-27 16:55:43 -0400671 private void showStatus() {
672 mStatusContainer.setAlpha(0f);
Rohan Shahd3cf7562018-02-23 11:12:28 -0800673
Amin Shaikh761c5662018-03-27 16:55:43 -0400674 mStatusContainer.animate()
Rohan Shahd3cf7562018-02-23 11:12:28 -0800675 .alpha(1f)
676 .setDuration(FADE_ANIMATION_DURATION_MS)
677 .start();
678 }
679
Fabian Kozynski3f789332018-09-04 16:42:43 -0400680 /** Fades out the status text. */
Amin Shaikh761c5662018-03-27 16:55:43 -0400681 private void hideStatusText() {
Fabian Kozynski3f789332018-09-04 16:42:43 -0400682 mStatusContainer.animate()
683 .alpha(0f)
684 .setDuration(FADE_ANIMATION_DURATION_MS)
685 .start();
Rohan Shahd3cf7562018-02-23 11:12:28 -0800686 }
687
Fabian Kozynskif3a77012019-01-09 15:37:30 +0000688 public void updateEverything() {
689 post(() -> setClickable(false));
690 }
691
Jason Monke5b770e2017-03-03 21:49:29 -0500692 public void setQSPanel(final QSPanel qsPanel) {
693 mQsPanel = qsPanel;
694 setupHost(qsPanel.getHost());
695 }
696
697 public void setupHost(final QSTileHost host) {
698 mHost = host;
699 //host.setHeaderView(mExpandIndicator);
700 mHeaderQsPanel.setQSPanelAndHeader(mQsPanel, this);
701 mHeaderQsPanel.setHost(host, null /* No customization in header */);
Evan Lairdef160f22018-01-29 14:08:45 -0500702
703 // Use SystemUI context to get battery meter colors, and let it use the default tint (white)
Rohan Shahcc3d1d82018-03-30 21:24:17 +0000704 mBatteryMeterView.setColorsFromContext(mHost.getContext());
705 mBatteryMeterView.onDarkChanged(new Rect(), 0, DarkIconDispatcher.DEFAULT_ICON_TINT);
Evan Laird4bf21df2018-10-22 14:24:32 -0400706
707 Rect tintArea = new Rect(0, 0, 0, 0);
708 int colorForeground = Utils.getColorAttrDefaultColor(getContext(),
709 android.R.attr.colorForeground);
710 float intensity = getColorIntensity(colorForeground);
711 int fillColor = fillColorForIntensity(intensity, getContext());
712 mBatteryRemainingIcon.setColorsFromContext(mHost.getContext());
713 mBatteryRemainingIcon.onDarkChanged(tintArea, intensity, fillColor);
Jason Monke5b770e2017-03-03 21:49:29 -0500714 }
715
716 public void setCallback(Callback qsPanelCallback) {
717 mHeaderQsPanel.setCallback(qsPanelCallback);
718 }
Lucas Dupin1f7374a2018-02-26 18:08:33 -0800719
720 private String formatNextAlarm(AlarmManager.AlarmClockInfo info) {
721 if (info == null) {
722 return "";
723 }
724 String skeleton = android.text.format.DateFormat
725 .is24HourFormat(mContext, ActivityManager.getCurrentUser()) ? "EHm" : "Ehma";
726 String pattern = android.text.format.DateFormat
727 .getBestDateTimePattern(Locale.getDefault(), skeleton);
728 return android.text.format.DateFormat.format(pattern, info.getTriggerTime()).toString();
729 }
Amin Shaikh0e003312018-03-08 11:39:01 -0500730
731 public static float getColorIntensity(@ColorInt int color) {
732 return color == Color.WHITE ? 0 : 1;
733 }
Amin Shaikh50d2d1e2018-04-25 14:48:13 -0400734
735 public void setMargins(int sideMargins) {
736 for (int i = 0; i < getChildCount(); i++) {
737 View v = getChildAt(i);
Fabian Kozynskief124492018-11-02 11:02:11 -0400738 if (v == mSystemIconsView || v == mQuickQsStatusIcons || v == mHeaderQsPanel
739 || v == mPrivacyChip) {
Amin Shaikh50d2d1e2018-04-25 14:48:13 -0400740 continue;
741 }
742 RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) v.getLayoutParams();
743 lp.leftMargin = sideMargins;
744 lp.rightMargin = sideMargins;
745 }
746 }
Evan Laird4bf21df2018-10-22 14:24:32 -0400747
748 private void updateShowPercent() {
749 final boolean systemSetting = 0 != Settings.System
750 .getIntForUser(getContext().getContentResolver(),
751 SHOW_BATTERY_PERCENT, 0, ActivityManager.getCurrentUser());
752
753 mShowBatteryPercentAndEstimate = systemSetting;
754
755 updateBatteryViews();
756 }
757
758 private void updateBatteryViews() {
759 if (mShowBatteryPercentAndEstimate) {
760 mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_ON);
761 mBatteryRemainingIcon.setVisibility(View.VISIBLE);
762 mBatteryRemainingText.setVisibility(View.VISIBLE);
763 updateBatteryRemainingText();
764 } else {
765 mBatteryMeterView.setPercentShowMode(BatteryMeterView.MODE_OFF);
766 mBatteryRemainingIcon.setVisibility(View.GONE);
767 mBatteryRemainingText.setVisibility(View.GONE);
768 }
769 }
770
771 private final class PercentSettingObserver extends ContentObserver {
772 PercentSettingObserver(Handler handler) {
773 super(handler);
774 }
775
776 @Override
777 public void onChange(boolean selfChange, Uri uri) {
778 super.onChange(selfChange, uri);
779 updateShowPercent();
780 }
781 }
Jason Monke5b770e2017-03-03 21:49:29 -0500782}