Consolidate app notification setting prefs
Test: manual Fixes: 189201867 Change-Id: If5cc03e0bd2d4273cd842e097b99b15d1178f3dc
This commit is contained in:
@@ -96,10 +96,6 @@ public class ConfigureNotificationSettings extends DashboardFragment implements
|
||||
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
|
||||
Application app, Fragment host) {
|
||||
final List<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||
controllers.add(new RecentNotifyingAppsPreferenceController(
|
||||
context, new NotificationBackend(), IUsageStatsManager.Stub.asInterface(
|
||||
ServiceManager.getService(Context.USAGE_STATS_SERVICE)),
|
||||
context.getSystemService(UserManager.class), app, host));
|
||||
controllers.add(new ShowOnLockScreenNotificationPreferenceController(
|
||||
context, KEY_LOCKSCREEN));
|
||||
controllers.add(new NotificationRingtonePreferenceController(context) {
|
||||
|
@@ -1,301 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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 android.app.Application;
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.app.usage.IUsageStatsManager;
|
||||
import android.app.usage.UsageEvents;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.service.notification.NotifyingApp;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.IconDrawableFactory;
|
||||
import android.util.Slog;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.applications.AppInfoBase;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.core.SubSettingLauncher;
|
||||
import com.android.settings.notification.app.AppNotificationSettings;
|
||||
import com.android.settings.widget.PrimarySwitchPreference;
|
||||
import com.android.settingslib.applications.ApplicationsState;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.utils.StringUtil;
|
||||
import com.android.settingslib.utils.ThreadUtils;
|
||||
import com.android.settingslib.widget.TwoTargetPreference;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This controller displays a list of recently used apps and a "See all" button. If there is
|
||||
* no recently used app, "See all" will be displayed as "Notifications".
|
||||
*/
|
||||
public class RecentNotifyingAppsPreferenceController extends AbstractPreferenceController
|
||||
implements PreferenceControllerMixin {
|
||||
|
||||
private static final String TAG = "RecentNotisCtrl";
|
||||
private static final String KEY_PREF_CATEGORY = "recent_notifications_category";
|
||||
|
||||
@VisibleForTesting
|
||||
static final String KEY_SEE_ALL = "all_notifications";
|
||||
static final String KEY_PLACEHOLDER = "app";
|
||||
private static final int SHOW_RECENT_APP_COUNT = 3;
|
||||
private static final int DAYS = 3;
|
||||
|
||||
private final Fragment mHost;
|
||||
private final PackageManager mPm;
|
||||
private final NotificationBackend mNotificationBackend;
|
||||
private IUsageStatsManager mUsageStatsManager;
|
||||
private final IconDrawableFactory mIconDrawableFactory;
|
||||
|
||||
private Calendar mCal;
|
||||
List<NotifyingApp> mApps;
|
||||
private final ApplicationsState mApplicationsState;
|
||||
|
||||
private PreferenceCategory mCategory;
|
||||
private Preference mSeeAllPref;
|
||||
protected List<Integer> mUserIds;
|
||||
|
||||
public RecentNotifyingAppsPreferenceController(Context context, NotificationBackend backend,
|
||||
IUsageStatsManager usageStatsManager, UserManager userManager,
|
||||
Application app, Fragment host) {
|
||||
this(context, backend, usageStatsManager, userManager,
|
||||
app == null ? null : ApplicationsState.getInstance(app), host);
|
||||
}
|
||||
|
||||
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
|
||||
RecentNotifyingAppsPreferenceController(Context context, NotificationBackend backend,
|
||||
IUsageStatsManager usageStatsManager, UserManager userManager,
|
||||
ApplicationsState appState, Fragment host) {
|
||||
super(context);
|
||||
mIconDrawableFactory = IconDrawableFactory.newInstance(context);
|
||||
mPm = context.getPackageManager();
|
||||
mHost = host;
|
||||
mApplicationsState = appState;
|
||||
mNotificationBackend = backend;
|
||||
mUsageStatsManager = usageStatsManager;
|
||||
mUserIds = new ArrayList<>();
|
||||
mUserIds.add(mContext.getUserId());
|
||||
int workUserId = Utils.getManagedProfileId(userManager, mContext.getUserId());
|
||||
if (workUserId != UserHandle.USER_NULL) {
|
||||
mUserIds.add(workUserId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return mApplicationsState != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return KEY_PREF_CATEGORY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateNonIndexableKeys(List<String> keys) {
|
||||
PreferenceControllerMixin.super.updateNonIndexableKeys(keys);
|
||||
// Don't index category name into search. It's not actionable.
|
||||
keys.add(KEY_PREF_CATEGORY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
mCategory = screen.findPreference(getPreferenceKey());
|
||||
mSeeAllPref = screen.findPreference(KEY_SEE_ALL);
|
||||
super.displayPreference(screen);
|
||||
refreshUi(mCategory.getContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
super.updateState(preference);
|
||||
refreshUi(mCategory.getContext());
|
||||
mSeeAllPref.setTitle(mContext.getString(R.string.recent_notifications_see_all_title));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void refreshUi(Context prefContext) {
|
||||
for (int i = 1; i <= SHOW_RECENT_APP_COUNT; i++) {
|
||||
PrimarySwitchPreference app = mCategory.findPreference(KEY_PLACEHOLDER + i);
|
||||
if (app != null) {
|
||||
app.setChecked(true);
|
||||
}
|
||||
}
|
||||
ThreadUtils.postOnBackgroundThread(() -> {
|
||||
reloadData();
|
||||
final List<NotifyingApp> recentApps = getDisplayableRecentAppList();
|
||||
ThreadUtils.postOnMainThread(() -> {
|
||||
if (recentApps != null && !recentApps.isEmpty()) {
|
||||
displayRecentApps(prefContext, recentApps);
|
||||
} else {
|
||||
displayOnlyAllAppsLink();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void reloadData() {
|
||||
mApps = new ArrayList<>();
|
||||
mCal = Calendar.getInstance();
|
||||
mCal.add(Calendar.DAY_OF_YEAR, -DAYS);
|
||||
for (int userId : mUserIds) {
|
||||
UsageEvents events = null;
|
||||
try {
|
||||
events = mUsageStatsManager.queryEventsForUser(mCal.getTimeInMillis(),
|
||||
System.currentTimeMillis(), userId, mContext.getPackageName());
|
||||
} catch (RemoteException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (events != null) {
|
||||
ArrayMap<String, NotifyingApp> aggregatedStats = new ArrayMap<>();
|
||||
|
||||
UsageEvents.Event event = new UsageEvents.Event();
|
||||
while (events.hasNextEvent()) {
|
||||
events.getNextEvent(event);
|
||||
|
||||
if (event.getEventType() == UsageEvents.Event.NOTIFICATION_INTERRUPTION) {
|
||||
NotifyingApp app =
|
||||
aggregatedStats.get(getKey(userId, event.getPackageName()));
|
||||
if (app == null) {
|
||||
app = new NotifyingApp();
|
||||
aggregatedStats.put(getKey(userId, event.getPackageName()), app);
|
||||
app.setPackage(event.getPackageName());
|
||||
app.setUserId(userId);
|
||||
}
|
||||
if (event.getTimeStamp() > app.getLastNotified()) {
|
||||
app.setLastNotified(event.getTimeStamp());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
mApps.addAll(aggregatedStats.values());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String getKey(int userId, String pkg) {
|
||||
return userId + "|" + pkg;
|
||||
}
|
||||
|
||||
private void displayOnlyAllAppsLink() {
|
||||
mCategory.setTitle(null);
|
||||
mSeeAllPref.setTitle(R.string.notifications_title);
|
||||
mSeeAllPref.setIcon(null);
|
||||
int prefCount = mCategory.getPreferenceCount();
|
||||
for (int i = prefCount - 1; i >= 0; i--) {
|
||||
final Preference pref = mCategory.getPreference(i);
|
||||
if (!TextUtils.equals(pref.getKey(), KEY_SEE_ALL)) {
|
||||
mCategory.removePreference(pref);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void displayRecentApps(Context prefContext, List<NotifyingApp> recentApps) {
|
||||
mCategory.setTitle(R.string.recent_notifications);
|
||||
mSeeAllPref.setSummary(null);
|
||||
mSeeAllPref.setIcon(R.drawable.ic_chevron_right_24dp);
|
||||
|
||||
int keyIndex = 1;
|
||||
final int recentAppsCount = recentApps.size();
|
||||
for (int i = 0; i < recentAppsCount; i++, keyIndex++) {
|
||||
final NotifyingApp app = recentApps.get(i);
|
||||
// Bind recent apps to existing prefs if possible, or create a new pref.
|
||||
final String pkgName = app.getPackage();
|
||||
final ApplicationsState.AppEntry appEntry =
|
||||
mApplicationsState.getEntry(app.getPackage(), app.getUserId());
|
||||
if (appEntry == null || appEntry.label == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
PrimarySwitchPreference pref = mCategory.findPreference(KEY_PLACEHOLDER + keyIndex);
|
||||
pref.setTitle(appEntry.label);
|
||||
pref.setIcon(mIconDrawableFactory.getBadgedIcon(appEntry.info));
|
||||
pref.setIconSize(TwoTargetPreference.ICON_SIZE_SMALL);
|
||||
pref.setSummary(StringUtil.formatRelativeTime(mContext,
|
||||
System.currentTimeMillis() - app.getLastNotified(), true));
|
||||
Bundle args = new Bundle();
|
||||
args.putString(AppInfoBase.ARG_PACKAGE_NAME, pkgName);
|
||||
args.putInt(AppInfoBase.ARG_PACKAGE_UID, appEntry.info.uid);
|
||||
pref.setOnPreferenceClickListener(preference -> {
|
||||
new SubSettingLauncher(mHost.getActivity())
|
||||
.setDestination(AppNotificationSettings.class.getName())
|
||||
.setTitleRes(R.string.notifications_title)
|
||||
.setArguments(args)
|
||||
.setUserHandle(new UserHandle(UserHandle.getUserId(appEntry.info.uid)))
|
||||
.setSourceMetricsCategory(
|
||||
SettingsEnums.MANAGE_APPLICATIONS_NOTIFICATIONS)
|
||||
.launch();
|
||||
return true;
|
||||
});
|
||||
pref.setSwitchEnabled(mNotificationBackend.isBlockable(mContext, appEntry.info));
|
||||
pref.setOnPreferenceChangeListener((preference, newValue) -> {
|
||||
mNotificationBackend.setNotificationsEnabledForPackage(
|
||||
pkgName, appEntry.info.uid, (Boolean) newValue);
|
||||
return true;
|
||||
});
|
||||
pref.setChecked(
|
||||
!mNotificationBackend.getNotificationsBanned(pkgName, appEntry.info.uid));
|
||||
|
||||
}
|
||||
// If there are less than SHOW_RECENT_APP_COUNT recent apps, remove placeholders
|
||||
for (int i = keyIndex; i <= SHOW_RECENT_APP_COUNT; i++) {
|
||||
mCategory.removePreferenceRecursively(KEY_PLACEHOLDER + i);
|
||||
}
|
||||
}
|
||||
|
||||
private List<NotifyingApp> getDisplayableRecentAppList() {
|
||||
Collections.sort(mApps);
|
||||
List<NotifyingApp> displayableApps = new ArrayList<>(SHOW_RECENT_APP_COUNT);
|
||||
int count = 0;
|
||||
for (NotifyingApp app : mApps) {
|
||||
try {
|
||||
final ApplicationsState.AppEntry appEntry = mApplicationsState.getEntry(
|
||||
app.getPackage(), app.getUserId());
|
||||
if (appEntry == null) {
|
||||
continue;
|
||||
}
|
||||
displayableApps.add(app);
|
||||
count++;
|
||||
if (count >= SHOW_RECENT_APP_COUNT) {
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Slog.e(TAG, "Failed to find app " + app.getPackage() + "/" + app.getUserId(), e);
|
||||
}
|
||||
}
|
||||
return displayableApps;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user