• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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.interruption;
18 
19 import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP;
20 
21 import android.util.ArrayMap;
22 
23 import androidx.annotation.Nullable;
24 import androidx.core.os.CancellationSignal;
25 
26 import com.android.systemui.dagger.SysUISingleton;
27 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
28 import com.android.systemui.statusbar.notification.collection.coordinator.HeadsUpCoordinator;
29 import com.android.systemui.statusbar.notification.row.RowContentBindParams;
30 import com.android.systemui.statusbar.notification.row.RowContentBindStage;
31 
32 import java.util.Map;
33 
34 import javax.inject.Inject;
35 
36 /**
37  * Wrapper around heads up view binding logic. {@link HeadsUpViewBinder} is responsible for
38  * figuring out the right heads up inflation parameters and inflating/freeing the heads up
39  * content view.
40  *
41  * TODO: This should be moved into {@link HeadsUpCoordinator} when the old pipeline is deprecated.
42  */
43 @SysUISingleton
44 public class HeadsUpViewBinder {
45     private final RowContentBindStage mStage;
46     private final Map<NotificationEntry, CancellationSignal> mOngoingBindCallbacks =
47             new ArrayMap<>();
48     private final HeadsUpViewBinderLogger mLogger;
49 
50 
51     @Inject
HeadsUpViewBinder(RowContentBindStage bindStage, HeadsUpViewBinderLogger logger)52     HeadsUpViewBinder(RowContentBindStage bindStage, HeadsUpViewBinderLogger logger) {
53         mStage = bindStage;
54         mLogger = logger;
55     }
56 
57     /**
58      * Bind heads up view to the notification row.
59      * @param callback callback after heads up view is bound
60      */
bindHeadsUpView( NotificationEntry entry, boolean isPinnedByUser, @Nullable HeadsUpBindCallback callback)61     public void bindHeadsUpView(
62             NotificationEntry entry,
63             boolean isPinnedByUser,
64             @Nullable HeadsUpBindCallback callback) {
65         RowContentBindParams params = mStage.getStageParams(entry);
66         params.requireContentViews(FLAG_CONTENT_VIEW_HEADS_UP);
67         CancellationSignal signal = mStage.requestRebind(entry, en -> {
68             mLogger.entryBoundSuccessfully(entry);
69             // requestRebind promises that if we called cancel before this callback would be
70             // invoked, then we will not enter this callback, and because we always cancel before
71             // adding to this map, we know this will remove the correct signal.
72             mOngoingBindCallbacks.remove(entry);
73             if (callback != null) {
74                 callback.onHeadsUpBindFinished(en, isPinnedByUser);
75             }
76         });
77         abortBindCallback(entry);
78         mLogger.startBindingHun(entry, isPinnedByUser);
79         mOngoingBindCallbacks.put(entry, signal);
80     }
81 
82     /**
83      * Abort any callbacks waiting for heads up view binding to finish for a given notification.
84      * @param entry notification with bind in progress
85      */
abortBindCallback(NotificationEntry entry)86     public void abortBindCallback(NotificationEntry entry) {
87         CancellationSignal ongoingBindCallback = mOngoingBindCallbacks.remove(entry);
88         if (ongoingBindCallback != null) {
89             mLogger.currentOngoingBindingAborted(entry);
90             ongoingBindCallback.cancel();
91         }
92     }
93 
94     /**
95      * Unbind the heads up view from the notification row.
96      */
unbindHeadsUpView(NotificationEntry entry)97     public void unbindHeadsUpView(NotificationEntry entry) {
98         abortBindCallback(entry);
99 
100         // params may be null if the notification was already removed from the collection but we let
101         // it stick around during a launch animation. In this case, the heads up view has already
102         // been unbound, so we don't need to unbind it.
103         // TODO(b/253081345): Change this back to getStageParams and remove null check.
104         RowContentBindParams params = mStage.tryGetStageParams(entry);
105         if (params == null) {
106             mLogger.entryBindStageParamsNullOnUnbind(entry);
107             return;
108         }
109 
110         params.markContentViewsFreeable(FLAG_CONTENT_VIEW_HEADS_UP);
111         mLogger.entryContentViewMarkedFreeable(entry);
112         mStage.requestRebind(entry, e -> mLogger.entryUnbound(e));
113     }
114 
115     /**
116      * Interface for bind callback.
117      */
118     public interface HeadsUpBindCallback {
119         /**
120          * Called when all views are fully bound on the notification.
121          */
onHeadsUpBindFinished(NotificationEntry entry, boolean isPinnedByUser)122         void onHeadsUpBindFinished(NotificationEntry entry, boolean isPinnedByUser);
123     }
124 }
125