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.row;
18 
19 import android.annotation.MainThread;
20 import android.util.ArrayMap;
21 import android.util.Log;
22 
23 import androidx.annotation.NonNull;
24 import androidx.annotation.Nullable;
25 
26 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
27 
28 import java.util.Map;
29 
30 /**
31  * A {@link BindStage} is an abstraction for a unit of work in inflating/binding/unbinding
32  * views to a notification. Used by {@link NotifBindPipeline}.
33  *
34  * Clients may also use {@link #getStageParams} to provide parameters for this stage for a given
35  * notification and request a rebind.
36  *
37  * @param <Params> params to do this stage
38  */
39 @MainThread
40 public abstract class BindStage<Params> extends BindRequester {
41 
42     private Map<NotificationEntry, Params> mContentParams = new ArrayMap<>();
43 
44     /**
45      * Execute the stage asynchronously.
46      *
47      * @param entry the NotificationEntry to bind
48      * @param row notification top-level view to bind views to
49      * @param callback callback after stage finishes
50      */
executeStage( @onNull NotificationEntry entry, @NonNull ExpandableNotificationRow row, @NonNull StageCallback callback)51     protected abstract void executeStage(
52             @NonNull NotificationEntry entry,
53             @NonNull ExpandableNotificationRow row,
54             @NonNull StageCallback callback);
55 
56     /**
57      * Abort the stage if in progress.
58      *
59      * @param row notification top-level view to bind views to
60      */
abortStage( @onNull NotificationEntry entry, @NonNull ExpandableNotificationRow row)61     protected abstract void abortStage(
62             @NonNull NotificationEntry entry,
63             @NonNull ExpandableNotificationRow row);
64 
65     /**
66      * Get the stage parameters for the entry. Clients should use this to modify how the stage
67      * handles the notification content.
68      */
getStageParams(@onNull NotificationEntry entry)69     public final @NonNull Params getStageParams(@NonNull NotificationEntry entry) {
70         Params params = mContentParams.get(entry);
71         if (params == null) {
72             // TODO: This should throw an exception but there are some cases of re-entrant calls
73             // in NotificationEntryManager (e.g. b/155324756) that cause removal in update that
74             // lead to inflation after the notification is "removed". We return an empty params
75             // to avoid any NPEs for now, but we should remove this when all re-entrant calls are
76             // fixed.
77             Log.wtf(TAG, String.format("Entry does not have any stage parameters. key: %s",
78                             entry.getKey()));
79             return newStageParams();
80         }
81         return params;
82     }
83 
84     // TODO(b/253081345): Remove this method.
85     /**
86      * Get the stage parameters for the entry, or null if there are no stage parameters for the
87      * entry.
88      *
89      * @see #getStageParams(NotificationEntry)
90      */
tryGetStageParams(@onNull NotificationEntry entry)91     public final @Nullable Params tryGetStageParams(@NonNull NotificationEntry entry) {
92         return mContentParams.get(entry);
93     }
94 
95     /**
96      * Create a params entry for the notification for this stage.
97      */
createStageParams(@onNull NotificationEntry entry)98     final void createStageParams(@NonNull NotificationEntry entry) {
99         mContentParams.put(entry, newStageParams());
100     }
101 
102     /**
103      * Delete params entry for notification.
104      */
deleteStageParams(@onNull NotificationEntry entry)105     final void deleteStageParams(@NonNull NotificationEntry entry) {
106         mContentParams.remove(entry);
107     }
108 
109     /**
110      * Create a new, empty stage params object.
111      */
newStageParams()112     protected abstract Params newStageParams();
113 
114     private static final String TAG = "BindStage";
115 
116     /**
117      * Interface for callback.
118      */
119     interface StageCallback {
120         /**
121          * Callback for when the stage is complete.
122          */
onStageFinished(NotificationEntry entry)123         void onStageFinished(NotificationEntry entry);
124     }
125 }
126