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 row notification top-level view to bind views to
48      * @param callback callback after stage finishes
49      */
executeStage( @onNull NotificationEntry entry, @NonNull ExpandableNotificationRow row, @NonNull StageCallback callback)50     protected abstract void executeStage(
51             @NonNull NotificationEntry entry,
52             @NonNull ExpandableNotificationRow row,
53             @NonNull StageCallback callback);
54 
55     /**
56      * Abort the stage if in progress.
57      *
58      * @param row notification top-level view to bind views to
59      */
abortStage( @onNull NotificationEntry entry, @NonNull ExpandableNotificationRow row)60     protected abstract void abortStage(
61             @NonNull NotificationEntry entry,
62             @NonNull ExpandableNotificationRow row);
63 
64     /**
65      * Get the stage parameters for the entry. Clients should use this to modify how the stage
66      * handles the notification content.
67      */
getStageParams(@onNull NotificationEntry entry)68     public final @NonNull Params getStageParams(@NonNull NotificationEntry entry) {
69         Params params = mContentParams.get(entry);
70         if (params == null) {
71             // TODO: This should throw an exception but there are some cases of re-entrant calls
72             // in NotificationEntryManager (e.g. b/155324756) that cause removal in update that
73             // lead to inflation after the notification is "removed". We return an empty params
74             // to avoid any NPEs for now, but we should remove this when all re-entrant calls are
75             // fixed.
76             Log.wtf(TAG, String.format("Entry does not have any stage parameters. key: %s",
77                             entry.getKey()));
78             return newStageParams();
79         }
80         return params;
81     }
82 
83     // TODO(b/253081345): Remove this method.
84     /**
85      * Get the stage parameters for the entry, or null if there are no stage parameters for the
86      * entry.
87      *
88      * @see #getStageParams(NotificationEntry)
89      */
tryGetStageParams(@onNull NotificationEntry entry)90     public final @Nullable Params tryGetStageParams(@NonNull NotificationEntry entry) {
91         return mContentParams.get(entry);
92     }
93 
94     /**
95      * Create a params entry for the notification for this stage.
96      */
createStageParams(@onNull NotificationEntry entry)97     final void createStageParams(@NonNull NotificationEntry entry) {
98         mContentParams.put(entry, newStageParams());
99     }
100 
101     /**
102      * Delete params entry for notification.
103      */
deleteStageParams(@onNull NotificationEntry entry)104     final void deleteStageParams(@NonNull NotificationEntry entry) {
105         mContentParams.remove(entry);
106     }
107 
108     /**
109      * Create a new, empty stage params object.
110      */
newStageParams()111     protected abstract Params newStageParams();
112 
113     private static final String TAG = "BindStage";
114 
115     /**
116      * Interface for callback.
117      */
118     interface StageCallback {
119         /**
120          * Callback for when the stage is complete.
121          */
onStageFinished(NotificationEntry entry)122         void onStageFinished(NotificationEntry entry);
123     }
124 }
125