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