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.internal.util.NotificationMessagingUtil;
27 import com.android.systemui.dagger.SysUISingleton;
28 import com.android.systemui.statusbar.NotificationPresenter;
29 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
30 import com.android.systemui.statusbar.notification.collection.coordinator.HeadsUpCoordinator;
31 import com.android.systemui.statusbar.notification.row.NotifBindPipeline.BindCallback;
32 import com.android.systemui.statusbar.notification.row.RowContentBindParams;
33 import com.android.systemui.statusbar.notification.row.RowContentBindStage;
34 
35 import java.util.Map;
36 
37 import javax.inject.Inject;
38 
39 /**
40  * Wrapper around heads up view binding logic. {@link HeadsUpViewBinder} is responsible for
41  * figuring out the right heads up inflation parameters and inflating/freeing the heads up
42  * content view.
43  *
44  * TODO: This should be moved into {@link HeadsUpCoordinator} when the old pipeline is deprecated
45  * (i.e. when {@link HeadsUpController} is removed).
46  */
47 @SysUISingleton
48 public class HeadsUpViewBinder {
49     private final RowContentBindStage mStage;
50     private final NotificationMessagingUtil mNotificationMessagingUtil;
51     private final Map<NotificationEntry, CancellationSignal> mOngoingBindCallbacks =
52             new ArrayMap<>();
53 
54     private NotificationPresenter mNotificationPresenter;
55 
56     @Inject
HeadsUpViewBinder( NotificationMessagingUtil notificationMessagingUtil, RowContentBindStage bindStage)57     HeadsUpViewBinder(
58             NotificationMessagingUtil notificationMessagingUtil,
59             RowContentBindStage bindStage) {
60         mNotificationMessagingUtil = notificationMessagingUtil;
61         mStage = bindStage;
62     }
63 
64     /**
65      * Set notification presenter to determine parameters for heads up view inflation.
66      */
setPresenter(NotificationPresenter presenter)67     public void setPresenter(NotificationPresenter presenter) {
68         mNotificationPresenter = presenter;
69     }
70 
71     /**
72      * Bind heads up view to the notification row.
73      * @param callback callback after heads up view is bound
74      */
bindHeadsUpView(NotificationEntry entry, @Nullable BindCallback callback)75     public void bindHeadsUpView(NotificationEntry entry, @Nullable BindCallback callback) {
76         RowContentBindParams params = mStage.getStageParams(entry);
77         final boolean isImportantMessage = mNotificationMessagingUtil.isImportantMessaging(
78                 entry.getSbn(), entry.getImportance());
79         final boolean useIncreasedHeadsUp = isImportantMessage
80                 && !mNotificationPresenter.isPresenterFullyCollapsed();
81         params.setUseIncreasedHeadsUpHeight(useIncreasedHeadsUp);
82         params.requireContentViews(FLAG_CONTENT_VIEW_HEADS_UP);
83         CancellationSignal signal = mStage.requestRebind(entry, en -> {
84             en.getRow().setUsesIncreasedHeadsUpHeight(params.useIncreasedHeadsUpHeight());
85             if (callback != null) {
86                 callback.onBindFinished(en);
87             }
88         });
89         abortBindCallback(entry);
90         mOngoingBindCallbacks.put(entry, signal);
91     }
92 
93     /**
94      * Abort any callbacks waiting for heads up view binding to finish for a given notification.
95      * @param entry notification with bind in progress
96      */
abortBindCallback(NotificationEntry entry)97     public void abortBindCallback(NotificationEntry entry) {
98         CancellationSignal ongoingBindCallback = mOngoingBindCallbacks.remove(entry);
99         if (ongoingBindCallback != null) {
100             ongoingBindCallback.cancel();
101         }
102     }
103 
104     /**
105      * Unbind the heads up view from the notification row.
106      */
unbindHeadsUpView(NotificationEntry entry)107     public void unbindHeadsUpView(NotificationEntry entry) {
108         abortBindCallback(entry);
109         mStage.getStageParams(entry).markContentViewsFreeable(FLAG_CONTENT_VIEW_HEADS_UP);
110         mStage.requestRebind(entry, null);
111     }
112 }
113