Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6c804f12 authored by Steve Elliott's avatar Steve Elliott Committed by Android (Google) Code Review
Browse files

Merge "Remove Controller usage from NotificationShelf" into udc-dev

parents ce3bd36b 3f3c6244
Loading
Loading
Loading
Loading
+5 −2
Original line number Original line Diff line number Diff line
@@ -92,6 +92,9 @@ interface DeviceEntryFaceAuthRepository {
    /** Current state of whether face authentication is running. */
    /** Current state of whether face authentication is running. */
    val isAuthRunning: Flow<Boolean>
    val isAuthRunning: Flow<Boolean>


    /** Whether bypass is currently enabled */
    val isBypassEnabled: Flow<Boolean>

    /**
    /**
     * Trigger face authentication.
     * Trigger face authentication.
     *
     *
@@ -166,7 +169,7 @@ constructor(
    override val isAuthenticated: Flow<Boolean>
    override val isAuthenticated: Flow<Boolean>
        get() = _isAuthenticated
        get() = _isAuthenticated


    private val bypassEnabled: Flow<Boolean> =
    override val isBypassEnabled: Flow<Boolean> =
        keyguardBypassController?.let {
        keyguardBypassController?.let {
            conflatedCallbackFlow {
            conflatedCallbackFlow {
                val callback =
                val callback =
@@ -222,7 +225,7 @@ constructor(
        // & detection is supported & biometric unlock is not allowed.
        // & detection is supported & biometric unlock is not allowed.
        listOf(
        listOf(
                canFaceAuthOrDetectRun(),
                canFaceAuthOrDetectRun(),
                logAndObserve(bypassEnabled, "bypassEnabled"),
                logAndObserve(isBypassEnabled, "isBypassEnabled"),
                logAndObserve(
                logAndObserve(
                    biometricSettingsRepository.isNonStrongBiometricAllowed.isFalse(),
                    biometricSettingsRepository.isNonStrongBiometricAllowed.isFalse(),
                    "nonStrongBiometricIsNotAllowed"
                    "nonStrongBiometricIsNotAllowed"
+37 −1
Original line number Original line Diff line number Diff line
@@ -24,6 +24,7 @@ import android.content.res.Resources;
import android.graphics.Rect;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.AttributeSet;
import android.util.IndentingPrintWriter;
import android.util.IndentingPrintWriter;
import android.util.Log;
import android.util.MathUtils;
import android.util.MathUtils;
import android.view.View;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup;
@@ -96,6 +97,8 @@ public class NotificationShelf extends ActivatableNotificationView implements St
    private NotificationShelfController mController;
    private NotificationShelfController mController;
    private float mActualWidth = -1;
    private float mActualWidth = -1;
    private boolean mSensitiveRevealAnimEndabled;
    private boolean mSensitiveRevealAnimEndabled;
    private boolean mShelfRefactorFlagEnabled;
    private boolean mCanModifyColorOfNotifications;


    public NotificationShelf(Context context, AttributeSet attrs) {
    public NotificationShelf(Context context, AttributeSet attrs) {
        super(context, attrs);
        super(context, attrs);
@@ -425,7 +428,7 @@ public class NotificationShelf extends ActivatableNotificationView implements St
                    transitionAmount = inShelfAmount;
                    transitionAmount = inShelfAmount;
                }
                }
                // We don't want to modify the color if the notification is hun'd
                // We don't want to modify the color if the notification is hun'd
                if (isLastChild && mController.canModifyColorOfNotifications()) {
                if (isLastChild && canModifyColorOfNotifications()) {
                    if (colorOfViewBeforeLast == NO_COLOR) {
                    if (colorOfViewBeforeLast == NO_COLOR) {
                        colorOfViewBeforeLast = ownColorUntinted;
                        colorOfViewBeforeLast = ownColorUntinted;
                    }
                    }
@@ -490,6 +493,14 @@ public class NotificationShelf extends ActivatableNotificationView implements St
        }
        }
    }
    }


    private boolean canModifyColorOfNotifications() {
        if (mShelfRefactorFlagEnabled) {
            return mCanModifyColorOfNotifications && mAmbientState.isShadeExpanded();
        } else {
            return mController.canModifyColorOfNotifications();
        }
    }

    private void updateCornerRoundnessOnScroll(
    private void updateCornerRoundnessOnScroll(
            ActivatableNotificationView anv,
            ActivatableNotificationView anv,
            float viewStart,
            float viewStart,
@@ -959,10 +970,31 @@ public class NotificationShelf extends ActivatableNotificationView implements St
        return false;
        return false;
    }
    }


    private void assertRefactorFlagDisabled() {
        if (mShelfRefactorFlagEnabled) {
            throw new IllegalStateException(
                    "Code path not supported when Flags.NOTIFICATION_SHELF_REFACTOR is enabled.");
        }
    }

    private boolean checkRefactorFlagEnabled() {
        if (!mShelfRefactorFlagEnabled) {
            Log.wtf(TAG,
                    "Code path not supported when Flags.NOTIFICATION_SHELF_REFACTOR is disabled.");
        }
        return mShelfRefactorFlagEnabled;
    }

    public void setController(NotificationShelfController notificationShelfController) {
    public void setController(NotificationShelfController notificationShelfController) {
        assertRefactorFlagDisabled();
        mController = notificationShelfController;
        mController = notificationShelfController;
    }
    }


    public void setCanModifyColorOfNotifications(boolean canModifyColorOfNotifications) {
        if (!checkRefactorFlagEnabled()) return;
        mCanModifyColorOfNotifications = canModifyColorOfNotifications;
    }

    public void setIndexOfFirstViewInShelf(ExpandableView firstViewInShelf) {
    public void setIndexOfFirstViewInShelf(ExpandableView firstViewInShelf) {
        mIndexOfFirstViewInShelf = mHostLayoutController.indexOfChild(firstViewInShelf);
        mIndexOfFirstViewInShelf = mHostLayoutController.indexOfChild(firstViewInShelf);
    }
    }
@@ -975,6 +1007,10 @@ public class NotificationShelf extends ActivatableNotificationView implements St
        mSensitiveRevealAnimEndabled = enabled;
        mSensitiveRevealAnimEndabled = enabled;
    }
    }


    public void setRefactorFlagEnabled(boolean enabled) {
        mShelfRefactorFlagEnabled = enabled;
    }

    /**
    /**
     * This method resets the OnScroll roundness of a view to 0f
     * This method resets the OnScroll roundness of a view to 0f
     * <p>
     * <p>
+44 −0
Original line number Original line Diff line number Diff line
/*
 * 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.domain.interactor

import com.android.systemui.keyguard.data.repository.DeviceEntryFaceAuthRepository
import com.android.systemui.keyguard.data.repository.KeyguardRepository
import com.android.systemui.statusbar.NotificationShelf
import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine

/** Interactor for the [NotificationShelf] */
@CentralSurfacesComponent.CentralSurfacesScope
class NotificationShelfInteractor
@Inject
constructor(
    private val keyguardRepository: KeyguardRepository,
    private val deviceEntryFaceAuthRepository: DeviceEntryFaceAuthRepository,
) {
    /** Is the system in a state where the shelf is just a static display of notification icons? */
    val isShelfStatic: Flow<Boolean>
        get() =
            combine(
                keyguardRepository.isKeyguardShowing,
                deviceEntryFaceAuthRepository.isBypassEnabled,
            ) { isKeyguardShowing, isBypassEnabled ->
                isKeyguardShowing && isBypassEnabled
            }
}
+25 −30
Original line number Original line Diff line number Diff line
@@ -14,14 +14,17 @@
 * limitations under the License.
 * limitations under the License.
 */
 */


package com.android.systemui.statusbar.notification.shelf.view
package com.android.systemui.statusbar.notification.shelf.ui.viewbinder


import android.view.View
import android.view.View
import android.view.View.OnAttachStateChangeListener
import android.view.View.OnAttachStateChangeListener
import android.view.accessibility.AccessibilityManager
import android.view.accessibility.AccessibilityManager
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.flags.Flags
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.statusbar.LegacyNotificationShelfControllerImpl
import com.android.systemui.statusbar.LegacyNotificationShelfControllerImpl
import com.android.systemui.statusbar.NotificationShelf
import com.android.systemui.statusbar.NotificationShelf
@@ -31,21 +34,16 @@ import com.android.systemui.statusbar.notification.row.ActivatableNotificationVi
import com.android.systemui.statusbar.notification.row.ActivatableNotificationViewController
import com.android.systemui.statusbar.notification.row.ActivatableNotificationViewController
import com.android.systemui.statusbar.notification.row.ExpandableOutlineViewController
import com.android.systemui.statusbar.notification.row.ExpandableOutlineViewController
import com.android.systemui.statusbar.notification.row.ExpandableViewController
import com.android.systemui.statusbar.notification.row.ExpandableViewController
import com.android.systemui.statusbar.notification.shelf.ui.viewmodel.NotificationShelfViewModel
import com.android.systemui.statusbar.notification.stack.AmbientState
import com.android.systemui.statusbar.notification.stack.AmbientState
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
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.NotificationIconContainer
import com.android.systemui.statusbar.phone.NotificationTapHelper
import com.android.systemui.statusbar.phone.NotificationTapHelper
import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent.CentralSurfacesScope
import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent.CentralSurfacesScope
import dagger.Binds
import kotlinx.coroutines.flow.launchIn
import dagger.Module
import kotlinx.coroutines.flow.onEach
import javax.inject.Inject
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
 * Controller class for [NotificationShelf]. This implementation serves as a temporary wrapper
 * around a [NotificationShelfViewBinder], so that external code can continue to depend on the
 * around a [NotificationShelfViewBinder], so that external code can continue to depend on the
@@ -57,8 +55,7 @@ class NotificationShelfViewBinderWrapperControllerImpl
@Inject
@Inject
constructor(
constructor(
    private val shelf: NotificationShelf,
    private val shelf: NotificationShelf,
    private val viewBinder: NotificationShelfViewBinder,
    private val viewModel: NotificationShelfViewModel,
    private val keyguardBypassController: KeyguardBypassController,
    featureFlags: FeatureFlags,
    featureFlags: FeatureFlags,
    private val notifTapHelperFactory: NotificationTapHelper.Factory,
    private val notifTapHelperFactory: NotificationTapHelper.Factory,
    private val a11yManager: AccessibilityManager,
    private val a11yManager: AccessibilityManager,
@@ -67,20 +64,19 @@ constructor(
    private val statusBarStateController: SysuiStatusBarStateController,
    private val statusBarStateController: SysuiStatusBarStateController,
) : NotificationShelfController {
) : NotificationShelfController {


    private var ambientState: AmbientState? = null

    override val view: NotificationShelf
    override val view: NotificationShelf
        get() = shelf
        get() = shelf


    init {
    init {
        shelf.apply {
        shelf.apply {
            setRefactorFlagEnabled(featureFlags.isEnabled(Flags.NOTIFICATION_SHELF_REFACTOR))
            useRoundnessSourceTypes(featureFlags.isEnabled(Flags.USE_ROUNDNESS_SOURCETYPES))
            useRoundnessSourceTypes(featureFlags.isEnabled(Flags.USE_ROUNDNESS_SOURCETYPES))
            setSensitiveRevealAnimEndabled(featureFlags.isEnabled(Flags.SENSITIVE_REVEAL_ANIM))
            setSensitiveRevealAnimEndabled(featureFlags.isEnabled(Flags.SENSITIVE_REVEAL_ANIM))
        }
        }
    }
    }


    fun init() {
    fun init() {
        viewBinder.bind(shelf)
        NotificationShelfViewBinder.bind(viewModel, shelf)


        ActivatableNotificationViewController(
        ActivatableNotificationViewController(
                shelf,
                shelf,
@@ -91,7 +87,6 @@ constructor(
                falsingCollector,
                falsingCollector,
            )
            )
            .init()
            .init()
        shelf.setController(this)
        val onAttachStateListener =
        val onAttachStateListener =
            object : OnAttachStateChangeListener {
            object : OnAttachStateChangeListener {
                override fun onViewAttachedToWindow(v: View) {
                override fun onViewAttachedToWindow(v: View) {
@@ -117,10 +112,7 @@ constructor(
    override val shelfIcons: NotificationIconContainer
    override val shelfIcons: NotificationIconContainer
        get() = shelf.shelfIcons
        get() = shelf.shelfIcons


    override fun canModifyColorOfNotifications(): Boolean {
    override fun canModifyColorOfNotifications(): Boolean = unsupported
        return (ambientState?.isShadeExpanded == true &&
            !(ambientState?.isOnKeyguard == true && keyguardBypassController.bypassEnabled))
    }


    override fun setOnActivatedListener(listener: ActivatableNotificationView.OnActivatedListener) {
    override fun setOnActivatedListener(listener: ActivatableNotificationView.OnActivatedListener) {
        shelf.setOnActivatedListener(listener)
        shelf.setOnActivatedListener(listener)
@@ -128,25 +120,28 @@ constructor(


    override fun bind(
    override fun bind(
        ambientState: AmbientState,
        ambientState: AmbientState,
        notificationStackScrollLayoutController: NotificationStackScrollLayoutController
        notificationStackScrollLayoutController: NotificationStackScrollLayoutController,
    ) {
    ) {
        shelf.bind(ambientState, notificationStackScrollLayoutController)
        shelf.bind(ambientState, notificationStackScrollLayoutController)
        this.ambientState = ambientState
    }
    }


    override fun setOnClickListener(listener: View.OnClickListener) {
    override fun setOnClickListener(listener: View.OnClickListener) {
        shelf.setOnClickListener(listener)
        shelf.setOnClickListener(listener)
    }
    }
}


@Module(includes = [PrivateShelfViewBinderModule::class]) object NotificationShelfViewBinderModule
    private val unsupported: Nothing

        get() = error("Code path not supported when Flags.NOTIFICATION_SHELF_REFACTOR is enabled")
@Module
private interface PrivateShelfViewBinderModule {
    @Binds fun bindImpl(impl: NotificationShelfViewBinderImpl): NotificationShelfViewBinder
}
}


@CentralSurfacesScope
/** Binds a [NotificationShelf] to its backend. */
private class NotificationShelfViewBinderImpl @Inject constructor() : NotificationShelfViewBinder {
object NotificationShelfViewBinder {
    override fun bind(shelf: NotificationShelf) {}
    fun bind(viewModel: NotificationShelfViewModel, shelf: NotificationShelf) {
        shelf.repeatWhenAttached {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                viewModel.canModifyColorOfNotifications
                    .onEach(shelf::setCanModifyColorOfNotifications)
                    .launchIn(this)
            }
        }
    }
}
}
+36 −0
Original line number Original line Diff line number Diff line
/*
 * 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.ui.viewmodel

import com.android.systemui.statusbar.NotificationShelf
import com.android.systemui.statusbar.notification.shelf.domain.interactor.NotificationShelfInteractor
import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent.CentralSurfacesScope
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map

/** ViewModel for [NotificationShelf]. */
@CentralSurfacesScope
class NotificationShelfViewModel
@Inject
constructor(
    private val interactor: NotificationShelfInteractor,
) {
    /** Is the shelf allowed to modify the color of notifications in the host layout? */
    val canModifyColorOfNotifications: Flow<Boolean>
        get() = interactor.isShelfStatic.map { static -> !static }
}
Loading