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 static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME; 20 import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENABLE_REMOTE_INPUT; 21 import static com.android.systemui.statusbar.StatusBarState.KEYGUARD; 22 23 import android.view.View; 24 import android.view.ViewGroup; 25 26 import androidx.annotation.NonNull; 27 28 import com.android.systemui.classifier.FalsingCollector; 29 import com.android.systemui.plugins.FalsingManager; 30 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; 31 import com.android.systemui.plugins.statusbar.StatusBarStateController; 32 import com.android.systemui.shared.plugins.PluginManager; 33 import com.android.systemui.statusbar.NotificationMediaManager; 34 import com.android.systemui.statusbar.notification.collection.NotificationEntry; 35 import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager; 36 import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager; 37 import com.android.systemui.statusbar.notification.collection.render.NodeController; 38 import com.android.systemui.statusbar.notification.logging.NotificationLogger; 39 import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier; 40 import com.android.systemui.statusbar.notification.row.dagger.AppName; 41 import com.android.systemui.statusbar.notification.row.dagger.NotificationKey; 42 import com.android.systemui.statusbar.notification.row.dagger.NotificationRowScope; 43 import com.android.systemui.statusbar.notification.stack.NotificationListContainer; 44 import com.android.systemui.statusbar.phone.KeyguardBypassController; 45 import com.android.systemui.statusbar.policy.HeadsUpManager; 46 import com.android.systemui.util.time.SystemClock; 47 import com.android.systemui.wmshell.BubblesManager; 48 49 import java.util.List; 50 import java.util.Optional; 51 52 import javax.inject.Inject; 53 import javax.inject.Named; 54 55 /** 56 * Controller for {@link ExpandableNotificationRow}. 57 */ 58 @NotificationRowScope 59 public class ExpandableNotificationRowController implements NodeController { 60 private final ExpandableNotificationRow mView; 61 private final NotificationListContainer mListContainer; 62 private final ActivatableNotificationViewController mActivatableNotificationViewController; 63 private final NotificationMediaManager mMediaManager; 64 private final PluginManager mPluginManager; 65 private final SystemClock mClock; 66 private final String mAppName; 67 private final String mNotificationKey; 68 private final KeyguardBypassController mKeyguardBypassController; 69 private final GroupMembershipManager mGroupMembershipManager; 70 private final GroupExpansionManager mGroupExpansionManager; 71 private final RowContentBindStage mRowContentBindStage; 72 private final NotificationLogger mNotificationLogger; 73 private final HeadsUpManager mHeadsUpManager; 74 private final ExpandableNotificationRow.OnExpandClickListener mOnExpandClickListener; 75 private final StatusBarStateController mStatusBarStateController; 76 77 private final ExpandableNotificationRow.ExpansionLogger mExpansionLogger = 78 this::logNotificationExpansion; 79 private final ExpandableNotificationRow.CoordinateOnClickListener mOnFeedbackClickListener; 80 private final NotificationGutsManager mNotificationGutsManager; 81 private final OnUserInteractionCallback mOnUserInteractionCallback; 82 private final FalsingManager mFalsingManager; 83 private final FalsingCollector mFalsingCollector; 84 private final boolean mAllowLongPress; 85 private final PeopleNotificationIdentifier mPeopleNotificationIdentifier; 86 private final Optional<BubblesManager> mBubblesManagerOptional; 87 88 @Inject ExpandableNotificationRowController( ExpandableNotificationRow view, NotificationListContainer listContainer, ActivatableNotificationViewController activatableNotificationViewController, NotificationMediaManager mediaManager, PluginManager pluginManager, SystemClock clock, @AppName String appName, @NotificationKey String notificationKey, KeyguardBypassController keyguardBypassController, GroupMembershipManager groupMembershipManager, GroupExpansionManager groupExpansionManager, RowContentBindStage rowContentBindStage, NotificationLogger notificationLogger, HeadsUpManager headsUpManager, ExpandableNotificationRow.OnExpandClickListener onExpandClickListener, StatusBarStateController statusBarStateController, NotificationGutsManager notificationGutsManager, @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowLongPress, OnUserInteractionCallback onUserInteractionCallback, FalsingManager falsingManager, FalsingCollector falsingCollector, PeopleNotificationIdentifier peopleNotificationIdentifier, Optional<BubblesManager> bubblesManagerOptional)89 public ExpandableNotificationRowController( 90 ExpandableNotificationRow view, 91 NotificationListContainer listContainer, 92 ActivatableNotificationViewController activatableNotificationViewController, 93 NotificationMediaManager mediaManager, 94 PluginManager pluginManager, 95 SystemClock clock, 96 @AppName String appName, 97 @NotificationKey String notificationKey, 98 KeyguardBypassController keyguardBypassController, 99 GroupMembershipManager groupMembershipManager, 100 GroupExpansionManager groupExpansionManager, 101 RowContentBindStage rowContentBindStage, 102 NotificationLogger notificationLogger, 103 HeadsUpManager headsUpManager, 104 ExpandableNotificationRow.OnExpandClickListener onExpandClickListener, 105 StatusBarStateController statusBarStateController, 106 NotificationGutsManager notificationGutsManager, 107 @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowLongPress, 108 OnUserInteractionCallback onUserInteractionCallback, 109 FalsingManager falsingManager, 110 FalsingCollector falsingCollector, 111 PeopleNotificationIdentifier peopleNotificationIdentifier, 112 Optional<BubblesManager> bubblesManagerOptional) { 113 mView = view; 114 mListContainer = listContainer; 115 mActivatableNotificationViewController = activatableNotificationViewController; 116 mMediaManager = mediaManager; 117 mPluginManager = pluginManager; 118 mClock = clock; 119 mAppName = appName; 120 mNotificationKey = notificationKey; 121 mKeyguardBypassController = keyguardBypassController; 122 mGroupMembershipManager = groupMembershipManager; 123 mGroupExpansionManager = groupExpansionManager; 124 mRowContentBindStage = rowContentBindStage; 125 mNotificationLogger = notificationLogger; 126 mHeadsUpManager = headsUpManager; 127 mOnExpandClickListener = onExpandClickListener; 128 mStatusBarStateController = statusBarStateController; 129 mNotificationGutsManager = notificationGutsManager; 130 mOnUserInteractionCallback = onUserInteractionCallback; 131 mFalsingManager = falsingManager; 132 mOnFeedbackClickListener = mNotificationGutsManager::openGuts; 133 mAllowLongPress = allowLongPress; 134 mFalsingCollector = falsingCollector; 135 mPeopleNotificationIdentifier = peopleNotificationIdentifier; 136 mBubblesManagerOptional = bubblesManagerOptional; 137 } 138 139 /** 140 * Initialize the controller. 141 */ init(NotificationEntry entry)142 public void init(NotificationEntry entry) { 143 mActivatableNotificationViewController.init(); 144 mView.initialize( 145 entry, 146 mAppName, 147 mNotificationKey, 148 mExpansionLogger, 149 mKeyguardBypassController, 150 mGroupMembershipManager, 151 mGroupExpansionManager, 152 mHeadsUpManager, 153 mRowContentBindStage, 154 mOnExpandClickListener, 155 mMediaManager, 156 mOnFeedbackClickListener, 157 mFalsingManager, 158 mFalsingCollector, 159 mStatusBarStateController, 160 mPeopleNotificationIdentifier, 161 mOnUserInteractionCallback, 162 mBubblesManagerOptional, 163 mNotificationGutsManager 164 ); 165 mView.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); 166 if (mAllowLongPress) { 167 mView.setLongPressListener((v, x, y, item) -> { 168 if (mView.isSummaryWithChildren()) { 169 mView.expandNotification(); 170 return true; 171 } 172 return mNotificationGutsManager.openGuts(v, x, y, item); 173 }); 174 } 175 if (ENABLE_REMOTE_INPUT) { 176 mView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS); 177 } 178 179 mView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() { 180 @Override 181 public void onViewAttachedToWindow(View v) { 182 mView.getEntry().setInitializationTime(mClock.elapsedRealtime()); 183 mPluginManager.addPluginListener(mView, 184 NotificationMenuRowPlugin.class, false /* Allow multiple */); 185 mView.setOnKeyguard(mStatusBarStateController.getState() == KEYGUARD); 186 mStatusBarStateController.addCallback(mStatusBarStateListener); 187 } 188 189 @Override 190 public void onViewDetachedFromWindow(View v) { 191 mPluginManager.removePluginListener(mView); 192 mStatusBarStateController.removeCallback(mStatusBarStateListener); 193 } 194 }); 195 } 196 197 private final StatusBarStateController.StateListener mStatusBarStateListener = 198 new StatusBarStateController.StateListener() { 199 @Override 200 public void onStateChanged(int newState) { 201 mView.setOnKeyguard(newState == KEYGUARD); 202 } 203 }; 204 logNotificationExpansion(String key, boolean userAction, boolean expanded)205 private void logNotificationExpansion(String key, boolean userAction, boolean expanded) { 206 mNotificationLogger.onExpansionChanged(key, userAction, expanded); 207 } 208 209 @Override 210 @NonNull getNodeLabel()211 public String getNodeLabel() { 212 return mView.getEntry().getKey(); 213 } 214 215 @Override 216 @NonNull getView()217 public View getView() { 218 return mView; 219 } 220 221 @Override getChildAt(int index)222 public View getChildAt(int index) { 223 return mView.getChildNotificationAt(index); 224 } 225 226 @Override addChildAt(NodeController child, int index)227 public void addChildAt(NodeController child, int index) { 228 ExpandableNotificationRow childView = (ExpandableNotificationRow) child.getView(); 229 230 mView.addChildNotification((ExpandableNotificationRow) child.getView()); 231 mListContainer.notifyGroupChildAdded(childView); 232 } 233 234 @Override moveChildTo(NodeController child, int index)235 public void moveChildTo(NodeController child, int index) { 236 ExpandableNotificationRow childView = (ExpandableNotificationRow) child.getView(); 237 mView.removeChildNotification(childView); 238 mView.addChildNotification(childView, index); 239 } 240 241 @Override removeChild(NodeController child, boolean isTransfer)242 public void removeChild(NodeController child, boolean isTransfer) { 243 ExpandableNotificationRow childView = (ExpandableNotificationRow) child.getView(); 244 245 mView.removeChildNotification(childView); 246 if (!isTransfer) { 247 mListContainer.notifyGroupChildRemoved(childView, mView); 248 } 249 } 250 251 @Override getChildCount()252 public int getChildCount() { 253 final List<ExpandableNotificationRow> mChildren = mView.getAttachedChildren(); 254 return mChildren != null ? mChildren.size() : 0; 255 } 256 } 257