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 import static com.android.systemui.statusbar.notification.NotificationUtils.logKey; 23 import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow; 24 25 import android.net.Uri; 26 import android.os.UserHandle; 27 import android.provider.Settings; 28 import android.util.Log; 29 import android.view.View; 30 import android.view.ViewGroup; 31 32 import androidx.annotation.NonNull; 33 import androidx.annotation.Nullable; 34 import androidx.annotation.VisibleForTesting; 35 36 import com.android.internal.logging.MetricsLogger; 37 import com.android.internal.logging.UiEventLogger; 38 import com.android.internal.statusbar.IStatusBarService; 39 import com.android.systemui.Flags; 40 import com.android.systemui.flags.FeatureFlagsClassic; 41 import com.android.systemui.plugins.FalsingManager; 42 import com.android.systemui.plugins.PluginManager; 43 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; 44 import com.android.systemui.plugins.statusbar.StatusBarStateController; 45 import com.android.systemui.scene.shared.flag.SceneContainerFlag; 46 import com.android.systemui.statusbar.SmartReplyController; 47 import com.android.systemui.statusbar.notification.ColorUpdateLogger; 48 import com.android.systemui.statusbar.notification.FeedbackIcon; 49 import com.android.systemui.statusbar.notification.collection.EntryAdapterFactory; 50 import com.android.systemui.statusbar.notification.collection.PipelineEntry; 51 import com.android.systemui.statusbar.notification.collection.provider.NotificationDismissibilityProvider; 52 import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager; 53 import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager; 54 import com.android.systemui.statusbar.notification.collection.render.NodeController; 55 import com.android.systemui.statusbar.notification.collection.render.NotifViewController; 56 import com.android.systemui.statusbar.notification.headsup.HeadsUpManager; 57 import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier; 58 import com.android.systemui.statusbar.notification.row.dagger.AppName; 59 import com.android.systemui.statusbar.notification.row.dagger.NotificationKey; 60 import com.android.systemui.statusbar.notification.row.dagger.NotificationRowScope; 61 import com.android.systemui.statusbar.notification.shared.NotificationBundleUi; 62 import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainerLogger; 63 import com.android.systemui.statusbar.notification.stack.NotificationListContainer; 64 import com.android.systemui.statusbar.notification.stack.ui.view.NotificationRowStatsLogger; 65 import com.android.systemui.statusbar.phone.KeyguardBypassController; 66 import com.android.systemui.statusbar.policy.SmartReplyConstants; 67 import com.android.systemui.statusbar.policy.dagger.RemoteInputViewSubcomponent; 68 import com.android.systemui.util.time.SystemClock; 69 import com.android.systemui.window.domain.interactor.WindowRootViewBlurInteractor; 70 71 import com.google.android.msdl.data.model.MSDLToken; 72 import com.google.android.msdl.domain.MSDLPlayer; 73 74 import java.util.List; 75 76 import javax.inject.Inject; 77 import javax.inject.Named; 78 79 /** 80 * Controller for {@link ExpandableNotificationRow}. 81 */ 82 @NotificationRowScope 83 public class ExpandableNotificationRowController implements NotifViewController { 84 private static final String TAG = "NotifRowController"; 85 86 static final Uri BUBBLES_SETTING_URI = 87 Settings.Secure.getUriFor(Settings.Secure.NOTIFICATION_BUBBLES); 88 private static final String BUBBLES_SETTING_ENABLED_VALUE = "1"; 89 private final ExpandableNotificationRow mView; 90 private final NotificationListContainer mListContainer; 91 private final RemoteInputViewSubcomponent.Factory mRemoteInputViewSubcomponentFactory; 92 private final ActivatableNotificationViewController mActivatableNotificationViewController; 93 private final PluginManager mPluginManager; 94 private final SystemClock mClock; 95 private final String mAppName; 96 private final String mNotificationKey; 97 private final ColorUpdateLogger mColorUpdateLogger; 98 private final KeyguardBypassController mKeyguardBypassController; 99 private final GroupMembershipManager mGroupMembershipManager; 100 private final GroupExpansionManager mGroupExpansionManager; 101 private final RowContentBindStage mRowContentBindStage; 102 private final NotificationRowStatsLogger mStatsLogger; 103 private final NotificationRowLogger mLogBufferLogger; 104 private final HeadsUpManager mHeadsUpManager; 105 private final ExpandableNotificationRow.OnExpandClickListener mOnExpandClickListener; 106 private final StatusBarStateController mStatusBarStateController; 107 private final MetricsLogger mMetricsLogger; 108 private final NotificationChildrenContainerLogger mChildrenContainerLogger; 109 private final ExpandableNotificationRow.CoordinateOnClickListener mOnFeedbackClickListener; 110 private final NotificationGutsManager mNotificationGutsManager; 111 private final OnUserInteractionCallback mOnUserInteractionCallback; 112 private final FalsingManager mFalsingManager; 113 private final NotificationRebindingTracker mNotificationRebindingTracker; 114 private final FeatureFlagsClassic mFeatureFlags; 115 private final boolean mAllowLongPress; 116 private final PeopleNotificationIdentifier mPeopleNotificationIdentifier; 117 private final SmartReplyConstants mSmartReplyConstants; 118 private final SmartReplyController mSmartReplyController; 119 private final ExpandableNotificationRowDragController mDragController; 120 private final NotificationDismissibilityProvider mDismissibilityProvider; 121 private final IStatusBarService mStatusBarService; 122 private final UiEventLogger mUiEventLogger; 123 private final MSDLPlayer mMSDLPlayer; 124 private final NotificationSettingsController mSettingsController; 125 private final EntryAdapterFactory mEntryAdapterFactory; 126 private final WindowRootViewBlurInteractor mWindowRootViewBlurInteractor; 127 128 @VisibleForTesting 129 final NotificationSettingsController.Listener mSettingsListener = 130 new NotificationSettingsController.Listener() { 131 @Override 132 public void onSettingChanged(Uri setting, int userId, String value) { 133 if (BUBBLES_SETTING_URI.equals(setting)) { 134 if (NotificationBundleUi.isEnabled() 135 && mView.getEntryAdapter().getSbn() == null) { 136 // only valid for notification rows 137 return; 138 } 139 final int viewUserId = NotificationBundleUi.isEnabled() 140 ? mView.getEntryAdapter().getSbn().getUserId() 141 : mView.getEntryLegacy().getSbn().getUserId(); 142 if (viewUserId == UserHandle.USER_ALL || viewUserId == userId) { 143 mView.getPrivateLayout().setBubblesEnabledForUser( 144 BUBBLES_SETTING_ENABLED_VALUE.equals(value)); 145 } 146 } 147 } 148 }; 149 private final ExpandableNotificationRow.ExpandableNotificationRowLogger mLoggerCallback = 150 new ExpandableNotificationRow.ExpandableNotificationRowLogger() { 151 @Override 152 public void logNotificationExpansion(String key, int location, boolean userAction, 153 boolean expanded) { 154 mStatsLogger.onNotificationExpansionChanged(key, expanded, location, 155 userAction); 156 } 157 158 @Override 159 public void logKeepInParentChildDetached( 160 String child, 161 String oldParent 162 ) { 163 mLogBufferLogger.logKeepInParentChildDetached(child, oldParent); 164 } 165 166 @Override 167 public void logSkipAttachingKeepInParentChild( 168 String child, 169 String newParent 170 ) { 171 mLogBufferLogger.logSkipAttachingKeepInParentChild(child, newParent); 172 } 173 174 @Override 175 public void logRemoveTransientFromContainer( 176 String childEntry, 177 String containerEntry 178 ) { 179 mLogBufferLogger.logRemoveTransientFromContainer(childEntry, containerEntry); 180 } 181 182 @Override 183 public void logRemoveTransientFromNssl( 184 String childEntry 185 ) { 186 mLogBufferLogger.logRemoveTransientFromNssl(childEntry); 187 } 188 189 @Override 190 public void logRemoveTransientFromViewGroup( 191 String childEntry, 192 ViewGroup containerView 193 ) { 194 mLogBufferLogger.logRemoveTransientFromViewGroup(childEntry, containerView); 195 } 196 197 @Override 198 public void logAddTransientRow( 199 String childEntry, 200 String containerEntry, 201 int index 202 ) { 203 mLogBufferLogger.logAddTransientRow(childEntry, containerEntry, index); 204 } 205 206 @Override 207 public void logRemoveTransientRow( 208 String childEntry, 209 String containerEntry 210 ) { 211 mLogBufferLogger.logRemoveTransientRow(childEntry, containerEntry); 212 } 213 214 @Override 215 public void logResetAllContentAlphas( 216 String entry 217 ) { 218 mLogBufferLogger.logResetAllContentAlphas(entry); 219 } 220 221 @Override 222 public void logSkipResetAllContentAlphas( 223 String entry 224 ) { 225 mLogBufferLogger.logSkipResetAllContentAlphas(entry); 226 } 227 228 @Override 229 public void logStartAppearAnimation(String entry, boolean isAppear) { 230 mLogBufferLogger.logStartAppearAnimation(entry, isAppear); 231 } 232 233 @Override 234 public void logCancelAppearDrawing(String entry, boolean wasDrawing) { 235 mLogBufferLogger.logCancelAppearDrawing(entry, wasDrawing); 236 } 237 238 @Override 239 public void logAppearAnimationStarted(String entry, boolean isAppear) { 240 mLogBufferLogger.logAppearAnimationStarted(entry, isAppear); 241 } 242 243 @Override 244 public void logAppearAnimationSkipped(String entry, boolean isAppear) { 245 mLogBufferLogger.logAppearAnimationSkipped(entry, isAppear); 246 } 247 248 @Override 249 public void logAppearAnimationFinished(String entry, boolean isAppear, 250 boolean cancelled) { 251 mLogBufferLogger.logAppearAnimationFinished(entry, isAppear, cancelled); 252 } 253 }; 254 255 256 @Inject ExpandableNotificationRowController( ExpandableNotificationRow view, ActivatableNotificationViewController activatableNotificationViewController, RemoteInputViewSubcomponent.Factory rivSubcomponentFactory, MetricsLogger metricsLogger, ColorUpdateLogger colorUpdateLogger, NotificationRowLogger logBufferLogger, NotificationChildrenContainerLogger childrenContainerLogger, NotificationListContainer listContainer, SmartReplyConstants smartReplyConstants, SmartReplyController smartReplyController, PluginManager pluginManager, SystemClock clock, @AppName String appName, @NotificationKey String notificationKey, KeyguardBypassController keyguardBypassController, GroupMembershipManager groupMembershipManager, GroupExpansionManager groupExpansionManager, RowContentBindStage rowContentBindStage, NotificationRowStatsLogger statsLogger, HeadsUpManager headsUpManager, ExpandableNotificationRow.OnExpandClickListener onExpandClickListener, StatusBarStateController statusBarStateController, NotificationGutsManager notificationGutsManager, @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowLongPress, OnUserInteractionCallback onUserInteractionCallback, FalsingManager falsingManager, FeatureFlagsClassic featureFlags, PeopleNotificationIdentifier peopleNotificationIdentifier, NotificationSettingsController settingsController, ExpandableNotificationRowDragController dragController, NotificationDismissibilityProvider dismissibilityProvider, IStatusBarService statusBarService, UiEventLogger uiEventLogger, MSDLPlayer msdlPlayer, NotificationRebindingTracker notificationRebindingTracker, EntryAdapterFactory entryAdapterFactory, WindowRootViewBlurInteractor windowRootViewBlurInteractor)257 public ExpandableNotificationRowController( 258 ExpandableNotificationRow view, 259 ActivatableNotificationViewController activatableNotificationViewController, 260 RemoteInputViewSubcomponent.Factory rivSubcomponentFactory, 261 MetricsLogger metricsLogger, 262 ColorUpdateLogger colorUpdateLogger, 263 NotificationRowLogger logBufferLogger, 264 NotificationChildrenContainerLogger childrenContainerLogger, 265 NotificationListContainer listContainer, 266 SmartReplyConstants smartReplyConstants, 267 SmartReplyController smartReplyController, 268 PluginManager pluginManager, 269 SystemClock clock, 270 @AppName String appName, 271 @NotificationKey String notificationKey, 272 KeyguardBypassController keyguardBypassController, 273 GroupMembershipManager groupMembershipManager, 274 GroupExpansionManager groupExpansionManager, 275 RowContentBindStage rowContentBindStage, 276 NotificationRowStatsLogger statsLogger, 277 HeadsUpManager headsUpManager, 278 ExpandableNotificationRow.OnExpandClickListener onExpandClickListener, 279 StatusBarStateController statusBarStateController, 280 NotificationGutsManager notificationGutsManager, 281 @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowLongPress, 282 OnUserInteractionCallback onUserInteractionCallback, 283 FalsingManager falsingManager, 284 FeatureFlagsClassic featureFlags, 285 PeopleNotificationIdentifier peopleNotificationIdentifier, 286 NotificationSettingsController settingsController, 287 ExpandableNotificationRowDragController dragController, 288 NotificationDismissibilityProvider dismissibilityProvider, 289 IStatusBarService statusBarService, 290 UiEventLogger uiEventLogger, 291 MSDLPlayer msdlPlayer, 292 NotificationRebindingTracker notificationRebindingTracker, 293 EntryAdapterFactory entryAdapterFactory, 294 WindowRootViewBlurInteractor windowRootViewBlurInteractor) { 295 mView = view; 296 mListContainer = listContainer; 297 mRemoteInputViewSubcomponentFactory = rivSubcomponentFactory; 298 mActivatableNotificationViewController = activatableNotificationViewController; 299 mPluginManager = pluginManager; 300 mClock = clock; 301 mAppName = appName; 302 mNotificationKey = notificationKey; 303 mKeyguardBypassController = keyguardBypassController; 304 mGroupMembershipManager = groupMembershipManager; 305 mGroupExpansionManager = groupExpansionManager; 306 mRowContentBindStage = rowContentBindStage; 307 mStatsLogger = statsLogger; 308 mHeadsUpManager = headsUpManager; 309 mOnExpandClickListener = onExpandClickListener; 310 mStatusBarStateController = statusBarStateController; 311 mNotificationGutsManager = notificationGutsManager; 312 mOnUserInteractionCallback = onUserInteractionCallback; 313 mFalsingManager = falsingManager; 314 mNotificationRebindingTracker = notificationRebindingTracker; 315 mOnFeedbackClickListener = mNotificationGutsManager::openGuts; 316 mAllowLongPress = allowLongPress; 317 mFeatureFlags = featureFlags; 318 mPeopleNotificationIdentifier = peopleNotificationIdentifier; 319 mSettingsController = settingsController; 320 mDragController = dragController; 321 mMetricsLogger = metricsLogger; 322 mChildrenContainerLogger = childrenContainerLogger; 323 mColorUpdateLogger = colorUpdateLogger; 324 mLogBufferLogger = logBufferLogger; 325 mSmartReplyConstants = smartReplyConstants; 326 mSmartReplyController = smartReplyController; 327 mDismissibilityProvider = dismissibilityProvider; 328 mStatusBarService = statusBarService; 329 mUiEventLogger = uiEventLogger; 330 mMSDLPlayer = msdlPlayer; 331 mEntryAdapterFactory = entryAdapterFactory; 332 mWindowRootViewBlurInteractor = windowRootViewBlurInteractor; 333 } 334 335 /** 336 * Initialize the controller. 337 */ init(PipelineEntry entry)338 public void init(PipelineEntry entry) { 339 mActivatableNotificationViewController.init(); 340 mView.initialize( 341 mEntryAdapterFactory.create(entry), 342 entry, 343 mRemoteInputViewSubcomponentFactory, 344 mAppName, 345 mNotificationKey, 346 mLoggerCallback, 347 mKeyguardBypassController, 348 mGroupMembershipManager, 349 mGroupExpansionManager, 350 mHeadsUpManager, 351 mRowContentBindStage, 352 mOnExpandClickListener, 353 mOnFeedbackClickListener, 354 mFalsingManager, 355 mStatusBarStateController, 356 mPeopleNotificationIdentifier, 357 mOnUserInteractionCallback, 358 mNotificationGutsManager, 359 mDismissibilityProvider, 360 mMetricsLogger, 361 mChildrenContainerLogger, 362 mColorUpdateLogger, 363 mSmartReplyConstants, 364 mSmartReplyController, 365 mStatusBarService, 366 mUiEventLogger, 367 mNotificationRebindingTracker 368 ); 369 mView.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); 370 if (mAllowLongPress) { 371 if (mFeatureFlags.isEnabled( 372 com.android.systemui.flags.Flags.NOTIFICATION_DRAG_TO_CONTENTS)) { 373 mView.setDragController(mDragController); 374 } 375 376 mView.setLongPressListener((v, x, y, item) -> { 377 if (com.android.systemui.Flags.msdlFeedback()) { 378 mMSDLPlayer.playToken(MSDLToken.LONG_PRESS, null); 379 } 380 if (mView.isSummaryWithChildren()) { 381 mView.expandNotification(); 382 return true; 383 } 384 return mNotificationGutsManager.openGuts(v, x, y, item); 385 }); 386 } 387 if (ENABLE_REMOTE_INPUT) { 388 mView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS); 389 } 390 391 mView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() { 392 @Override 393 public void onViewAttachedToWindow(View v) { 394 if (NotificationBundleUi.isEnabled()) { 395 mView.setInitializationTime(mClock.elapsedRealtime()); 396 if (mView.getEntryAdapter().getSbn() != null) { 397 mSettingsController.addCallback(BUBBLES_SETTING_URI, mSettingsListener); 398 } 399 } else { 400 mView.getEntryLegacy().setInitializationTime(mClock.elapsedRealtime()); 401 mSettingsController.addCallback(BUBBLES_SETTING_URI, mSettingsListener); 402 } 403 mPluginManager.addPluginListener(mView, 404 NotificationMenuRowPlugin.class, false /* Allow multiple */); 405 if (!SceneContainerFlag.isEnabled()) { 406 mView.setOnKeyguard(mStatusBarStateController.getState() == KEYGUARD); 407 mStatusBarStateController.addCallback(mStatusBarStateListener); 408 } 409 410 } 411 412 @Override 413 public void onViewDetachedFromWindow(View v) { 414 mPluginManager.removePluginListener(mView); 415 if (!SceneContainerFlag.isEnabled()) { 416 mStatusBarStateController.removeCallback(mStatusBarStateListener); 417 } 418 mSettingsController.removeCallback(BUBBLES_SETTING_URI, mSettingsListener); 419 } 420 }); 421 422 if (Flags.notificationRowTransparency()) { 423 collectFlow(mView, mWindowRootViewBlurInteractor.isBlurCurrentlySupported(), 424 mView::setIsBlurSupported); 425 } 426 } 427 428 private final StatusBarStateController.StateListener mStatusBarStateListener = 429 new StatusBarStateController.StateListener() { 430 @Override 431 public void onStateChanged(int newState) { 432 mView.setOnKeyguard(newState == KEYGUARD); 433 } 434 }; 435 436 @Override 437 @NonNull getNodeLabel()438 public String getNodeLabel() { 439 return NotificationBundleUi.isEnabled() 440 ? mView.getLoggingKey() 441 : logKey(mView.getEntryLegacy()); 442 } 443 444 @Override 445 @NonNull getView()446 public View getView() { 447 return mView; 448 } 449 450 @Override getChildAt(int index)451 public View getChildAt(int index) { 452 return mView.getChildNotificationAt(index); 453 } 454 455 @Override addChildAt(NodeController child, int index)456 public void addChildAt(NodeController child, int index) { 457 ExpandableNotificationRow childView = (ExpandableNotificationRow) child.getView(); 458 459 mView.addChildNotification((ExpandableNotificationRow) child.getView(), index); 460 mListContainer.notifyGroupChildAdded(childView); 461 childView.setChangingPosition(false); 462 } 463 464 @Override moveChildTo(NodeController child, int index)465 public void moveChildTo(NodeController child, int index) { 466 ExpandableNotificationRow childView = (ExpandableNotificationRow) child.getView(); 467 childView.setChangingPosition(true); 468 mView.removeChildNotification(childView); 469 mView.addChildNotification(childView, index); 470 childView.setChangingPosition(false); 471 } 472 473 @Override removeChild(NodeController child, boolean isTransfer)474 public void removeChild(NodeController child, boolean isTransfer) { 475 ExpandableNotificationRow childView = (ExpandableNotificationRow) child.getView(); 476 477 if (isTransfer) { 478 childView.setChangingPosition(true); 479 } 480 mView.removeChildNotification(childView); 481 if (!isTransfer) { 482 mListContainer.notifyGroupChildRemoved(childView, mView.getChildrenContainer()); 483 } 484 } 485 486 @Override onViewAdded()487 public void onViewAdded() { 488 } 489 490 @Override onViewMoved()491 public void onViewMoved() { 492 } 493 494 @Override onViewRemoved()495 public void onViewRemoved() { 496 } 497 498 @Override getChildCount()499 public int getChildCount() { 500 final List<ExpandableNotificationRow> mChildren = mView.getAttachedChildren(); 501 return mChildren != null ? mChildren.size() : 0; 502 } 503 504 @Override setUntruncatedChildCount(int childCount)505 public void setUntruncatedChildCount(int childCount) { 506 if (mView.isSummaryWithChildren()) { 507 mView.setUntruncatedChildCount(childCount); 508 } else { 509 Log.w(TAG, "Called setUntruncatedChildCount(" + childCount + ") on a leaf row"); 510 } 511 } 512 513 @Override setNotificationGroupWhen(long whenMillis)514 public void setNotificationGroupWhen(long whenMillis) { 515 if (mView.isSummaryWithChildren()) { 516 mView.setNotificationGroupWhen(whenMillis); 517 } else { 518 Log.w(TAG, "Called setNotificationTime(" + whenMillis + ") on a leaf row"); 519 } 520 } 521 522 @Override setSystemExpanded(boolean systemExpanded)523 public void setSystemExpanded(boolean systemExpanded) { 524 mView.setSystemExpanded(systemExpanded); 525 } 526 527 @Override setLastAudibleMs(long lastAudibleMs)528 public void setLastAudibleMs(long lastAudibleMs) { 529 mView.setLastAudiblyAlertedMs(lastAudibleMs); 530 } 531 532 @Override setFeedbackIcon(@ullable FeedbackIcon icon)533 public void setFeedbackIcon(@Nullable FeedbackIcon icon) { 534 mView.setFeedbackIcon(icon); 535 } 536 537 @Override offerToKeepInParentForAnimation()538 public boolean offerToKeepInParentForAnimation() { 539 //If the User dismissed the notification's parent, we want to keep it attached until the 540 //dismiss animation is ongoing. Therefore we don't want to remove it in the ShadeViewDiffer. 541 if (mView.isParentDismissed()) { 542 mView.setKeepInParentForDismissAnimation(true); 543 return true; 544 } 545 546 //Otherwise the view system doesn't do the removal, so we rely on the ShadeViewDiffer 547 return false; 548 } 549 550 @Override removeFromParentIfKeptForAnimation()551 public boolean removeFromParentIfKeptForAnimation() { 552 ExpandableNotificationRow parent = mView.getNotificationParent(); 553 if (mView.keepInParentForDismissAnimation() && parent != null) { 554 parent.removeChildNotification(mView); 555 return true; 556 } 557 558 return false; 559 } 560 561 @Override resetKeepInParentForAnimation()562 public void resetKeepInParentForAnimation() { 563 mView.setKeepInParentForDismissAnimation(false); 564 } 565 } 566