Merge "Add list of selected/excluded convos to bubble settings" into rvc-dev am: 2b42301a6e am: 0ffd6c0b17

Change-Id: I9cea0ab8a2d0c1173e8bbd412a08065f9c18794d
This commit is contained in:
Mady Mellor
2020-04-28 22:43:11 +00:00
committed by Automerger Merge Worker
10 changed files with 472 additions and 35 deletions

View File

@@ -0,0 +1,154 @@
/*
* Copyright (C) 2020 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.settings.notification;
import static android.app.NotificationChannel.DEFAULT_ALLOW_BUBBLE;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_ALL;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_NONE;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_SELECTED;
import android.annotation.Nullable;
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
import android.content.Context;
import android.content.pm.ShortcutInfo;
import android.graphics.drawable.Drawable;
import android.service.notification.ConversationChannelWrapper;
import android.view.View;
import android.widget.ImageView;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
import com.android.settings.R;
import com.android.settings.notification.app.AppConversationListPreferenceController;
import com.android.settingslib.RestrictedLockUtils;
import com.google.common.annotations.VisibleForTesting;
import java.util.List;
import java.util.stream.Collectors;
/**
* Displays a list of conversations that have either been selected or excluded from bubbling.
*/
public class AppBubbleListPreferenceController extends AppConversationListPreferenceController {
private static final String KEY = "bubble_conversations";
public AppBubbleListPreferenceController(Context context, NotificationBackend backend) {
super(context, backend);
}
@Override
public void onResume(NotificationBackend.AppRow appRow,
@Nullable NotificationChannel channel, @Nullable NotificationChannelGroup group,
Drawable conversationDrawable,
ShortcutInfo conversationInfo,
RestrictedLockUtils.EnforcedAdmin admin) {
super.onResume(appRow, channel, group, conversationDrawable, conversationInfo, admin);
// In case something changed in the foreground (e.g. via bubble button on notification)
loadConversationsAndPopulate();
}
@Override
public String getPreferenceKey() {
return KEY;
}
@Override
public boolean isAvailable() {
if (!super.isAvailable()) {
return false;
}
if (mAppRow.bubblePreference == BUBBLE_PREFERENCE_NONE) {
return false;
}
return true;
}
@VisibleForTesting
@Override
public List<ConversationChannelWrapper> filterAndSortConversations(
List<ConversationChannelWrapper> conversations) {
return conversations.stream()
.sorted(mConversationComparator)
.filter((c) -> {
if (mAppRow.bubblePreference == BUBBLE_PREFERENCE_SELECTED) {
return c.getNotificationChannel().canBubble();
} else if (mAppRow.bubblePreference == BUBBLE_PREFERENCE_ALL) {
return c.getNotificationChannel().getAllowBubbles() == 0;
}
return false;
})
.collect(Collectors.toList());
}
@Override
protected int getTitleResId() {
// TODO: possible to left align like mocks?
return mAppRow.bubblePreference == BUBBLE_PREFERENCE_SELECTED
? R.string.bubble_app_setting_selected_conversation_title
: R.string.bubble_app_setting_excluded_conversation_title;
}
@VisibleForTesting
@Override
public Preference createConversationPref(final ConversationChannelWrapper conversation) {
final ConversationPreference pref = new ConversationPreference(mContext);
populateConversationPreference(conversation, pref);
pref.setOnClickListener((v) -> {
conversation.getNotificationChannel().setAllowBubbles(DEFAULT_ALLOW_BUBBLE);
mBackend.updateChannel(mAppRow.pkg, mAppRow.uid, conversation.getNotificationChannel());
mPreference.removePreference(pref);
if (mPreference.getPreferenceCount() == 0) {
mPreference.setVisible(false);
}
});
return pref;
}
/** Simple preference with a 'x' button at the end. */
@VisibleForTesting
public static class ConversationPreference extends Preference implements View.OnClickListener {
View.OnClickListener mOnClickListener;
ConversationPreference(Context context) {
super(context);
setWidgetLayoutResource(R.layout.bubble_conversation_remove_button);
}
@Override
public void onBindViewHolder(final PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
ImageView view = holder.itemView.findViewById(R.id.button);
view.setOnClickListener(mOnClickListener);
}
public void setOnClickListener(View.OnClickListener listener) {
mOnClickListener = listener;
}
@Override
public void onClick(View v) {
if (mOnClickListener != null) {
mOnClickListener.onClick(v);
}
}
}
}

View File

@@ -22,6 +22,7 @@ import android.text.TextUtils;
import android.util.Log;
import com.android.settings.R;
import com.android.settings.notification.AppBubbleListPreferenceController;
import com.android.settings.notification.NotificationBackend;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.core.AbstractPreferenceController;
@@ -56,18 +57,20 @@ public class AppBubbleNotificationSettings extends NotificationSettings implemen
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
mControllers = getPreferenceControllers(context, this);
mControllers = getPreferenceControllers(context, this, mDependentFieldListener);
return new ArrayList<>(mControllers);
}
protected static List<NotificationPreferenceController> getPreferenceControllers(
Context context, AppBubbleNotificationSettings fragment) {
Context context, AppBubbleNotificationSettings fragment,
DependentFieldListener listener) {
List<NotificationPreferenceController> controllers = new ArrayList<>();
controllers.add(new HeaderPreferenceController(context, fragment));
controllers.add(new BubblePreferenceController(context, fragment != null
? fragment.getChildFragmentManager()
: null,
new NotificationBackend(), true /* isAppPage */));
new NotificationBackend(), true /* isAppPage */, listener));
controllers.add(new AppBubbleListPreferenceController(context, new NotificationBackend()));
return controllers;
}
@@ -114,7 +117,7 @@ public class AppBubbleNotificationSettings extends NotificationSettings implemen
public List<AbstractPreferenceController> createPreferenceControllers(Context
context) {
return new ArrayList<>(AppBubbleNotificationSettings.getPreferenceControllers(
context, null));
context, null, null));
}
};
}

View File

@@ -19,6 +19,7 @@ package com.android.settings.notification.app;
import android.app.NotificationChannel;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.pm.ParceledListSlice;
import android.content.pm.ShortcutInfo;
import android.os.AsyncTask;
import android.os.Bundle;
@@ -33,6 +34,7 @@ import com.android.settings.applications.AppInfoBase;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.notification.NotificationBackend;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
@@ -42,8 +44,8 @@ public class AppConversationListPreferenceController extends NotificationPrefere
private static final String KEY = "conversations";
public static final String ARG_FROM_SETTINGS = "fromSettings";
private List<ConversationChannelWrapper> mConversations;
private PreferenceCategory mPreference;
protected List<ConversationChannelWrapper> mConversations = new ArrayList<>();
protected PreferenceCategory mPreference;
private boolean mHasSentMsg;
public AppConversationListPreferenceController(Context context, NotificationBackend backend) {
@@ -75,13 +77,23 @@ public class AppConversationListPreferenceController extends NotificationPrefere
@Override
public void updateState(Preference preference) {
mPreference = (PreferenceCategory) preference;
loadConversationsAndPopulate();
}
protected void loadConversationsAndPopulate() {
if (mAppRow == null) {
return;
}
// Load channel settings
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... unused) {
mHasSentMsg = mBackend.hasSentMessage(mAppRow.pkg, mAppRow.uid);
mConversations = mBackend.getConversations(mAppRow.pkg, mAppRow.uid).getList();
Collections.sort(mConversations, mConversationComparator);
ParceledListSlice<ConversationChannelWrapper> list =
mBackend.getConversations(mAppRow.pkg, mAppRow.uid);
if (list != null) {
mConversations = filterAndSortConversations(list.getList());
}
return null;
}
@@ -95,11 +107,22 @@ public class AppConversationListPreferenceController extends NotificationPrefere
}.execute();
}
protected List<ConversationChannelWrapper> filterAndSortConversations(
List<ConversationChannelWrapper> conversations) {
Collections.sort(conversations, mConversationComparator);
return conversations;
}
protected int getTitleResId() {
return R.string.conversations_category_title;
}
private void populateList() {
if (mPreference == null) {
return;
}
// TODO: if preference has children, compare with newly loaded list
mPreference.removeAll();
mPreference.setTitle(R.string.conversations_category_title);
if (mConversations.isEmpty()) {
if (mHasSentMsg) {
mPreference.setVisible(true);
@@ -112,6 +135,7 @@ public class AppConversationListPreferenceController extends NotificationPrefere
}
} else {
mPreference.setVisible(true);
mPreference.setTitle(getTitleResId());
populateConversations();
}
}
@@ -127,6 +151,12 @@ public class AppConversationListPreferenceController extends NotificationPrefere
protected Preference createConversationPref(final ConversationChannelWrapper conversation) {
Preference pref = new Preference(mContext);
populateConversationPreference(conversation, pref);
return pref;
}
protected void populateConversationPreference(final ConversationChannelWrapper conversation,
final Preference pref) {
ShortcutInfo si = conversation.getShortcutInfo();
pref.setTitle(si != null
@@ -157,7 +187,6 @@ public class AppConversationListPreferenceController extends NotificationPrefere
.setTitleText(pref.getTitle())
.setSourceMetricsCategory(SettingsEnums.NOTIFICATION_APP_NOTIFICATION)
.toIntent());
return pref;
}
protected Comparator<ConversationChannelWrapper> mConversationComparator =

View File

@@ -49,12 +49,15 @@ public class BubblePreferenceController extends NotificationPreferenceController
private boolean mIsAppPage;
private boolean mHasSentInvalidMsg;
private int mNumConversations;
private NotificationSettings.DependentFieldListener mListener;
public BubblePreferenceController(Context context, @Nullable FragmentManager fragmentManager,
NotificationBackend backend, boolean isAppPage) {
NotificationBackend backend, boolean isAppPage,
@Nullable NotificationSettings.DependentFieldListener listener) {
super(context, backend);
mFragmentManager = fragmentManager;
mIsAppPage = isAppPage;
mListener = listener;
}
@Override
@@ -128,6 +131,9 @@ public class BubblePreferenceController extends NotificationPreferenceController
mBackend.setAllowBubbles(mAppRow.pkg, mAppRow.uid, value);
}
}
if (mListener != null) {
mListener.onFieldValueChanged();
}
}
return true;
}

View File

@@ -92,7 +92,7 @@ public class ConversationNotificationSettings extends NotificationSettings {
mControllers.add(new BadgePreferenceController(context, mBackend));
mControllers.add(new NotificationsOffPreferenceController(context));
mControllers.add(new BubblePreferenceController(context, getChildFragmentManager(),
mBackend, false /* isAppPage */));
mBackend, false /* isAppPage */, null /* dependentFieldListener */));
mControllers.add(new ConversationDemotePreferenceController(context, this, mBackend));
mControllers.add(new BubbleCategoryPreferenceController(context));
mControllers.add(new BubbleLinkPreferenceController(context));