Since the button for clearing recent conversations may still exist after the user triggers the button since some of the conversations might not be removable Test: manual with talkback Fixes: 185433664 Change-Id: Id58d76237643e4e206ea6d551cdf7dd9f5742282
258 lines
10 KiB
Java
258 lines
10 KiB
Java
/*
|
|
* 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.app;
|
|
|
|
import static android.app.NotificationManager.IMPORTANCE_NONE;
|
|
|
|
import android.app.people.ConversationChannel;
|
|
import android.app.people.IPeopleManager;
|
|
import android.app.settings.SettingsEnums;
|
|
import android.content.Context;
|
|
import android.content.pm.ShortcutInfo;
|
|
import android.os.AsyncTask;
|
|
import android.os.Bundle;
|
|
import android.os.RemoteException;
|
|
import android.os.UserHandle;
|
|
import android.provider.Settings;
|
|
import android.util.Slog;
|
|
import android.widget.Button;
|
|
|
|
import androidx.preference.Preference;
|
|
import androidx.preference.PreferenceCategory;
|
|
import androidx.preference.PreferenceGroup;
|
|
|
|
import com.android.settings.R;
|
|
import com.android.settings.applications.AppInfoBase;
|
|
import com.android.settings.core.SubSettingLauncher;
|
|
import com.android.settings.notification.NotificationBackend;
|
|
import com.android.settingslib.core.AbstractPreferenceController;
|
|
import com.android.settingslib.widget.LayoutPreference;
|
|
|
|
import java.text.Collator;
|
|
import java.util.Collections;
|
|
import java.util.Comparator;
|
|
import java.util.List;
|
|
|
|
public class RecentConversationsPreferenceController extends AbstractPreferenceController {
|
|
|
|
private static final String TAG = "RecentConversationsPC";
|
|
private static final String KEY = "recent_conversations";
|
|
private List<ConversationChannel> mConversations;
|
|
private final IPeopleManager mPs;
|
|
private final NotificationBackend mBackend;
|
|
|
|
public RecentConversationsPreferenceController(Context context, NotificationBackend backend,
|
|
IPeopleManager ps) {
|
|
super(context);
|
|
mBackend = backend;
|
|
mPs = ps;
|
|
}
|
|
|
|
@Override
|
|
public String getPreferenceKey() {
|
|
return KEY;
|
|
}
|
|
|
|
@Override
|
|
public boolean isAvailable() {
|
|
return true;
|
|
}
|
|
|
|
LayoutPreference getClearAll(PreferenceGroup parent) {
|
|
LayoutPreference pref = new LayoutPreference(
|
|
mContext, R.layout.conversations_clear_recents);
|
|
pref.setOrder(1);
|
|
Button button = pref.findViewById(R.id.conversation_settings_clear_recents);
|
|
button.setOnClickListener(v -> {
|
|
try {
|
|
mPs.removeAllRecentConversations();
|
|
// Removing recents is asynchronous, so we can't immediately reload the list from
|
|
// the backend. Instead, proactively remove all of items that were marked as
|
|
// clearable, so long as we didn't get an error
|
|
|
|
for (int i = parent.getPreferenceCount() - 1; i >= 0; i--) {
|
|
Preference p = parent.getPreference(i);
|
|
if (p instanceof RecentConversationPreference) {
|
|
if (((RecentConversationPreference) p).hasClearListener()) {
|
|
parent.removePreference(p);
|
|
}
|
|
}
|
|
}
|
|
button.announceForAccessibility(mContext.getString(R.string.recent_convos_removed));
|
|
} catch (RemoteException e) {
|
|
Slog.w(TAG, "Could not clear recents", e);
|
|
}
|
|
});
|
|
return pref;
|
|
}
|
|
|
|
@Override
|
|
public void updateState(Preference preference) {
|
|
PreferenceCategory pref = (PreferenceCategory) preference;
|
|
// Load conversations
|
|
new AsyncTask<Void, Void, Void>() {
|
|
@Override
|
|
protected Void doInBackground(Void... unused) {
|
|
try {
|
|
mConversations = mPs.getRecentConversations().getList();
|
|
} catch (RemoteException e) {
|
|
Slog.w(TAG, "Could get recents", e);
|
|
}
|
|
Collections.sort(mConversations, mConversationComparator);
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
protected void onPostExecute(Void unused) {
|
|
if (mContext == null) {
|
|
return;
|
|
}
|
|
populateList(mConversations, pref);
|
|
}
|
|
}.execute();
|
|
|
|
}
|
|
|
|
protected void populateList(List<ConversationChannel> conversations,
|
|
PreferenceGroup containerGroup) {
|
|
containerGroup.removeAll();
|
|
boolean hasClearable = false;
|
|
if (conversations != null) {
|
|
hasClearable = populateConversations(conversations, containerGroup);
|
|
}
|
|
|
|
if (containerGroup.getPreferenceCount() == 0) {
|
|
containerGroup.setVisible(false);
|
|
} else {
|
|
containerGroup.setVisible(true);
|
|
if (hasClearable) {
|
|
Preference clearAll = getClearAll(containerGroup);
|
|
if (clearAll != null) {
|
|
containerGroup.addPreference(clearAll);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
protected boolean populateConversations(List<ConversationChannel> conversations,
|
|
PreferenceGroup containerGroup) {
|
|
int order = 100;
|
|
boolean hasClearable = false;
|
|
for (ConversationChannel conversation : conversations) {
|
|
if (conversation.getParentNotificationChannel().getImportance() == IMPORTANCE_NONE
|
|
|| (conversation.getParentNotificationChannelGroup() != null
|
|
&& conversation.getParentNotificationChannelGroup().isBlocked())) {
|
|
continue;
|
|
}
|
|
RecentConversationPreference pref =
|
|
createConversationPref(containerGroup, conversation, order++);
|
|
containerGroup.addPreference(pref);
|
|
if (pref.hasClearListener()) {
|
|
hasClearable = true;
|
|
}
|
|
}
|
|
return hasClearable;
|
|
}
|
|
|
|
protected RecentConversationPreference createConversationPref(PreferenceGroup parent,
|
|
final ConversationChannel conversation, int order) {
|
|
final String pkg = conversation.getShortcutInfo().getPackage();
|
|
final int uid = conversation.getUid();
|
|
final String conversationId = conversation.getShortcutInfo().getId();
|
|
RecentConversationPreference pref = new RecentConversationPreference(mContext);
|
|
|
|
if (!conversation.hasActiveNotifications()) {
|
|
pref.setOnClearClickListener(() -> {
|
|
try {
|
|
mPs.removeRecentConversation(pkg, UserHandle.getUserId(uid), conversationId);
|
|
parent.removePreference(pref);
|
|
} catch (RemoteException e) {
|
|
Slog.w(TAG, "Could not clear recent", e);
|
|
}
|
|
});
|
|
}
|
|
pref.setOrder(order);
|
|
|
|
pref.setTitle(getTitle(conversation));
|
|
pref.setSummary(getSummary(conversation));
|
|
pref.setIcon(mBackend.getConversationDrawable(mContext, conversation.getShortcutInfo(),
|
|
pkg, uid, false));
|
|
pref.setKey(conversation.getParentNotificationChannel().getId()
|
|
+ ":" + conversationId);
|
|
pref.setOnPreferenceClickListener(preference -> {
|
|
mBackend.createConversationNotificationChannel(
|
|
pkg, uid,
|
|
conversation.getParentNotificationChannel(),
|
|
conversationId);
|
|
getSubSettingLauncher(conversation, pref.getTitle()).launch();
|
|
return true;
|
|
});
|
|
|
|
return pref;
|
|
}
|
|
|
|
CharSequence getSummary(ConversationChannel conversation) {
|
|
return conversation.getParentNotificationChannelGroup() == null
|
|
? conversation.getParentNotificationChannel().getName()
|
|
: mContext.getString(R.string.notification_conversation_summary,
|
|
conversation.getParentNotificationChannel().getName(),
|
|
conversation.getParentNotificationChannelGroup().getName());
|
|
}
|
|
|
|
CharSequence getTitle(ConversationChannel conversation) {
|
|
ShortcutInfo si = conversation.getShortcutInfo();
|
|
return si.getLabel();
|
|
}
|
|
|
|
SubSettingLauncher getSubSettingLauncher(ConversationChannel conversation,
|
|
CharSequence title) {
|
|
Bundle channelArgs = new Bundle();
|
|
channelArgs.putInt(AppInfoBase.ARG_PACKAGE_UID, conversation.getUid());
|
|
channelArgs.putString(AppInfoBase.ARG_PACKAGE_NAME,
|
|
conversation.getShortcutInfo().getPackage());
|
|
channelArgs.putString(Settings.EXTRA_CHANNEL_ID,
|
|
conversation.getParentNotificationChannel().getId());
|
|
channelArgs.putString(Settings.EXTRA_CONVERSATION_ID,
|
|
conversation.getShortcutInfo().getId());
|
|
|
|
return new SubSettingLauncher(mContext)
|
|
.setDestination(ChannelNotificationSettings.class.getName())
|
|
.setArguments(channelArgs)
|
|
.setExtras(channelArgs)
|
|
.setUserHandle(UserHandle.getUserHandleForUid(conversation.getUid()))
|
|
.setTitleText(title)
|
|
.setSourceMetricsCategory(SettingsEnums.NOTIFICATION_CONVERSATION_LIST_SETTINGS);
|
|
}
|
|
|
|
protected Comparator<ConversationChannel> mConversationComparator =
|
|
new Comparator<ConversationChannel>() {
|
|
private final Collator sCollator = Collator.getInstance();
|
|
@Override
|
|
public int compare(ConversationChannel o1, ConversationChannel o2) {
|
|
int labelComparison = sCollator.compare(o1.getShortcutInfo().getLabel(),
|
|
o2.getShortcutInfo().getLabel());
|
|
|
|
if (labelComparison == 0) {
|
|
return o1.getParentNotificationChannel().getId().compareTo(
|
|
o2.getParentNotificationChannel().getId());
|
|
}
|
|
|
|
return labelComparison;
|
|
}
|
|
};
|
|
}
|