• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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.notification;
18 
19 import android.util.ArraySet;
20 import android.view.View;
21 
22 import com.android.systemui.statusbar.ExpandableNotificationRow;
23 import com.android.systemui.statusbar.NotificationData;
24 import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
25 
26 import java.util.ArrayList;
27 
28 /**
29  * A manager that ensures that notifications are visually stable. It will suppress reorderings
30  * and reorder at the right time when they are out of view.
31  */
32 public class VisualStabilityManager implements OnHeadsUpChangedListener {
33 
34     private final ArrayList<Callback> mCallbacks =  new ArrayList<>();
35 
36     private boolean mPanelExpanded;
37     private boolean mScreenOn;
38     private boolean mReorderingAllowed;
39     private VisibilityLocationProvider mVisibilityLocationProvider;
40     private ArraySet<View> mAllowedReorderViews = new ArraySet<>();
41     private ArraySet<View> mAddedChildren = new ArraySet<>();
42 
43     /**
44      * Add a callback to invoke when reordering is allowed again.
45      * @param callback
46      */
addReorderingAllowedCallback(Callback callback)47     public void addReorderingAllowedCallback(Callback callback) {
48         if (mCallbacks.contains(callback)) {
49             return;
50         }
51         mCallbacks.add(callback);
52     }
53 
54     /**
55      * Set the panel to be expanded.
56      */
setPanelExpanded(boolean expanded)57     public void setPanelExpanded(boolean expanded) {
58         mPanelExpanded = expanded;
59         updateReorderingAllowed();
60     }
61 
62     /**
63      * @param screenOn whether the screen is on
64      */
setScreenOn(boolean screenOn)65     public void setScreenOn(boolean screenOn) {
66         mScreenOn = screenOn;
67         updateReorderingAllowed();
68     }
69 
updateReorderingAllowed()70     private void updateReorderingAllowed() {
71         boolean reorderingAllowed = !mScreenOn || !mPanelExpanded;
72         boolean changed = reorderingAllowed && !mReorderingAllowed;
73         mReorderingAllowed = reorderingAllowed;
74         if (changed) {
75             notifyCallbacks();
76         }
77     }
78 
notifyCallbacks()79     private void notifyCallbacks() {
80         for (int i = 0; i < mCallbacks.size(); i++) {
81             Callback callback = mCallbacks.get(i);
82             callback.onReorderingAllowed();
83         }
84         mCallbacks.clear();
85     }
86 
87     /**
88      * @return whether reordering is currently allowed in general.
89      */
isReorderingAllowed()90     public boolean isReorderingAllowed() {
91         return mReorderingAllowed;
92     }
93 
94     /**
95      * @return whether a specific notification is allowed to reorder. Certain notifications are
96      * allowed to reorder even if {@link #isReorderingAllowed()} returns false, like newly added
97      * notifications or heads-up notifications that are out of view.
98      */
canReorderNotification(ExpandableNotificationRow row)99     public boolean canReorderNotification(ExpandableNotificationRow row) {
100         if (mReorderingAllowed) {
101             return true;
102         }
103         if (mAddedChildren.contains(row)) {
104             return true;
105         }
106         if (mAllowedReorderViews.contains(row)
107                 && !mVisibilityLocationProvider.isInVisibleLocation(row)) {
108             return true;
109         }
110         return false;
111     }
112 
setVisibilityLocationProvider( VisibilityLocationProvider visibilityLocationProvider)113     public void setVisibilityLocationProvider(
114             VisibilityLocationProvider visibilityLocationProvider) {
115         mVisibilityLocationProvider = visibilityLocationProvider;
116     }
117 
onReorderingFinished()118     public void onReorderingFinished() {
119         mAllowedReorderViews.clear();
120         mAddedChildren.clear();
121     }
122 
123     @Override
onHeadsUpStateChanged(NotificationData.Entry entry, boolean isHeadsUp)124     public void onHeadsUpStateChanged(NotificationData.Entry entry, boolean isHeadsUp) {
125         if (isHeadsUp) {
126             // Heads up notifications should in general be allowed to reorder if they are out of
127             // view and stay at the current location if they aren't.
128             mAllowedReorderViews.add(entry.row);
129         }
130     }
131 
132     /**
133      * Notify the visual stability manager that a new view was added and should be allowed to
134      * reorder next time.
135      */
notifyViewAddition(View view)136     public void notifyViewAddition(View view) {
137         mAddedChildren.add(view);
138     }
139 
140     public interface Callback {
141         /**
142          * Called when reordering is allowed again.
143          */
onReorderingAllowed()144         void onReorderingAllowed();
145     }
146 
147 }
148