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

Commit b47f1c7d authored by Steve Elliott's avatar Steve Elliott
Browse files

Current user and work profile availability in peoplehub

Fixes: 144285253
Test: manual, atest
Change-Id: I94afce96f6e164e7f4d4bb212920e3de8c5c1208
parent 20cc19de
Loading
Loading
Loading
Loading
+8 −5
Original line number Diff line number Diff line
@@ -344,11 +344,14 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
        mSavedBubbleKeysPerUser = new SparseSetArray<>();
        mCurrentUserId = mNotifUserManager.getCurrentUserId();
        mNotifUserManager.addUserChangedListener(
                newUserId -> {
                    saveBubbles(mCurrentUserId);
                new NotificationLockscreenUserManager.UserChangedListener() {
                    @Override
                    public void onUserChanged(int newUserId) {
                        BubbleController.this.saveBubbles(mCurrentUserId);
                        mBubbleData.dismissAll(DISMISS_USER_CHANGED);
                    restoreBubbles(newUserId);
                        BubbleController.this.restoreBubbles(newUserId);
                        mCurrentUserId = newUserId;
                    }
                });

        mUserCreatedBubbles = new HashSet<>();
+8 −1
Original line number Diff line number Diff line
@@ -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<UserInfo> 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<UserInfo> currentProfiles) {}
    }
}
+67 −43
Original line number Diff line number Diff line
@@ -117,14 +117,18 @@ 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);
            switch (action) {
                case Intent.ACTION_USER_SWITCHED:
                    mCurrentUserId = intent.getIntExtra(
                            Intent.EXTRA_USER_HANDLE, UserHandle.USER_ALL);
                    updateCurrentProfilesCache();

                    Log.v(TAG, "userId " + mCurrentUserId + " is in the house");

                    updateLockscreenNotificationSetting();
                    updatePublicMode();
                // The filtering needs to happen before the update call below in order to make sure
                    // 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);
@@ -132,13 +136,19 @@ public class NotificationLockscreenUserManagerImpl implements
                    for (UserChangedListener listener : mListeners) {
                        listener.onUserChanged(mCurrentUserId);
                    }
            } else if (Intent.ACTION_USER_ADDED.equals(action)) {
                    break;
                case Intent.ACTION_USER_ADDED:
                case Intent.ACTION_MANAGED_PROFILE_AVAILABLE:
                case Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE:
                    updateCurrentProfilesCache();
            } else if (Intent.ACTION_USER_UNLOCKED.equals(action)) {
                    break;
                case Intent.ACTION_USER_UNLOCKED:
                    // 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);
                    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 {
@@ -154,7 +164,8 @@ public class NotificationLockscreenUserManagerImpl implements
                        final int rank = entry != null ? entry.getRanking().getRank() : 0;
                        NotificationVisibility.NotificationLocation location =
                                NotificationLogger.getNotificationLocation(entry);
                    final NotificationVisibility nv = NotificationVisibility.obtain(notificationKey,
                        final NotificationVisibility nv = NotificationVisibility.obtain(
                                notificationKey,
                                rank, count, true, location);
                        try {
                            mBarService.onNotificationClick(notificationKey, nv);
@@ -162,6 +173,7 @@ public class NotificationLockscreenUserManagerImpl implements
                            /* 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
+2 −1
Original line number Diff line number Diff line
@@ -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. */
+73 −16
Original line number Diff line number Diff line
@@ -18,13 +18,16 @@ package com.android.systemui.statusbar.notification.people

import android.app.Notification
import android.content.Context
import android.content.pm.UserInfo
import android.graphics.Canvas
import android.graphics.ColorFilter
import android.graphics.PixelFormat
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.os.UserHandle
import android.os.UserManager
import android.service.notification.StatusBarNotification
import android.util.SparseArray
import android.util.TypedValue
import android.view.View
import android.view.ViewGroup
@@ -33,12 +36,16 @@ 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

@@ -72,7 +79,7 @@ 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)
                PersonModel(data.key, data.name, badged, data.clickIntent, sbn.user.identifier)
            }

    override fun extractPersonKey(sbn: StatusBarNotification) = plugin?.extractPersonKey(sbn)
@@ -84,11 +91,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<PeopleHubModel> {

    private var userChangeSubscription: Subscription? = null
    private val dataListeners = mutableListOf<DataListener<PeopleHubModel>>()
    private val peopleHubManagerForUser = SparseArray<PeopleHubManager>()

    private val notificationEntryListener = object : NotificationEntryListener {
        override fun onEntryInflated(entry: NotificationEntry, inflatedFlags: Int) =
@@ -106,31 +118,56 @@ class PeopleHubDataSourceImpl @Inject constructor(
    }

    private fun removeVisibleEntry(entry: NotificationEntry) {
        val key = extractor.extractPersonKey(entry.sbn) ?: entry.extractPersonKey()
        if (key?.let(peopleHubManager::removeActivePerson) == true) {
        (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) {
        (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<PeopleHubModel>): 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<UserInfo>?
                        ) = 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 +175,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<PersonKey, PersonModel>()
    private val inactivePeople = ArrayDeque<PersonModel>(MAX_STORED_INACTIVE_PEOPLE)
@@ -191,7 +248,7 @@ private fun NotificationEntry.extractPerson(): PersonModel? {
            ?: return null
    val drawable = extractAvatarFromRow(this) ?: return null
    val badgedAvatar = addBadgeToDrawable(drawable, row.context, sbn.packageName, sbn.user)
    return PersonModel(key, name, badgedAvatar, clickIntent)
    return PersonModel(key, name, badgedAvatar, clickIntent, sbn.user.identifier)
}

private fun addBadgeToDrawable(
Loading