• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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 package com.android.systemui.bubbles;
17 
18 
19 import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE;
20 
21 import android.content.Context;
22 import android.content.pm.ApplicationInfo;
23 import android.content.pm.PackageManager;
24 import android.os.UserHandle;
25 import android.view.LayoutInflater;
26 
27 import com.android.internal.annotations.VisibleForTesting;
28 import com.android.systemui.R;
29 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
30 
31 import java.util.Objects;
32 
33 /**
34  * Encapsulates the data and UI elements of a bubble.
35  */
36 class Bubble {
37 
38     private static final boolean DEBUG = false;
39     private static final String TAG = "Bubble";
40 
41     private final String mKey;
42     private final String mGroupId;
43     private String mAppName;
44     private final BubbleExpandedView.OnBubbleBlockedListener mListener;
45 
46     private boolean mInflated;
47     public NotificationEntry entry;
48     BubbleView iconView;
49     BubbleExpandedView expandedView;
50     private long mLastUpdated;
51     private long mLastAccessed;
52     private PackageManager mPm;
53 
groupId(NotificationEntry entry)54     public static String groupId(NotificationEntry entry) {
55         UserHandle user = entry.notification.getUser();
56         return user.getIdentifier() + "|" + entry.notification.getPackageName();
57     }
58 
59     /** Used in tests when no UI is required. */
60     @VisibleForTesting(visibility = PRIVATE)
Bubble(Context context, NotificationEntry e)61     Bubble(Context context, NotificationEntry e) {
62         this (context, e, null);
63     }
64 
Bubble(Context context, NotificationEntry e, BubbleExpandedView.OnBubbleBlockedListener listener)65     Bubble(Context context, NotificationEntry e,
66             BubbleExpandedView.OnBubbleBlockedListener listener) {
67         entry = e;
68         mKey = e.key;
69         mLastUpdated = e.notification.getPostTime();
70         mGroupId = groupId(e);
71         mListener = listener;
72 
73         mPm = context.getPackageManager();
74         ApplicationInfo info;
75         try {
76             info = mPm.getApplicationInfo(
77                 entry.notification.getPackageName(),
78                 PackageManager.MATCH_UNINSTALLED_PACKAGES
79                     | PackageManager.MATCH_DISABLED_COMPONENTS
80                     | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
81                     | PackageManager.MATCH_DIRECT_BOOT_AWARE);
82             if (info != null) {
83                 mAppName = String.valueOf(mPm.getApplicationLabel(info));
84             }
85         } catch (PackageManager.NameNotFoundException unused) {
86             mAppName = entry.notification.getPackageName();
87         }
88     }
89 
getKey()90     public String getKey() {
91         return mKey;
92     }
93 
getGroupId()94     public String getGroupId() {
95         return mGroupId;
96     }
97 
getPackageName()98     public String getPackageName() {
99         return entry.notification.getPackageName();
100     }
101 
getAppName()102     public String getAppName() {
103         return mAppName;
104     }
105 
isInflated()106     boolean isInflated() {
107         return mInflated;
108     }
109 
updateDotVisibility()110     public void updateDotVisibility() {
111         if (iconView != null) {
112             iconView.updateDotVisibility(true /* animate */);
113         }
114     }
115 
inflate(LayoutInflater inflater, BubbleStackView stackView)116     void inflate(LayoutInflater inflater, BubbleStackView stackView) {
117         if (mInflated) {
118             return;
119         }
120         iconView = (BubbleView) inflater.inflate(
121                 R.layout.bubble_view, stackView, false /* attachToRoot */);
122         iconView.setNotif(entry);
123 
124         expandedView = (BubbleExpandedView) inflater.inflate(
125                 R.layout.bubble_expanded_view, stackView, false /* attachToRoot */);
126         expandedView.setEntry(entry, stackView, mAppName);
127         expandedView.setOnBlockedListener(mListener);
128 
129         mInflated = true;
130     }
131 
setDismissed()132     void setDismissed() {
133         entry.setBubbleDismissed(true);
134         // TODO: move this somewhere where it can be guaranteed not to run until safe from flicker
135         if (expandedView != null) {
136             expandedView.cleanUpExpandedState();
137         }
138     }
139 
setEntry(NotificationEntry entry)140     void setEntry(NotificationEntry entry) {
141         this.entry = entry;
142         mLastUpdated = entry.notification.getPostTime();
143         if (mInflated) {
144             iconView.update(entry);
145             expandedView.update(entry);
146         }
147     }
148 
149     /**
150      * @return the newer of {@link #getLastUpdateTime()} and {@link #getLastAccessTime()}
151      */
getLastActivity()152     public long getLastActivity() {
153         return Math.max(mLastUpdated, mLastAccessed);
154     }
155 
156     /**
157      * @return the timestamp in milliseconds of the most recent notification entry for this bubble
158      */
getLastUpdateTime()159     public long getLastUpdateTime() {
160         return mLastUpdated;
161     }
162 
163     /**
164      * @return the timestamp in milliseconds when this bubble was last displayed in expanded state
165      */
getLastAccessTime()166     public long getLastAccessTime() {
167         return mLastAccessed;
168     }
169 
170     /**
171      * Should be invoked whenever a Bubble is accessed (selected while expanded).
172      */
markAsAccessedAt(long lastAccessedMillis)173     void markAsAccessedAt(long lastAccessedMillis) {
174         mLastAccessed = lastAccessedMillis;
175         entry.setShowInShadeWhenBubble(false);
176     }
177 
178     /**
179      * @return whether bubble is from a notification associated with a foreground service.
180      */
isOngoing()181     public boolean isOngoing() {
182         return entry.isForegroundService();
183     }
184 
185     @Override
toString()186     public String toString() {
187         return "Bubble{" + mKey + '}';
188     }
189 
190     @Override
equals(Object o)191     public boolean equals(Object o) {
192         if (this == o) return true;
193         if (!(o instanceof Bubble)) return false;
194         Bubble bubble = (Bubble) o;
195         return Objects.equals(mKey, bubble.mKey);
196     }
197 
198     @Override
hashCode()199     public int hashCode() {
200         return Objects.hash(mKey);
201     }
202 }
203