blob: 256cc6b6ae3f773f4836aea8b0f52bebdf02ce4e [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
86 private TouchAnimator mAnimator;
87 private TouchAnimator mSecondHalfAnimator;
88 private TouchAnimator mFirstHalfAnimator;
89 private TouchAnimator mDateSizeAnimator;
90 private TouchAnimator mAlarmTranslation;
Jason Monk162011e2016-02-19 08:11:55 -050091 private TouchAnimator mSettingsAlpha;
Jason Monk97cb9c72016-02-17 16:41:01 -050092 private float mExpansionAmount;
Jason Monk46dbfb42016-02-25 14:59:20 -050093 private QSTileHost mHost;
Jason Monkc34befb2015-10-07 16:40:02 -040094
95 public QuickStatusBarHeader(Context context, AttributeSet attrs) {
96 super(context, attrs);
97 }
98
99 @Override
100 protected void onFinishInflate() {
101 super.onFinishInflate();
102
Jason Monkdbd88172016-02-17 15:20:29 -0500103 mEmergencyOnly = (TextView) findViewById(R.id.header_emergency_calls_only);
104
105 mDateTimeAlarmGroup = (ViewGroup) findViewById(R.id.date_time_alarm_group);
106 mDateTimeAlarmGroup.findViewById(R.id.empty_time_view).setVisibility(View.GONE);
Jason Monkec9af012015-12-10 11:10:23 -0500107 mDateTimeGroup = (ViewGroup) findViewById(R.id.date_time_group);
Jason Monk97cb9c72016-02-17 16:41:01 -0500108 mDateTimeGroup.setPivotX(0);
109 mDateTimeGroup.setPivotY(0);
Jason Monkdbd88172016-02-17 15:20:29 -0500110
Jason Monk97cb9c72016-02-17 16:41:01 -0500111 mExpandIndicator = (ExpandableIndicator) findViewById(R.id.expand_indicator);
Jason Monkc34befb2015-10-07 16:40:02 -0400112
Jason Monkdc35dcb2015-12-04 16:36:15 -0500113 mHeaderQsPanel = (QuickQSPanel) findViewById(R.id.quick_qs_panel);
Jason Monkc34befb2015-10-07 16:40:02 -0400114
115 mSettingsButton = (SettingsButton) findViewById(R.id.settings_button);
116 mSettingsContainer = findViewById(R.id.settings_button_container);
117 mSettingsButton.setOnClickListener(this);
118
Jason Monkdbd88172016-02-17 15:20:29 -0500119 mAlarmStatusCollapsed = (TextView) findViewById(R.id.alarm_status_collapsed);
Jason Monkc34befb2015-10-07 16:40:02 -0400120 mAlarmStatus = (TextView) findViewById(R.id.alarm_status);
121 mAlarmStatus.setOnClickListener(this);
122
Jason Monk69e76cc2016-01-26 10:56:37 -0500123 mMultiUserSwitch = (MultiUserSwitch) findViewById(R.id.multi_user_switch);
124 mMultiUserAvatar = (ImageView) mMultiUserSwitch.findViewById(R.id.multi_user_avatar);
125
Jason Monk94a1bf62015-10-20 08:43:36 -0700126 // RenderThread is doing more harm than good when touching the header (to expand quick
127 // settings), so disable it for this view
128 ((RippleDrawable) getBackground()).setForceSoftware(true);
129 ((RippleDrawable) mSettingsButton.getBackground()).setForceSoftware(true);
130
Jason Monkdbd88172016-02-17 15:20:29 -0500131 updateResources();
132 }
133
134 @Override
135 protected void onConfigurationChanged(Configuration newConfig) {
136 super.onConfigurationChanged(newConfig);
137 updateResources();
138 }
139
140 private void updateResources() {
141 FontSizeUtils.updateFontSize(mAlarmStatus, R.dimen.qs_date_collapsed_size);
142 FontSizeUtils.updateFontSize(mEmergencyOnly, R.dimen.qs_emergency_calls_only_text_size);
143
Jason Monk97cb9c72016-02-17 16:41:01 -0500144 mGearTranslation = mContext.getResources().getDimension(R.dimen.qs_header_gear_translation);
145
Jason Monkdbd88172016-02-17 15:20:29 -0500146 mDateTimeTranslation = mContext.getResources().getDimension(
147 R.dimen.qs_date_anim_translation);
148 mDateTimeAlarmTranslation = mContext.getResources().getDimension(
149 R.dimen.qs_date_alarm_anim_translation);
150 float dateCollapsedSize = mContext.getResources().getDimension(
151 R.dimen.qs_date_collapsed_text_size);
152 float dateExpandedSize = mContext.getResources().getDimension(
153 R.dimen.qs_date_text_size);
Jason Monk97cb9c72016-02-17 16:41:01 -0500154 mDateScaleFactor = dateExpandedSize / dateCollapsedSize;
Jason Monkdbd88172016-02-17 15:20:29 -0500155 updateDateTimePosition();
Jason Monk97cb9c72016-02-17 16:41:01 -0500156
157 mAnimator = new TouchAnimator.Builder()
158 .addFloat(mSettingsContainer, "translationY", -mGearTranslation, 0)
159 .addFloat(mMultiUserSwitch, "translationY", -mGearTranslation, 0)
Jason Monk97cb9c72016-02-17 16:41:01 -0500160 .build();
161 mSecondHalfAnimator = new TouchAnimator.Builder()
Jason Monk162011e2016-02-19 08:11:55 -0500162 .addFloat(mSettingsButton, "rotation", -180, 0)
Jason Monk97cb9c72016-02-17 16:41:01 -0500163 .addFloat(mAlarmStatus, "alpha", 0, 1)
164 .addFloat(mEmergencyOnly, "alpha", 0, 1)
165 .setStartDelay(.5f)
166 .build();
167 mFirstHalfAnimator = new TouchAnimator.Builder()
168 .addFloat(mAlarmStatusCollapsed, "alpha", 1, 0)
Jason Monk97cb9c72016-02-17 16:41:01 -0500169 .setEndDelay(.5f)
170 .build();
171 mDateSizeAnimator = new TouchAnimator.Builder()
172 .addFloat(mDateTimeGroup, "scaleX", 1, mDateScaleFactor)
173 .addFloat(mDateTimeGroup, "scaleY", 1, mDateScaleFactor)
174 .setStartDelay(.36f)
175 .build();
Jason Monk162011e2016-02-19 08:11:55 -0500176 mSettingsAlpha = new TouchAnimator.Builder()
177 .addFloat(mSettingsContainer, "alpha", 0, 1)
178 .addFloat(mMultiUserSwitch, "alpha", 0, 1)
179 .setStartDelay(QSAnimator.EXPANDED_TILE_DELAY)
180 .build();
Jason Monkc34befb2015-10-07 16:40:02 -0400181 }
182
183 @Override
184 public int getCollapsedHeight() {
185 return getHeight();
186 }
187
188 @Override
189 public int getExpandedHeight() {
190 return getHeight();
191 }
192
193 @Override
194 public void setExpanded(boolean expanded) {
195 mExpanded = expanded;
Jason Monkdeba7a42015-12-08 16:14:10 -0500196 updateEverything();
Jason Monkc34befb2015-10-07 16:40:02 -0400197 }
198
199 @Override
200 public void onNextAlarmChanged(AlarmManager.AlarmClockInfo nextAlarm) {
201 mNextAlarm = nextAlarm;
202 if (nextAlarm != null) {
Jason Monkdeba7a42015-12-08 16:14:10 -0500203 mAlarmStatus.setText(KeyguardStatusView.formatNextAlarm(getContext(), nextAlarm));
Jason Monkc34befb2015-10-07 16:40:02 -0400204 }
Jason Monk97cb9c72016-02-17 16:41:01 -0500205 if (mAlarmShowing != (nextAlarm != null)) {
206 mAlarmShowing = nextAlarm != null;
207 updateEverything();
208 }
Jason Monkc34befb2015-10-07 16:40:02 -0400209 }
210
211 @Override
212 public void setExpansion(float headerExpansionFraction) {
Jason Monk97cb9c72016-02-17 16:41:01 -0500213 mExpansionAmount = headerExpansionFraction;
214 mAnimator.setPosition(headerExpansionFraction);
215 mSecondHalfAnimator.setPosition(headerExpansionFraction);
216 mFirstHalfAnimator.setPosition(headerExpansionFraction);
217 mDateSizeAnimator.setPosition(headerExpansionFraction);
218 mAlarmTranslation.setPosition(headerExpansionFraction);
Jason Monk162011e2016-02-19 08:11:55 -0500219 mSettingsAlpha.setPosition(headerExpansionFraction);
Jason Monkdbd88172016-02-17 15:20:29 -0500220
Jason Monkdbd88172016-02-17 15:20:29 -0500221 updateAlarmVisibilities();
222
Jason Monk97cb9c72016-02-17 16:41:01 -0500223 mExpandIndicator.setExpanded(headerExpansionFraction > EXPAND_INDICATOR_THRESHOLD);
224 }
Jason Monkdbd88172016-02-17 15:20:29 -0500225
Jason Monk46dbfb42016-02-25 14:59:20 -0500226 @Override
227 protected void onDetachedFromWindow() {
228 setListening(false);
229 mHost.getUserInfoController().remListener(mUserListener);
230 mHost.getNetworkController().removeEmergencyListener(this);
231 super.onDetachedFromWindow();
232 }
233
Jason Monkdbd88172016-02-17 15:20:29 -0500234 private void updateAlarmVisibilities() {
Jason Monk97cb9c72016-02-17 16:41:01 -0500235 mAlarmStatus.setVisibility(mAlarmShowing ? View.VISIBLE : View.INVISIBLE);
236 mAlarmStatusCollapsed.setVisibility(mAlarmShowing ? View.VISIBLE : View.INVISIBLE);
Jason Monkdbd88172016-02-17 15:20:29 -0500237 }
238
239 private void updateDateTimePosition() {
Jason Monk97cb9c72016-02-17 16:41:01 -0500240 // This one has its own because we have to rebuild it every time the alarm state changes.
241 mAlarmTranslation = new TouchAnimator.Builder()
242 .addFloat(mDateTimeAlarmGroup, "translationY", 0, mAlarmShowing
243 ? mDateTimeAlarmTranslation : mDateTimeTranslation)
244 .build();
245 mAlarmTranslation.setPosition(mExpansionAmount);
Jason Monkdbd88172016-02-17 15:20:29 -0500246 }
247
Jason Monkc34befb2015-10-07 16:40:02 -0400248 public void setListening(boolean listening) {
249 if (listening == mListening) {
250 return;
251 }
252 mHeaderQsPanel.setListening(listening);
253 mListening = listening;
254 updateListeners();
255 }
256
257 @Override
258 public void updateEverything() {
Jason Monkdbd88172016-02-17 15:20:29 -0500259 updateDateTimePosition();
Jason Monkc34befb2015-10-07 16:40:02 -0400260 updateVisibilities();
261 }
262
263 private void updateVisibilities() {
Jason Monkdbd88172016-02-17 15:20:29 -0500264 updateAlarmVisibilities();
Jason Monkec9af012015-12-10 11:10:23 -0500265 mEmergencyOnly.setVisibility(mExpanded && mShowEmergencyCallsOnly
266 ? View.VISIBLE : View.INVISIBLE);
Jason Monkc34befb2015-10-07 16:40:02 -0400267 mSettingsContainer.findViewById(R.id.tuner_icon).setVisibility(
268 TunerService.isTunerEnabled(mContext) ? View.VISIBLE : View.INVISIBLE);
Jason Monk69e76cc2016-01-26 10:56:37 -0500269 mMultiUserSwitch.setVisibility(mMultiUserSwitch.hasMultipleUsers() ? View.VISIBLE
270 : View.GONE);
271 }
272
Jason Monkc34befb2015-10-07 16:40:02 -0400273 private void updateListeners() {
274 if (mListening) {
275 mNextAlarmController.addStateChangedCallback(this);
276 } else {
277 mNextAlarmController.removeStateChangedCallback(this);
278 }
279 }
280
281 @Override
282 public void setActivityStarter(ActivityStarter activityStarter) {
283 mActivityStarter = activityStarter;
284 }
285
286 @Override
287 public void setQSPanel(final QSPanel qsPanel) {
288 mQsPanel = qsPanel;
289 setupHost(qsPanel.getHost());
290 if (mQsPanel != null) {
Jason Monk69e76cc2016-01-26 10:56:37 -0500291 mMultiUserSwitch.setQsPanel(qsPanel);
Jason Monkc34befb2015-10-07 16:40:02 -0400292 }
293 }
294
Jason Monkca894a02016-01-12 15:30:22 -0500295 public void setupHost(final QSTileHost host) {
Jason Monk46dbfb42016-02-25 14:59:20 -0500296 mHost = host;
Jason Monkca894a02016-01-12 15:30:22 -0500297 host.setHeaderView(this);
Jason Monkdc35dcb2015-12-04 16:36:15 -0500298 mHeaderQsPanel.setQSPanelAndHeader(mQsPanel, this);
Jason Monkdeba7a42015-12-08 16:14:10 -0500299 mHeaderQsPanel.setMaxTiles(5);
Jason Monk46dbfb42016-02-25 14:59:20 -0500300 mHeaderQsPanel.setHost(host);
301 setUserInfoController(host.getUserInfoController());
302 setBatteryController(host.getBatteryController());
303 setNextAlarmController(host.getNextAlarmController());
304
305 final boolean isAPhone = mHost.getNetworkController().hasVoiceCallingFeature();
306 if (isAPhone) {
307 mHost.getNetworkController().addEmergencyListener(this);
308 }
Jason Monkc34befb2015-10-07 16:40:02 -0400309 }
310
311 @Override
312 public void onClick(View v) {
313 if (v == mSettingsButton) {
314 if (mSettingsButton.isTunerClick()) {
315 if (TunerService.isTunerEnabled(mContext)) {
316 TunerService.showResetRequest(mContext, new Runnable() {
317 @Override
318 public void run() {
319 // Relaunch settings so that the tuner disappears.
320 startSettingsActivity();
321 }
322 });
323 } else {
324 Toast.makeText(getContext(), R.string.tuner_toast, Toast.LENGTH_LONG).show();
325 TunerService.setTunerEnabled(mContext, true);
326 }
327 }
328 startSettingsActivity();
329 } else if (v == mAlarmStatus && mNextAlarm != null) {
330 PendingIntent showIntent = mNextAlarm.getShowIntent();
331 if (showIntent != null && showIntent.isActivity()) {
332 mActivityStarter.startActivity(showIntent.getIntent(), true /* dismissShade */);
333 }
334 }
335 }
336
337 private void startSettingsActivity() {
338 mActivityStarter.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS),
339 true /* dismissShade */);
340 }
341
342 @Override
343 public void setNextAlarmController(NextAlarmController nextAlarmController) {
344 mNextAlarmController = nextAlarmController;
345 }
346
347 @Override
348 public void setBatteryController(BatteryController batteryController) {
349 // Don't care
350 }
351
352 @Override
353 public void setUserInfoController(UserInfoController userInfoController) {
Jason Monk46dbfb42016-02-25 14:59:20 -0500354 userInfoController.addListener(mUserListener);
Jason Monkc34befb2015-10-07 16:40:02 -0400355 }
356
357 @Override
Jason Monkec9af012015-12-10 11:10:23 -0500358 public void setEmergencyCallsOnly(boolean show) {
359 boolean changed = show != mShowEmergencyCallsOnly;
360 if (changed) {
361 mShowEmergencyCallsOnly = show;
362 if (mExpanded) {
363 updateEverything();
364 }
365 }
Jason Monkc34befb2015-10-07 16:40:02 -0400366 }
Jason Monk46dbfb42016-02-25 14:59:20 -0500367
368 private final OnUserInfoChangedListener mUserListener = new OnUserInfoChangedListener() {
369 @Override
370 public void onUserInfoChanged(String name, Drawable picture) {
371 mMultiUserAvatar.setImageDrawable(picture);
372 }
373 };
Jason Monkc34befb2015-10-07 16:40:02 -0400374}