Merge changes from topic "shelf-refactor-flag" into udc-dev

* changes:
  NotificationShelf ViewBinder + WrapperController
  Extract interface for NotificationShelfController
  Remove dead code from NotificationShelf+Controller
  Add flag for NotificationShelf refactor
This commit is contained in:
Steve Elliott
2023-04-07 19:57:52 +00:00
committed by Android (Google) Code Review
8 changed files with 246 additions and 70 deletions

View File

@@ -103,6 +103,11 @@ object Flags {
val FILTER_UNSEEN_NOTIFS_ON_KEYGUARD =
releasedFlag(254647461, "filter_unseen_notifs_on_keyguard")
// TODO(b/277338665): Tracking Bug
@JvmField
val NOTIFICATION_SHELF_REFACTOR =
unreleasedFlag(271161129, "notification_shelf_refactor")
// TODO(b/263414400): Tracking Bug
@JvmField
val NOTIFICATION_ANIMATE_BIG_PICTURE =

View File

@@ -25,7 +25,6 @@ import com.android.systemui.statusbar.notification.row.ActivatableNotificationVi
import com.android.systemui.statusbar.notification.row.dagger.NotificationRowScope;
import com.android.systemui.statusbar.notification.stack.AmbientState;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.NotificationIconContainer;
@@ -35,7 +34,7 @@ import javax.inject.Inject;
* Controller class for {@link NotificationShelf}.
*/
@NotificationRowScope
public class NotificationShelfController {
public class LegacyNotificationShelfControllerImpl implements NotificationShelfController {
private final NotificationShelf mView;
private final ActivatableNotificationViewController mActivatableNotificationViewController;
private final KeyguardBypassController mKeyguardBypassController;
@@ -44,7 +43,7 @@ public class NotificationShelfController {
private AmbientState mAmbientState;
@Inject
public NotificationShelfController(
public LegacyNotificationShelfControllerImpl(
NotificationShelf notificationShelf,
ActivatableNotificationViewController activatableNotificationViewController,
KeyguardBypassController keyguardBypassController,
@@ -79,56 +78,42 @@ public class NotificationShelfController {
}
}
@Override
public NotificationShelf getView() {
return mView;
}
@Override
public boolean canModifyColorOfNotifications() {
return mAmbientState.isShadeExpanded()
&& !(mAmbientState.isOnKeyguard() && mKeyguardBypassController.getBypassEnabled());
}
@Override
public NotificationIconContainer getShelfIcons() {
return mView.getShelfIcons();
}
public @View.Visibility int getVisibility() {
return mView.getVisibility();
}
public void setCollapsedIcons(NotificationIconContainer notificationIcons) {
mView.setCollapsedIcons(notificationIcons);
}
@Override
public void bind(AmbientState ambientState,
NotificationStackScrollLayoutController notificationStackScrollLayoutController) {
mView.bind(ambientState, notificationStackScrollLayoutController);
mAmbientState = ambientState;
}
public int getHeight() {
return mView.getHeight();
}
public void updateState(StackScrollAlgorithm.StackScrollAlgorithmState algorithmState,
AmbientState ambientState) {
mAmbientState = ambientState;
mView.updateState(algorithmState, ambientState);
}
@Override
public int getIntrinsicHeight() {
return mView.getIntrinsicHeight();
}
@Override
public void setOnActivatedListener(ActivatableNotificationView.OnActivatedListener listener) {
mView.setOnActivatedListener(listener);
}
@Override
public void setOnClickListener(View.OnClickListener onClickListener) {
mView.setOnClickListener(onClickListener);
}
public int getNotGoneIndex() {
return mView.getNotGoneIndex();
}
}

View File

@@ -64,8 +64,7 @@ import java.io.PrintWriter;
* A notification shelf view that is placed inside the notification scroller. It manages the
* overflow icons that don't fit into the regular list anymore.
*/
public class NotificationShelf extends ActivatableNotificationView implements
View.OnLayoutChangeListener, StateListener {
public class NotificationShelf extends ActivatableNotificationView implements StateListener {
private static final int TAG_CONTINUOUS_CLIPPING = R.id.continuous_clipping_tag;
private static final String TAG = "NotificationShelf";
@@ -78,7 +77,6 @@ public class NotificationShelf extends ActivatableNotificationView implements
private static final SourceType SHELF_SCROLL = SourceType.from("ShelfScroll");
private NotificationIconContainer mShelfIcons;
private int[] mTmp = new int[2];
private boolean mHideBackground;
private int mStatusBarHeight;
private boolean mEnableNotificationClipping;
@@ -87,7 +85,6 @@ public class NotificationShelf extends ActivatableNotificationView implements
private int mPaddingBetweenElements;
private int mNotGoneIndex;
private boolean mHasItemsInStableShelf;
private NotificationIconContainer mCollapsedIcons;
private int mScrollFastThreshold;
private int mStatusBarState;
private boolean mInteractive;
@@ -868,10 +865,6 @@ public class NotificationShelf extends ActivatableNotificationView implements
return mShelfIcons.getIconState(icon);
}
private float getFullyClosedTranslation() {
return -(getIntrinsicHeight() - mStatusBarHeight) / 2;
}
@Override
public boolean hasNoContentHeight() {
return true;
@@ -893,7 +886,6 @@ public class NotificationShelf extends ActivatableNotificationView implements
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
updateRelativeOffset();
// we always want to clip to our sides, such that nothing can draw outside of these bounds
int height = getResources().getDisplayMetrics().heightPixels;
@@ -903,13 +895,6 @@ public class NotificationShelf extends ActivatableNotificationView implements
}
}
private void updateRelativeOffset() {
if (mCollapsedIcons != null) {
mCollapsedIcons.getLocationOnScreen(mTmp);
}
getLocationOnScreen(mTmp);
}
/**
* @return the index of the notification at which the shelf visually resides
*/
@@ -924,19 +909,6 @@ public class NotificationShelf extends ActivatableNotificationView implements
}
}
/**
* @return whether the shelf has any icons in it when a potential animation has finished, i.e
* if the current state would be applied right now
*/
public boolean hasItemsInStableShelf() {
return mHasItemsInStableShelf;
}
public void setCollapsedIcons(NotificationIconContainer collapsedIcons) {
mCollapsedIcons = collapsedIcons;
mCollapsedIcons.addOnLayoutChangeListener(this);
}
@Override
public void onStateChanged(int newState) {
mStatusBarState = newState;
@@ -982,12 +954,6 @@ public class NotificationShelf extends ActivatableNotificationView implements
}
}
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
int oldTop, int oldRight, int oldBottom) {
updateRelativeOffset();
}
@Override
public boolean needsClippingToShelf() {
return false;

View File

@@ -0,0 +1,54 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.statusbar
import android.view.View
import android.view.View.OnClickListener
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView.OnActivatedListener
import com.android.systemui.statusbar.notification.row.ExpandableView
import com.android.systemui.statusbar.notification.stack.AmbientState
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
import com.android.systemui.statusbar.phone.NotificationIconContainer
/** Controller interface for [NotificationShelf]. */
interface NotificationShelfController {
/** The [NotificationShelf] controlled by this Controller. */
val view: NotificationShelf
/** @see ExpandableView.getIntrinsicHeight */
val intrinsicHeight: Int
/** Container view for icons displayed in the shelf. */
val shelfIcons: NotificationIconContainer
/** Whether or not the shelf can modify the color of notifications in the shade. */
fun canModifyColorOfNotifications(): Boolean
/** @see ActivatableNotificationView.setOnActivatedListener */
fun setOnActivatedListener(listener: OnActivatedListener)
/** Binds the shelf to the host [NotificationStackScrollLayout], via its Controller. */
fun bind(
ambientState: AmbientState,
notificationStackScrollLayoutController: NotificationStackScrollLayoutController,
)
/** @see View.setOnClickListener */
fun setOnClickListener(listener: OnClickListener)
}

View File

@@ -16,8 +16,8 @@
package com.android.systemui.statusbar.notification.row.dagger;
import com.android.systemui.statusbar.LegacyNotificationShelfControllerImpl;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.NotificationShelfController;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import dagger.Binds;
@@ -46,7 +46,8 @@ public interface NotificationShelfComponent {
* Creates a NotificationShelfController.
*/
@NotificationRowScope
NotificationShelfController getNotificationShelfController();
LegacyNotificationShelfControllerImpl getNotificationShelfController();
/**
* Dagger Module that extracts interesting properties from a NotificationShelf.
*/

View File

@@ -0,0 +1,152 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.statusbar.notification.shelf.view
import android.view.View
import android.view.View.OnAttachStateChangeListener
import android.view.accessibility.AccessibilityManager
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.statusbar.LegacyNotificationShelfControllerImpl
import com.android.systemui.statusbar.NotificationShelf
import com.android.systemui.statusbar.NotificationShelfController
import com.android.systemui.statusbar.SysuiStatusBarStateController
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView
import com.android.systemui.statusbar.notification.row.ActivatableNotificationViewController
import com.android.systemui.statusbar.notification.row.ExpandableOutlineViewController
import com.android.systemui.statusbar.notification.row.ExpandableViewController
import com.android.systemui.statusbar.notification.stack.AmbientState
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.phone.NotificationIconContainer
import com.android.systemui.statusbar.phone.NotificationTapHelper
import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent.CentralSurfacesScope
import dagger.Binds
import dagger.Module
import javax.inject.Inject
/** Binds a [NotificationShelf] to its backend. */
interface NotificationShelfViewBinder {
fun bind(shelf: NotificationShelf)
}
/**
* Controller class for [NotificationShelf]. This implementation serves as a temporary wrapper
* around a [NotificationShelfViewBinder], so that external code can continue to depend on the
* [NotificationShelfController] interface. Once the [LegacyNotificationShelfControllerImpl] is
* removed, this class can go away and the ViewBinder can be used directly.
*/
@CentralSurfacesScope
class NotificationShelfViewBinderWrapperControllerImpl
@Inject
constructor(
private val shelf: NotificationShelf,
private val viewBinder: NotificationShelfViewBinder,
private val keyguardBypassController: KeyguardBypassController,
featureFlags: FeatureFlags,
private val notifTapHelperFactory: NotificationTapHelper.Factory,
private val a11yManager: AccessibilityManager,
private val falsingManager: FalsingManager,
private val falsingCollector: FalsingCollector,
private val statusBarStateController: SysuiStatusBarStateController,
) : NotificationShelfController {
private var ambientState: AmbientState? = null
override val view: NotificationShelf
get() = shelf
init {
shelf.apply {
useRoundnessSourceTypes(featureFlags.isEnabled(Flags.USE_ROUNDNESS_SOURCETYPES))
setSensitiveRevealAnimEndabled(featureFlags.isEnabled(Flags.SENSITIVE_REVEAL_ANIM))
}
}
fun init() {
viewBinder.bind(shelf)
ActivatableNotificationViewController(
shelf,
notifTapHelperFactory,
ExpandableOutlineViewController(shelf, ExpandableViewController(shelf)),
a11yManager,
falsingManager,
falsingCollector,
)
.init()
shelf.setController(this)
val onAttachStateListener =
object : OnAttachStateChangeListener {
override fun onViewAttachedToWindow(v: View) {
statusBarStateController.addCallback(
shelf,
SysuiStatusBarStateController.RANK_SHELF,
)
}
override fun onViewDetachedFromWindow(v: View) {
statusBarStateController.removeCallback(shelf)
}
}
shelf.addOnAttachStateChangeListener(onAttachStateListener)
if (shelf.isAttachedToWindow) {
onAttachStateListener.onViewAttachedToWindow(shelf)
}
}
override val intrinsicHeight: Int
get() = shelf.intrinsicHeight
override val shelfIcons: NotificationIconContainer
get() = shelf.shelfIcons
override fun canModifyColorOfNotifications(): Boolean {
return (ambientState?.isShadeExpanded == true &&
!(ambientState?.isOnKeyguard == true && keyguardBypassController.bypassEnabled))
}
override fun setOnActivatedListener(listener: ActivatableNotificationView.OnActivatedListener) {
shelf.setOnActivatedListener(listener)
}
override fun bind(
ambientState: AmbientState,
notificationStackScrollLayoutController: NotificationStackScrollLayoutController
) {
shelf.bind(ambientState, notificationStackScrollLayoutController)
this.ambientState = ambientState
}
override fun setOnClickListener(listener: View.OnClickListener) {
shelf.setOnClickListener(listener)
}
}
@Module(includes = [PrivateShelfViewBinderModule::class]) object NotificationShelfViewBinderModule
@Module
private interface PrivateShelfViewBinderModule {
@Binds fun bindImpl(impl: NotificationShelfViewBinderImpl): NotificationShelfViewBinder
}
@CentralSurfacesScope
private class NotificationShelfViewBinderImpl @Inject constructor() : NotificationShelfViewBinder {
override fun bind(shelf: NotificationShelf) {}
}

View File

@@ -193,7 +193,6 @@ public class NotificationIconAreaController implements
public void setupShelf(NotificationShelfController notificationShelfController) {
mShelfIcons = notificationShelfController.getShelfIcons();
notificationShelfController.setCollapsedIcons(mNotificationIcons);
}
public void onDensityOrFontScaleChanged(Context context) {

View File

@@ -33,6 +33,7 @@ import com.android.systemui.biometrics.AuthRippleView;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.privacy.OngoingPrivacyChip;
import com.android.systemui.settings.UserTracker;
@@ -44,12 +45,15 @@ import com.android.systemui.shade.NotificationShadeWindowView;
import com.android.systemui.shade.NotificationsQuickSettingsContainer;
import com.android.systemui.shade.ShadeExpansionStateManager;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.LegacyNotificationShelfControllerImpl;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.NotificationShelfController;
import com.android.systemui.statusbar.OperatorNameViewController;
import com.android.systemui.statusbar.core.StatusBarInitializer.OnStatusBarViewInitializedListener;
import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfComponent;
import com.android.systemui.statusbar.notification.shelf.view.NotificationShelfViewBinderModule;
import com.android.systemui.statusbar.notification.shelf.view.NotificationShelfViewBinderWrapperControllerImpl;
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.phone.KeyguardBottomAreaView;
import com.android.systemui.statusbar.phone.LetterboxAppearanceCalculator;
@@ -76,13 +80,15 @@ import com.android.systemui.util.settings.SecureSettings;
import java.util.concurrent.Executor;
import javax.inject.Named;
import javax.inject.Provider;
import dagger.Binds;
import dagger.Module;
import dagger.Provides;
import dagger.multibindings.IntoSet;
@Module(subcomponents = StatusBarFragmentComponent.class)
@Module(subcomponents = StatusBarFragmentComponent.class,
includes = { NotificationShelfViewBinderModule.class })
public abstract class StatusBarViewModule {
public static final String SHADE_HEADER = "large_screen_shade_header";
@@ -130,16 +136,24 @@ public abstract class StatusBarViewModule {
@Provides
@CentralSurfacesComponent.CentralSurfacesScope
public static NotificationShelfController providesStatusBarWindowView(
FeatureFlags featureFlags,
Provider<NotificationShelfViewBinderWrapperControllerImpl> newImpl,
NotificationShelfComponent.Builder notificationShelfComponentBuilder,
NotificationShelf notificationShelf) {
NotificationShelfComponent component = notificationShelfComponentBuilder
.notificationShelf(notificationShelf)
.build();
NotificationShelfController notificationShelfController =
component.getNotificationShelfController();
notificationShelfController.init();
if (featureFlags.isEnabled(Flags.NOTIFICATION_SHELF_REFACTOR)) {
NotificationShelfViewBinderWrapperControllerImpl impl = newImpl.get();
impl.init();
return impl;
} else {
NotificationShelfComponent component = notificationShelfComponentBuilder
.notificationShelf(notificationShelf)
.build();
LegacyNotificationShelfControllerImpl notificationShelfController =
component.getNotificationShelfController();
notificationShelfController.init();
return notificationShelfController;
return notificationShelfController;
}
}
/** */