Home | History | Annotate | Download | only in stack
      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 
     17 package com.android.systemui.statusbar.stack;
     18 
     19 import android.annotation.Nullable;
     20 import android.content.Context;
     21 import android.view.View;
     22 
     23 import com.android.systemui.R;
     24 import com.android.systemui.statusbar.ActivatableNotificationView;
     25 import com.android.systemui.statusbar.ExpandableNotificationRow;
     26 import com.android.systemui.statusbar.ExpandableView;
     27 import com.android.systemui.statusbar.NotificationData;
     28 import com.android.systemui.statusbar.NotificationShelf;
     29 import com.android.systemui.statusbar.StatusBarState;
     30 import com.android.systemui.statusbar.policy.HeadsUpManager;
     31 
     32 import java.util.ArrayList;
     33 
     34 /**
     35  * A global state to track all input states for the algorithm.
     36  */
     37 public class AmbientState {
     38     private ArrayList<View> mDraggedViews = new ArrayList<View>();
     39     private int mScrollY;
     40     private boolean mDimmed;
     41     private ActivatableNotificationView mActivatedChild;
     42     private float mOverScrollTopAmount;
     43     private float mOverScrollBottomAmount;
     44     private int mSpeedBumpIndex = -1;
     45     private boolean mDark;
     46     private boolean mHideSensitive;
     47     private HeadsUpManager mHeadsUpManager;
     48     private float mStackTranslation;
     49     private int mLayoutHeight;
     50     private int mTopPadding;
     51     private boolean mShadeExpanded;
     52     private float mMaxHeadsUpTranslation;
     53     private boolean mDismissAllInProgress;
     54     private int mLayoutMinHeight;
     55     private NotificationShelf mShelf;
     56     private int mZDistanceBetweenElements;
     57     private int mBaseZHeight;
     58     private int mMaxLayoutHeight;
     59     private ActivatableNotificationView mLastVisibleBackgroundChild;
     60     private float mCurrentScrollVelocity;
     61     private int mStatusBarState;
     62     private float mExpandingVelocity;
     63     private boolean mPanelTracking;
     64     private boolean mExpansionChanging;
     65     private boolean mPanelFullWidth;
     66     private boolean mPulsing;
     67     private boolean mUnlockHintRunning;
     68     private boolean mQsCustomizerShowing;
     69     private int mIntrinsicPadding;
     70     private int mExpandAnimationTopChange;
     71     private ExpandableNotificationRow mExpandingNotification;
     72     private int mDarkTopPadding;
     73     private float mDarkAmount;
     74     private boolean mAppearing;
     75 
     76     public AmbientState(Context context) {
     77         reload(context);
     78     }
     79 
     80     /**
     81      * Reload the dimens e.g. if the density changed.
     82      */
     83     public void reload(Context context) {
     84         mZDistanceBetweenElements = getZDistanceBetweenElements(context);
     85         mBaseZHeight = getBaseHeight(mZDistanceBetweenElements);
     86     }
     87 
     88     private static int getZDistanceBetweenElements(Context context) {
     89         return Math.max(1, context.getResources()
     90                 .getDimensionPixelSize(R.dimen.z_distance_between_notifications));
     91     }
     92 
     93     private static int getBaseHeight(int zdistanceBetweenElements) {
     94         return 4 * zdistanceBetweenElements;
     95     }
     96 
     97     /**
     98      * @return the launch height for notifications that are launched
     99      */
    100     public static int getNotificationLaunchHeight(Context context) {
    101         int zDistance = getZDistanceBetweenElements(context);
    102         return getBaseHeight(zDistance) * 2;
    103     }
    104 
    105     /**
    106      * @return the basic Z height on which notifications remain.
    107      */
    108     public int getBaseZHeight() {
    109         return mBaseZHeight;
    110     }
    111 
    112     /**
    113      * @return the distance in Z between two overlaying notifications.
    114      */
    115     public int getZDistanceBetweenElements() {
    116         return mZDistanceBetweenElements;
    117     }
    118 
    119     public int getScrollY() {
    120         return mScrollY;
    121     }
    122 
    123     public void setScrollY(int scrollY) {
    124         this.mScrollY = scrollY;
    125     }
    126 
    127     public void onBeginDrag(View view) {
    128         mDraggedViews.add(view);
    129     }
    130 
    131     public void onDragFinished(View view) {
    132         mDraggedViews.remove(view);
    133     }
    134 
    135     public ArrayList<View> getDraggedViews() {
    136         return mDraggedViews;
    137     }
    138 
    139     /**
    140      * @param dimmed Whether we are in a dimmed state (on the lockscreen), where the backgrounds are
    141      *               translucent and everything is scaled back a bit.
    142      */
    143     public void setDimmed(boolean dimmed) {
    144         mDimmed = dimmed;
    145     }
    146 
    147     /** In dark mode, we draw as little as possible, assuming a black background */
    148     public void setDark(boolean dark) {
    149         mDark = dark;
    150     }
    151 
    152     /** Dark ratio of the status bar **/
    153     public void setDarkAmount(float darkAmount) {
    154         mDarkAmount = darkAmount;
    155     }
    156 
    157     /** Returns the dark ratio of the status bar */
    158     public float getDarkAmount() {
    159         return mDarkAmount;
    160     }
    161 
    162     public void setHideSensitive(boolean hideSensitive) {
    163         mHideSensitive = hideSensitive;
    164     }
    165 
    166     /**
    167      * In dimmed mode, a child can be activated, which happens on the first tap of the double-tap
    168      * interaction. This child is then scaled normally and its background is fully opaque.
    169      */
    170     public void setActivatedChild(ActivatableNotificationView activatedChild) {
    171         mActivatedChild = activatedChild;
    172     }
    173 
    174     public boolean isDimmed() {
    175         return mDimmed;
    176     }
    177 
    178     public boolean isDark() {
    179         return mDark;
    180     }
    181 
    182     public boolean isHideSensitive() {
    183         return mHideSensitive;
    184     }
    185 
    186     public ActivatableNotificationView getActivatedChild() {
    187         return mActivatedChild;
    188     }
    189 
    190     public void setOverScrollAmount(float amount, boolean onTop) {
    191         if (onTop) {
    192             mOverScrollTopAmount = amount;
    193         } else {
    194             mOverScrollBottomAmount = amount;
    195         }
    196     }
    197 
    198     public float getOverScrollAmount(boolean top) {
    199         return top ? mOverScrollTopAmount : mOverScrollBottomAmount;
    200     }
    201 
    202     public int getSpeedBumpIndex() {
    203         return mSpeedBumpIndex;
    204     }
    205 
    206     public void setSpeedBumpIndex(int shelfIndex) {
    207         mSpeedBumpIndex = shelfIndex;
    208     }
    209 
    210     public void setHeadsUpManager(HeadsUpManager headsUpManager) {
    211         mHeadsUpManager = headsUpManager;
    212     }
    213 
    214     public float getStackTranslation() {
    215         return mStackTranslation;
    216     }
    217 
    218     public void setStackTranslation(float stackTranslation) {
    219         mStackTranslation = stackTranslation;
    220     }
    221 
    222     public void setLayoutHeight(int layoutHeight) {
    223         mLayoutHeight = layoutHeight;
    224     }
    225 
    226     public float getTopPadding() {
    227         return mTopPadding;
    228     }
    229 
    230     public void setTopPadding(int topPadding) {
    231         mTopPadding = topPadding;
    232     }
    233 
    234     public int getInnerHeight() {
    235         return Math.max(Math.min(mLayoutHeight, mMaxLayoutHeight) - mTopPadding, mLayoutMinHeight);
    236     }
    237 
    238     public boolean isShadeExpanded() {
    239         return mShadeExpanded;
    240     }
    241 
    242     public void setShadeExpanded(boolean shadeExpanded) {
    243         mShadeExpanded = shadeExpanded;
    244     }
    245 
    246     public void setMaxHeadsUpTranslation(float maxHeadsUpTranslation) {
    247         mMaxHeadsUpTranslation = maxHeadsUpTranslation;
    248     }
    249 
    250     public float getMaxHeadsUpTranslation() {
    251         return mMaxHeadsUpTranslation;
    252     }
    253 
    254     public void setDismissAllInProgress(boolean dismissAllInProgress) {
    255         mDismissAllInProgress = dismissAllInProgress;
    256     }
    257 
    258     public boolean isDismissAllInProgress() {
    259         return mDismissAllInProgress;
    260     }
    261 
    262     public void setLayoutMinHeight(int layoutMinHeight) {
    263         mLayoutMinHeight = layoutMinHeight;
    264     }
    265 
    266     public void setShelf(NotificationShelf shelf) {
    267         mShelf = shelf;
    268     }
    269 
    270     @Nullable
    271     public NotificationShelf getShelf() {
    272         return mShelf;
    273     }
    274 
    275     public void setLayoutMaxHeight(int maxLayoutHeight) {
    276         mMaxLayoutHeight = maxLayoutHeight;
    277     }
    278 
    279     /**
    280      * Sets the last visible view of the host layout, that has a background, i.e the very last
    281      * view in the shade, without the clear all button.
    282      */
    283     public void setLastVisibleBackgroundChild(
    284             ActivatableNotificationView lastVisibleBackgroundChild) {
    285         mLastVisibleBackgroundChild = lastVisibleBackgroundChild;
    286     }
    287 
    288     public ActivatableNotificationView getLastVisibleBackgroundChild() {
    289         return mLastVisibleBackgroundChild;
    290     }
    291 
    292     public void setCurrentScrollVelocity(float currentScrollVelocity) {
    293         mCurrentScrollVelocity = currentScrollVelocity;
    294     }
    295 
    296     public float getCurrentScrollVelocity() {
    297         return mCurrentScrollVelocity;
    298     }
    299 
    300     public boolean isOnKeyguard() {
    301         return mStatusBarState == StatusBarState.KEYGUARD;
    302     }
    303 
    304     public void setStatusBarState(int statusBarState) {
    305         mStatusBarState = statusBarState;
    306     }
    307 
    308     public void setExpandingVelocity(float expandingVelocity) {
    309         mExpandingVelocity = expandingVelocity;
    310     }
    311 
    312     public void setExpansionChanging(boolean expansionChanging) {
    313         mExpansionChanging = expansionChanging;
    314     }
    315 
    316     public boolean isExpansionChanging() {
    317         return mExpansionChanging;
    318     }
    319 
    320     public float getExpandingVelocity() {
    321         return mExpandingVelocity;
    322     }
    323 
    324     public void setPanelTracking(boolean panelTracking) {
    325         mPanelTracking = panelTracking;
    326     }
    327 
    328     public boolean hasPulsingNotifications() {
    329         return mPulsing;
    330     }
    331 
    332     public void setPulsing(boolean hasPulsing) {
    333         mPulsing = hasPulsing;
    334     }
    335 
    336     public boolean isPulsing(NotificationData.Entry entry) {
    337         if (!mPulsing || mHeadsUpManager == null) {
    338             return false;
    339         }
    340         return mHeadsUpManager.getAllEntries().anyMatch(e -> (e == entry));
    341     }
    342 
    343     public boolean isPanelTracking() {
    344         return mPanelTracking;
    345     }
    346 
    347     public boolean isPanelFullWidth() {
    348         return mPanelFullWidth;
    349     }
    350 
    351     public void setPanelFullWidth(boolean panelFullWidth) {
    352         mPanelFullWidth = panelFullWidth;
    353     }
    354 
    355     public void setUnlockHintRunning(boolean unlockHintRunning) {
    356         mUnlockHintRunning = unlockHintRunning;
    357     }
    358 
    359     public boolean isUnlockHintRunning() {
    360         return mUnlockHintRunning;
    361     }
    362 
    363     public boolean isQsCustomizerShowing() {
    364         return mQsCustomizerShowing;
    365     }
    366 
    367     public void setQsCustomizerShowing(boolean qsCustomizerShowing) {
    368         mQsCustomizerShowing = qsCustomizerShowing;
    369     }
    370 
    371     public void setIntrinsicPadding(int intrinsicPadding) {
    372         mIntrinsicPadding = intrinsicPadding;
    373     }
    374 
    375     public int getIntrinsicPadding() {
    376         return mIntrinsicPadding;
    377     }
    378 
    379     /**
    380      * Similar to the normal is above shelf logic but doesn't allow it to be above in AOD1.
    381      *
    382      * @param expandableView the view to check
    383      */
    384     public boolean isAboveShelf(ExpandableView expandableView) {
    385         if (!(expandableView instanceof ExpandableNotificationRow)) {
    386             return expandableView.isAboveShelf();
    387         }
    388         ExpandableNotificationRow row = (ExpandableNotificationRow) expandableView;
    389         return row.isAboveShelf() && !isDozingAndNotPulsing(row);
    390     }
    391 
    392     /**
    393      * @return whether a view is dozing and not pulsing right now
    394      */
    395     public boolean isDozingAndNotPulsing(ExpandableView view) {
    396         if (view instanceof ExpandableNotificationRow) {
    397             return isDozingAndNotPulsing((ExpandableNotificationRow) view);
    398         }
    399         return false;
    400     }
    401 
    402     /**
    403      * @return whether a row is dozing and not pulsing right now
    404      */
    405     public boolean isDozingAndNotPulsing(ExpandableNotificationRow row) {
    406         return isDark() && !isPulsing(row.getEntry());
    407     }
    408 
    409     public void setExpandAnimationTopChange(int expandAnimationTopChange) {
    410         mExpandAnimationTopChange = expandAnimationTopChange;
    411     }
    412 
    413     public void setExpandingNotification(ExpandableNotificationRow row) {
    414         mExpandingNotification = row;
    415     }
    416 
    417     public ExpandableNotificationRow getExpandingNotification() {
    418         return mExpandingNotification;
    419     }
    420 
    421     public int getExpandAnimationTopChange() {
    422         return mExpandAnimationTopChange;
    423     }
    424 
    425     /**
    426      * @return {@code true } when shade is completely dark: in AOD or ambient display.
    427      */
    428     public boolean isFullyDark() {
    429         return mDarkAmount == 1;
    430     }
    431 
    432     public void setDarkTopPadding(int darkTopPadding) {
    433         mDarkTopPadding = darkTopPadding;
    434     }
    435 
    436     public int getDarkTopPadding() {
    437         return mDarkTopPadding;
    438     }
    439 
    440     public void setAppearing(boolean appearing) {
    441         mAppearing = appearing;
    442     }
    443 
    444     public boolean isAppearing() {
    445         return mAppearing;
    446     }
    447 }
    448