1 /*
2  * Copyright (C) 2018 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.stack;
18 
19 import androidx.annotation.NonNull;
20 
21 import com.android.systemui.Dumpable;
22 import com.android.systemui.dagger.SysUISingleton;
23 import com.android.systemui.dump.DumpManager;
24 import com.android.systemui.statusbar.notification.Roundable;
25 import com.android.systemui.statusbar.notification.SourceType;
26 import com.android.systemui.statusbar.notification.row.ExpandableView;
27 
28 import java.io.PrintWriter;
29 import java.util.HashSet;
30 
31 import javax.inject.Inject;
32 
33 /**
34  * A class that manages the roundness for notification views
35  */
36 @SysUISingleton
37 public class NotificationRoundnessManager implements Dumpable {
38 
39     private static final String TAG = "NotificationRoundnessManager";
40     private static final SourceType DISMISS_ANIMATION = SourceType.from("DismissAnimation");
41 
42     private final DumpManager mDumpManager;
43     private HashSet<ExpandableView> mAnimatedChildren;
44     private boolean mRoundForPulsingViews;
45     private boolean mIsClearAllInProgress;
46 
47     private ExpandableView mSwipedView = null;
48     private Roundable mViewBeforeSwipedView = null;
49     private Roundable mViewAfterSwipedView = null;
50 
51     @Inject
NotificationRoundnessManager(DumpManager dumpManager)52     NotificationRoundnessManager(DumpManager dumpManager) {
53         mDumpManager = dumpManager;
54         mDumpManager.registerDumpable(TAG, this);
55     }
56 
57     @Override
dump(@onNull PrintWriter pw, @NonNull String[] args)58     public void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
59         pw.println("roundForPulsingViews=" + mRoundForPulsingViews);
60         pw.println("isClearAllInProgress=" + mIsClearAllInProgress);
61     }
62 
isViewAffectedBySwipe(ExpandableView expandableView)63     public boolean isViewAffectedBySwipe(ExpandableView expandableView) {
64         return expandableView != null
65                 && (expandableView == mSwipedView
66                 || expandableView == mViewBeforeSwipedView
67                 || expandableView == mViewAfterSwipedView);
68     }
69 
setViewsAffectedBySwipe( Roundable viewBefore, ExpandableView viewSwiped, Roundable viewAfter)70     void setViewsAffectedBySwipe(
71             Roundable viewBefore,
72             ExpandableView viewSwiped,
73             Roundable viewAfter) {
74         // This method requires you to change the roundness of the current View targets and reset
75         // the roundness of the old View targets (if any) to 0f.
76         // To avoid conflicts, it generates a set of old Views and removes the current Views
77         // from this set.
78         HashSet<Roundable> oldViews = new HashSet<>();
79         if (mViewBeforeSwipedView != null) oldViews.add(mViewBeforeSwipedView);
80         if (mSwipedView != null) oldViews.add(mSwipedView);
81         if (mViewAfterSwipedView != null) oldViews.add(mViewAfterSwipedView);
82 
83         mViewBeforeSwipedView = viewBefore;
84         if (viewBefore != null) {
85             oldViews.remove(viewBefore);
86             viewBefore.requestRoundness(/* top = */ 0f, /* bottom = */ 1f, DISMISS_ANIMATION);
87         }
88 
89         mSwipedView = viewSwiped;
90         if (viewSwiped != null) {
91             oldViews.remove(viewSwiped);
92             viewSwiped.requestRoundness(/* top = */ 1f, /* bottom = */ 1f, DISMISS_ANIMATION);
93         }
94 
95         mViewAfterSwipedView = viewAfter;
96         if (viewAfter != null) {
97             oldViews.remove(viewAfter);
98             viewAfter.requestRoundness(/* top = */ 1f, /* bottom = */ 0f, DISMISS_ANIMATION);
99         }
100 
101         // After setting the current Views, reset the views that are still present in the set.
102         for (Roundable oldView : oldViews) {
103             oldView.requestRoundnessReset(DISMISS_ANIMATION);
104         }
105     }
106 
setClearAllInProgress(boolean isClearingAll)107     void setClearAllInProgress(boolean isClearingAll) {
108         mIsClearAllInProgress = isClearingAll;
109     }
110 
111     /**
112      * Check if "Clear all" notifications is in progress.
113      */
isClearAllInProgress()114     public boolean isClearAllInProgress() {
115         return mIsClearAllInProgress;
116     }
117 
118     /**
119      * Check if we can request the `Pulsing` roundness for notification.
120      */
shouldRoundNotificationPulsing()121     public boolean shouldRoundNotificationPulsing() {
122         return mRoundForPulsingViews;
123     }
124 
setAnimatedChildren(HashSet<ExpandableView> animatedChildren)125     public void setAnimatedChildren(HashSet<ExpandableView> animatedChildren) {
126         mAnimatedChildren = animatedChildren;
127     }
128 
129     /**
130      * Check if the view should be animated
131      * @param view target view
132      * @return true, if is in the AnimatedChildren set
133      */
isAnimatedChild(ExpandableView view)134     public boolean isAnimatedChild(ExpandableView view) {
135         return mAnimatedChildren.contains(view);
136     }
137 
setShouldRoundPulsingViews(boolean shouldRoundPulsingViews)138     public void setShouldRoundPulsingViews(boolean shouldRoundPulsingViews) {
139         mRoundForPulsingViews = shouldRoundPulsingViews;
140     }
141 }
142