diff --git a/packages/SystemUI/res/layout/people_strip.xml b/packages/SystemUI/res/layout/people_strip.xml index f0ac08bdad376..982aa8ef6d16d 100644 --- a/packages/SystemUI/res/layout/people_strip.xml +++ b/packages/SystemUI/res/layout/people_strip.xml @@ -18,7 +18,10 @@ + android:layout_height="@dimen/notification_section_header_height" + android:focusable="true" + android:clickable="true" +> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -236,4 +96,4 @@ android:layout_width="match_parent" android:layout_height="match_parent" /> - \ No newline at end of file + diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 52c0a26f09ba2..4f532b7b751d4 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -1163,6 +1163,9 @@ Silent notifications + + Conversations + Clear all silent notifications diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java index 7cd29ea48199f..c7492a233a2b1 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java @@ -344,11 +344,14 @@ public class BubbleController implements ConfigurationController.ConfigurationLi mSavedBubbleKeysPerUser = new SparseSetArray<>(); mCurrentUserId = mNotifUserManager.getCurrentUserId(); mNotifUserManager.addUserChangedListener( - newUserId -> { - saveBubbles(mCurrentUserId); - mBubbleData.dismissAll(DISMISS_USER_CHANGED); - restoreBubbles(newUserId); - mCurrentUserId = newUserId; + new NotificationLockscreenUserManager.UserChangedListener() { + @Override + public void onUserChanged(int newUserId) { + BubbleController.this.saveBubbles(mCurrentUserId); + mBubbleData.dismissAll(DISMISS_USER_CHANGED); + BubbleController.this.restoreBubbles(newUserId); + mCurrentUserId = newUserId; + } }); mUserCreatedBubbles = new HashSet<>(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java index ff4ce94920824..ebf7c2d58c2d9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java @@ -49,6 +49,12 @@ public interface NotificationLockscreenUserManager { /** Adds a listener to be notified when the current user changes. */ void addUserChangedListener(UserChangedListener listener); + /** + * Removes a listener previously registered with + * {@link #addUserChangedListener(UserChangedListener)} + */ + void removeUserChangedListener(UserChangedListener listener); + SparseArray getCurrentProfiles(); void setLockscreenPublicMode(boolean isProfilePublic, int userId); @@ -79,6 +85,7 @@ public interface NotificationLockscreenUserManager { /** Notified when the current user changes. */ interface UserChangedListener { - void onUserChanged(int userId); + default void onUserChanged(int userId) {} + default void onCurrentProfilesChanged(SparseArray currentProfiles) {} } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java index 2e369b3295b82..976531d8b49d9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java @@ -117,51 +117,63 @@ public class NotificationLockscreenUserManagerImpl implements @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); - if (Intent.ACTION_USER_SWITCHED.equals(action)) { - mCurrentUserId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); - updateCurrentProfilesCache(); - Log.v(TAG, "userId " + mCurrentUserId + " is in the house"); + switch (action) { + case Intent.ACTION_USER_SWITCHED: + mCurrentUserId = intent.getIntExtra( + Intent.EXTRA_USER_HANDLE, UserHandle.USER_ALL); + updateCurrentProfilesCache(); - updateLockscreenNotificationSetting(); - updatePublicMode(); - // The filtering needs to happen before the update call below in order to make sure - // the presenter has the updated notifications from the new user - getEntryManager().reapplyFilterAndSort("user switched"); - mPresenter.onUserSwitched(mCurrentUserId); + Log.v(TAG, "userId " + mCurrentUserId + " is in the house"); - for (UserChangedListener listener : mListeners) { - listener.onUserChanged(mCurrentUserId); - } - } else if (Intent.ACTION_USER_ADDED.equals(action)) { - updateCurrentProfilesCache(); - } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) { - // Start the overview connection to the launcher service - Dependency.get(OverviewProxyService.class).startConnectionToCurrentUser(); - } else if (NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION.equals(action)) { - final IntentSender intentSender = intent.getParcelableExtra(Intent.EXTRA_INTENT); - final String notificationKey = intent.getStringExtra(Intent.EXTRA_INDEX); - if (intentSender != null) { - try { - mContext.startIntentSender(intentSender, null, 0, 0, 0); - } catch (IntentSender.SendIntentException e) { - /* ignore */ + updateLockscreenNotificationSetting(); + updatePublicMode(); + // The filtering needs to happen before the update call below in order to + // make sure + // the presenter has the updated notifications from the new user + getEntryManager().reapplyFilterAndSort("user switched"); + mPresenter.onUserSwitched(mCurrentUserId); + + for (UserChangedListener listener : mListeners) { + listener.onUserChanged(mCurrentUserId); } - } - if (notificationKey != null) { - NotificationEntry entry = - getEntryManager().getActiveNotificationUnfiltered(notificationKey); - final int count = getEntryManager().getActiveNotificationsCount(); - final int rank = entry != null ? entry.getRanking().getRank() : 0; - NotificationVisibility.NotificationLocation location = - NotificationLogger.getNotificationLocation(entry); - final NotificationVisibility nv = NotificationVisibility.obtain(notificationKey, - rank, count, true, location); - try { - mBarService.onNotificationClick(notificationKey, nv); - } catch (RemoteException exception) { - /* ignore */ + break; + case Intent.ACTION_USER_ADDED: + case Intent.ACTION_MANAGED_PROFILE_AVAILABLE: + case Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE: + updateCurrentProfilesCache(); + break; + case Intent.ACTION_USER_UNLOCKED: + // Start the overview connection to the launcher service + Dependency.get(OverviewProxyService.class).startConnectionToCurrentUser(); + break; + case NOTIFICATION_UNLOCKED_BY_WORK_CHALLENGE_ACTION: + final IntentSender intentSender = intent.getParcelableExtra( + Intent.EXTRA_INTENT); + final String notificationKey = intent.getStringExtra(Intent.EXTRA_INDEX); + if (intentSender != null) { + try { + mContext.startIntentSender(intentSender, null, 0, 0, 0); + } catch (IntentSender.SendIntentException e) { + /* ignore */ + } } - } + if (notificationKey != null) { + NotificationEntry entry = + getEntryManager().getActiveNotificationUnfiltered(notificationKey); + final int count = getEntryManager().getActiveNotificationsCount(); + final int rank = entry != null ? entry.getRanking().getRank() : 0; + NotificationVisibility.NotificationLocation location = + NotificationLogger.getNotificationLocation(entry); + final NotificationVisibility nv = NotificationVisibility.obtain( + notificationKey, + rank, count, true, location); + try { + mBarService.onNotificationClick(notificationKey, nv); + } catch (RemoteException exception) { + /* ignore */ + } + } + break; } } }; @@ -266,6 +278,8 @@ public class NotificationLockscreenUserManagerImpl implements filter.addAction(Intent.ACTION_USER_SWITCHED); filter.addAction(Intent.ACTION_USER_ADDED); filter.addAction(Intent.ACTION_USER_UNLOCKED); + filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE); + filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE); mBroadcastDispatcher.registerReceiver(mBaseBroadcastReceiver, filter); IntentFilter internalFilter = new IntentFilter(); @@ -489,6 +503,11 @@ public class NotificationLockscreenUserManagerImpl implements } } } + mMainHandler.post(() -> { + for (UserChangedListener listener : mListeners) { + listener.onCurrentProfilesChanged(mCurrentProfiles); + } + }); } public boolean isAnyProfilePublicMode() { @@ -555,6 +574,11 @@ public class NotificationLockscreenUserManagerImpl implements mListeners.add(listener); } + @Override + public void removeUserChangedListener(UserChangedListener listener) { + mListeners.remove(listener); + } + // public void updatePublicMode() { // //TODO: I think there may be a race condition where mKeyguardViewManager.isShowing() returns // // false when it should be true. Therefore, if we are not on the SHADE, don't even bother diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHub.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHub.kt index 2c0c9420a8c4b..e81d361f58f7f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHub.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHub.kt @@ -37,7 +37,8 @@ data class PersonModel( val key: PersonKey, val name: CharSequence, val avatar: Drawable, - val clickIntent: PendingIntent + val clickIntent: PendingIntent, + val userId: Int ) /** Unique identifier for a Person in PeopleHub. */ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt index 784673e64ff8c..88b41471a063c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubNotificationListener.kt @@ -17,28 +17,27 @@ package com.android.systemui.statusbar.notification.people import android.app.Notification -import android.content.Context -import android.graphics.Canvas -import android.graphics.ColorFilter -import android.graphics.PixelFormat -import android.graphics.drawable.BitmapDrawable +import android.content.pm.UserInfo import android.graphics.drawable.Drawable -import android.os.UserHandle +import android.os.UserManager import android.service.notification.StatusBarNotification -import android.util.TypedValue +import android.util.SparseArray import android.view.View import android.view.ViewGroup import android.widget.ImageView import com.android.internal.statusbar.NotificationVisibility import com.android.internal.widget.MessagingGroup -import com.android.launcher3.icons.BaseIconFactory import com.android.systemui.R +import com.android.systemui.dagger.qualifiers.Background +import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.plugins.NotificationPersonExtractorPlugin +import com.android.systemui.statusbar.NotificationLockscreenUserManager import com.android.systemui.statusbar.notification.NotificationEntryListener import com.android.systemui.statusbar.notification.NotificationEntryManager import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.policy.ExtensionController import java.util.ArrayDeque +import java.util.concurrent.Executor import javax.inject.Inject import javax.inject.Singleton @@ -52,8 +51,7 @@ interface NotificationPersonExtractor { @Singleton class NotificationPersonExtractorPluginBoundary @Inject constructor( - extensionController: ExtensionController, - private val context: Context + extensionController: ExtensionController ) : NotificationPersonExtractor { private var plugin: NotificationPersonExtractorPlugin? = null @@ -70,9 +68,8 @@ class NotificationPersonExtractorPluginBoundary @Inject constructor( } override fun extractPerson(sbn: StatusBarNotification) = - plugin?.extractPerson(sbn)?.let { data -> - val badged = addBadgeToDrawable(data.avatar, context, sbn.packageName, sbn.user) - PersonModel(data.key, data.name, badged, data.clickIntent) + plugin?.extractPerson(sbn)?.run { + PersonModel(key, name, avatar, clickIntent, sbn.user.identifier) } override fun extractPersonKey(sbn: StatusBarNotification) = plugin?.extractPersonKey(sbn) @@ -84,11 +81,16 @@ class NotificationPersonExtractorPluginBoundary @Inject constructor( @Singleton class PeopleHubDataSourceImpl @Inject constructor( private val notificationEntryManager: NotificationEntryManager, - private val peopleHubManager: PeopleHubManager, - private val extractor: NotificationPersonExtractor + private val extractor: NotificationPersonExtractor, + private val userManager: UserManager, + @Background private val bgExecutor: Executor, + @Main private val mainExecutor: Executor, + private val notifLockscreenUserMgr: NotificationLockscreenUserManager ) : DataSource { + private var userChangeSubscription: Subscription? = null private val dataListeners = mutableListOf>() + private val peopleHubManagerForUser = SparseArray() private val notificationEntryListener = object : NotificationEntryListener { override fun onEntryInflated(entry: NotificationEntry, inflatedFlags: Int) = @@ -106,31 +108,56 @@ class PeopleHubDataSourceImpl @Inject constructor( } private fun removeVisibleEntry(entry: NotificationEntry) { - val key = extractor.extractPersonKey(entry.sbn) ?: entry.extractPersonKey() - if (key?.let(peopleHubManager::removeActivePerson) == true) { - updateUi() + (extractor.extractPersonKey(entry.sbn) ?: entry.extractPersonKey())?.let { key -> + val userId = entry.sbn.user.identifier + bgExecutor.execute { + val parentId = userManager.getProfileParent(userId)?.id ?: userId + mainExecutor.execute { + if (peopleHubManagerForUser[parentId]?.removeActivePerson(key) == true) { + updateUi() + } + } + } } } private fun addVisibleEntry(entry: NotificationEntry) { - val personModel = extractor.extractPerson(entry.sbn) ?: entry.extractPerson() - if (personModel?.let(peopleHubManager::addActivePerson) == true) { - updateUi() + (extractor.extractPerson(entry.sbn) ?: entry.extractPerson())?.let { personModel -> + val userId = entry.sbn.user.identifier + bgExecutor.execute { + val parentId = userManager.getProfileParent(userId)?.id ?: userId + mainExecutor.execute { + val manager = peopleHubManagerForUser[parentId] + ?: PeopleHubManager().also { peopleHubManagerForUser.put(parentId, it) } + if (manager.addActivePerson(personModel)) { + updateUi() + } + } + } } } override fun registerListener(listener: DataListener): Subscription { - val registerWithNotificationEntryManager = dataListeners.isEmpty() + val register = dataListeners.isEmpty() dataListeners.add(listener) - if (registerWithNotificationEntryManager) { + if (register) { + userChangeSubscription = notifLockscreenUserMgr.registerListener( + object : NotificationLockscreenUserManager.UserChangedListener { + override fun onUserChanged(userId: Int) = updateUi() + override fun onCurrentProfilesChanged( + currentProfiles: SparseArray? + ) = updateUi() + }) notificationEntryManager.addNotificationEntryListener(notificationEntryListener) } else { - listener.onDataChanged(peopleHubManager.getPeopleHubModel()) + getPeopleHubModelForCurrentUser()?.let(listener::onDataChanged) } return object : Subscription { override fun unsubscribe() { dataListeners.remove(listener) if (dataListeners.isEmpty()) { + userChangeSubscription?.unsubscribe() + userChangeSubscription = null notificationEntryManager .removeNotificationEntryListener(notificationEntryListener) } @@ -138,16 +165,36 @@ class PeopleHubDataSourceImpl @Inject constructor( } } + private fun getPeopleHubModelForCurrentUser(): PeopleHubModel? { + val currentUserId = notifLockscreenUserMgr.currentUserId + val model = peopleHubManagerForUser[currentUserId]?.getPeopleHubModel() + ?: return null + val currentProfiles = notifLockscreenUserMgr.currentProfiles + return model.copy(people = model.people.filter { person -> + currentProfiles[person.userId]?.isQuietModeEnabled == false + }) + } + private fun updateUi() { - val model = peopleHubManager.getPeopleHubModel() + val model = getPeopleHubModelForCurrentUser() ?: return for (listener in dataListeners) { listener.onDataChanged(model) } } } -@Singleton -class PeopleHubManager @Inject constructor() { +private fun NotificationLockscreenUserManager.registerListener( + listener: NotificationLockscreenUserManager.UserChangedListener +): Subscription { + addUserChangedListener(listener) + return object : Subscription { + override fun unsubscribe() { + removeUserChangedListener(listener) + } + } +} + +class PeopleHubManager { private val activePeople = mutableMapOf() private val inactivePeople = ArrayDeque(MAX_STORED_INACTIVE_PEOPLE) @@ -157,7 +204,7 @@ class PeopleHubManager @Inject constructor() { if (inactivePeople.size >= MAX_STORED_INACTIVE_PEOPLE) { inactivePeople.removeLast() } - inactivePeople.push(data) + inactivePeople.add(data) return true } return false @@ -190,63 +237,7 @@ private fun NotificationEntry.extractPerson(): PersonModel? { ?: extras.getString(Notification.EXTRA_TITLE) ?: return null val drawable = extractAvatarFromRow(this) ?: return null - val badgedAvatar = addBadgeToDrawable(drawable, row.context, sbn.packageName, sbn.user) - return PersonModel(key, name, badgedAvatar, clickIntent) -} - -private fun addBadgeToDrawable( - drawable: Drawable, - context: Context, - packageName: String, - user: UserHandle -): Drawable { - val pm = context.packageManager - val appInfo = pm.getApplicationInfoAsUser(packageName, 0, user) - return object : Drawable() { - override fun draw(canvas: Canvas) { - val iconBounds = getBounds() - val factory = object : BaseIconFactory( - context, - 0 /* unused */, - iconBounds.width(), - true) {} - val badge = factory.createBadgedIconBitmap( - appInfo.loadIcon(pm), - user, - true, - appInfo.isInstantApp, - null) - val badgeDrawable = BitmapDrawable(context.resources, badge.icon) - .apply { - alpha = drawable.alpha - colorFilter = drawable.colorFilter - val badgeWidth = TypedValue.applyDimension( - TypedValue.COMPLEX_UNIT_DIP, - 15f, - context.resources.displayMetrics - ).toInt() - setBounds( - iconBounds.left + (iconBounds.width() - badgeWidth), - iconBounds.top + (iconBounds.height() - badgeWidth), - iconBounds.right, - iconBounds.bottom) - } - drawable.bounds = iconBounds - drawable.draw(canvas) - badgeDrawable.draw(canvas) - } - - override fun setAlpha(alpha: Int) { - drawable.alpha = alpha - } - - override fun setColorFilter(colorFilter: ColorFilter?) { - drawable.colorFilter = colorFilter - } - - @PixelFormat.Opacity - override fun getOpacity(): Int = PixelFormat.OPAQUE - } + return PersonModel(key, name, drawable, clickIntent, sbn.user.identifier) } fun extractAvatarFromRow(entry: NotificationEntry): Drawable? = @@ -272,4 +263,4 @@ private fun NotificationEntry.extractPersonKey(): PersonKey? = if (isMessagingNotification()) key else null private fun NotificationEntry.isMessagingNotification() = - sbn.notification.notificationStyle == Notification.MessagingStyle::class.java \ No newline at end of file + sbn.notification.notificationStyle == Notification.MessagingStyle::class.java diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java index 2761689ec4096..09c1fad423d33 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java @@ -187,18 +187,18 @@ public class NotificationSectionsManager implements StackScrollAlgorithm.Section @Override public boolean beginsSection(@NonNull View view, @Nullable View previous) { boolean begin = false; - if (view instanceof ExpandableNotificationRow) { - if (previous instanceof ExpandableNotificationRow) { + if (view instanceof ActivatableNotificationView) { + if (previous instanceof ActivatableNotificationView) { // If we're drawing the first non-person notification, break out a section - ExpandableNotificationRow curr = (ExpandableNotificationRow) view; - ExpandableNotificationRow prev = (ExpandableNotificationRow) previous; + ActivatableNotificationView curr = (ActivatableNotificationView) view; + ActivatableNotificationView prev = (ActivatableNotificationView) previous; - begin = curr.getEntry().getBucket() != prev.getEntry().getBucket(); + begin = getBucket(curr) != getBucket(prev); } } if (!begin) { - begin = view == mGentleHeader || previous == mPeopleHubView; + begin = view == mGentleHeader || view == mPeopleHubView; } return begin; @@ -230,29 +230,42 @@ public class NotificationSectionsManager implements StackScrollAlgorithm.Section return; } - int lastPersonIndex = -1; - int firstGentleNotifIndex = -1; + boolean peopleNotificationsPresent = false; + int firstNonHeadsUpIndex = -1; + int firstGentleIndex = -1; + int notifCount = 0; final int n = mParent.getChildCount(); for (int i = 0; i < n; i++) { View child = mParent.getChildAt(i); - if (child instanceof ExpandableNotificationRow - && child.getVisibility() != View.GONE) { + if (child instanceof ExpandableNotificationRow && child.getVisibility() != View.GONE) { + notifCount++; ExpandableNotificationRow row = (ExpandableNotificationRow) child; + if (firstNonHeadsUpIndex == -1 && !row.isHeadsUp()) { + firstNonHeadsUpIndex = i; + } if (row.getEntry().getBucket() == BUCKET_PEOPLE) { - lastPersonIndex = i; + peopleNotificationsPresent = true; } if (row.getEntry().getBucket() == BUCKET_SILENT) { - firstGentleNotifIndex = i; + firstGentleIndex = i; break; } } } - // make room for peopleHub - firstGentleNotifIndex += adjustPeopleHubVisibilityAndPosition(lastPersonIndex); + if (firstNonHeadsUpIndex == -1) { + firstNonHeadsUpIndex = firstGentleIndex != -1 ? firstGentleIndex : notifCount; + } - adjustGentleHeaderVisibilityAndPosition(firstGentleNotifIndex); + // make room for peopleHub + int offset = adjustPeopleHubVisibilityAndPosition( + firstNonHeadsUpIndex, peopleNotificationsPresent); + if (firstGentleIndex != -1) { + firstGentleIndex += offset; + } + + adjustGentleHeaderVisibilityAndPosition(firstGentleIndex); mGentleHeader.setAreThereDismissableGentleNotifs( mParent.hasActiveClearableNotifications(ROWS_GENTLE)); @@ -294,13 +307,15 @@ public class NotificationSectionsManager implements StackScrollAlgorithm.Section } } - private int adjustPeopleHubVisibilityAndPosition(int lastPersonIndex) { - final boolean showPeopleHeader = mPeopleHubVisible - && mNumberOfSections > 2 - && mStatusBarStateController.getState() != StatusBarState.KEYGUARD; + private int adjustPeopleHubVisibilityAndPosition( + int targetIndex, boolean peopleNotificationsPresent) { + final boolean showPeopleHeader = mNumberOfSections > 2 + && mStatusBarStateController.getState() != StatusBarState.KEYGUARD + && (peopleNotificationsPresent || mPeopleHubVisible); final int currentHubIndex = mParent.indexOfChild(mPeopleHubView); final boolean currentlyVisible = currentHubIndex >= 0; - int targetIndex = lastPersonIndex + 1; + + mPeopleHubView.setCanSwipe(showPeopleHeader && !peopleNotificationsPresent); if (!showPeopleHeader) { if (currentlyVisible) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java index 6d0fcc3862815..4845ea16020bf 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java @@ -31,6 +31,7 @@ import com.android.systemui.SwipeHelper; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper; +import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.ExpandableView; class NotificationSwipeHelper extends SwipeHelper implements NotificationSwipeActionHelper { @@ -298,8 +299,8 @@ class NotificationSwipeHelper extends SwipeHelper implements NotificationSwipeAc @Override public Animator getViewTranslationAnimator(View v, float target, ValueAnimator.AnimatorUpdateListener listener) { - if (v instanceof SwipeableView) { - return ((SwipeableView) v).getTranslateViewAnimator(target, listener); + if (v instanceof ExpandableNotificationRow) { + return ((ExpandableNotificationRow) v).getTranslateViewAnimator(target, listener); } else { return superGetViewTranslationAnimator(v, target, listener); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt index a0796060e9d87..e5717aeefdcbd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt @@ -16,38 +16,22 @@ package com.android.systemui.statusbar.notification.stack -import android.animation.Animator -import android.animation.AnimatorListenerAdapter -import android.animation.ObjectAnimator -import android.animation.ValueAnimator import android.content.Context import android.util.AttributeSet -import android.util.FloatProperty import android.view.View import android.view.ViewGroup import android.widget.ImageView -import android.widget.LinearLayout -import android.widget.TextView import com.android.systemui.R import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin import com.android.systemui.statusbar.notification.people.DataListener import com.android.systemui.statusbar.notification.people.PersonViewModel import com.android.systemui.statusbar.notification.row.ActivatableNotificationView -private val TRANSLATE_CONTENT = object : FloatProperty("translate") { - override fun setValue(view: PeopleHubView, value: Float) { - view.translation = value - } - - override fun get(view: PeopleHubView) = view.translation -} - class PeopleHubView(context: Context, attrs: AttributeSet) : ActivatableNotificationView(context, attrs), SwipeableView { private lateinit var contents: ViewGroup private lateinit var personControllers: List - private var translateAnim: ObjectAnimator? = null val personViewAdapters: Sequence> get() = personControllers.asSequence() @@ -56,9 +40,10 @@ class PeopleHubView(context: Context, attrs: AttributeSet) : super.onFinishInflate() contents = requireViewById(R.id.people_list) personControllers = (0 until contents.childCount) + .reversed() .asSequence() .mapNotNull { idx -> - (contents.getChildAt(idx) as? LinearLayout)?.let(::PersonDataListenerImpl) + (contents.getChildAt(idx) as? ImageView)?.let(::PersonDataListenerImpl) } .toList() } @@ -69,41 +54,32 @@ class PeopleHubView(context: Context, attrs: AttributeSet) : override fun createMenu(): NotificationMenuRowPlugin? = null - override fun getTranslateViewAnimator( - leftTarget: Float, - listener: ValueAnimator.AnimatorUpdateListener? - ): Animator = - ObjectAnimator - .ofFloat(this, TRANSLATE_CONTENT, leftTarget) - .apply { - listener?.let { addUpdateListener(listener) } - addListener(object : AnimatorListenerAdapter() { - override fun onAnimationEnd(anim: Animator) { - translateAnim = null - } - }) - } - .also { - translateAnim?.cancel() - translateAnim = it - } - override fun resetTranslation() { - translateAnim?.cancel() translationX = 0f } - private inner class PersonDataListenerImpl(val viewGroup: ViewGroup) : + override fun setTranslation(translation: Float) { + if (canSwipe) { + super.setTranslation(translation) + } + } + + var canSwipe: Boolean = true + set(value) { + if (field != value) { + if (field) { + resetTranslation() + } + field = value + } + } + + private inner class PersonDataListenerImpl(val avatarView: ImageView) : DataListener { - val nameView = viewGroup.requireViewById(R.id.person_name) - val avatarView = viewGroup.requireViewById(R.id.person_icon) - override fun onDataChanged(data: PersonViewModel?) { - viewGroup.visibility = data?.let { View.VISIBLE } ?: View.INVISIBLE - nameView.text = data?.name avatarView.setImageDrawable(data?.icon) - viewGroup.setOnClickListener { data?.onClick?.invoke() } + avatarView.setOnClickListener { data?.onClick?.invoke() } } } } \ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SwipeableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SwipeableView.java index 6c6ef61cfdaf4..49e59a2e7200e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SwipeableView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SwipeableView.java @@ -16,9 +16,6 @@ package com.android.systemui.statusbar.notification.stack; -import android.animation.Animator; -import android.animation.ValueAnimator; - import androidx.annotation.Nullable; import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; @@ -32,10 +29,6 @@ public interface SwipeableView { /** Optionally creates a menu for this view. */ @Nullable NotificationMenuRowPlugin createMenu(); - /** Animator for translating the view, simulating a swipe. */ - Animator getTranslateViewAnimator( - float leftTarget, ValueAnimator.AnimatorUpdateListener listener); - /** Sets the translation amount for an in-progress swipe. */ void setTranslation(float translate); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt index f7d52b5f5ab0d..ad1aa8370495c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt @@ -98,7 +98,12 @@ class KeyguardBypassController : Dumpable { bypassEnabled = tunerService.getValue(key, dismissByDefault) != 0 } }, Settings.Secure.FACE_UNLOCK_DISMISSES_KEYGUARD) - lockscreenUserManager.addUserChangedListener { pendingUnlockType = null } + lockscreenUserManager.addUserChangedListener( + object : NotificationLockscreenUserManager.UserChangedListener { + override fun onUserChanged(userId: Int) { + pendingUnlockType = null + } + }) } /** diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/people/PeopleHubViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/people/PeopleHubViewControllerTest.kt index 0764d0cd4b880..867a9b97d6229 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/people/PeopleHubViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/people/PeopleHubViewControllerTest.kt @@ -178,9 +178,10 @@ private fun castNull(): T = null as T private fun fakePersonModel( id: String, name: CharSequence, - clickIntent: PendingIntent + clickIntent: PendingIntent, + userId: Int = 0 ): PersonModel = - PersonModel(id, name, mock(Drawable::class.java), clickIntent) + PersonModel(id, name, mock(Drawable::class.java), clickIntent, userId) private fun fakePersonViewModel(name: CharSequence): PersonViewModel = PersonViewModel(name, mock(Drawable::class.java), mock({}.javaClass)) @@ -207,4 +208,4 @@ class FakeDataListener : DataListener { override fun onDataChanged(data: T) { lastSeen = Maybe.Just(data) } -} \ No newline at end of file +}