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 17 package com.android.systemui.statusbar.notification; 18 19 import static com.android.internal.util.Preconditions.checkNotNull; 20 21 import android.os.UserHandle; 22 import android.service.notification.StatusBarNotification; 23 import android.util.ArraySet; 24 25 import com.android.internal.statusbar.NotificationVisibility; 26 import com.android.systemui.ForegroundServiceController; 27 import com.android.systemui.statusbar.notification.collection.NotificationEntry; 28 import com.android.systemui.statusbar.notification.stack.NotificationListContainer; 29 import com.android.systemui.statusbar.policy.DeviceProvisionedController; 30 import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener; 31 32 /** 33 * Root controller for the list of notifications in the shade. 34 * 35 * TODO: Much of the code in NotificationPresenter should eventually move in here. It will proxy 36 * domain-specific behavior (ARC, etc) to subcontrollers. 37 */ 38 public class NotificationListController { 39 private final NotificationEntryManager mEntryManager; 40 private final NotificationListContainer mListContainer; 41 private final ForegroundServiceController mForegroundServiceController; 42 private final DeviceProvisionedController mDeviceProvisionedController; 43 NotificationListController( NotificationEntryManager entryManager, NotificationListContainer listContainer, ForegroundServiceController foregroundServiceController, DeviceProvisionedController deviceProvisionedController)44 public NotificationListController( 45 NotificationEntryManager entryManager, 46 NotificationListContainer listContainer, 47 ForegroundServiceController foregroundServiceController, 48 DeviceProvisionedController deviceProvisionedController) { 49 mEntryManager = checkNotNull(entryManager); 50 mListContainer = checkNotNull(listContainer); 51 mForegroundServiceController = checkNotNull(foregroundServiceController); 52 mDeviceProvisionedController = checkNotNull(deviceProvisionedController); 53 } 54 55 /** 56 * Causes the controller to register listeners on its dependencies. This method must be called 57 * before the controller is ready to perform its duties. 58 */ bind()59 public void bind() { 60 mEntryManager.addNotificationEntryListener(mEntryListener); 61 mDeviceProvisionedController.addCallback(mDeviceProvisionedListener); 62 } 63 64 @SuppressWarnings("FieldCanBeLocal") 65 private final NotificationEntryListener mEntryListener = new NotificationEntryListener() { 66 @Override 67 public void onEntryRemoved( 68 NotificationEntry entry, 69 NotificationVisibility visibility, 70 boolean removedByUser) { 71 mListContainer.cleanUpViewStateForEntry(entry); 72 } 73 74 @Override 75 public void onBeforeNotificationAdded(NotificationEntry entry) { 76 tagForeground(entry.notification); 77 } 78 }; 79 80 private final DeviceProvisionedListener mDeviceProvisionedListener = 81 new DeviceProvisionedListener() { 82 @Override 83 public void onDeviceProvisionedChanged() { 84 mEntryManager.updateNotifications(); 85 } 86 }; 87 88 // TODO: This method is horrifically inefficient tagForeground(StatusBarNotification notification)89 private void tagForeground(StatusBarNotification notification) { 90 ArraySet<Integer> activeOps = 91 mForegroundServiceController.getAppOps( 92 notification.getUserId(), notification.getPackageName()); 93 if (activeOps != null) { 94 int len = activeOps.size(); 95 for (int i = 0; i < len; i++) { 96 updateNotificationsForAppOp(activeOps.valueAt(i), notification.getUid(), 97 notification.getPackageName(), true); 98 } 99 } 100 } 101 102 /** When an app op changes, propagate that change to notifications. */ updateNotificationsForAppOp(int appOp, int uid, String pkg, boolean showIcon)103 public void updateNotificationsForAppOp(int appOp, int uid, String pkg, boolean showIcon) { 104 String foregroundKey = 105 mForegroundServiceController.getStandardLayoutKey(UserHandle.getUserId(uid), pkg); 106 if (foregroundKey != null) { 107 mEntryManager 108 .getNotificationData().updateAppOp(appOp, uid, pkg, foregroundKey, showIcon); 109 mEntryManager.updateNotifications(); 110 } 111 } 112 } 113