blob: 96b62ac918ab4e3f8fc2f75932ed514d71d22751 [file] [log] [blame]
Gus Prevaseb4e2e12018-12-28 14:57:59 -05001/*
2 * Copyright (C) 2018 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
17package com.android.systemui;
18
19import android.app.Notification;
20import android.app.NotificationManager;
21import android.content.Context;
22import android.os.Bundle;
23import android.service.notification.StatusBarNotification;
24import android.util.Log;
25
26import com.android.internal.statusbar.NotificationVisibility;
Gus Prevaseb4e2e12018-12-28 14:57:59 -050027import com.android.systemui.statusbar.notification.NotificationEntryListener;
28import com.android.systemui.statusbar.notification.NotificationEntryManager;
Ned Burnsf81c4c42019-01-07 14:10:43 -050029import com.android.systemui.statusbar.notification.collection.NotificationEntry;
Gus Prevaseb4e2e12018-12-28 14:57:59 -050030
31import javax.inject.Inject;
32import javax.inject.Singleton;
33
34/** Updates foreground service notification state in response to notification data events. */
35@Singleton
36public class ForegroundServiceNotificationListener {
37
38 private static final String TAG = "FgServiceController";
39 private static final boolean DBG = false;
40
41 private final Context mContext;
42 private final ForegroundServiceController mForegroundServiceController;
43
44 @Inject
45 public ForegroundServiceNotificationListener(Context context,
46 ForegroundServiceController foregroundServiceController,
47 NotificationEntryManager notificationEntryManager) {
48 mContext = context;
49 mForegroundServiceController = foregroundServiceController;
50 notificationEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
51 @Override
Ned Burnsf81c4c42019-01-07 14:10:43 -050052 public void onPendingEntryAdded(NotificationEntry entry) {
Gus Prevaseb4e2e12018-12-28 14:57:59 -050053 addNotification(entry.notification, entry.importance);
54 }
55
56 @Override
Mady Mellor0ad5b9d2019-01-08 14:59:55 -080057 public void onPostEntryUpdated(NotificationEntry entry) {
Gus Prevaseb4e2e12018-12-28 14:57:59 -050058 updateNotification(entry.notification, entry.importance);
59 }
60
61 @Override
62 public void onEntryRemoved(
Ned Burnsf81c4c42019-01-07 14:10:43 -050063 NotificationEntry entry,
Gus Prevaseb4e2e12018-12-28 14:57:59 -050064 NotificationVisibility visibility,
Gus Prevaseb4e2e12018-12-28 14:57:59 -050065 boolean removedByUser) {
Ned Burnsef2ef6c2019-01-02 16:48:08 -050066 removeNotification(entry.notification);
Gus Prevaseb4e2e12018-12-28 14:57:59 -050067 }
68 });
69 }
70
71 /**
72 * @param sbn notification that was just posted
73 */
74 private void addNotification(StatusBarNotification sbn, int importance) {
75 updateNotification(sbn, importance);
76 }
77
78 /**
79 * @param sbn notification that was just removed
80 */
81 private void removeNotification(StatusBarNotification sbn) {
82 mForegroundServiceController.updateUserState(
83 sbn.getUserId(),
84 new ForegroundServiceController.UserStateUpdateCallback() {
85 @Override
86 public boolean updateUserState(ForegroundServicesUserState userState) {
87 if (mForegroundServiceController.isDisclosureNotification(sbn)) {
88 // if you remove the dungeon entirely, we take that to mean there are
89 // no running services
90 userState.setRunningServices(null, 0);
91 return true;
92 } else {
93 // this is safe to call on any notification, not just
94 // FLAG_FOREGROUND_SERVICE
95 return userState.removeNotification(sbn.getPackageName(), sbn.getKey());
96 }
97 }
98
99 @Override
100 public void userStateNotFound(int userId) {
101 if (DBG) {
102 Log.w(TAG, String.format(
103 "user %d with no known notifications got removeNotification "
104 + "for %s",
105 sbn.getUserId(), sbn));
106 }
107 }
108 },
109 false /* don't create */);
110 }
111
112 /**
113 * @param sbn notification that was just changed in some way
114 */
115 private void updateNotification(StatusBarNotification sbn, int newImportance) {
116 mForegroundServiceController.updateUserState(
117 sbn.getUserId(),
118 userState -> {
119 if (mForegroundServiceController.isDisclosureNotification(sbn)) {
120 final Bundle extras = sbn.getNotification().extras;
121 if (extras != null) {
122 final String[] svcs = extras.getStringArray(
123 Notification.EXTRA_FOREGROUND_APPS);
124 userState.setRunningServices(svcs, sbn.getNotification().when);
125 }
126 } else {
127 userState.removeNotification(sbn.getPackageName(), sbn.getKey());
128 if (0 != (sbn.getNotification().flags
129 & Notification.FLAG_FOREGROUND_SERVICE)) {
130 if (newImportance > NotificationManager.IMPORTANCE_MIN) {
131 userState.addImportantNotification(sbn.getPackageName(),
132 sbn.getKey());
133 }
134 final Notification.Builder builder =
135 Notification.Builder.recoverBuilder(
136 mContext, sbn.getNotification());
137 if (builder.usesStandardHeader()) {
138 userState.addStandardLayoutNotification(
139 sbn.getPackageName(), sbn.getKey());
140 }
141 }
142 }
143 return true;
144 },
145 true /* create if not found */);
146 }
147}