1 /*
2  * Copyright (C) 2022 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.dreams;
18 
19 import android.view.View;
20 
21 import androidx.annotation.NonNull;
22 
23 import com.android.systemui.dagger.SysUISingleton;
24 import com.android.systemui.dagger.qualifiers.Main;
25 import com.android.systemui.statusbar.policy.CallbackController;
26 
27 import java.util.ArrayList;
28 import java.util.List;
29 import java.util.Objects;
30 import java.util.concurrent.Executor;
31 
32 import javax.inject.Inject;
33 
34 /**
35  * {@link DreamOverlayStatusBarItemsProvider} provides extra dream overlay status bar items. A
36  * callback can be registered that will be informed of items being added or removed from the
37  * provider.
38  */
39 @SysUISingleton
40 public class DreamOverlayStatusBarItemsProvider implements
41         CallbackController<DreamOverlayStatusBarItemsProvider.Callback> {
42     /**
43      * Represents one item in the dream overlay status bar.
44      */
45     public interface StatusBarItem {
46         /**
47          * Return the {@link View} associated with this item.
48          */
getView()49         View getView();
50     }
51 
52     /**
53      * A callback to be registered with the provider to be informed of when the list of status bar
54      * items has changed.
55      */
56     public interface Callback {
57         /**
58          * Inform the callback that status bar items have changed.
59          */
onStatusBarItemsChanged(List<StatusBarItem> newItems)60         void onStatusBarItemsChanged(List<StatusBarItem> newItems);
61     }
62 
63     private final Executor mExecutor;
64     private final List<StatusBarItem> mItems = new ArrayList<>();
65     private final List<Callback> mCallbacks = new ArrayList<>();
66 
67     @Inject
DreamOverlayStatusBarItemsProvider(@ain Executor executor)68     public DreamOverlayStatusBarItemsProvider(@Main Executor executor) {
69         mExecutor = executor;
70     }
71 
72     @Override
addCallback(@onNull Callback callback)73     public void addCallback(@NonNull Callback callback) {
74         mExecutor.execute(() -> {
75             Objects.requireNonNull(callback, "Callback must not be null.");
76             if (mCallbacks.contains(callback)) {
77                 return;
78             }
79 
80             mCallbacks.add(callback);
81             if (!mItems.isEmpty()) {
82                 callback.onStatusBarItemsChanged(mItems);
83             }
84         });
85     }
86 
87     @Override
removeCallback(@onNull Callback callback)88     public void removeCallback(@NonNull Callback callback) {
89         mExecutor.execute(() -> {
90             Objects.requireNonNull(callback, "Callback must not be null.");
91             mCallbacks.remove(callback);
92         });
93     }
94 
95     /**
96      * Adds an item to the dream overlay status bar.
97      */
addStatusBarItem(StatusBarItem item)98     public void addStatusBarItem(StatusBarItem item) {
99         mExecutor.execute(() -> {
100             if (!mItems.contains(item)) {
101                 mItems.add(item);
102                 mCallbacks.forEach(callback -> callback.onStatusBarItemsChanged(mItems));
103             }
104         });
105     }
106 
107     /**
108      * Removes an item from the dream overlay status bar.
109      */
removeStatusBarItem(StatusBarItem item)110     public void removeStatusBarItem(StatusBarItem item) {
111         mExecutor.execute(() -> {
112             if (mItems.remove(item)) {
113                 mCallbacks.forEach(callback -> callback.onStatusBarItemsChanged(mItems));
114             }
115         });
116     }
117 }
118