Current user and work profile availability in peoplehub
Fixes: 144285253 Test: manual, atest Change-Id: I94afce96f6e164e7f4d4bb212920e3de8c5c1208
This commit is contained in:
@@ -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<>();
|
||||
|
||||
@@ -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) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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) {
|
||||
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<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(
|
||||
|
||||
@@ -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
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -178,9 +178,10 @@ private fun <T> 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<T> : DataListener<T> {
|
||||
override fun onDataChanged(data: T) {
|
||||
lastSeen = Maybe.Just(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user