StatusBarHeaderView.java revision 87d84d4d9533814e92bc7b1b0f91347a4982c1d0
1/*
2 * Copyright (C) 2014 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.AlarmClockInfo;
20import android.app.PendingIntent;
21import android.content.Context;
22import android.content.Intent;
23import android.graphics.Outline;
24import android.graphics.Rect;
25import android.graphics.drawable.Drawable;
26import android.util.AttributeSet;
27import android.view.View;
28import android.view.ViewGroup;
29import android.view.ViewOutlineProvider;
30import android.widget.ImageView;
31import android.widget.LinearLayout;
32import android.widget.RelativeLayout;
33import android.widget.Switch;
34import android.widget.TextView;
35
36import com.android.keyguard.KeyguardStatusView;
37import com.android.systemui.R;
38import com.android.systemui.qs.QSPanel;
39import com.android.systemui.qs.QSTile;
40import com.android.systemui.statusbar.policy.BatteryController;
41import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
42import com.android.systemui.statusbar.policy.NextAlarmController;
43import com.android.systemui.statusbar.policy.UserInfoController;
44
45/**
46 * The view to manage the header area in the expanded status bar.
47 */
48public class StatusBarHeaderView extends RelativeLayout implements View.OnClickListener,
49        BatteryController.BatteryStateChangeCallback, NextAlarmController.NextAlarmChangeCallback {
50
51    private boolean mExpanded;
52    private boolean mListening;
53    private boolean mOverscrolled;
54    private boolean mKeyguardShowing;
55    private boolean mCharging;
56
57    private ViewGroup mSystemIconsContainer;
58    private View mSystemIconsSuperContainer;
59    private View mDateGroup;
60    private View mClock;
61    private View mTime;
62    private View mAmPm;
63    private View mKeyguardCarrierText;
64    private MultiUserSwitch mMultiUserSwitch;
65    private ImageView mMultiUserAvatar;
66    private View mDateCollapsed;
67    private View mDateExpanded;
68    private View mStatusIcons;
69    private View mSignalCluster;
70    private View mSettingsButton;
71    private View mQsDetailHeader;
72    private TextView mQsDetailHeaderTitle;
73    private Switch mQsDetailHeaderSwitch;
74    private View mEmergencyCallsOnly;
75    private TextView mBatteryLevel;
76    private TextView mAlarmStatus;
77
78    private boolean mShowEmergencyCallsOnly;
79    private boolean mKeyguardUserSwitcherShowing;
80    private boolean mAlarmShowing;
81    private AlarmClockInfo mNextAlarm;
82
83    private int mCollapsedHeight;
84    private int mExpandedHeight;
85    private int mKeyguardHeight;
86
87    private int mKeyguardWidth = ViewGroup.LayoutParams.MATCH_PARENT;
88    private int mNormalWidth;
89    private int mPadding;
90    private int mMultiUserExpandedMargin;
91    private int mMultiUserCollapsedMargin;
92    private int mMultiUserKeyguardMargin;
93    private int mSystemIconsSwitcherHiddenExpandedMargin;
94    private int mClockMarginBottomExpanded;
95    private int mClockMarginBottomCollapsed;
96    private int mMultiUserSwitchWidthCollapsed;
97    private int mMultiUserSwitchWidthExpanded;
98    private int mMultiUserSwitchWidthKeyguard;
99    private int mBatteryPaddingEnd;
100    private int mBatteryMarginExpanded;
101    private int mBatteryMarginKeyguard;
102
103    /**
104     * In collapsed QS, the clock and avatar are scaled down a bit post-layout to allow for a nice
105     * transition. These values determine that factor.
106     */
107    private float mClockCollapsedScaleFactor;
108    private float mAvatarCollapsedScaleFactor;
109    private float mAvatarKeyguardScaleFactor;
110
111    private ActivityStarter mActivityStarter;
112    private BatteryController mBatteryController;
113    private NextAlarmController mNextAlarmController;
114    private QSPanel mQSPanel;
115    private KeyguardUserSwitcher mKeyguardUserSwitcher;
116
117    private final Rect mClipBounds = new Rect();
118    private final StatusIconClipper mStatusIconClipper = new StatusIconClipper();
119
120    public StatusBarHeaderView(Context context, AttributeSet attrs) {
121        super(context, attrs);
122    }
123
124    @Override
125    protected void onFinishInflate() {
126        super.onFinishInflate();
127        mSystemIconsSuperContainer = findViewById(R.id.system_icons_super_container);
128        mSystemIconsContainer = (ViewGroup) findViewById(R.id.system_icons_container);
129        mSystemIconsSuperContainer.setOnClickListener(this);
130        mDateGroup = findViewById(R.id.date_group);
131        mClock = findViewById(R.id.clock);
132        mTime = findViewById(R.id.time_view);
133        mAmPm = findViewById(R.id.am_pm_view);
134        mKeyguardCarrierText = findViewById(R.id.keyguard_carrier_text);
135        mMultiUserSwitch = (MultiUserSwitch) findViewById(R.id.multi_user_switch);
136        mMultiUserAvatar = (ImageView) findViewById(R.id.multi_user_avatar);
137        mDateCollapsed = findViewById(R.id.date_collapsed);
138        mDateExpanded = findViewById(R.id.date_expanded);
139        mSettingsButton = findViewById(R.id.settings_button);
140        mSettingsButton.setOnClickListener(this);
141        mQsDetailHeader = findViewById(R.id.qs_detail_header);
142        mQsDetailHeader.setAlpha(0);
143        mQsDetailHeaderTitle = (TextView) mQsDetailHeader.findViewById(android.R.id.title);
144        mQsDetailHeaderSwitch = (Switch) mQsDetailHeader.findViewById(android.R.id.toggle);
145        mEmergencyCallsOnly = findViewById(R.id.header_emergency_calls_only);
146        mBatteryLevel = (TextView) findViewById(R.id.battery_level);
147        mAlarmStatus = (TextView) findViewById(R.id.alarm_status);
148        mAlarmStatus.setOnClickListener(this);
149        loadDimens();
150        updateVisibilities();
151        updateClockScale();
152        updateAvatarScale();
153        addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
154            @Override
155            public void onLayoutChange(View v, int left, int top, int right,
156                    int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
157                if ((right - left) != (oldRight - oldLeft)) {
158                    // width changed, update clipping
159                    setClipping(getHeight());
160                }
161                boolean rtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
162                mTime.setPivotX(rtl ? mTime.getWidth() : 0);
163                mTime.setPivotY(mTime.getBaseline());
164                mAmPm.setPivotX(rtl ? mAmPm.getWidth() : 0);
165                mAmPm.setPivotY(mAmPm.getBaseline());
166                updateAmPmTranslation();
167            }
168        });
169        setOutlineProvider(new ViewOutlineProvider() {
170            @Override
171            public void getOutline(View view, Outline outline) {
172                outline.setRect(mClipBounds);
173            }
174        });
175    }
176
177    private void loadDimens() {
178        mCollapsedHeight = getResources().getDimensionPixelSize(R.dimen.status_bar_header_height);
179        mExpandedHeight = getResources().getDimensionPixelSize(
180                R.dimen.status_bar_header_height_expanded);
181        mKeyguardHeight = getResources().getDimensionPixelSize(
182                R.dimen.status_bar_header_height_keyguard);
183        mNormalWidth = getLayoutParams().width;
184        mPadding = getResources().getDimensionPixelSize(R.dimen.notification_side_padding);
185        mMultiUserExpandedMargin =
186                getResources().getDimensionPixelSize(R.dimen.multi_user_switch_expanded_margin);
187        mMultiUserCollapsedMargin =
188                getResources().getDimensionPixelSize(R.dimen.multi_user_switch_collapsed_margin);
189        mMultiUserKeyguardMargin =
190                getResources().getDimensionPixelSize(R.dimen.multi_user_switch_keyguard_margin);
191        mSystemIconsSwitcherHiddenExpandedMargin = getResources().getDimensionPixelSize(
192                R.dimen.system_icons_switcher_hidden_expanded_margin);
193        mClockMarginBottomExpanded =
194                getResources().getDimensionPixelSize(R.dimen.clock_expanded_bottom_margin);
195        mClockMarginBottomCollapsed =
196                getResources().getDimensionPixelSize(R.dimen.clock_collapsed_bottom_margin);
197        mMultiUserSwitchWidthCollapsed =
198                getResources().getDimensionPixelSize(R.dimen.multi_user_switch_width_collapsed);
199        mMultiUserSwitchWidthExpanded =
200                getResources().getDimensionPixelSize(R.dimen.multi_user_switch_width_expanded);
201        mMultiUserSwitchWidthKeyguard =
202                getResources().getDimensionPixelSize(R.dimen.multi_user_switch_width_keyguard);
203        mAvatarCollapsedScaleFactor =
204                getResources().getDimensionPixelSize(R.dimen.multi_user_avatar_collapsed_size)
205                / (float) mMultiUserAvatar.getLayoutParams().width;
206        mAvatarKeyguardScaleFactor =
207                getResources().getDimensionPixelSize(R.dimen.multi_user_avatar_keyguard_size)
208                        / (float) mMultiUserAvatar.getLayoutParams().width;
209        mClockCollapsedScaleFactor =
210                (float) getResources().getDimensionPixelSize(R.dimen.qs_time_collapsed_size)
211                / (float) getResources().getDimensionPixelSize(R.dimen.qs_time_expanded_size);
212        mBatteryPaddingEnd =
213                getResources().getDimensionPixelSize(R.dimen.battery_level_padding_end);
214        mBatteryMarginExpanded =
215                getResources().getDimensionPixelSize(R.dimen.header_battery_margin_expanded);
216        mBatteryMarginKeyguard =
217                getResources().getDimensionPixelSize(R.dimen.header_battery_margin_keyguard);
218    }
219
220    public void setActivityStarter(ActivityStarter activityStarter) {
221        mActivityStarter = activityStarter;
222    }
223
224    public void setBatteryController(BatteryController batteryController) {
225        mBatteryController = batteryController;
226    }
227
228    public void setNextAlarmController(NextAlarmController nextAlarmController) {
229        mNextAlarmController = nextAlarmController;
230    }
231
232    public int getCollapsedHeight() {
233        return mKeyguardShowing ? mKeyguardHeight : mCollapsedHeight;
234    }
235
236    public int getExpandedHeight() {
237        return mExpandedHeight;
238    }
239
240    public void setListening(boolean listening) {
241        if (listening == mListening) {
242            return;
243        }
244        mListening = listening;
245        updateListeners();
246    }
247
248    public void setExpanded(boolean expanded, boolean overscrolled) {
249        boolean changed = expanded != mExpanded;
250        boolean overscrollChanged = overscrolled != mOverscrolled;
251        mExpanded = expanded;
252        mOverscrolled = overscrolled;
253        if (changed || overscrollChanged) {
254            updateHeights();
255            updateVisibilities();
256            updateSystemIconsLayoutParams();
257            updateZTranslation();
258            updateClickTargets();
259            updateWidth();
260            updatePadding();
261            updateMultiUserSwitch();
262            if (mQSPanel != null) {
263                mQSPanel.setExpanded(expanded && !overscrolled);
264            }
265            updateClockScale();
266            updateAvatarScale();
267            updateClockLp();
268            updateBatteryLevelPaddingEnd();
269            updateBatteryLevelLp();
270            mStatusIconClipper.update();
271        }
272    }
273
274    private void updateHeights() {
275        boolean onKeyguardAndCollapsed = mKeyguardShowing && !mExpanded;
276        int height;
277        if (mExpanded) {
278            height = mExpandedHeight;
279        } else if (onKeyguardAndCollapsed) {
280            height = mKeyguardHeight;
281        } else {
282            height = mCollapsedHeight;
283        }
284        ViewGroup.LayoutParams lp = getLayoutParams();
285        if (lp.height != height) {
286            lp.height = height;
287            setLayoutParams(lp);
288        }
289        int systemIconsContainerHeight = onKeyguardAndCollapsed ? mKeyguardHeight : mCollapsedHeight;
290        lp = mSystemIconsSuperContainer.getLayoutParams();
291        if (lp.height != systemIconsContainerHeight) {
292            lp.height = systemIconsContainerHeight;
293            mSystemIconsSuperContainer.setLayoutParams(lp);
294        }
295        lp = mMultiUserSwitch.getLayoutParams();
296        if (lp.height != systemIconsContainerHeight) {
297            lp.height = systemIconsContainerHeight;
298            mMultiUserSwitch.setLayoutParams(lp);
299        }
300    }
301
302    private void updateWidth() {
303        int width = (mKeyguardShowing && !mExpanded) ? mKeyguardWidth : mNormalWidth;
304        ViewGroup.LayoutParams lp = getLayoutParams();
305        if (width != lp.width) {
306            lp.width = width;
307            setLayoutParams(lp);
308        }
309    }
310
311    private void updateVisibilities() {
312        boolean onKeyguardAndCollapsed = mKeyguardShowing && !mExpanded;
313        if (onKeyguardAndCollapsed) {
314            setBackground(null);
315        } else {
316            setBackgroundResource(R.drawable.notification_header_bg);
317        }
318        mDateGroup.setVisibility(onKeyguardAndCollapsed ? View.INVISIBLE : View.VISIBLE);
319        mClock.setVisibility(onKeyguardAndCollapsed ? View.INVISIBLE : View.VISIBLE);
320        mKeyguardCarrierText.setVisibility(onKeyguardAndCollapsed ? View.VISIBLE : View.GONE);
321        mDateCollapsed.setVisibility(mExpanded && !mOverscrolled && mAlarmShowing
322                ? View.VISIBLE : View.GONE);
323        mDateExpanded.setVisibility(mExpanded && !mOverscrolled && mAlarmShowing
324                ? View.GONE : View.VISIBLE);
325        mAlarmStatus.setVisibility(mExpanded && !mOverscrolled && mAlarmShowing
326                ? View.VISIBLE : View.GONE);
327        mSettingsButton.setVisibility(mExpanded && !mOverscrolled ? View.VISIBLE : View.GONE);
328        mQsDetailHeader.setVisibility(mExpanded ? View.VISIBLE : View.GONE);
329        if (mStatusIcons != null) {
330            mStatusIcons.setVisibility(!mExpanded || mOverscrolled ? View.VISIBLE : View.GONE);
331        }
332        if (mSignalCluster != null) {
333            mSignalCluster.setVisibility(!mExpanded || mOverscrolled ? View.VISIBLE : View.GONE);
334        }
335        mEmergencyCallsOnly.setVisibility(mExpanded && !mOverscrolled && mShowEmergencyCallsOnly
336                ? VISIBLE : GONE);
337        mMultiUserSwitch.setVisibility(mExpanded || !mKeyguardUserSwitcherShowing
338                ? VISIBLE : GONE);
339        mBatteryLevel.setVisibility(mKeyguardShowing && mCharging || mExpanded && !mOverscrolled
340                ? View.VISIBLE : View.GONE);
341        if (mExpanded && !mOverscrolled && mKeyguardUserSwitcherShowing) {
342            mKeyguardUserSwitcher.hide();
343        }
344    }
345
346    private void updateSystemIconsLayoutParams() {
347        RelativeLayout.LayoutParams lp = (LayoutParams) mSystemIconsSuperContainer.getLayoutParams();
348        lp.addRule(RelativeLayout.START_OF, mExpanded && !mOverscrolled
349                ? mSettingsButton.getId()
350                : mMultiUserSwitch.getId());
351        lp.removeRule(ALIGN_PARENT_START);
352        if (mMultiUserSwitch.getVisibility() == GONE) {
353            lp.setMarginEnd(mSystemIconsSwitcherHiddenExpandedMargin);
354        } else {
355            lp.setMarginEnd(0);
356        }
357        mSystemIconsSuperContainer.setLayoutParams(lp);
358    }
359
360    private void updateListeners() {
361        if (mListening) {
362            mBatteryController.addStateChangedCallback(this);
363            mNextAlarmController.addStateChangedCallback(this);
364        } else {
365            mBatteryController.removeStateChangedCallback(this);
366            mNextAlarmController.removeStateChangedCallback(this);
367        }
368    }
369
370    private void updateAvatarScale() {
371        if (mExpanded && !mOverscrolled) {
372            mMultiUserSwitch.setScaleX(1f);
373            mMultiUserSwitch.setScaleY(1f);
374        } else if (mKeyguardShowing) {
375            mMultiUserSwitch.setScaleX(mAvatarKeyguardScaleFactor);
376            mMultiUserSwitch.setScaleY(mAvatarKeyguardScaleFactor);
377        } else {
378            mMultiUserSwitch.setScaleX(mAvatarCollapsedScaleFactor);
379            mMultiUserSwitch.setScaleY(mAvatarCollapsedScaleFactor);
380        }
381    }
382
383    private void updateClockScale() {
384        mAmPm.setScaleX(mClockCollapsedScaleFactor);
385        mAmPm.setScaleY(mClockCollapsedScaleFactor);
386        if (!mExpanded || mOverscrolled) {
387            mTime.setScaleX(mClockCollapsedScaleFactor);
388            mTime.setScaleY(mClockCollapsedScaleFactor);
389        } else {
390            mTime.setScaleX(1f);
391            mTime.setScaleY(1f);
392        }
393        updateAmPmTranslation();
394    }
395
396    private void updateAmPmTranslation() {
397        boolean rtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
398        mAmPm.setTranslationX((rtl ? 1 : -1) * mTime.getWidth() * (1 - mTime.getScaleX()));
399    }
400
401    private void updateBatteryLevelPaddingEnd() {
402        mBatteryLevel.setPaddingRelative(0, 0,
403                mKeyguardShowing && !mExpanded ? 0 : mBatteryPaddingEnd, 0);
404    }
405
406    @Override
407    public void onBatteryLevelChanged(int level, boolean pluggedIn, boolean charging) {
408        mBatteryLevel.setText(getResources().getString(R.string.battery_level_template, level));
409        boolean changed = mCharging != charging;
410        mCharging = charging;
411        if (changed) {
412            updateVisibilities();
413        }
414    }
415
416    @Override
417    public void onPowerSaveChanged() {
418        // could not care less
419    }
420
421    @Override
422    public void onNextAlarmChanged(AlarmClockInfo nextAlarm) {
423        mNextAlarm = nextAlarm;
424        if (nextAlarm != null) {
425            mAlarmStatus.setText(KeyguardStatusView.formatNextAlarm(getContext(), nextAlarm));
426        }
427        mAlarmShowing = nextAlarm != null;
428        updateVisibilities();
429    }
430
431
432    private void updateClickTargets() {
433        setClickable(!mKeyguardShowing || mExpanded);
434
435        boolean keyguardSwitcherAvailable =
436                mKeyguardUserSwitcher != null && mKeyguardShowing && !mExpanded;
437        mMultiUserSwitch.setClickable(mExpanded || keyguardSwitcherAvailable);
438        mMultiUserSwitch.setKeyguardMode(keyguardSwitcherAvailable);
439        mSystemIconsSuperContainer.setClickable(mExpanded);
440        mAlarmStatus.setClickable(mNextAlarm != null && mNextAlarm.getShowIntent() != null);
441    }
442
443    private void updateZTranslation() {
444
445        // If we are on the Keyguard, we need to set our z position to zero, so we don't get
446        // shadows.
447        if (mKeyguardShowing && !mExpanded) {
448            setZ(0);
449        } else {
450            setTranslationZ(0);
451        }
452    }
453
454    private void updatePadding() {
455        boolean padded = !mKeyguardShowing || mExpanded;
456        int padding = padded ? mPadding : 0;
457        setPaddingRelative(padding, 0, padding, 0);
458    }
459
460    private void updateClockLp() {
461        int marginBottom = mExpanded && !mOverscrolled
462                ? mClockMarginBottomExpanded
463                : mClockMarginBottomCollapsed;
464        LayoutParams lp = (LayoutParams) mDateGroup.getLayoutParams();
465        if (marginBottom != lp.bottomMargin) {
466            lp.bottomMargin = marginBottom;
467            mDateGroup.setLayoutParams(lp);
468        }
469    }
470
471    private void updateMultiUserSwitch() {
472        int marginEnd;
473        int width;
474        if (mExpanded && !mOverscrolled) {
475            marginEnd = mMultiUserExpandedMargin;
476            width = mMultiUserSwitchWidthExpanded;
477        } else if (mKeyguardShowing) {
478            marginEnd = mMultiUserKeyguardMargin;
479            width = mMultiUserSwitchWidthKeyguard;
480        } else {
481            marginEnd = mMultiUserCollapsedMargin;
482            width = mMultiUserSwitchWidthCollapsed;
483        }
484        MarginLayoutParams lp = (MarginLayoutParams) mMultiUserSwitch.getLayoutParams();
485        if (marginEnd != lp.getMarginEnd() || lp.width != width) {
486            lp.setMarginEnd(marginEnd);
487            lp.width = width;
488            mMultiUserSwitch.setLayoutParams(lp);
489        }
490    }
491
492    private void updateBatteryLevelLp() {
493        int marginStart = mExpanded && !mOverscrolled
494                ? mBatteryMarginExpanded
495                : mBatteryMarginKeyguard;
496        MarginLayoutParams lp = (MarginLayoutParams) mBatteryLevel.getLayoutParams();
497        if (marginStart != lp.getMarginStart()) {
498            lp.setMarginStart(marginStart);
499            mBatteryLevel.setLayoutParams(lp);
500        }
501    }
502
503    public void setExpansion(float t) {
504        float height = mCollapsedHeight + t * (mExpandedHeight - mCollapsedHeight);
505        if (height < mCollapsedHeight) {
506            height = mCollapsedHeight;
507        }
508        if (height > mExpandedHeight) {
509            height = mExpandedHeight;
510        }
511        setClipping(height);
512    }
513
514    private void setClipping(float height) {
515        mClipBounds.set(getPaddingLeft(), 0, getWidth() - getPaddingRight(), (int) height);
516        setClipBounds(mClipBounds);
517        invalidateOutline();
518    }
519
520    public void attachSystemIcons(LinearLayout systemIcons) {
521        mSystemIconsContainer.addView(systemIcons);
522        mStatusIcons = systemIcons.findViewById(R.id.statusIcons);
523        mSignalCluster = systemIcons.findViewById(R.id.signal_cluster);
524        mSignalCluster.addOnLayoutChangeListener(mStatusIconClipper);
525    }
526
527    public void onSystemIconsDetached() {
528        if (mStatusIcons != null) {
529            mStatusIcons.setVisibility(View.VISIBLE);
530        }
531        if (mSignalCluster != null) {
532            mSignalCluster.removeOnLayoutChangeListener(mStatusIconClipper);
533            mSignalCluster.setVisibility(View.VISIBLE);
534        }
535        mStatusIcons = null;
536        mSignalCluster = null;
537    }
538
539    public void setKeyguardShowing(boolean keyguardShowing) {
540        mKeyguardShowing = keyguardShowing;
541        updateHeights();
542        updateWidth();
543        updateVisibilities();
544        updateZTranslation();
545        updatePadding();
546        updateMultiUserSwitch();
547        updateClickTargets();
548        updateBatteryLevelPaddingEnd();
549        updateAvatarScale();
550        mStatusIconClipper.update();
551    }
552
553    public void setUserInfoController(UserInfoController userInfoController) {
554        userInfoController.addListener(new UserInfoController.OnUserInfoChangedListener() {
555            @Override
556            public void onUserInfoChanged(String name, Drawable picture) {
557                mMultiUserAvatar.setImageDrawable(picture);
558            }
559        });
560    }
561
562    @Override
563    public void onClick(View v) {
564        if (v == mSettingsButton) {
565            startSettingsActivity();
566        } else if (v == mSystemIconsSuperContainer) {
567            startBatteryActivity();
568        } else if (v == mAlarmStatus && mNextAlarm != null) {
569            PendingIntent showIntent = mNextAlarm.getShowIntent();
570            if (showIntent != null && showIntent.isActivity()) {
571                mActivityStarter.startActivity(showIntent.getIntent());
572            }
573        }
574    }
575
576    private void startSettingsActivity() {
577        mActivityStarter.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS));
578    }
579
580    private void startBatteryActivity() {
581        mActivityStarter.startActivity(new Intent(Intent.ACTION_POWER_USAGE_SUMMARY));
582    }
583
584    public void setQSPanel(QSPanel qsp) {
585        mQSPanel = qsp;
586        if (mQSPanel != null) {
587            mQSPanel.setCallback(mQsPanelCallback);
588        }
589        mMultiUserSwitch.setQsPanel(qsp);
590    }
591
592    public void setKeyguarUserSwitcher(KeyguardUserSwitcher keyguardUserSwitcher) {
593        mKeyguardUserSwitcher = keyguardUserSwitcher;
594        mMultiUserSwitch.setKeyguardUserSwitcher(keyguardUserSwitcher);
595    }
596
597    @Override
598    public boolean shouldDelayChildPressedState() {
599        return true;
600    }
601
602    public void setShowEmergencyCallsOnly(boolean show) {
603        mShowEmergencyCallsOnly = show;
604        if (mExpanded) {
605            updateVisibilities();
606        }
607    }
608
609    public void setKeyguardUserSwitcherShowing(boolean showing) {
610        mKeyguardUserSwitcherShowing = showing;
611        updateVisibilities();
612        updateSystemIconsLayoutParams();
613    }
614
615    @Override
616    public boolean hasOverlappingRendering() {
617        return !mKeyguardShowing || mExpanded;
618    }
619
620    @Override
621    protected void dispatchSetPressed(boolean pressed) {
622        // We don't want that everything lights up when we click on the header, so block the request
623        // here.
624    }
625
626    private final class StatusIconClipper implements OnLayoutChangeListener {
627        private final Rect mClipBounds = new Rect();
628
629        @Override
630        public void onLayoutChange(View v, int left, int top, int right,
631                int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
632            // Hide the statusIcons in the header by clipping them.  Can't touch visibility since
633            // they are mirrored to the real status bar.
634            mClipBounds.set(left, 0, mSystemIconsContainer.getWidth(),
635                    mSystemIconsContainer.getHeight());
636            update();
637        }
638
639        public void update() {
640            final boolean collapsedKeyguard = mKeyguardShowing && !mExpanded;
641            final boolean expanded = mExpanded && !mOverscrolled;
642            mSystemIconsContainer.setClipBounds(collapsedKeyguard || expanded ? null : mClipBounds);
643        }
644    }
645
646    private final QSPanel.Callback mQsPanelCallback = new QSPanel.Callback() {
647        @Override
648        public void onToggleStateChanged(final boolean state) {
649            post(new Runnable() {
650                @Override
651                public void run() {
652                    handleToggleStateChanged(state);
653                }
654            });
655        }
656
657        @Override
658        public void onShowingDetail(final QSTile.DetailAdapter detail) {
659            post(new Runnable() {
660                @Override
661                public void run() {
662                    handleShowingDetail(detail);
663                }
664            });
665        }
666
667        @Override
668        public void onScanStateChanged(final boolean state) {
669            post(new Runnable() {
670                @Override
671                public void run() {
672                    handleScanStateChanged(state);
673                }
674            });
675        }
676
677        private void handleToggleStateChanged(boolean state) {
678            mQsDetailHeaderSwitch.setChecked(state);
679        }
680
681        private void handleScanStateChanged(boolean state) {
682            // TODO - waiting on framework asset
683        }
684
685        private void handleShowingDetail(final QSTile.DetailAdapter detail) {
686            final boolean showingDetail = detail != null;
687            transition(mClock, !showingDetail);
688            transition(mDateGroup, !showingDetail);
689            transition(mQsDetailHeader, showingDetail);
690            if (showingDetail) {
691                mQsDetailHeaderTitle.setText(detail.getTitle());
692                final Boolean toggleState = detail.getToggleState();
693                if (toggleState == null) {
694                    mQsDetailHeaderSwitch.setVisibility(INVISIBLE);
695                    mQsDetailHeader.setClickable(false);
696                } else {
697                    mQsDetailHeaderSwitch.setVisibility(VISIBLE);
698                    mQsDetailHeaderSwitch.setChecked(toggleState);
699                    mQsDetailHeader.setClickable(true);
700                    mQsDetailHeader.setOnClickListener(new OnClickListener() {
701                        @Override
702                        public void onClick(View v) {
703                            detail.setToggleState(!mQsDetailHeaderSwitch.isChecked());
704                        }
705                    });
706                }
707            } else {
708                mQsDetailHeader.setClickable(false);
709            }
710        }
711
712        private void transition(final View v, final boolean in) {
713            if (in) {
714                v.bringToFront();
715            }
716            v.animate().alpha(in ? 1 : 0).withLayer().start();
717        }
718    };
719}
720