Support updated rendering of conversation icons.

Note that changes to channel settings now generate
onResume() for all available controllers to ensure they get
the updated drawable.

Bug: 149747760
Change-Id: I3f73c025b1d32194e3d5147d03cb781e370f2a1b
Test: make -j64 RunSettingsRoboTests ROBOTEST_FILTER="com.android.settings.notification"
This commit is contained in:
Dan Sandler
2020-02-19 14:58:08 -05:00
parent 490eba353b
commit f9a8552f74
8 changed files with 23 additions and 15 deletions

View File

@@ -37,14 +37,11 @@ import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice; import android.content.pm.ParceledListSlice;
import android.content.pm.ShortcutInfo; import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager; import android.content.pm.ShortcutManager;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.ServiceManager; import android.os.ServiceManager;
import android.os.UserHandle; import android.os.UserHandle;
import android.service.notification.ConversationChannelWrapper; import android.service.notification.ConversationChannelWrapper;
import android.service.notification.NotifyingApp;
import android.text.format.DateUtils; import android.text.format.DateUtils;
import android.util.IconDrawableFactory; import android.util.IconDrawableFactory;
import android.util.Log; import android.util.Log;
@@ -522,17 +519,17 @@ public class NotificationBackend {
} }
public Drawable getConversationDrawable(Context context, ShortcutInfo info, String pkg, public Drawable getConversationDrawable(Context context, ShortcutInfo info, String pkg,
int uid) { int uid, boolean important) {
if (info == null) { if (info == null) {
return null; return null;
} }
ConversationIconFactory iconFactory = new ConversationIconFactory(context, ConversationIconFactory iconFactory = new ConversationIconFactory(context,
context.getSystemService(LauncherApps.class), context.getSystemService(LauncherApps.class),
context.getPackageManager(), IconDrawableFactory.newInstance(context), context.getPackageManager(),
IconDrawableFactory.newInstance(context, false),
context.getResources().getDimensionPixelSize( context.getResources().getDimensionPixelSize(
R.dimen.conversation_icon_size)); R.dimen.conversation_icon_size));
return new BitmapDrawable(context.getResources(), return iconFactory.getConversationDrawable(info, pkg, uid, important);
iconFactory.getConversationBitmap(info, pkg, uid));
} }
public void requestPinShortcut(Context context, ShortcutInfo shortcutInfo) { public void requestPinShortcut(Context context, ShortcutInfo shortcutInfo) {

View File

@@ -127,7 +127,8 @@ public class AppConversationListPreferenceController extends NotificationPrefere
conversation.getParentChannelLabel(), conversation.getGroupLabel()) conversation.getParentChannelLabel(), conversation.getGroupLabel())
: conversation.getParentChannelLabel()); : conversation.getParentChannelLabel());
if (si != null) { if (si != null) {
pref.setIcon(mBackend.getConversationDrawable(mContext, si, mAppRow.pkg, mAppRow.uid)); pref.setIcon(mBackend.getConversationDrawable(mContext, si, mAppRow.pkg, mAppRow.uid,
conversation.getNotificationChannel().isImportantConversation()));
} }
pref.setKey(conversation.getNotificationChannel().getId()); pref.setKey(conversation.getNotificationChannel().getId());

View File

@@ -86,6 +86,7 @@ public class ConversationHeaderPreferenceController extends NotificationPreferen
.setHasAppInfoLink(true) .setHasAppInfoLink(true)
.setRecyclerView(mFragment.getListView(), mFragment.getSettingsLifecycle()) .setRecyclerView(mFragment.getListView(), mFragment.getSettingsLifecycle())
.done(activity, mContext); .done(activity, mContext);
pref.findViewById(R.id.entity_header).setVisibility(View.VISIBLE); pref.findViewById(R.id.entity_header).setVisibility(View.VISIBLE);
} }
} }

View File

@@ -74,8 +74,8 @@ public class ConversationImportantPreferenceController extends NotificationPrefe
mChannel.setImportantConversation(value); mChannel.setImportantConversation(value);
if (value && bubbleImportantConversations()) { if (value && bubbleImportantConversations()) {
mChannel.setAllowBubbles(true); mChannel.setAllowBubbles(true);
mDependentFieldListener.onFieldValueChanged();
} }
mDependentFieldListener.onFieldValueChanged();
saveChannel(); saveChannel();
return true; return true;

View File

@@ -88,7 +88,8 @@ public abstract class ConversationListPreferenceController extends AbstractPrefe
pref.setTitle(getTitle(conversation)); pref.setTitle(getTitle(conversation));
pref.setSummary(getSummary(conversation)); pref.setSummary(getSummary(conversation));
pref.setIcon(mBackend.getConversationDrawable(mContext, conversation.getShortcutInfo(), pref.setIcon(mBackend.getConversationDrawable(mContext, conversation.getShortcutInfo(),
conversation.getPkg(), conversation.getUid())); conversation.getPkg(), conversation.getUid(),
conversation.getNotificationChannel().isImportantConversation()));
pref.setKey(conversation.getNotificationChannel().getId()); pref.setKey(conversation.getNotificationChannel().getId());
pref.setIntent(getIntent(conversation, pref.getTitle())); pref.setIntent(getIntent(conversation, pref.getTitle()));

View File

@@ -49,6 +49,7 @@ import com.android.settings.applications.AppInfoBase;
import com.android.settings.dashboard.DashboardFragment; import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.notification.NotificationBackend; import com.android.settings.notification.NotificationBackend;
import com.android.settingslib.RestrictedLockUtilsInternal; import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.notification.ConversationIconFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -204,7 +205,8 @@ abstract public class NotificationSettings extends DashboardFragment {
mContext, mPkg, mUid, mChannel.getConversationId()); mContext, mPkg, mUid, mChannel.getConversationId());
if (mConversationInfo != null) { if (mConversationInfo != null) {
mConversationDrawable = mBackend.getConversationDrawable( mConversationDrawable = mBackend.getConversationDrawable(
mContext, mConversationInfo, mAppRow.pkg, mAppRow.uid); mContext, mConversationInfo, mAppRow.pkg, mAppRow.uid,
mChannel.isImportantConversation());
} }
} }
@@ -329,6 +331,12 @@ abstract public class NotificationSettings extends DashboardFragment {
protected class DependentFieldListener { protected class DependentFieldListener {
protected void onFieldValueChanged() { protected void onFieldValueChanged() {
// Reload the conversation drawable, which shows some channel/conversation state
if (mConversationDrawable != null && mConversationDrawable
instanceof ConversationIconFactory.ConversationIconDrawable) {
((ConversationIconFactory.ConversationIconDrawable) mConversationDrawable)
.setImportant(mChannel.isImportantConversation());
}
final PreferenceScreen screen = getPreferenceScreen(); final PreferenceScreen screen = getPreferenceScreen();
for (NotificationPreferenceController controller : mControllers) { for (NotificationPreferenceController controller : mControllers) {
controller.displayPreference(screen); controller.displayPreference(screen);

View File

@@ -135,7 +135,8 @@ public class EntityHeaderController {
*/ */
public EntityHeaderController setIcon(Drawable icon) { public EntityHeaderController setIcon(Drawable icon) {
if (icon != null) { if (icon != null) {
mIcon = icon.getConstantState().newDrawable(mAppContext.getResources()); final Drawable.ConstantState state = icon.getConstantState();
mIcon = state != null ? state.newDrawable(mAppContext.getResources()) : icon;
} }
return this; return this;
} }

View File

@@ -26,7 +26,6 @@ import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy; import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
@@ -156,7 +155,7 @@ public class ConversationImportantPreferenceControllerTest {
assertTrue(channel.isImportantConversation()); assertTrue(channel.isImportantConversation());
assertFalse(channel.canBubble()); assertFalse(channel.canBubble());
verify(mBackend, times(1)).updateChannel(any(), anyInt(), any()); verify(mBackend, times(1)).updateChannel(any(), anyInt(), any());
verify(mDependentFieldListener, never()).onFieldValueChanged(); verify(mDependentFieldListener, times(1)).onFieldValueChanged();
} }
@Test @Test
@@ -202,6 +201,6 @@ public class ConversationImportantPreferenceControllerTest {
assertFalse(channel.isImportantConversation()); assertFalse(channel.isImportantConversation());
assertFalse(channel.canBubble()); assertFalse(channel.canBubble());
verify(mBackend, times(1)).updateChannel(any(), anyInt(), any()); verify(mBackend, times(1)).updateChannel(any(), anyInt(), any());
verify(mDependentFieldListener, never()).onFieldValueChanged(); verify(mDependentFieldListener, times(1)).onFieldValueChanged();
} }
} }