| /* |
| * Copyright (C) 2014 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License |
| */ |
| |
| package com.android.systemui.statusbar.stack; |
| |
| import android.annotation.Nullable; |
| import android.content.Context; |
| import android.view.View; |
| |
| import com.android.systemui.R; |
| import com.android.systemui.statusbar.ActivatableNotificationView; |
| import com.android.systemui.statusbar.ExpandableNotificationRow; |
| import com.android.systemui.statusbar.ExpandableView; |
| import com.android.systemui.statusbar.NotificationData; |
| import com.android.systemui.statusbar.NotificationShelf; |
| import com.android.systemui.statusbar.StatusBarState; |
| import com.android.systemui.statusbar.policy.HeadsUpManager; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| |
| /** |
| * A global state to track all input states for the algorithm. |
| */ |
| public class AmbientState { |
| private ArrayList<View> mDraggedViews = new ArrayList<View>(); |
| private int mScrollY; |
| private boolean mDimmed; |
| private ActivatableNotificationView mActivatedChild; |
| private float mOverScrollTopAmount; |
| private float mOverScrollBottomAmount; |
| private int mSpeedBumpIndex = -1; |
| private boolean mDark; |
| private boolean mHideSensitive; |
| private HeadsUpManager mHeadsUpManager; |
| private float mStackTranslation; |
| private int mLayoutHeight; |
| private int mTopPadding; |
| private boolean mShadeExpanded; |
| private float mMaxHeadsUpTranslation; |
| private boolean mDismissAllInProgress; |
| private int mLayoutMinHeight; |
| private NotificationShelf mShelf; |
| private int mZDistanceBetweenElements; |
| private int mBaseZHeight; |
| private int mMaxLayoutHeight; |
| private ActivatableNotificationView mLastVisibleBackgroundChild; |
| private float mCurrentScrollVelocity; |
| private int mStatusBarState; |
| private float mExpandingVelocity; |
| private boolean mPanelTracking; |
| private boolean mExpansionChanging; |
| private boolean mPanelFullWidth; |
| private boolean mPulsing; |
| private boolean mUnlockHintRunning; |
| private boolean mQsCustomizerShowing; |
| private int mIntrinsicPadding; |
| private int mExpandAnimationTopChange; |
| private ExpandableNotificationRow mExpandingNotification; |
| private int mDarkTopPadding; |
| private float mDarkAmount; |
| |
| public AmbientState(Context context) { |
| reload(context); |
| } |
| |
| /** |
| * Reload the dimens e.g. if the density changed. |
| */ |
| public void reload(Context context) { |
| mZDistanceBetweenElements = getZDistanceBetweenElements(context); |
| mBaseZHeight = getBaseHeight(mZDistanceBetweenElements); |
| } |
| |
| private static int getZDistanceBetweenElements(Context context) { |
| return Math.max(1, context.getResources() |
| .getDimensionPixelSize(R.dimen.z_distance_between_notifications)); |
| } |
| |
| private static int getBaseHeight(int zdistanceBetweenElements) { |
| return 4 * zdistanceBetweenElements; |
| } |
| |
| /** |
| * @return the launch height for notifications that are launched |
| */ |
| public static int getNotificationLaunchHeight(Context context) { |
| int zDistance = getZDistanceBetweenElements(context); |
| return getBaseHeight(zDistance) * 2; |
| } |
| |
| /** |
| * @return the basic Z height on which notifications remain. |
| */ |
| public int getBaseZHeight() { |
| return mBaseZHeight; |
| } |
| |
| /** |
| * @return the distance in Z between two overlaying notifications. |
| */ |
| public int getZDistanceBetweenElements() { |
| return mZDistanceBetweenElements; |
| } |
| |
| public int getScrollY() { |
| return mScrollY; |
| } |
| |
| public void setScrollY(int scrollY) { |
| this.mScrollY = scrollY; |
| } |
| |
| public void onBeginDrag(View view) { |
| mDraggedViews.add(view); |
| } |
| |
| public void onDragFinished(View view) { |
| mDraggedViews.remove(view); |
| } |
| |
| public ArrayList<View> getDraggedViews() { |
| return mDraggedViews; |
| } |
| |
| /** |
| * @param dimmed Whether we are in a dimmed state (on the lockscreen), where the backgrounds are |
| * translucent and everything is scaled back a bit. |
| */ |
| public void setDimmed(boolean dimmed) { |
| mDimmed = dimmed; |
| } |
| |
| /** In dark mode, we draw as little as possible, assuming a black background */ |
| public void setDark(boolean dark) { |
| mDark = dark; |
| } |
| |
| /** Dark ratio of the status bar **/ |
| public void setDarkAmount(float darkAmount) { |
| mDarkAmount = darkAmount; |
| } |
| |
| /** Returns the dark ratio of the status bar */ |
| public float getDarkAmount() { |
| return mDarkAmount; |
| } |
| |
| public void setHideSensitive(boolean hideSensitive) { |
| mHideSensitive = hideSensitive; |
| } |
| |
| /** |
| * In dimmed mode, a child can be activated, which happens on the first tap of the double-tap |
| * interaction. This child is then scaled normally and its background is fully opaque. |
| */ |
| public void setActivatedChild(ActivatableNotificationView activatedChild) { |
| mActivatedChild = activatedChild; |
| } |
| |
| public boolean isDimmed() { |
| return mDimmed; |
| } |
| |
| public boolean isDark() { |
| return mDark; |
| } |
| |
| public boolean isHideSensitive() { |
| return mHideSensitive; |
| } |
| |
| public ActivatableNotificationView getActivatedChild() { |
| return mActivatedChild; |
| } |
| |
| public void setOverScrollAmount(float amount, boolean onTop) { |
| if (onTop) { |
| mOverScrollTopAmount = amount; |
| } else { |
| mOverScrollBottomAmount = amount; |
| } |
| } |
| |
| public float getOverScrollAmount(boolean top) { |
| return top ? mOverScrollTopAmount : mOverScrollBottomAmount; |
| } |
| |
| public int getSpeedBumpIndex() { |
| return mSpeedBumpIndex; |
| } |
| |
| public void setSpeedBumpIndex(int shelfIndex) { |
| mSpeedBumpIndex = shelfIndex; |
| } |
| |
| public void setHeadsUpManager(HeadsUpManager headsUpManager) { |
| mHeadsUpManager = headsUpManager; |
| } |
| |
| public float getStackTranslation() { |
| return mStackTranslation; |
| } |
| |
| public void setStackTranslation(float stackTranslation) { |
| mStackTranslation = stackTranslation; |
| } |
| |
| public void setLayoutHeight(int layoutHeight) { |
| mLayoutHeight = layoutHeight; |
| } |
| |
| public float getTopPadding() { |
| return mTopPadding; |
| } |
| |
| public void setTopPadding(int topPadding) { |
| mTopPadding = topPadding; |
| } |
| |
| public int getInnerHeight() { |
| return Math.max(Math.min(mLayoutHeight, mMaxLayoutHeight) - mTopPadding, mLayoutMinHeight); |
| } |
| |
| public boolean isShadeExpanded() { |
| return mShadeExpanded; |
| } |
| |
| public void setShadeExpanded(boolean shadeExpanded) { |
| mShadeExpanded = shadeExpanded; |
| } |
| |
| public void setMaxHeadsUpTranslation(float maxHeadsUpTranslation) { |
| mMaxHeadsUpTranslation = maxHeadsUpTranslation; |
| } |
| |
| public float getMaxHeadsUpTranslation() { |
| return mMaxHeadsUpTranslation; |
| } |
| |
| public void setDismissAllInProgress(boolean dismissAllInProgress) { |
| mDismissAllInProgress = dismissAllInProgress; |
| } |
| |
| public boolean isDismissAllInProgress() { |
| return mDismissAllInProgress; |
| } |
| |
| public void setLayoutMinHeight(int layoutMinHeight) { |
| mLayoutMinHeight = layoutMinHeight; |
| } |
| |
| public void setShelf(NotificationShelf shelf) { |
| mShelf = shelf; |
| } |
| |
| @Nullable |
| public NotificationShelf getShelf() { |
| return mShelf; |
| } |
| |
| public void setLayoutMaxHeight(int maxLayoutHeight) { |
| mMaxLayoutHeight = maxLayoutHeight; |
| } |
| |
| /** |
| * Sets the last visible view of the host layout, that has a background, i.e the very last |
| * view in the shade, without the clear all button. |
| */ |
| public void setLastVisibleBackgroundChild( |
| ActivatableNotificationView lastVisibleBackgroundChild) { |
| mLastVisibleBackgroundChild = lastVisibleBackgroundChild; |
| } |
| |
| public ActivatableNotificationView getLastVisibleBackgroundChild() { |
| return mLastVisibleBackgroundChild; |
| } |
| |
| public void setCurrentScrollVelocity(float currentScrollVelocity) { |
| mCurrentScrollVelocity = currentScrollVelocity; |
| } |
| |
| public float getCurrentScrollVelocity() { |
| return mCurrentScrollVelocity; |
| } |
| |
| public boolean isOnKeyguard() { |
| return mStatusBarState == StatusBarState.KEYGUARD; |
| } |
| |
| public void setStatusBarState(int statusBarState) { |
| mStatusBarState = statusBarState; |
| } |
| |
| public void setExpandingVelocity(float expandingVelocity) { |
| mExpandingVelocity = expandingVelocity; |
| } |
| |
| public void setExpansionChanging(boolean expansionChanging) { |
| mExpansionChanging = expansionChanging; |
| } |
| |
| public boolean isExpansionChanging() { |
| return mExpansionChanging; |
| } |
| |
| public float getExpandingVelocity() { |
| return mExpandingVelocity; |
| } |
| |
| public void setPanelTracking(boolean panelTracking) { |
| mPanelTracking = panelTracking; |
| } |
| |
| public boolean hasPulsingNotifications() { |
| return mPulsing; |
| } |
| |
| public void setPulsing(boolean hasPulsing) { |
| mPulsing = hasPulsing; |
| } |
| |
| public boolean isPulsing(NotificationData.Entry entry) { |
| if (!mPulsing || mHeadsUpManager == null) { |
| return false; |
| } |
| return mHeadsUpManager.getAllEntries().anyMatch(e -> (e == entry)); |
| } |
| |
| public boolean isPanelTracking() { |
| return mPanelTracking; |
| } |
| |
| public boolean isPanelFullWidth() { |
| return mPanelFullWidth; |
| } |
| |
| public void setPanelFullWidth(boolean panelFullWidth) { |
| mPanelFullWidth = panelFullWidth; |
| } |
| |
| public void setUnlockHintRunning(boolean unlockHintRunning) { |
| mUnlockHintRunning = unlockHintRunning; |
| } |
| |
| public boolean isUnlockHintRunning() { |
| return mUnlockHintRunning; |
| } |
| |
| public boolean isQsCustomizerShowing() { |
| return mQsCustomizerShowing; |
| } |
| |
| public void setQsCustomizerShowing(boolean qsCustomizerShowing) { |
| mQsCustomizerShowing = qsCustomizerShowing; |
| } |
| |
| public void setIntrinsicPadding(int intrinsicPadding) { |
| mIntrinsicPadding = intrinsicPadding; |
| } |
| |
| public int getIntrinsicPadding() { |
| return mIntrinsicPadding; |
| } |
| |
| /** |
| * Similar to the normal is above shelf logic but doesn't allow it to be above in AOD1. |
| * |
| * @param expandableView the view to check |
| */ |
| public boolean isAboveShelf(ExpandableView expandableView) { |
| if (!(expandableView instanceof ExpandableNotificationRow)) { |
| return expandableView.isAboveShelf(); |
| } |
| ExpandableNotificationRow row = (ExpandableNotificationRow) expandableView; |
| return row.isAboveShelf() && !isDozingAndNotPulsing(row); |
| } |
| |
| /** |
| * @return whether a view is dozing and not pulsing right now |
| */ |
| public boolean isDozingAndNotPulsing(ExpandableView view) { |
| if (view instanceof ExpandableNotificationRow) { |
| return isDozingAndNotPulsing((ExpandableNotificationRow) view); |
| } |
| return false; |
| } |
| |
| /** |
| * @return whether a row is dozing and not pulsing right now |
| */ |
| public boolean isDozingAndNotPulsing(ExpandableNotificationRow row) { |
| return isDark() && !isPulsing(row.getEntry()); |
| } |
| |
| public void setExpandAnimationTopChange(int expandAnimationTopChange) { |
| mExpandAnimationTopChange = expandAnimationTopChange; |
| } |
| |
| public void setExpandingNotification(ExpandableNotificationRow row) { |
| mExpandingNotification = row; |
| } |
| |
| public ExpandableNotificationRow getExpandingNotification() { |
| return mExpandingNotification; |
| } |
| |
| public int getExpandAnimationTopChange() { |
| return mExpandAnimationTopChange; |
| } |
| |
| /** |
| * @return {@code true } when shade is completely dark: in AOD or ambient display. |
| */ |
| public boolean isFullyDark() { |
| return mDarkAmount == 1; |
| } |
| |
| public void setDarkTopPadding(int darkTopPadding) { |
| mDarkTopPadding = darkTopPadding; |
| } |
| |
| public int getDarkTopPadding() { |
| return mDarkTopPadding; |
| } |
| } |