blob: b50790305ca2712373742c7d3e11242dbb764d43 [file] [log] [blame]
Jason Monkc34befb2015-10-07 16:40:02 -04001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package com.android.systemui.statusbar.phone;
18
19import android.app.AlarmManager;
20import android.app.PendingIntent;
21import android.content.Context;
22import android.content.Intent;
Jason Monkdbd88172016-02-17 15:20:29 -050023import android.content.res.Configuration;
Jason Monk69e76cc2016-01-26 10:56:37 -050024import android.graphics.drawable.Drawable;
Jason Monk94a1bf62015-10-20 08:43:36 -070025import android.graphics.drawable.RippleDrawable;
Jason Monkc34befb2015-10-07 16:40:02 -040026import android.util.AttributeSet;
27import android.view.View;
Jason Monk97cb9c72016-02-17 16:41:01 -050028import android.view.View.OnClickListener;
Jason Monkc34befb2015-10-07 16:40:02 -040029import android.view.ViewGroup;
30import android.widget.ImageView;
Jason Monkc34befb2015-10-07 16:40:02 -040031import android.widget.TextView;
32import android.widget.Toast;
Jason Monkdeba7a42015-12-08 16:14:10 -050033import com.android.keyguard.KeyguardStatusView;
Jason Monkdbd88172016-02-17 15:20:29 -050034import com.android.systemui.FontSizeUtils;
Jason Monkc34befb2015-10-07 16:40:02 -040035import com.android.systemui.R;
Jason Monk162011e2016-02-19 08:11:55 -050036import com.android.systemui.qs.QSAnimator;
Jason Monkc34befb2015-10-07 16:40:02 -040037import com.android.systemui.qs.QSPanel;
Jason Monkdc35dcb2015-12-04 16:36:15 -050038import com.android.systemui.qs.QuickQSPanel;
Jason Monk97cb9c72016-02-17 16:41:01 -050039import com.android.systemui.qs.TouchAnimator;
Jason Monkc34befb2015-10-07 16:40:02 -040040import com.android.systemui.statusbar.policy.BatteryController;
41import com.android.systemui.statusbar.policy.NextAlarmController;
Jason Monk97cb9c72016-02-17 16:41:01 -050042import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback;
Jason Monkc34befb2015-10-07 16:40:02 -040043import com.android.systemui.statusbar.policy.UserInfoController;
Jason Monk46dbfb42016-02-25 14:59:20 -050044import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener;
Jason Monkc34befb2015-10-07 16:40:02 -040045import com.android.systemui.tuner.TunerService;
46
47public class QuickStatusBarHeader extends BaseStatusBarHeader implements
Jason Monkdf5459d2016-02-29 10:47:35 -050048 NextAlarmChangeCallback, OnClickListener {
Jason Monkc34befb2015-10-07 16:40:02 -040049
Jason Monkdeba7a42015-12-08 16:14:10 -050050 private static final String TAG = "QuickStatusBarHeader";
Jason Monk97cb9c72016-02-17 16:41:01 -050051
Jason Monk162011e2016-02-19 08:11:55 -050052 private static final float EXPAND_INDICATOR_THRESHOLD = .93f;
Jason Monk97cb9c72016-02-17 16:41:01 -050053
Jason Monkc34befb2015-10-07 16:40:02 -040054 private ActivityStarter mActivityStarter;
55 private NextAlarmController mNextAlarmController;
56 private SettingsButton mSettingsButton;
57 private View mSettingsContainer;
Jason Monkdbd88172016-02-17 15:20:29 -050058
Jason Monkc34befb2015-10-07 16:40:02 -040059 private TextView mAlarmStatus;
Jason Monkdbd88172016-02-17 15:20:29 -050060 private TextView mAlarmStatusCollapsed;
Jason Monkc34befb2015-10-07 16:40:02 -040061
Jason Monkc34befb2015-10-07 16:40:02 -040062 private QSPanel mQsPanel;
Jason Monkc34befb2015-10-07 16:40:02 -040063
64 private boolean mExpanded;
65 private boolean mAlarmShowing;
Jason Monkc34befb2015-10-07 16:40:02 -040066
Jason Monkec9af012015-12-10 11:10:23 -050067 private ViewGroup mDateTimeGroup;
Jason Monkdbd88172016-02-17 15:20:29 -050068 private ViewGroup mDateTimeAlarmGroup;
69 private TextView mEmergencyOnly;
70
Jason Monk97cb9c72016-02-17 16:41:01 -050071 private ExpandableIndicator mExpandIndicator;
72
Jason Monkc34befb2015-10-07 16:40:02 -040073 private boolean mListening;
74 private AlarmManager.AlarmClockInfo mNextAlarm;
75
Jason Monkdc35dcb2015-12-04 16:36:15 -050076 private QuickQSPanel mHeaderQsPanel;
Jason Monkec9af012015-12-10 11:10:23 -050077 private boolean mShowEmergencyCallsOnly;
Jason Monk69e76cc2016-01-26 10:56:37 -050078 private MultiUserSwitch mMultiUserSwitch;
79 private ImageView mMultiUserAvatar;
Jason Monkdb50de82016-02-03 15:34:54 -050080
Jason Monkdbd88172016-02-17 15:20:29 -050081 private float mDateTimeTranslation;
82 private float mDateTimeAlarmTranslation;
Jason Monkdbd88172016-02-17 15:20:29 -050083 private float mDateScaleFactor;
Jason Monk97cb9c72016-02-17 16:41:01 -050084 private float mGearTranslation;
85
Jason Monk97cb9c72016-02-17 16:41:01 -050086 private TouchAnimator mSecondHalfAnimator;
87 private TouchAnimator mFirstHalfAnimator;
88 private TouchAnimator mDateSizeAnimator;
89 private TouchAnimator mAlarmTranslation;
Jason Monk162011e2016-02-19 08:11:55 -050090 private TouchAnimator mSettingsAlpha;
Jason Monk97cb9c72016-02-17 16:41:01 -050091 private float mExpansionAmount;
Jason Monk46dbfb42016-02-25 14:59:20 -050092 private QSTileHost mHost;
Jason Monkc34befb2015-10-07 16:40:02 -040093
94 public QuickStatusBarHeader(Context context, AttributeSet attrs) {
95 super(context, attrs);
96 }
97
98 @Override
99 protected void onFinishInflate() {
100 super.onFinishInflate();
101
Jason Monkdbd88172016-02-17 15:20:29 -0500102 mEmergencyOnly = (TextView) findViewById(R.id.header_emergency_calls_only);
103
104 mDateTimeAlarmGroup = (ViewGroup) findViewById(R.id.date_time_alarm_group);
105 mDateTimeAlarmGroup.findViewById(R.id.empty_time_view).setVisibility(View.GONE);
Jason Monkec9af012015-12-10 11:10:23 -0500106 mDateTimeGroup = (ViewGroup) findViewById(R.id.date_time_group);
Jason Monk97cb9c72016-02-17 16:41:01 -0500107 mDateTimeGroup.setPivotX(0);
108 mDateTimeGroup.setPivotY(0);
Jason Monkdbd88172016-02-17 15:20:29 -0500109
Jason Monk97cb9c72016-02-17 16:41:01 -0500110 mExpandIndicator = (ExpandableIndicator) findViewById(R.id.expand_indicator);
Jason Monkc34befb2015-10-07 16:40:02 -0400111
Jason Monkdc35dcb2015-12-04 16:36:15 -0500112 mHeaderQsPanel = (QuickQSPanel) findViewById(R.id.quick_qs_panel);
Jason Monkc34befb2015-10-07 16:40:02 -0400113
114 mSettingsButton = (SettingsButton) findViewById(R.id.settings_button);
115 mSettingsContainer = findViewById(R.id.settings_button_container);
116 mSettingsButton.setOnClickListener(this);
117
Jason Monkdbd88172016-02-17 15:20:29 -0500118 mAlarmStatusCollapsed = (TextView) findViewById(R.id.alarm_status_collapsed);
Jason Monkc34befb2015-10-07 16:40:02 -0400119 mAlarmStatus = (TextView) findViewById(R.id.alarm_status);
120 mAlarmStatus.setOnClickListener(this);
121
Jason Monk69e76cc2016-01-26 10:56:37 -0500122 mMultiUserSwitch = (MultiUserSwitch) findViewById(R.id.multi_user_switch);
123 mMultiUserAvatar = (ImageView) mMultiUserSwitch.findViewById(R.id.multi_user_avatar);
124
Jason Monk94a1bf62015-10-20 08:43:36 -0700125 // RenderThread is doing more harm than good when touching the header (to expand quick
126 // settings), so disable it for this view
Jason Monk94a1bf62015-10-20 08:43:36 -0700127 ((RippleDrawable) mSettingsButton.getBackground()).setForceSoftware(true);
128
Jason Monkdbd88172016-02-17 15:20:29 -0500129 updateResources();
130 }
131
132 @Override
133 protected void onConfigurationChanged(Configuration newConfig) {
134 super.onConfigurationChanged(newConfig);
135 updateResources();
136 }
137
Jason Monk51fb85a2016-03-28 14:06:04 -0400138 @Override
139 public void onRtlPropertiesChanged(int layoutDirection) {
140 super.onRtlPropertiesChanged(layoutDirection);
141 updateResources();
142 }
143
Jason Monkdbd88172016-02-17 15:20:29 -0500144 private void updateResources() {
145 FontSizeUtils.updateFontSize(mAlarmStatus, R.dimen.qs_date_collapsed_size);
146 FontSizeUtils.updateFontSize(mEmergencyOnly, R.dimen.qs_emergency_calls_only_text_size);
147
Jason Monk97cb9c72016-02-17 16:41:01 -0500148 mGearTranslation = mContext.getResources().getDimension(R.dimen.qs_header_gear_translation);
149
Jason Monkdbd88172016-02-17 15:20:29 -0500150 mDateTimeTranslation = mContext.getResources().getDimension(
151 R.dimen.qs_date_anim_translation);
152 mDateTimeAlarmTranslation = mContext.getResources().getDimension(
153 R.dimen.qs_date_alarm_anim_translation);
154 float dateCollapsedSize = mContext.getResources().getDimension(
155 R.dimen.qs_date_collapsed_text_size);
156 float dateExpandedSize = mContext.getResources().getDimension(
157 R.dimen.qs_date_text_size);
Jason Monk97cb9c72016-02-17 16:41:01 -0500158 mDateScaleFactor = dateExpandedSize / dateCollapsedSize;
Jason Monkdbd88172016-02-17 15:20:29 -0500159 updateDateTimePosition();
Jason Monk97cb9c72016-02-17 16:41:01 -0500160
Jason Monk97cb9c72016-02-17 16:41:01 -0500161 mSecondHalfAnimator = new TouchAnimator.Builder()
Jason Monk97cb9c72016-02-17 16:41:01 -0500162 .addFloat(mAlarmStatus, "alpha", 0, 1)
163 .addFloat(mEmergencyOnly, "alpha", 0, 1)
164 .setStartDelay(.5f)
165 .build();
166 mFirstHalfAnimator = new TouchAnimator.Builder()
167 .addFloat(mAlarmStatusCollapsed, "alpha", 1, 0)
Jason Monk97cb9c72016-02-17 16:41:01 -0500168 .setEndDelay(.5f)
169 .build();
170 mDateSizeAnimator = new TouchAnimator.Builder()
171 .addFloat(mDateTimeGroup, "scaleX", 1, mDateScaleFactor)
172 .addFloat(mDateTimeGroup, "scaleY", 1, mDateScaleFactor)
173 .setStartDelay(.36f)
174 .build();
Jason Monk162011e2016-02-19 08:11:55 -0500175 mSettingsAlpha = new TouchAnimator.Builder()
Jason Monk98196b02016-03-14 10:33:02 -0400176 .addFloat(mSettingsContainer, "translationY", -mGearTranslation, 0)
177 .addFloat(mMultiUserSwitch, "translationY", -mGearTranslation, 0)
178 .addFloat(mSettingsButton, "rotation", -90, 0)
Jason Monk162011e2016-02-19 08:11:55 -0500179 .addFloat(mSettingsContainer, "alpha", 0, 1)
180 .addFloat(mMultiUserSwitch, "alpha", 0, 1)
181 .setStartDelay(QSAnimator.EXPANDED_TILE_DELAY)
182 .build();
Jason Monk51fb85a2016-03-28 14:06:04 -0400183
184 final boolean isRtl = isLayoutRtl();
185 if (isRtl && mDateTimeGroup.getWidth() == 0) {
186 mDateTimeGroup.addOnLayoutChangeListener(new OnLayoutChangeListener() {
187 @Override
188 public void onLayoutChange(View v, int left, int top, int right, int bottom,
189 int oldLeft, int oldTop, int oldRight, int oldBottom) {
190 mDateTimeGroup.setPivotX(getWidth());
191 mDateTimeGroup.removeOnLayoutChangeListener(this);
192 }
193 });
194 } else {
195 mDateTimeGroup.setPivotX(isRtl ? mDateTimeGroup.getWidth() : 0);
196 }
Jason Monkc34befb2015-10-07 16:40:02 -0400197 }
198
199 @Override
200 public int getCollapsedHeight() {
201 return getHeight();
202 }
203
204 @Override
205 public int getExpandedHeight() {
206 return getHeight();
207 }
208
209 @Override
210 public void setExpanded(boolean expanded) {
211 mExpanded = expanded;
Jason Monkdeba7a42015-12-08 16:14:10 -0500212 updateEverything();
Jason Monkc34befb2015-10-07 16:40:02 -0400213 }
214
215 @Override
216 public void onNextAlarmChanged(AlarmManager.AlarmClockInfo nextAlarm) {
217 mNextAlarm = nextAlarm;
218 if (nextAlarm != null) {
Jason Monkdeba7a42015-12-08 16:14:10 -0500219 mAlarmStatus.setText(KeyguardStatusView.formatNextAlarm(getContext(), nextAlarm));
Jason Monkc34befb2015-10-07 16:40:02 -0400220 }
Jason Monk97cb9c72016-02-17 16:41:01 -0500221 if (mAlarmShowing != (nextAlarm != null)) {
222 mAlarmShowing = nextAlarm != null;
223 updateEverything();
224 }
Jason Monkc34befb2015-10-07 16:40:02 -0400225 }
226
227 @Override
228 public void setExpansion(float headerExpansionFraction) {
Jason Monk97cb9c72016-02-17 16:41:01 -0500229 mExpansionAmount = headerExpansionFraction;
Jason Monk97cb9c72016-02-17 16:41:01 -0500230 mSecondHalfAnimator.setPosition(headerExpansionFraction);
231 mFirstHalfAnimator.setPosition(headerExpansionFraction);
232 mDateSizeAnimator.setPosition(headerExpansionFraction);
233 mAlarmTranslation.setPosition(headerExpansionFraction);
Jason Monk162011e2016-02-19 08:11:55 -0500234 mSettingsAlpha.setPosition(headerExpansionFraction);
Jason Monkdbd88172016-02-17 15:20:29 -0500235
Jason Monkdbd88172016-02-17 15:20:29 -0500236 updateAlarmVisibilities();
237
Jason Monk97cb9c72016-02-17 16:41:01 -0500238 mExpandIndicator.setExpanded(headerExpansionFraction > EXPAND_INDICATOR_THRESHOLD);
239 }
Jason Monkdbd88172016-02-17 15:20:29 -0500240
Jason Monk46dbfb42016-02-25 14:59:20 -0500241 @Override
242 protected void onDetachedFromWindow() {
243 setListening(false);
244 mHost.getUserInfoController().remListener(mUserListener);
245 mHost.getNetworkController().removeEmergencyListener(this);
246 super.onDetachedFromWindow();
247 }
248
Jason Monkdbd88172016-02-17 15:20:29 -0500249 private void updateAlarmVisibilities() {
Jason Monk97cb9c72016-02-17 16:41:01 -0500250 mAlarmStatus.setVisibility(mAlarmShowing ? View.VISIBLE : View.INVISIBLE);
251 mAlarmStatusCollapsed.setVisibility(mAlarmShowing ? View.VISIBLE : View.INVISIBLE);
Jason Monkdbd88172016-02-17 15:20:29 -0500252 }
253
254 private void updateDateTimePosition() {
Jason Monk97cb9c72016-02-17 16:41:01 -0500255 // This one has its own because we have to rebuild it every time the alarm state changes.
256 mAlarmTranslation = new TouchAnimator.Builder()
257 .addFloat(mDateTimeAlarmGroup, "translationY", 0, mAlarmShowing
258 ? mDateTimeAlarmTranslation : mDateTimeTranslation)
259 .build();
260 mAlarmTranslation.setPosition(mExpansionAmount);
Jason Monkdbd88172016-02-17 15:20:29 -0500261 }
262
Jason Monkc34befb2015-10-07 16:40:02 -0400263 public void setListening(boolean listening) {
264 if (listening == mListening) {
265 return;
266 }
267 mHeaderQsPanel.setListening(listening);
268 mListening = listening;
269 updateListeners();
270 }
271
272 @Override
273 public void updateEverything() {
Jason Monkdbd88172016-02-17 15:20:29 -0500274 updateDateTimePosition();
Jason Monkc34befb2015-10-07 16:40:02 -0400275 updateVisibilities();
276 }
277
278 private void updateVisibilities() {
Jason Monkdbd88172016-02-17 15:20:29 -0500279 updateAlarmVisibilities();
Jason Monkec9af012015-12-10 11:10:23 -0500280 mEmergencyOnly.setVisibility(mExpanded && mShowEmergencyCallsOnly
281 ? View.VISIBLE : View.INVISIBLE);
Jason Monkc34befb2015-10-07 16:40:02 -0400282 mSettingsContainer.findViewById(R.id.tuner_icon).setVisibility(
283 TunerService.isTunerEnabled(mContext) ? View.VISIBLE : View.INVISIBLE);
Jason Monk69e76cc2016-01-26 10:56:37 -0500284 mMultiUserSwitch.setVisibility(mMultiUserSwitch.hasMultipleUsers() ? View.VISIBLE
285 : View.GONE);
286 }
287
Jason Monkc34befb2015-10-07 16:40:02 -0400288 private void updateListeners() {
289 if (mListening) {
290 mNextAlarmController.addStateChangedCallback(this);
291 } else {
292 mNextAlarmController.removeStateChangedCallback(this);
293 }
294 }
295
296 @Override
297 public void setActivityStarter(ActivityStarter activityStarter) {
298 mActivityStarter = activityStarter;
299 }
300
301 @Override
302 public void setQSPanel(final QSPanel qsPanel) {
303 mQsPanel = qsPanel;
304 setupHost(qsPanel.getHost());
305 if (mQsPanel != null) {
Jason Monk69e76cc2016-01-26 10:56:37 -0500306 mMultiUserSwitch.setQsPanel(qsPanel);
Jason Monkc34befb2015-10-07 16:40:02 -0400307 }
308 }
309
Jason Monkca894a02016-01-12 15:30:22 -0500310 public void setupHost(final QSTileHost host) {
Jason Monk46dbfb42016-02-25 14:59:20 -0500311 mHost = host;
Jason Monkca894a02016-01-12 15:30:22 -0500312 host.setHeaderView(this);
Jason Monkdc35dcb2015-12-04 16:36:15 -0500313 mHeaderQsPanel.setQSPanelAndHeader(mQsPanel, this);
Jason Monk8b9d67f2016-03-02 08:59:08 -0500314 mHeaderQsPanel.setHost(host, null /* No customization in header */);
Jason Monk46dbfb42016-02-25 14:59:20 -0500315 setUserInfoController(host.getUserInfoController());
316 setBatteryController(host.getBatteryController());
317 setNextAlarmController(host.getNextAlarmController());
318
319 final boolean isAPhone = mHost.getNetworkController().hasVoiceCallingFeature();
320 if (isAPhone) {
321 mHost.getNetworkController().addEmergencyListener(this);
322 }
Jason Monkc34befb2015-10-07 16:40:02 -0400323 }
324
325 @Override
326 public void onClick(View v) {
327 if (v == mSettingsButton) {
328 if (mSettingsButton.isTunerClick()) {
329 if (TunerService.isTunerEnabled(mContext)) {
330 TunerService.showResetRequest(mContext, new Runnable() {
331 @Override
332 public void run() {
333 // Relaunch settings so that the tuner disappears.
334 startSettingsActivity();
335 }
336 });
337 } else {
338 Toast.makeText(getContext(), R.string.tuner_toast, Toast.LENGTH_LONG).show();
339 TunerService.setTunerEnabled(mContext, true);
340 }
341 }
342 startSettingsActivity();
343 } else if (v == mAlarmStatus && mNextAlarm != null) {
344 PendingIntent showIntent = mNextAlarm.getShowIntent();
345 if (showIntent != null && showIntent.isActivity()) {
346 mActivityStarter.startActivity(showIntent.getIntent(), true /* dismissShade */);
347 }
348 }
349 }
350
351 private void startSettingsActivity() {
352 mActivityStarter.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS),
353 true /* dismissShade */);
354 }
355
356 @Override
357 public void setNextAlarmController(NextAlarmController nextAlarmController) {
358 mNextAlarmController = nextAlarmController;
359 }
360
361 @Override
362 public void setBatteryController(BatteryController batteryController) {
363 // Don't care
364 }
365
366 @Override
367 public void setUserInfoController(UserInfoController userInfoController) {
Jason Monk46dbfb42016-02-25 14:59:20 -0500368 userInfoController.addListener(mUserListener);
Jason Monkc34befb2015-10-07 16:40:02 -0400369 }
370
371 @Override
Jason Monkec9af012015-12-10 11:10:23 -0500372 public void setEmergencyCallsOnly(boolean show) {
373 boolean changed = show != mShowEmergencyCallsOnly;
374 if (changed) {
375 mShowEmergencyCallsOnly = show;
376 if (mExpanded) {
377 updateEverything();
378 }
379 }
Jason Monkc34befb2015-10-07 16:40:02 -0400380 }
Jason Monk46dbfb42016-02-25 14:59:20 -0500381
382 private final OnUserInfoChangedListener mUserListener = new OnUserInfoChangedListener() {
383 @Override
384 public void onUserInfoChanged(String name, Drawable picture) {
385 mMultiUserAvatar.setImageDrawable(picture);
386 }
387 };
Jason Monkc34befb2015-10-07 16:40:02 -0400388}