PreferenceControllers are the way of the future.
Migrates Notification settings (app level, group level, and channel level) into PreferenceControllers (and most importantly: PreferenceControllerTest) Note: this removes the 'Advanced' preference group, but does not yet use the standard system 'Advanced' grouping as it does not currently support our use case (where we don't know how many fields to show outside of 'Advanced' until onResume() and also where we need fields to show below the 'Advanced' group). Test: make RunSettingsRoboTests Change-Id: Iddd1b4771922db322e5f73562e9d63ed077c5396
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.NotificationManager.IMPORTANCE_DEFAULT;
|
||||
import static android.app.NotificationManager.IMPORTANCE_LOW;
|
||||
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
|
||||
|
||||
import android.app.NotificationChannel;
|
||||
import android.content.Context;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settingslib.RestrictedSwitchPreference;
|
||||
|
||||
public class AllowSoundPreferenceController extends NotificationPreferenceController
|
||||
implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener {
|
||||
|
||||
private static final String TAG = "AllowSoundPrefContr";
|
||||
private static final String KEY_IMPORTANCE = "allow_sound";
|
||||
private NotificationSettingsBase.ImportanceListener mImportanceListener;
|
||||
|
||||
public AllowSoundPreferenceController(Context context,
|
||||
NotificationSettingsBase.ImportanceListener importanceListener,
|
||||
NotificationBackend backend) {
|
||||
super(context, backend);
|
||||
mImportanceListener = importanceListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return KEY_IMPORTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
if (!super.isAvailable()) {
|
||||
return false;
|
||||
}
|
||||
return mChannel != null && NotificationChannel.DEFAULT_CHANNEL_ID.equals(mChannel.getId());
|
||||
|
||||
}
|
||||
|
||||
public void updateState(Preference preference) {
|
||||
if (mChannel != null) {
|
||||
RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference;
|
||||
pref.setDisabledByAdmin(mAdmin);
|
||||
pref.setEnabled(isChannelConfigurable() && !pref.isDisabledByAdmin());
|
||||
pref.setChecked(mChannel.getImportance() >= IMPORTANCE_DEFAULT
|
||||
|| mChannel.getImportance() == IMPORTANCE_UNSPECIFIED);
|
||||
} else { Log.i(TAG, "tried to updatestate on a null channel?!"); }
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
if (mChannel != null) {
|
||||
final int importance =
|
||||
((Boolean) newValue ? IMPORTANCE_UNSPECIFIED : IMPORTANCE_LOW);
|
||||
mChannel.setImportance(importance);
|
||||
mChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
|
||||
saveChannel();
|
||||
mImportanceListener.onImportanceChanged();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.content.Context;
|
||||
import android.support.v7.preference.Preference;
|
||||
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
|
||||
/**
|
||||
* Controls link to reach more preference settings inside the app.
|
||||
*/
|
||||
public class AppLinkPreferenceController extends NotificationPreferenceController
|
||||
implements PreferenceControllerMixin {
|
||||
|
||||
private static final String TAG = "AppLinkPrefContr";
|
||||
private static final String KEY_APP_LINK = "app_link";
|
||||
|
||||
public AppLinkPreferenceController(Context context) {
|
||||
super(context, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return KEY_APP_LINK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
if (!super.isAvailable()) {
|
||||
return false;
|
||||
}
|
||||
return mAppRow.settingsIntent != null;
|
||||
}
|
||||
|
||||
public void updateState(Preference preference) {
|
||||
if (mAppRow != null) {
|
||||
preference.setIntent(mAppRow.settingsIntent);
|
||||
}
|
||||
}
|
||||
}
|
@@ -16,12 +16,10 @@
|
||||
|
||||
package com.android.settings.notification;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationChannelGroup;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
@@ -29,43 +27,29 @@ import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceCategory;
|
||||
import android.support.v7.preference.PreferenceGroup;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.Switch;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.applications.AppInfoBase;
|
||||
import com.android.settings.applications.LayoutPreference;
|
||||
import com.android.settings.notification.NotificationBackend.AppRow;
|
||||
import com.android.settings.widget.EntityHeaderController;
|
||||
import com.android.settings.widget.MasterSwitchPreference;
|
||||
import com.android.settings.widget.SwitchBar;
|
||||
import com.android.settingslib.RestrictedSwitchPreference;
|
||||
import com.android.settingslib.widget.FooterPreference;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import static android.app.NotificationManager.IMPORTANCE_NONE;
|
||||
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
|
||||
|
||||
/** These settings are per app, so should not be returned in global search results. */
|
||||
public class AppNotificationSettings extends NotificationSettingsBase {
|
||||
private static final String TAG = "AppNotificationSettings";
|
||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
|
||||
private static String KEY_GENERAL_CATEGORY = "categories";
|
||||
private static String KEY_DELETED = "deleted";
|
||||
|
||||
private List<NotificationChannelGroup> mChannelGroupList;
|
||||
private List<PreferenceCategory> mChannelGroups = new ArrayList();
|
||||
private FooterPreference mDeletedChannels;
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
@@ -84,24 +68,13 @@ public class AppNotificationSettings extends NotificationSettingsBase {
|
||||
|
||||
if (getPreferenceScreen() != null) {
|
||||
getPreferenceScreen().removeAll();
|
||||
mChannelGroups.clear();
|
||||
mDeletedChannels = null;
|
||||
mShowLegacyChannelConfig = false;
|
||||
mDynamicPreferences.clear();
|
||||
}
|
||||
|
||||
addPreferencesFromResource(R.xml.notification_settings);
|
||||
getPreferenceScreen().setOrderingAsAdded(true);
|
||||
setupBlock();
|
||||
addHeaderPref();
|
||||
|
||||
mShowLegacyChannelConfig = mBackend.onlyHasDefaultChannel(mAppRow.pkg, mAppRow.uid);
|
||||
if (mShowLegacyChannelConfig) {
|
||||
mChannel = mBackend.getChannel(
|
||||
mAppRow.pkg, mAppRow.uid, NotificationChannel.DEFAULT_CHANNEL_ID);
|
||||
populateDefaultChannelPrefs();
|
||||
addPreferencesFromResource(R.xml.channel_notification_settings);
|
||||
} else {
|
||||
addPreferencesFromResource(R.xml.upgraded_app_notification_settings);
|
||||
setupBadge();
|
||||
addPreferencesFromResource(R.xml.app_notification_settings);
|
||||
// Load channel settings
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
@@ -117,41 +90,59 @@ public class AppNotificationSettings extends NotificationSettingsBase {
|
||||
return;
|
||||
}
|
||||
populateList();
|
||||
addAppLinkPref();
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
getPreferenceScreen().setOrderingAsAdded(true);
|
||||
|
||||
updateDependents(mAppRow.banned);
|
||||
for (NotificationPreferenceController controller : mControllers) {
|
||||
controller.onResume(mAppRow, mChannel, mChannelGroup, mSuspendedAppsAdmin);
|
||||
controller.displayPreference(getPreferenceScreen());
|
||||
}
|
||||
updatePreferenceStates();
|
||||
}
|
||||
|
||||
private void addHeaderPref() {
|
||||
ArrayMap<String, AppRow> rows = new ArrayMap<>();
|
||||
rows.put(mAppRow.pkg, mAppRow);
|
||||
collectConfigActivities(rows);
|
||||
final Activity activity = getActivity();
|
||||
final Preference pref = EntityHeaderController
|
||||
.newInstance(activity, this /* fragment */, null /* header */)
|
||||
.setRecyclerView(getListView(), getLifecycle())
|
||||
.setIcon(mAppRow.icon)
|
||||
.setLabel(mAppRow.label)
|
||||
.setPackageName(mAppRow.pkg)
|
||||
.setUid(mAppRow.uid)
|
||||
.setHasAppInfoLink(true)
|
||||
.setButtonActions(EntityHeaderController.ActionType.ACTION_NONE,
|
||||
EntityHeaderController.ActionType.ACTION_NOTIF_PREFERENCE)
|
||||
.done(activity, getPrefContext());
|
||||
pref.setKey(KEY_HEADER);
|
||||
getPreferenceScreen().addPreference(pref);
|
||||
@Override
|
||||
protected String getLogTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getPreferenceScreenResId() {
|
||||
return R.xml.notification_settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
|
||||
mControllers = new ArrayList<>();
|
||||
mControllers.add(new HeaderPreferenceController(context, this));
|
||||
mControllers.add(new BlockPreferenceController(context, mImportanceListener, mBackend));
|
||||
mControllers.add(new BadgePreferenceController(context, mBackend));
|
||||
mControllers.add(new AllowSoundPreferenceController(
|
||||
context, mImportanceListener, mBackend));
|
||||
mControllers.add(new ImportancePreferenceController(context));
|
||||
mControllers.add(new SoundPreferenceController(context, this,
|
||||
mImportanceListener, mBackend));
|
||||
mControllers.add(new LightsPreferenceController(context, mBackend));
|
||||
mControllers.add(new VibrationPreferenceController(context, mBackend));
|
||||
mControllers.add(new VisibilityPreferenceController(context, new LockPatternUtils(context),
|
||||
mBackend));
|
||||
mControllers.add(new DndPreferenceController(context, getLifecycle(), mBackend));
|
||||
mControllers.add(new AppLinkPreferenceController(context));
|
||||
mControllers.add(new DescriptionPreferenceController(context));
|
||||
mControllers.add(new NotificationsOffPreferenceController(context));
|
||||
mControllers.add(new DeletedChannelsPreferenceController(context, mBackend));
|
||||
return new ArrayList<>(mControllers);
|
||||
}
|
||||
|
||||
|
||||
private void populateList() {
|
||||
if (!mChannelGroups.isEmpty()) {
|
||||
if (!mDynamicPreferences.isEmpty()) {
|
||||
// If there's anything in mChannelGroups, we've called populateChannelList twice.
|
||||
// Clear out existing channels and log.
|
||||
Log.w(TAG, "Notification channel group posted twice to settings - old size " +
|
||||
mChannelGroups.size() + ", new size " + mChannelGroupList.size());
|
||||
for (Preference p : mChannelGroups) {
|
||||
mDynamicPreferences.size() + ", new size " + mChannelGroupList.size());
|
||||
for (Preference p : mDynamicPreferences) {
|
||||
getPreferenceScreen().removePreference(p);
|
||||
}
|
||||
}
|
||||
@@ -160,7 +151,7 @@ public class AppNotificationSettings extends NotificationSettingsBase {
|
||||
groupCategory.setTitle(R.string.notification_channels);
|
||||
groupCategory.setKey(KEY_GENERAL_CATEGORY);
|
||||
getPreferenceScreen().addPreference(groupCategory);
|
||||
mChannelGroups.add(groupCategory);
|
||||
mDynamicPreferences.add(groupCategory);
|
||||
|
||||
Preference empty = new Preference(getPrefContext());
|
||||
empty.setTitle(R.string.no_channels);
|
||||
@@ -168,20 +159,8 @@ public class AppNotificationSettings extends NotificationSettingsBase {
|
||||
groupCategory.addPreference(empty);
|
||||
} else {
|
||||
populateGroupList();
|
||||
int deletedChannelCount = mBackend.getDeletedChannelCount(mAppRow.pkg, mAppRow.uid);
|
||||
if (deletedChannelCount > 0 &&
|
||||
getPreferenceScreen().findPreference(KEY_DELETED) == null) {
|
||||
mDeletedChannels = new FooterPreference(getPrefContext());
|
||||
mDeletedChannels.setSelectable(false);
|
||||
mDeletedChannels.setTitle(getResources().getQuantityString(
|
||||
R.plurals.deleted_channels, deletedChannelCount, deletedChannelCount));
|
||||
mDeletedChannels.setEnabled(false);
|
||||
mDeletedChannels.setKey(KEY_DELETED);
|
||||
mDeletedChannels.setOrder(ORDER_LAST);
|
||||
getPreferenceScreen().addPreference(mDeletedChannels);
|
||||
}
|
||||
mImportanceListener.onImportanceChanged();
|
||||
}
|
||||
updateDependents(mAppRow.banned);
|
||||
}
|
||||
|
||||
private void populateGroupList() {
|
||||
@@ -190,7 +169,7 @@ public class AppNotificationSettings extends NotificationSettingsBase {
|
||||
groupCategory.setKey(KEY_GENERAL_CATEGORY);
|
||||
groupCategory.setOrderingAsAdded(true);
|
||||
getPreferenceScreen().addPreference(groupCategory);
|
||||
mChannelGroups.add(groupCategory);
|
||||
mDynamicPreferences.add(groupCategory);
|
||||
for (NotificationChannelGroup group : mChannelGroupList) {
|
||||
final List<NotificationChannel> channels = group.getChannels();
|
||||
int N = channels.size();
|
||||
@@ -240,91 +219,6 @@ public class AppNotificationSettings extends NotificationSettingsBase {
|
||||
parent.addPreference(groupPref);
|
||||
}
|
||||
|
||||
void setupBadge() {
|
||||
mBadge = (RestrictedSwitchPreference) getPreferenceScreen().findPreference(KEY_BADGE);
|
||||
mBadge.setDisabledByAdmin(mSuspendedAppsAdmin);
|
||||
if (mChannel == null) {
|
||||
mBadge.setChecked(mAppRow.showBadge);
|
||||
} else {
|
||||
mBadge.setChecked(mChannel.canShowBadge());
|
||||
}
|
||||
mBadge.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
final boolean value = (Boolean) newValue;
|
||||
if (mChannel == null) {
|
||||
mBackend.setShowBadge(mPkg, mUid, value);
|
||||
} else {
|
||||
mChannel.setShowBadge(value);
|
||||
mChannel.lockFields(NotificationChannel.USER_LOCKED_SHOW_BADGE);
|
||||
mBackend.updateChannel(mPkg, mUid, mChannel);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void setupBlock() {
|
||||
View switchBarContainer = LayoutInflater.from(
|
||||
getPrefContext()).inflate(R.layout.styled_switch_bar, null);
|
||||
mSwitchBar = switchBarContainer.findViewById(R.id.switch_bar);
|
||||
mSwitchBar.show();
|
||||
mSwitchBar.setDisabledByAdmin(mSuspendedAppsAdmin);
|
||||
mSwitchBar.setChecked(!mAppRow.banned);
|
||||
mSwitchBar.addOnSwitchChangeListener(new SwitchBar.OnSwitchChangeListener() {
|
||||
@Override
|
||||
public void onSwitchChanged(Switch switchView, boolean isChecked) {
|
||||
if (mShowLegacyChannelConfig && mChannel != null) {
|
||||
final int importance = isChecked ? IMPORTANCE_UNSPECIFIED : IMPORTANCE_NONE;
|
||||
mImportanceToggle.setChecked(importance == IMPORTANCE_UNSPECIFIED);
|
||||
mChannel.setImportance(importance);
|
||||
mChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
|
||||
mBackend.updateChannel(mPkg, mUid, mChannel);
|
||||
}
|
||||
mBackend.setNotificationsEnabledForPackage(mPkgInfo.packageName, mUid, isChecked);
|
||||
mAppRow.banned = true;
|
||||
updateDependents(!isChecked);
|
||||
}
|
||||
});
|
||||
|
||||
mBlockBar = new LayoutPreference(getPrefContext(), switchBarContainer);
|
||||
mBlockBar.setOrder(ORDER_FIRST);
|
||||
mBlockBar.setKey(KEY_BLOCK);
|
||||
getPreferenceScreen().addPreference(mBlockBar);
|
||||
|
||||
if (mAppRow.systemApp && !mAppRow.banned) {
|
||||
setVisible(mBlockBar, false);
|
||||
}
|
||||
|
||||
setupBlockDesc(R.string.app_notifications_off_desc);
|
||||
}
|
||||
|
||||
protected void updateDependents(boolean banned) {
|
||||
for (PreferenceCategory category : mChannelGroups) {
|
||||
setVisible(category, !banned);
|
||||
}
|
||||
if (mDeletedChannels != null) {
|
||||
setVisible(mDeletedChannels, !banned);
|
||||
}
|
||||
setVisible(mBlockedDesc, banned);
|
||||
setVisible(mBadge, !banned);
|
||||
if (mShowLegacyChannelConfig) {
|
||||
setVisible(mImportanceToggle, !banned);
|
||||
setVisible(mPriority, checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT)
|
||||
|| (checkCanBeVisible(NotificationManager.IMPORTANCE_LOW)
|
||||
&& mDndVisualEffectsSuppressed));
|
||||
setVisible(mVisibilityOverride, !banned &&
|
||||
checkCanBeVisible(NotificationManager.IMPORTANCE_LOW) && isLockScreenSecure());
|
||||
}
|
||||
if (mAppLink != null) {
|
||||
setVisible(mAppLink, !banned);
|
||||
}
|
||||
if (mAppRow.systemApp && !mAppRow.banned) {
|
||||
setVisible(mBlockBar, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Comparator<NotificationChannelGroup> mChannelGroupComparator =
|
||||
new Comparator<NotificationChannelGroup>() {
|
||||
|
||||
|
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.provider.Settings.Secure.NOTIFICATION_BADGING;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
import android.support.v7.preference.Preference;
|
||||
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settingslib.RestrictedSwitchPreference;
|
||||
|
||||
public class BadgePreferenceController extends NotificationPreferenceController
|
||||
implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener {
|
||||
|
||||
private static final String TAG = "BadgePrefContr";
|
||||
private static final String KEY_BADGE = "badge";
|
||||
private static final int SYSTEM_WIDE_ON = 1;
|
||||
private static final int SYSTEM_WIDE_OFF = 0;
|
||||
|
||||
public BadgePreferenceController(Context context,
|
||||
NotificationBackend backend) {
|
||||
super(context, backend);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return KEY_BADGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
if (!super.isAvailable()) {
|
||||
return false;
|
||||
}
|
||||
if (mAppRow == null && mChannel == null) {
|
||||
return false;
|
||||
}
|
||||
if (Settings.Secure.getInt(mContext.getContentResolver(),
|
||||
NOTIFICATION_BADGING, SYSTEM_WIDE_ON) == SYSTEM_WIDE_OFF) {
|
||||
return false;
|
||||
}
|
||||
if (mChannel != null && !mAppRow.showBadge) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void updateState(Preference preference) {
|
||||
if (mAppRow != null) {
|
||||
RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference;
|
||||
pref.setDisabledByAdmin(mAdmin);
|
||||
if (mChannel != null) {
|
||||
pref.setChecked(mChannel.canShowBadge());
|
||||
pref.setEnabled(isChannelConfigurable() && !pref.isDisabledByAdmin());
|
||||
} else {
|
||||
pref.setChecked(mAppRow.showBadge);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
final boolean showBadge = (Boolean) newValue;
|
||||
if (mChannel != null) {
|
||||
mChannel.setShowBadge(showBadge);
|
||||
saveChannel();
|
||||
} else if (mAppRow != null){
|
||||
mAppRow.showBadge = showBadge;
|
||||
mBackend.setShowBadge(mAppRow.pkg, mAppRow.uid, showBadge);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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_CHANNEL_ID;
|
||||
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
|
||||
import static android.app.NotificationManager.IMPORTANCE_NONE;
|
||||
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
|
||||
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.widget.Switch;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.applications.LayoutPreference;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.widget.SwitchBar;
|
||||
|
||||
public class BlockPreferenceController extends NotificationPreferenceController
|
||||
implements PreferenceControllerMixin, SwitchBar.OnSwitchChangeListener {
|
||||
|
||||
private static final String KEY_BLOCK = "block";
|
||||
private NotificationSettingsBase.ImportanceListener mImportanceListener;
|
||||
|
||||
public BlockPreferenceController(Context context,
|
||||
NotificationSettingsBase.ImportanceListener importanceListener,
|
||||
NotificationBackend backend) {
|
||||
super(context, backend);
|
||||
mImportanceListener = importanceListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return KEY_BLOCK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
if (mAppRow == null) {
|
||||
return false;
|
||||
}
|
||||
if (mChannel != null) {
|
||||
return isChannelBlockable();
|
||||
} else if (mChannelGroup != null && mChannelGroup.getGroup() != null) {
|
||||
return isChannelGroupBlockable();
|
||||
} else {
|
||||
return !mAppRow.systemApp || (mAppRow.systemApp && mAppRow.banned);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateState(Preference preference) {
|
||||
LayoutPreference pref = (LayoutPreference) preference;
|
||||
SwitchBar bar = pref.findViewById(R.id.switch_bar);
|
||||
if (bar != null) {
|
||||
bar.show();
|
||||
try {
|
||||
bar.addOnSwitchChangeListener(this);
|
||||
} catch (IllegalStateException e) {
|
||||
// an exception is thrown if you try to add the listener twice
|
||||
}
|
||||
bar.setDisabledByAdmin(mAdmin);
|
||||
|
||||
if (mChannel != null) {
|
||||
bar.setChecked(!mAppRow.banned
|
||||
&& mChannel.getImportance() != NotificationManager.IMPORTANCE_NONE);
|
||||
} else if (mChannelGroup != null && mChannelGroup.getGroup() != null) {
|
||||
bar.setChecked(!mAppRow.banned && !mChannelGroup.isBlocked());
|
||||
} else {
|
||||
bar.setChecked(!mAppRow.banned);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSwitchChanged(Switch switchView, boolean isChecked) {
|
||||
boolean blocked = !isChecked;
|
||||
if (mChannel != null) {
|
||||
final int originalImportance = mChannel.getImportance();
|
||||
// setting the initial state of the switch in updateState() triggers this callback.
|
||||
// It's always safe to override the importance if it's meant to be blocked or if
|
||||
// it was blocked and we are unblocking it.
|
||||
if (blocked || originalImportance == IMPORTANCE_NONE) {
|
||||
final int importance = blocked ? IMPORTANCE_NONE
|
||||
: DEFAULT_CHANNEL_ID.equals(mChannel.getId())
|
||||
? IMPORTANCE_UNSPECIFIED : IMPORTANCE_DEFAULT;
|
||||
mChannel.setImportance(importance);
|
||||
saveChannel();
|
||||
}
|
||||
} else if (mChannelGroup != null && mChannelGroup.getGroup() != null) {
|
||||
mChannelGroup.setBlocked(blocked);
|
||||
mBackend.updateChannelGroup(mAppRow.pkg, mAppRow.uid, mChannelGroup.getGroup());
|
||||
} else if (mAppRow != null) {
|
||||
mAppRow.banned = blocked;
|
||||
mBackend.setNotificationsEnabledForPackage(mAppRow.pkg, mAppRow.uid, !blocked);
|
||||
}
|
||||
mImportanceListener.onImportanceChanged();
|
||||
}
|
||||
}
|
@@ -16,20 +16,15 @@
|
||||
|
||||
package com.android.settings.notification;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.NotificationChannel;
|
||||
import android.content.Context;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.applications.LayoutPreference;
|
||||
import com.android.settings.widget.EntityHeaderController;
|
||||
import com.android.settingslib.widget.FooterPreference;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -38,12 +33,6 @@ import java.util.List;
|
||||
public class ChannelGroupNotificationSettings extends NotificationSettingsBase {
|
||||
private static final String TAG = "ChannelGroupSettings";
|
||||
|
||||
private static String KEY_DELETED = "deleted";
|
||||
|
||||
private EntityHeaderController mHeaderPref;
|
||||
private List<Preference> mChannels = new ArrayList();
|
||||
private FooterPreference mDeletedChannels;
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsEvent.NOTIFICATION_CHANNEL_GROUP;
|
||||
@@ -52,137 +41,68 @@ public class ChannelGroupNotificationSettings extends NotificationSettingsBase {
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
if (mUid < 0 || TextUtils.isEmpty(mPkg) || mPkgInfo == null || mChannelGroup == null) {
|
||||
if (mAppRow == null || mChannelGroup == null || mChannelGroup.getGroup() == null) {
|
||||
Log.w(TAG, "Missing package or uid or packageinfo or group");
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
if (getPreferenceScreen() != null) {
|
||||
getPreferenceScreen().removeAll();
|
||||
}
|
||||
addPreferencesFromResource(R.xml.notification_settings);
|
||||
setupBlock();
|
||||
addHeaderPref();
|
||||
addAppLinkPref();
|
||||
addFooterPref();
|
||||
populateChannelList();
|
||||
|
||||
updateDependents(mChannelGroup.isBlocked());
|
||||
for (NotificationPreferenceController controller : mControllers) {
|
||||
controller.onResume(mAppRow, mChannel, mChannelGroup, mSuspendedAppsAdmin);
|
||||
controller.displayPreference(getPreferenceScreen());
|
||||
}
|
||||
updatePreferenceStates();
|
||||
}
|
||||
|
||||
@Override
|
||||
void setupBadge() {
|
||||
protected String getLogTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getPreferenceScreenResId() {
|
||||
return R.xml.notification_group_settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
|
||||
mControllers = new ArrayList<>();
|
||||
mControllers.add(new HeaderPreferenceController(context, this));
|
||||
mControllers.add(new BlockPreferenceController(context, mImportanceListener, mBackend));
|
||||
mControllers.add(new AppLinkPreferenceController(context));
|
||||
mControllers.add(new NotificationsOffPreferenceController(context));
|
||||
mControllers.add(new DescriptionPreferenceController(context));
|
||||
return new ArrayList<>(mControllers);
|
||||
}
|
||||
|
||||
private void populateChannelList() {
|
||||
if (!mChannels.isEmpty()) {
|
||||
// If there's anything in mChannels, we've called populateChannelList twice.
|
||||
if (!mDynamicPreferences.isEmpty()) {
|
||||
// If there's anything in mDynamicPreferences, we've called populateChannelList twice.
|
||||
// Clear out existing channels and log.
|
||||
Log.w(TAG, "Notification channel group posted twice to settings - old size " +
|
||||
mChannels.size() + ", new size " + mChannels.size());
|
||||
for (Preference p : mChannels) {
|
||||
mDynamicPreferences.size() + ", new size " + mDynamicPreferences.size());
|
||||
for (Preference p : mDynamicPreferences) {
|
||||
getPreferenceScreen().removePreference(p);
|
||||
}
|
||||
}
|
||||
if (mChannelGroup.getChannels().isEmpty()) {
|
||||
if (mChannelGroup.getGroup().getChannels().isEmpty()) {
|
||||
Preference empty = new Preference(getPrefContext());
|
||||
empty.setTitle(R.string.no_channels);
|
||||
empty.setEnabled(false);
|
||||
getPreferenceScreen().addPreference(empty);
|
||||
mChannels.add(empty);
|
||||
mDynamicPreferences.add(empty);
|
||||
|
||||
} else {
|
||||
final List<NotificationChannel> channels = mChannelGroup.getChannels();
|
||||
final List<NotificationChannel> channels = mChannelGroup.getGroup().getChannels();
|
||||
Collections.sort(channels, mChannelComparator);
|
||||
for (NotificationChannel channel : channels) {
|
||||
mChannels.add(populateSingleChannelPrefs(
|
||||
getPreferenceScreen(), channel, getImportanceSummary(channel)));
|
||||
mDynamicPreferences.add(populateSingleChannelPrefs(
|
||||
getPreferenceScreen(), channel,
|
||||
ImportancePreferenceController.getImportanceSummary(
|
||||
getPrefContext(), channel)));
|
||||
}
|
||||
|
||||
int deletedChannelCount = mBackend.getDeletedChannelCount(mAppRow.pkg, mAppRow.uid);
|
||||
if (deletedChannelCount > 0) {
|
||||
mDeletedChannels = new FooterPreference(getPrefContext());
|
||||
mDeletedChannels.setSelectable(false);
|
||||
mDeletedChannels.setTitle(getResources().getQuantityString(
|
||||
R.plurals.deleted_channels, deletedChannelCount, deletedChannelCount));
|
||||
mDeletedChannels.setEnabled(false);
|
||||
mDeletedChannels.setKey(KEY_DELETED);
|
||||
mDeletedChannels.setOrder(ORDER_LAST);
|
||||
getPreferenceScreen().addPreference(mDeletedChannels);
|
||||
mChannels.add(mDeletedChannels);
|
||||
}
|
||||
}
|
||||
|
||||
updateDependents(mAppRow.banned);
|
||||
}
|
||||
|
||||
private void addHeaderPref() {
|
||||
ArrayMap<String, NotificationBackend.AppRow> rows = new ArrayMap<>();
|
||||
rows.put(mAppRow.pkg, mAppRow);
|
||||
collectConfigActivities(rows);
|
||||
final Activity activity = getActivity();
|
||||
mHeaderPref = EntityHeaderController
|
||||
.newInstance(activity, this /* fragment */, null /* header */)
|
||||
.setRecyclerView(getListView(), getLifecycle());
|
||||
final Preference pref = mHeaderPref
|
||||
.setIcon(mAppRow.icon)
|
||||
.setLabel(mChannelGroup.getName())
|
||||
.setSummary(mAppRow.label)
|
||||
.setPackageName(mAppRow.pkg)
|
||||
.setUid(mAppRow.uid)
|
||||
.setButtonActions(EntityHeaderController.ActionType.ACTION_NOTIF_PREFERENCE,
|
||||
EntityHeaderController.ActionType.ACTION_NONE)
|
||||
.setHasAppInfoLink(true)
|
||||
.done(activity, getPrefContext());
|
||||
getPreferenceScreen().addPreference(pref);
|
||||
}
|
||||
|
||||
private void addFooterPref() {
|
||||
if (!TextUtils.isEmpty(mChannelGroup.getDescription())) {
|
||||
FooterPreference descPref = new FooterPreference(getPrefContext());
|
||||
descPref.setOrder(ORDER_LAST);
|
||||
descPref.setSelectable(false);
|
||||
descPref.setTitle(mChannelGroup.getDescription());
|
||||
getPreferenceScreen().addPreference(descPref);
|
||||
mChannels.add(descPref);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupBlock() {
|
||||
View switchBarContainer = LayoutInflater.from(
|
||||
getPrefContext()).inflate(R.layout.styled_switch_bar, null);
|
||||
mSwitchBar = switchBarContainer.findViewById(R.id.switch_bar);
|
||||
mSwitchBar.show();
|
||||
mSwitchBar.setDisabledByAdmin(mSuspendedAppsAdmin);
|
||||
mSwitchBar.setChecked(!mChannelGroup.isBlocked());
|
||||
mSwitchBar.addOnSwitchChangeListener((switchView, isChecked) -> {
|
||||
mChannelGroup.setBlocked(!isChecked);
|
||||
mBackend.updateChannelGroup(mPkg, mUid, mChannelGroup);
|
||||
updateDependents(!isChecked);
|
||||
});
|
||||
|
||||
mBlockBar = new LayoutPreference(getPrefContext(), switchBarContainer);
|
||||
mBlockBar.setOrder(ORDER_FIRST);
|
||||
mBlockBar.setKey(KEY_BLOCK);
|
||||
getPreferenceScreen().addPreference(mBlockBar);
|
||||
|
||||
if (!isChannelGroupBlockable(mChannelGroup)) {
|
||||
setVisible(mBlockBar, false);
|
||||
}
|
||||
|
||||
setupBlockDesc(R.string.channel_group_notifications_off_desc);
|
||||
}
|
||||
|
||||
protected void updateDependents(boolean banned) {
|
||||
for (Preference channel : mChannels) {
|
||||
setVisible(channel, !banned);
|
||||
}
|
||||
if (mAppLink != null) {
|
||||
setVisible(mAppLink, !banned);
|
||||
}
|
||||
setVisible(mBlockBar, isChannelGroupBlockable(mChannelGroup));
|
||||
setVisible(mBlockedDesc, mAppRow.banned || mChannelGroup.isBlocked());
|
||||
}
|
||||
}
|
||||
|
@@ -37,6 +37,7 @@ import com.android.settings.R;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settings.search.Indexable;
|
||||
import com.android.settings.widget.RadioButtonPreference;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -60,8 +61,8 @@ public class ChannelImportanceSettings extends NotificationSettingsBase
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
if (mUid < 0 || TextUtils.isEmpty(mPkg) || mPkgInfo == null || mChannel == null) {
|
||||
Log.w(TAG, "Missing package or uid or packageinfo or channel");
|
||||
if (mAppRow == null || mChannel == null) {
|
||||
Log.w(TAG, "Missing package or channel");
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
@@ -69,10 +70,19 @@ public class ChannelImportanceSettings extends NotificationSettingsBase
|
||||
}
|
||||
|
||||
@Override
|
||||
void setupBadge() {}
|
||||
protected String getLogTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
void updateDependents(boolean banned) {}
|
||||
protected int getPreferenceScreenResId() {
|
||||
return R.xml.notification_importance;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
@@ -81,11 +91,6 @@ public class ChannelImportanceSettings extends NotificationSettingsBase
|
||||
|
||||
private PreferenceScreen createPreferenceHierarchy() {
|
||||
PreferenceScreen root = getPreferenceScreen();
|
||||
if (root != null) {
|
||||
root.removeAll();
|
||||
}
|
||||
addPreferencesFromResource(R.xml.notification_importance);
|
||||
root = getPreferenceScreen();
|
||||
|
||||
for (int i = 0; i < root.getPreferenceCount(); i++) {
|
||||
Preference pref = root.getPreference(i);
|
||||
@@ -148,8 +153,9 @@ public class ChannelImportanceSettings extends NotificationSettingsBase
|
||||
// but the sound you had selected was "Silence",
|
||||
// then set sound for this channel to your default sound,
|
||||
// because you probably intended to cause this channel to actually start making sound.
|
||||
if (oldImportance < IMPORTANCE_DEFAULT && !hasValidSound(mChannel) &&
|
||||
mChannel.getImportance() >= IMPORTANCE_DEFAULT) {
|
||||
if (oldImportance < IMPORTANCE_DEFAULT
|
||||
&& !SoundPreferenceController.hasValidSound(mChannel)
|
||||
&& mChannel.getImportance() >= IMPORTANCE_DEFAULT) {
|
||||
mChannel.setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION),
|
||||
mChannel.getAudioAttributes());
|
||||
mChannel.lockFields(USER_LOCKED_SOUND);
|
||||
|
@@ -16,59 +16,23 @@
|
||||
|
||||
package com.android.settings.notification;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationChannelGroup;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.AsyncTask;
|
||||
import android.provider.Settings;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceGroup;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.text.TextUtils;
|
||||
import android.text.BidiFormatter;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.Switch;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.RingtonePreference;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.applications.AppInfoBase;
|
||||
import com.android.settings.applications.LayoutPreference;
|
||||
import com.android.settings.widget.EntityHeaderController;
|
||||
import com.android.settings.widget.SwitchBar;
|
||||
import com.android.settingslib.RestrictedSwitchPreference;
|
||||
import com.android.settingslib.widget.FooterPreference;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
import static android.app.NotificationManager.IMPORTANCE_LOW;
|
||||
import static android.app.NotificationManager.IMPORTANCE_NONE;
|
||||
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ChannelNotificationSettings extends NotificationSettingsBase {
|
||||
private static final String TAG = "ChannelSettings";
|
||||
|
||||
private static final String KEY_LIGHTS = "lights";
|
||||
private static final String KEY_VIBRATE = "vibrate";
|
||||
private static final String KEY_RINGTONE = "ringtone";
|
||||
private static final String KEY_IMPORTANCE = "importance";
|
||||
private static final String KEY_ADVANCED = "advanced";
|
||||
|
||||
private Preference mImportance;
|
||||
private RestrictedSwitchPreference mLights;
|
||||
private RestrictedSwitchPreference mVibrate;
|
||||
private NotificationSoundPreference mRingtone;
|
||||
private FooterPreference mFooter;
|
||||
private NotificationChannelGroup mChannelGroup;
|
||||
private EntityHeaderController mHeaderPref;
|
||||
private PreferenceGroup mAdvanced;
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return MetricsEvent.NOTIFICATION_TOPIC_NOTIFICATION;
|
||||
@@ -83,308 +47,52 @@ public class ChannelNotificationSettings extends NotificationSettingsBase {
|
||||
return;
|
||||
}
|
||||
|
||||
if (getPreferenceScreen() != null) {
|
||||
getPreferenceScreen().removeAll();
|
||||
for (NotificationPreferenceController controller : mControllers) {
|
||||
controller.onResume(mAppRow, mChannel, mChannelGroup, mSuspendedAppsAdmin);
|
||||
controller.displayPreference(getPreferenceScreen());
|
||||
}
|
||||
addPreferencesFromResource(R.xml.notification_settings);
|
||||
setupBlock();
|
||||
addHeaderPref();
|
||||
addAppLinkPref();
|
||||
addFooterPref();
|
||||
|
||||
if (NotificationChannel.DEFAULT_CHANNEL_ID.equals(mChannel.getId())) {
|
||||
populateDefaultChannelPrefs();
|
||||
mShowLegacyChannelConfig = true;
|
||||
} else {
|
||||
populateUpgradedChannelPrefs();
|
||||
|
||||
if (mChannel.getGroup() != null) {
|
||||
mChannelGroup = mBackend.getGroup(mPkg, mUid, mChannel.getGroup());
|
||||
if (mChannelGroup != null) {
|
||||
setChannelGroupLabel(mChannelGroup.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateDependents(mChannel.getImportance() == IMPORTANCE_NONE);
|
||||
}
|
||||
|
||||
private void populateUpgradedChannelPrefs() {
|
||||
addPreferencesFromResource(R.xml.upgraded_channel_notification_settings);
|
||||
setupBadge();
|
||||
setupPriorityPref(mChannel.canBypassDnd());
|
||||
setupVisOverridePref(mChannel.getLockscreenVisibility());
|
||||
setupLights();
|
||||
setupVibrate();
|
||||
setupRingtone();
|
||||
setupImportance();
|
||||
mAdvanced = (PreferenceGroup) findPreference(KEY_ADVANCED);
|
||||
}
|
||||
|
||||
private void addHeaderPref() {
|
||||
ArrayMap<String, NotificationBackend.AppRow> rows = new ArrayMap<>();
|
||||
rows.put(mAppRow.pkg, mAppRow);
|
||||
collectConfigActivities(rows);
|
||||
final Activity activity = getActivity();
|
||||
mHeaderPref = EntityHeaderController
|
||||
.newInstance(activity, this /* fragment */, null /* header */)
|
||||
.setRecyclerView(getListView(), getLifecycle());
|
||||
final Preference pref = mHeaderPref
|
||||
.setIcon(mAppRow.icon)
|
||||
.setLabel(mChannel.getName())
|
||||
.setSummary(mAppRow.label)
|
||||
.setPackageName(mAppRow.pkg)
|
||||
.setUid(mAppRow.uid)
|
||||
.setButtonActions(EntityHeaderController.ActionType.ACTION_NOTIF_PREFERENCE,
|
||||
EntityHeaderController.ActionType.ACTION_NONE)
|
||||
.setHasAppInfoLink(true)
|
||||
.done(activity, getPrefContext());
|
||||
getPreferenceScreen().addPreference(pref);
|
||||
}
|
||||
|
||||
private void setChannelGroupLabel(CharSequence groupName) {
|
||||
final SpannableStringBuilder summary = new SpannableStringBuilder();
|
||||
BidiFormatter bidi = BidiFormatter.getInstance();
|
||||
summary.append(bidi.unicodeWrap(mAppRow.label.toString()));
|
||||
if (groupName != null) {
|
||||
summary.append(bidi.unicodeWrap(mContext.getText(
|
||||
R.string.notification_header_divider_symbol_with_spaces)));
|
||||
summary.append(bidi.unicodeWrap(groupName.toString()));
|
||||
}
|
||||
final Activity activity = getActivity();
|
||||
mHeaderPref.setSummary(summary.toString());
|
||||
mHeaderPref.done(activity, getPrefContext());
|
||||
}
|
||||
|
||||
private void addFooterPref() {
|
||||
if (!TextUtils.isEmpty(mChannel.getDescription())) {
|
||||
FooterPreference descPref = new FooterPreference(getPrefContext());
|
||||
descPref.setOrder(ORDER_LAST);
|
||||
descPref.setSelectable(false);
|
||||
descPref.setTitle(mChannel.getDescription());
|
||||
getPreferenceScreen().addPreference(descPref);
|
||||
}
|
||||
}
|
||||
|
||||
protected void setupBadge() {
|
||||
mBadge = (RestrictedSwitchPreference) getPreferenceScreen().findPreference(KEY_BADGE);
|
||||
mBadge.setDisabledByAdmin(mSuspendedAppsAdmin);
|
||||
mBadge.setEnabled(mAppRow.showBadge);
|
||||
mBadge.setChecked(mChannel.canShowBadge());
|
||||
|
||||
mBadge.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
final boolean value = (Boolean) newValue;
|
||||
mChannel.setShowBadge(value);
|
||||
mChannel.lockFields(NotificationChannel.USER_LOCKED_SHOW_BADGE);
|
||||
mBackend.updateChannel(mPkg, mUid, mChannel);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setupLights() {
|
||||
mLights = (RestrictedSwitchPreference) findPreference(KEY_LIGHTS);
|
||||
mLights.setDisabledByAdmin(mSuspendedAppsAdmin);
|
||||
mLights.setChecked(mChannel.shouldShowLights());
|
||||
mLights.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
final boolean lights = (Boolean) newValue;
|
||||
mChannel.enableLights(lights);
|
||||
mChannel.lockFields(NotificationChannel.USER_LOCKED_LIGHTS);
|
||||
mBackend.updateChannel(mPkg, mUid, mChannel);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setupVibrate() {
|
||||
mVibrate = (RestrictedSwitchPreference) findPreference(KEY_VIBRATE);
|
||||
mVibrate.setDisabledByAdmin(mSuspendedAppsAdmin);
|
||||
mVibrate.setEnabled(!mVibrate.isDisabledByAdmin() && isChannelConfigurable(mChannel));
|
||||
mVibrate.setChecked(mChannel.shouldVibrate());
|
||||
mVibrate.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
final boolean vibrate = (Boolean) newValue;
|
||||
mChannel.enableVibration(vibrate);
|
||||
mChannel.lockFields(NotificationChannel.USER_LOCKED_VIBRATION);
|
||||
mBackend.updateChannel(mPkg, mUid, mChannel);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setupRingtone() {
|
||||
mRingtone = (NotificationSoundPreference) findPreference(KEY_RINGTONE);
|
||||
mRingtone.setRingtone(mChannel.getSound());
|
||||
mRingtone.setEnabled(isChannelConfigurable(mChannel));
|
||||
mRingtone.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
mChannel.setSound((Uri) newValue, mChannel.getAudioAttributes());
|
||||
mChannel.lockFields(NotificationChannel.USER_LOCKED_SOUND);
|
||||
mBackend.updateChannel(mPkg, mUid, mChannel);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setupBlock() {
|
||||
View switchBarContainer = LayoutInflater.from(
|
||||
getPrefContext()).inflate(R.layout.styled_switch_bar, null);
|
||||
mSwitchBar = switchBarContainer.findViewById(R.id.switch_bar);
|
||||
mSwitchBar.show();
|
||||
mSwitchBar.setDisabledByAdmin(mSuspendedAppsAdmin);
|
||||
mSwitchBar.setChecked(mChannel.getImportance() != NotificationManager.IMPORTANCE_NONE);
|
||||
mSwitchBar.addOnSwitchChangeListener(new SwitchBar.OnSwitchChangeListener() {
|
||||
@Override
|
||||
public void onSwitchChanged(Switch switchView, boolean isChecked) {
|
||||
int importance = 0;
|
||||
if (mShowLegacyChannelConfig) {
|
||||
importance = isChecked ? IMPORTANCE_UNSPECIFIED : IMPORTANCE_NONE;
|
||||
mImportanceToggle.setChecked(importance == IMPORTANCE_UNSPECIFIED);
|
||||
} else {
|
||||
importance = isChecked ? IMPORTANCE_LOW : IMPORTANCE_NONE;
|
||||
mImportance.setSummary(getImportanceSummary(importance));
|
||||
}
|
||||
mChannel.setImportance(importance);
|
||||
mChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
|
||||
mBackend.updateChannel(mPkg, mUid, mChannel);
|
||||
updateDependents(mChannel.getImportance() == IMPORTANCE_NONE);
|
||||
}
|
||||
});
|
||||
|
||||
mBlockBar = new LayoutPreference(getPrefContext(), switchBarContainer);
|
||||
mBlockBar.setOrder(ORDER_FIRST);
|
||||
mBlockBar.setKey(KEY_BLOCK);
|
||||
getPreferenceScreen().addPreference(mBlockBar);
|
||||
|
||||
if (!isChannelBlockable(mChannel)) {
|
||||
setVisible(mBlockBar, false);
|
||||
}
|
||||
|
||||
setupBlockDesc(R.string.channel_notifications_off_desc);
|
||||
}
|
||||
|
||||
private void setupImportance() {
|
||||
mImportance = findPreference(KEY_IMPORTANCE);
|
||||
Bundle channelArgs = new Bundle();
|
||||
channelArgs.putInt(AppInfoBase.ARG_PACKAGE_UID, mUid);
|
||||
channelArgs.putString(AppInfoBase.ARG_PACKAGE_NAME, mPkg);
|
||||
channelArgs.putString(Settings.EXTRA_CHANNEL_ID, mChannel.getId());
|
||||
mImportance.setEnabled(mSuspendedAppsAdmin == null && isChannelConfigurable(mChannel));
|
||||
// Set up intent to show importance selection only if this setting is enabled.
|
||||
if (mImportance.isEnabled()) {
|
||||
Intent channelIntent = Utils.onBuildStartFragmentIntent(getActivity(),
|
||||
ChannelImportanceSettings.class.getName(),
|
||||
channelArgs, null, R.string.notification_importance_title, null,
|
||||
false, getMetricsCategory());
|
||||
mImportance.setIntent(channelIntent);
|
||||
}
|
||||
mImportance.setSummary(getImportanceSummary(mChannel.getImportance()));
|
||||
}
|
||||
|
||||
private String getImportanceSummary(int importance) {
|
||||
String title;
|
||||
String summary = null;
|
||||
switch (importance) {
|
||||
case IMPORTANCE_UNSPECIFIED:
|
||||
title = getContext().getString(R.string.notification_importance_unspecified);
|
||||
break;
|
||||
case NotificationManager.IMPORTANCE_MIN:
|
||||
title = getContext().getString(R.string.notification_importance_min_title);
|
||||
summary = getContext().getString(R.string.notification_importance_min);
|
||||
break;
|
||||
case NotificationManager.IMPORTANCE_LOW:
|
||||
title = getContext().getString(R.string.notification_importance_low_title);
|
||||
summary = getContext().getString(R.string.notification_importance_low);
|
||||
break;
|
||||
case NotificationManager.IMPORTANCE_DEFAULT:
|
||||
title = getContext().getString(R.string.notification_importance_default_title);
|
||||
if (hasValidSound(mChannel)) {
|
||||
summary = getContext().getString(R.string.notification_importance_default);
|
||||
} else {
|
||||
summary = getContext().getString(R.string.notification_importance_low);
|
||||
}
|
||||
break;
|
||||
case NotificationManager.IMPORTANCE_HIGH:
|
||||
case NotificationManager.IMPORTANCE_MAX:
|
||||
title = getContext().getString(R.string.notification_importance_high_title);
|
||||
if (hasValidSound(mChannel)) {
|
||||
summary = getContext().getString(R.string.notification_importance_high);
|
||||
} else {
|
||||
summary = getContext().getString(R.string.notification_importance_high_silent);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
|
||||
if (summary != null) {
|
||||
return getContext().getString(R.string.notification_importance_divider, title, summary);
|
||||
} else {
|
||||
return title;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceTreeClick(Preference preference) {
|
||||
if (preference instanceof RingtonePreference) {
|
||||
mRingtone.onPrepareRingtonePickerIntent(mRingtone.getIntent());
|
||||
startActivityForResult(preference.getIntent(), 200);
|
||||
return true;
|
||||
}
|
||||
return super.onPreferenceTreeClick(preference);
|
||||
updatePreferenceStates();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (mRingtone != null) {
|
||||
mRingtone.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
if (mChannel != null) {
|
||||
mImportance.setSummary(getImportanceSummary(mChannel.getImportance()));
|
||||
for (NotificationPreferenceController controller : mControllers) {
|
||||
if (controller instanceof PreferenceManager.OnActivityResultListener) {
|
||||
((PreferenceManager.OnActivityResultListener) controller)
|
||||
.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean canPulseLight() {
|
||||
if (!getResources()
|
||||
.getBoolean(com.android.internal.R.bool.config_intrusiveNotificationLed)) {
|
||||
return false;
|
||||
}
|
||||
return Settings.System.getInt(getContentResolver(),
|
||||
Settings.System.NOTIFICATION_LIGHT_PULSE, 0) == 1;
|
||||
@Override
|
||||
protected String getLogTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
void updateDependents(boolean banned) {
|
||||
PreferenceGroup parent;
|
||||
if (mShowLegacyChannelConfig) {
|
||||
parent = getPreferenceScreen();
|
||||
setVisible(mImportanceToggle, checkCanBeVisible(NotificationManager.IMPORTANCE_MIN));
|
||||
} else {
|
||||
setVisible(mAdvanced, checkCanBeVisible(NotificationManager.IMPORTANCE_MIN));
|
||||
setVisible(mImportance, checkCanBeVisible(NotificationManager.IMPORTANCE_MIN));
|
||||
setVisible(mAdvanced, mLights, checkCanBeVisible(
|
||||
NotificationManager.IMPORTANCE_DEFAULT) && canPulseLight());
|
||||
setVisible(mVibrate, checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT));
|
||||
setVisible(mRingtone, checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT));
|
||||
parent = mAdvanced;
|
||||
}
|
||||
setVisible(parent, mBadge, checkCanBeVisible(NotificationManager.IMPORTANCE_MIN));
|
||||
setVisible(parent, mPriority, checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT)
|
||||
|| (checkCanBeVisible(NotificationManager.IMPORTANCE_LOW)
|
||||
&& mDndVisualEffectsSuppressed));
|
||||
setVisible(parent, mVisibilityOverride, isLockScreenSecure()
|
||||
&&checkCanBeVisible(NotificationManager.IMPORTANCE_LOW));
|
||||
setVisible(mBlockedDesc, mChannel.getImportance() == IMPORTANCE_NONE);
|
||||
if (mAppLink != null) {
|
||||
setVisible(mAppLink, checkCanBeVisible(NotificationManager.IMPORTANCE_MIN));
|
||||
}
|
||||
if (mFooter != null) {
|
||||
setVisible(mFooter, checkCanBeVisible(NotificationManager.IMPORTANCE_MIN));
|
||||
}
|
||||
@Override
|
||||
protected int getPreferenceScreenResId() {
|
||||
return R.xml.channel_notification_settings;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
|
||||
mControllers = new ArrayList<>();
|
||||
mControllers.add(new HeaderPreferenceController(context, this));
|
||||
mControllers.add(new BlockPreferenceController(context, mImportanceListener, mBackend));
|
||||
mControllers.add(new ImportancePreferenceController(context));
|
||||
mControllers.add(new AllowSoundPreferenceController(
|
||||
context, mImportanceListener, mBackend));
|
||||
mControllers.add(new SoundPreferenceController(context, this,
|
||||
mImportanceListener, mBackend));
|
||||
mControllers.add(new VibrationPreferenceController(context, mBackend));
|
||||
mControllers.add(new AppLinkPreferenceController(context));
|
||||
mControllers.add(new DescriptionPreferenceController(context));
|
||||
mControllers.add(new VisibilityPreferenceController(context, new LockPatternUtils(context),
|
||||
mBackend));
|
||||
mControllers.add(new LightsPreferenceController(context, mBackend));
|
||||
mControllers.add(new BadgePreferenceController(context, mBackend));
|
||||
mControllers.add(new DndPreferenceController(context, getLifecycle(), mBackend));
|
||||
mControllers.add(new NotificationsOffPreferenceController(context));
|
||||
return new ArrayList<>(mControllers);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.content.Context;
|
||||
import android.support.v7.preference.Preference;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
|
||||
public class DeletedChannelsPreferenceController extends NotificationPreferenceController
|
||||
implements PreferenceControllerMixin {
|
||||
|
||||
private static final String KEY_DELETED = "deleted";
|
||||
|
||||
public DeletedChannelsPreferenceController(Context context, NotificationBackend backend) {
|
||||
super(context, backend);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return KEY_DELETED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
if (!super.isAvailable()) {
|
||||
return false;
|
||||
}
|
||||
// only visible on app screen
|
||||
if (mChannel != null || hasValidGroup()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return mBackend.getDeletedChannelCount(mAppRow.pkg, mAppRow.uid) > 0;
|
||||
}
|
||||
|
||||
public void updateState(Preference preference) {
|
||||
if (mAppRow != null) {
|
||||
int deletedChannelCount = mBackend.getDeletedChannelCount(mAppRow.pkg, mAppRow.uid);
|
||||
preference.setTitle(mContext.getResources().getQuantityString(
|
||||
R.plurals.deleted_channels, deletedChannelCount, deletedChannelCount));
|
||||
}
|
||||
preference.setEnabled(false);
|
||||
preference.setSelectable(false);
|
||||
}
|
||||
}
|
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.content.Context;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
|
||||
public class DescriptionPreferenceController extends NotificationPreferenceController
|
||||
implements PreferenceControllerMixin {
|
||||
|
||||
private static final String KEY_DESC = "desc";
|
||||
|
||||
public DescriptionPreferenceController(Context context) {
|
||||
super(context, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return KEY_DESC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
if (!super.isAvailable()) {
|
||||
return false;
|
||||
}
|
||||
if (mChannel == null && !hasValidGroup()) {
|
||||
return false;
|
||||
}
|
||||
if (mChannel != null && !TextUtils.isEmpty(mChannel.getDescription())) {
|
||||
return true;
|
||||
}
|
||||
if (hasValidGroup() && !TextUtils.isEmpty(mChannelGroup.getDescription())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void updateState(Preference preference) {
|
||||
if (mAppRow != null) {
|
||||
if (mChannel != null) {
|
||||
preference.setTitle(mChannel.getDescription());
|
||||
} else if (hasValidGroup()) {
|
||||
preference.setTitle(mChannelGroup.getDescription());
|
||||
}
|
||||
}
|
||||
preference.setEnabled(false);
|
||||
preference.setSelectable(false);
|
||||
}
|
||||
}
|
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.support.v7.preference.Preference;
|
||||
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settingslib.RestrictedSwitchPreference;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnResume;
|
||||
|
||||
public class DndPreferenceController extends NotificationPreferenceController
|
||||
implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener,
|
||||
LifecycleObserver, OnResume {
|
||||
|
||||
private static final String KEY_BYPASS_DND = "bypass_dnd";
|
||||
private boolean mVisualEffectsSuppressed;
|
||||
|
||||
public DndPreferenceController(Context context, Lifecycle lifecycle,
|
||||
NotificationBackend backend) {
|
||||
super(context, backend);
|
||||
if (lifecycle != null) {
|
||||
lifecycle.addObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
NotificationManager.Policy policy = mNm.getNotificationPolicy();
|
||||
mVisualEffectsSuppressed = policy != null && policy.suppressedVisualEffects != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return KEY_BYPASS_DND;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
if (!super.isAvailable()) {
|
||||
return false;
|
||||
}
|
||||
return checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT)
|
||||
|| (checkCanBeVisible(NotificationManager.IMPORTANCE_LOW)
|
||||
&& mVisualEffectsSuppressed);
|
||||
}
|
||||
|
||||
public void updateState(Preference preference) {
|
||||
if (mChannel != null) {
|
||||
RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference;
|
||||
pref.setDisabledByAdmin(mAdmin);
|
||||
pref.setEnabled(isChannelConfigurable() && !pref.isDisabledByAdmin());
|
||||
pref.setChecked(mChannel.canBypassDnd());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
if (mChannel != null) {
|
||||
final boolean bypassZenMode = (Boolean) newValue;
|
||||
mChannel.setBypassDnd(bypassZenMode);
|
||||
mChannel.lockFields(NotificationChannel.USER_LOCKED_PRIORITY);
|
||||
saveChannel();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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 com.android.settings.widget.EntityHeaderController.PREF_KEY_APP_HEADER;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v14.preference.PreferenceFragment;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.text.BidiFormatter;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.applications.LayoutPreference;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.widget.EntityHeaderController;
|
||||
|
||||
public class HeaderPreferenceController extends NotificationPreferenceController
|
||||
implements PreferenceControllerMixin {
|
||||
|
||||
private final PreferenceFragment mFragment;
|
||||
|
||||
public HeaderPreferenceController(Context context, PreferenceFragment fragment) {
|
||||
super(context, null);
|
||||
mFragment = fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return PREF_KEY_APP_HEADER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return mAppRow != null;
|
||||
}
|
||||
|
||||
public void updateState(Preference preference) {
|
||||
if (mAppRow != null && mFragment != null) {
|
||||
LayoutPreference pref = (LayoutPreference) preference;
|
||||
EntityHeaderController controller = EntityHeaderController
|
||||
.newInstance(mFragment.getActivity(), mFragment,
|
||||
pref.findViewById(R.id.entity_header));
|
||||
pref = controller.setIcon(mAppRow.icon)
|
||||
.setLabel(getLabel())
|
||||
.setSummary(getSummary())
|
||||
.setPackageName(mAppRow.pkg)
|
||||
.setUid(mAppRow.uid)
|
||||
.setButtonActions(EntityHeaderController.ActionType.ACTION_NOTIF_PREFERENCE,
|
||||
EntityHeaderController.ActionType.ACTION_NONE)
|
||||
.setHasAppInfoLink(true)
|
||||
.done(mFragment.getActivity(), mContext);
|
||||
pref.findViewById(R.id.entity_header).setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
CharSequence getLabel() {
|
||||
return mChannel != null ? mChannel.getName()
|
||||
: mChannelGroup != null && mChannelGroup.getGroup() != null
|
||||
? mChannelGroup.getGroup().getName()
|
||||
: mAppRow.label;
|
||||
}
|
||||
|
||||
CharSequence getSummary() {
|
||||
if (mChannel != null) {
|
||||
if (mChannelGroup != null && mChannelGroup.getGroup() != null
|
||||
&& !TextUtils.isEmpty(mChannelGroup.getGroup().getName())) {
|
||||
final SpannableStringBuilder summary = new SpannableStringBuilder();
|
||||
BidiFormatter bidi = BidiFormatter.getInstance();
|
||||
summary.append(bidi.unicodeWrap(mAppRow.label.toString()));
|
||||
summary.append(bidi.unicodeWrap(mContext.getText(
|
||||
R.string.notification_header_divider_symbol_with_spaces)));
|
||||
summary.append(bidi.unicodeWrap(mChannelGroup.getGroup().getName().toString()));
|
||||
return summary;
|
||||
} else {
|
||||
return mAppRow.label;
|
||||
}
|
||||
} else if (mChannelGroup != null && mChannelGroup.getGroup() != null) {
|
||||
return mAppRow.label;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.NotificationManager.IMPORTANCE_UNSPECIFIED;
|
||||
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.support.v7.preference.Preference;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.applications.AppInfoBase;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
|
||||
public class ImportancePreferenceController extends NotificationPreferenceController
|
||||
implements PreferenceControllerMixin {
|
||||
|
||||
private static final String KEY_IMPORTANCE = "importance";
|
||||
|
||||
// Ironically doesn't take an importance listener because the importance is not changed
|
||||
// by this controller's preference but by the screen it links to.
|
||||
public ImportancePreferenceController(Context context) {
|
||||
super(context, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return KEY_IMPORTANCE;
|
||||
}
|
||||
|
||||
private int getMetricsCategory() {
|
||||
return MetricsProto.MetricsEvent.NOTIFICATION_TOPIC_NOTIFICATION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
if (!super.isAvailable()) {
|
||||
return false;
|
||||
}
|
||||
if (mChannel == null) {
|
||||
return false;
|
||||
}
|
||||
return !NotificationChannel.DEFAULT_CHANNEL_ID.equals(mChannel.getId());
|
||||
}
|
||||
|
||||
public void updateState(Preference preference) {
|
||||
if (mAppRow!= null && mChannel != null) {
|
||||
preference.setEnabled(mAdmin == null && isChannelConfigurable());
|
||||
Bundle channelArgs = new Bundle();
|
||||
channelArgs.putInt(AppInfoBase.ARG_PACKAGE_UID, mAppRow.uid);
|
||||
channelArgs.putString(AppInfoBase.ARG_PACKAGE_NAME, mAppRow.pkg);
|
||||
channelArgs.putString(Settings.EXTRA_CHANNEL_ID, mChannel.getId());
|
||||
if (preference.isEnabled()) {
|
||||
Intent channelIntent = Utils.onBuildStartFragmentIntent(mContext,
|
||||
ChannelImportanceSettings.class.getName(),
|
||||
channelArgs, null, R.string.notification_importance_title, null,
|
||||
false, getMetricsCategory());
|
||||
preference.setIntent(channelIntent);
|
||||
preference.setSummary(getImportanceSummary(mContext, mChannel));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected static String getImportanceSummary(Context context, NotificationChannel channel) {
|
||||
String title;
|
||||
String summary = null;
|
||||
int importance = channel.getImportance();
|
||||
switch (importance) {
|
||||
case IMPORTANCE_UNSPECIFIED:
|
||||
title = context.getString(R.string.notification_importance_unspecified);
|
||||
break;
|
||||
case NotificationManager.IMPORTANCE_MIN:
|
||||
title = context.getString(R.string.notification_importance_min_title);
|
||||
summary = context.getString(R.string.notification_importance_min);
|
||||
break;
|
||||
case NotificationManager.IMPORTANCE_LOW:
|
||||
title = context.getString(R.string.notification_importance_low_title);
|
||||
summary = context.getString(R.string.notification_importance_low);
|
||||
break;
|
||||
case NotificationManager.IMPORTANCE_DEFAULT:
|
||||
title = context.getString(R.string.notification_importance_default_title);
|
||||
if (SoundPreferenceController.hasValidSound(channel)) {
|
||||
summary = context.getString(R.string.notification_importance_default);
|
||||
} else {
|
||||
summary = context.getString(R.string.notification_importance_low);
|
||||
}
|
||||
break;
|
||||
case NotificationManager.IMPORTANCE_HIGH:
|
||||
case NotificationManager.IMPORTANCE_MAX:
|
||||
title = context.getString(R.string.notification_importance_high_title);
|
||||
if (SoundPreferenceController.hasValidSound(channel)) {
|
||||
summary = context.getString(R.string.notification_importance_high);
|
||||
} else {
|
||||
summary = context.getString(R.string.notification_importance_high_silent);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
|
||||
if (summary != null) {
|
||||
return context.getString(R.string.notification_importance_divider, title, summary);
|
||||
} else {
|
||||
return title;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
import android.support.v7.preference.Preference;
|
||||
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settingslib.RestrictedSwitchPreference;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnResume;
|
||||
|
||||
public class LightsPreferenceController extends NotificationPreferenceController
|
||||
implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener {
|
||||
|
||||
private static final String KEY_LIGHTS = "lights";
|
||||
|
||||
public LightsPreferenceController(Context context, NotificationBackend backend) {
|
||||
super(context, backend);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return KEY_LIGHTS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
if (!super.isAvailable()) {
|
||||
return false;
|
||||
}
|
||||
if (mChannel == null) {
|
||||
return false;
|
||||
}
|
||||
return checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT) && canPulseLight()
|
||||
&& !NotificationChannel.DEFAULT_CHANNEL_ID.equals(mChannel.getId());
|
||||
}
|
||||
|
||||
public void updateState(Preference preference) {
|
||||
if (mChannel != null) {
|
||||
RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference;
|
||||
pref.setDisabledByAdmin(mAdmin);
|
||||
pref.setEnabled(isChannelConfigurable() && !pref.isDisabledByAdmin());
|
||||
pref.setChecked(mChannel.shouldShowLights());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
if (mChannel != null) {
|
||||
final boolean lights = (Boolean) newValue;
|
||||
mChannel.enableLights(lights);
|
||||
saveChannel();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean canPulseLight() {
|
||||
if (!mContext.getResources()
|
||||
.getBoolean(com.android.internal.R.bool.config_intrusiveNotificationLed)) {
|
||||
return false;
|
||||
}
|
||||
return Settings.System.getInt(mContext.getContentResolver(),
|
||||
Settings.System.NOTIFICATION_LIGHT_PULSE, 0) == 1;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.content.Context;
|
||||
import android.support.v4.content.res.TypedArrayUtils;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceViewHolder;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.settingslib.R;
|
||||
|
||||
/**
|
||||
* FooterPreference that can have any key or ordering.
|
||||
*/
|
||||
public class NotificationFooterPreference extends Preference {
|
||||
|
||||
public NotificationFooterPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs, TypedArrayUtils.getAttr(
|
||||
context, R.attr.footerPreferenceStyle, android.R.attr.preferenceStyle));
|
||||
init();
|
||||
}
|
||||
|
||||
public NotificationFooterPreference(Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(PreferenceViewHolder holder) {
|
||||
super.onBindViewHolder(holder);
|
||||
TextView title = holder.itemView.findViewById(android.R.id.title);
|
||||
title.setMovementMethod(new LinkMovementMethod());
|
||||
title.setClickable(false);
|
||||
title.setLongClickable(false);
|
||||
}
|
||||
|
||||
private void init() {
|
||||
setIcon(R.drawable.ic_info_outline_24dp);
|
||||
setSelectable(false);
|
||||
}
|
||||
}
|
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.NotificationManager.IMPORTANCE_NONE;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationChannelGroup;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.UserManager;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceGroup;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.settings.wrapper.NotificationChannelGroupWrapper;
|
||||
import com.android.settingslib.RestrictedLockUtils;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Parent class for preferences appearing on notification setting pages at the app,
|
||||
* notification channel group, or notification channel level.
|
||||
*/
|
||||
public abstract class NotificationPreferenceController extends AbstractPreferenceController
|
||||
{
|
||||
private static final String TAG = "ChannelPrefContr";
|
||||
@Nullable protected NotificationChannel mChannel;
|
||||
@Nullable protected NotificationChannelGroupWrapper mChannelGroup;
|
||||
protected RestrictedLockUtils.EnforcedAdmin mAdmin;
|
||||
protected NotificationBackend.AppRow mAppRow;
|
||||
protected final NotificationManager mNm;
|
||||
protected final NotificationBackend mBackend;
|
||||
protected final Context mContext;
|
||||
protected final UserManager mUm;
|
||||
protected final PackageManager mPm;
|
||||
protected Preference mPreference;
|
||||
|
||||
public NotificationPreferenceController(Context context, NotificationBackend backend) {
|
||||
super(context);
|
||||
mContext = context;
|
||||
mNm = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
mBackend = backend;
|
||||
mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
|
||||
mPm = mContext.getPackageManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if field's parent object is not blocked.
|
||||
*/
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
if (mAppRow == null) {
|
||||
return false;
|
||||
}
|
||||
if (mAppRow.banned) {
|
||||
return false;
|
||||
}
|
||||
if (mChannel != null) {
|
||||
return mChannel.getImportance() != IMPORTANCE_NONE;
|
||||
}
|
||||
if (mChannelGroup != null && mChannelGroup.getGroup() == null) {
|
||||
return !mChannelGroup.isBlocked();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays or removes preference in this controller.
|
||||
*/
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
if (isAvailable()) {
|
||||
final Preference preference = screen.findPreference(getPreferenceKey());
|
||||
if (mPreference != null && preference == null) {
|
||||
screen.addPreference(mPreference);
|
||||
}
|
||||
if (preference != null) {
|
||||
mPreference = preference;
|
||||
}
|
||||
if (this instanceof Preference.OnPreferenceChangeListener) {
|
||||
mPreference.setOnPreferenceChangeListener(
|
||||
(Preference.OnPreferenceChangeListener) this);
|
||||
}
|
||||
} else {
|
||||
findAndRemovePreference(screen, getPreferenceKey());
|
||||
}
|
||||
}
|
||||
|
||||
// finds the preference recursively and removes it from its parent
|
||||
private void findAndRemovePreference(PreferenceGroup prefGroup, String key) {
|
||||
final int preferenceCount = prefGroup.getPreferenceCount();
|
||||
for (int i = preferenceCount - 1; i >= 0; i--) {
|
||||
final Preference preference = prefGroup.getPreference(i);
|
||||
final String curKey = preference.getKey();
|
||||
|
||||
if (curKey != null && curKey.equals(key)) {
|
||||
mPreference = preference;
|
||||
prefGroup.removePreference(preference);
|
||||
}
|
||||
|
||||
if (preference instanceof PreferenceGroup) {
|
||||
findAndRemovePreference((PreferenceGroup) preference, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void onResume(NotificationBackend.AppRow appRow,
|
||||
@Nullable NotificationChannel channel, @Nullable NotificationChannelGroupWrapper group,
|
||||
RestrictedLockUtils.EnforcedAdmin admin) {
|
||||
mAppRow = appRow;
|
||||
mChannel = channel;
|
||||
mChannelGroup = group;
|
||||
mAdmin = admin;
|
||||
}
|
||||
|
||||
protected boolean checkCanBeVisible(int minImportanceVisible) {
|
||||
if (mChannel == null) {
|
||||
Log.w(TAG, "No channel");
|
||||
return false;
|
||||
}
|
||||
|
||||
int importance = mChannel.getImportance();
|
||||
if (importance == NotificationManager.IMPORTANCE_UNSPECIFIED) {
|
||||
return true;
|
||||
}
|
||||
return importance >= minImportanceVisible;
|
||||
}
|
||||
|
||||
protected void saveChannel() {
|
||||
if (mChannel != null && mAppRow != null) {
|
||||
mBackend.updateChannel(mAppRow.pkg, mAppRow.uid, mChannel);
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isChannelConfigurable() {
|
||||
if (mChannel != null && mAppRow != null) {
|
||||
return !Objects.equals(mChannel.getId(), mAppRow.lockedChannelId);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean isChannelBlockable() {
|
||||
if (mChannel != null && mAppRow != null) {
|
||||
if (!mAppRow.systemApp) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return mChannel.isBlockableSystem()
|
||||
|| mChannel.getImportance() == IMPORTANCE_NONE;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean isChannelGroupBlockable() {
|
||||
if (mChannelGroup != null && mChannelGroup.getGroup() == null && mAppRow != null) {
|
||||
if (!mAppRow.systemApp) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return mChannelGroup.isBlocked();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean hasValidGroup() {
|
||||
return mChannelGroup != null && mChannelGroup.getGroup() != null;
|
||||
}
|
||||
}
|
@@ -27,10 +27,15 @@ import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.applications.AppInfoBase;
|
||||
import com.android.settings.applications.LayoutPreference;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settings.search.Indexable;
|
||||
import com.android.settings.widget.MasterSwitchPreference;
|
||||
import com.android.settings.widget.SwitchBar;
|
||||
import com.android.settings.wrapper.NotificationChannelGroupWrapper;
|
||||
import com.android.settingslib.RestrictedLockUtils;
|
||||
import com.android.settingslib.RestrictedSwitchPreference;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.widget.FooterPreference;
|
||||
|
||||
import android.app.Notification;
|
||||
@@ -53,10 +58,12 @@ import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.provider.SearchIndexableResource;
|
||||
import android.provider.Settings;
|
||||
import android.service.notification.NotificationListenerService;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceGroup;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
import android.text.TextUtils;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
@@ -68,66 +75,30 @@ import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
abstract public class NotificationSettingsBase extends SettingsPreferenceFragment {
|
||||
abstract public class NotificationSettingsBase extends DashboardFragment {
|
||||
private static final String TAG = "NotifiSettingsBase";
|
||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||
|
||||
private static final Intent APP_NOTIFICATION_PREFS_CATEGORY_INTENT
|
||||
= new Intent(Intent.ACTION_MAIN)
|
||||
.addCategory(Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES);
|
||||
|
||||
protected static final int ORDER_FIRST = -500;
|
||||
protected static final int ORDER_LAST = 1000;
|
||||
|
||||
protected static final String KEY_APP_LINK = "app_link";
|
||||
protected static final String KEY_HEADER = "header";
|
||||
protected static final String KEY_BLOCK = "block";
|
||||
protected static final String KEY_BADGE = "badge";
|
||||
protected static final String KEY_BYPASS_DND = "bypass_dnd";
|
||||
protected static final String KEY_VISIBILITY_OVERRIDE = "visibility_override";
|
||||
protected static final String KEY_BLOCKED_DESC = "block_desc";
|
||||
protected static final String KEY_ALLOW_SOUND = "allow_sound";
|
||||
|
||||
protected PackageManager mPm;
|
||||
protected UserManager mUm;
|
||||
protected NotificationBackend mBackend = new NotificationBackend();
|
||||
protected LockPatternUtils mLockPatternUtils;
|
||||
protected NotificationManager mNm;
|
||||
protected Context mContext;
|
||||
protected boolean mCreated;
|
||||
|
||||
protected int mUid;
|
||||
protected int mUserId;
|
||||
protected String mPkg;
|
||||
protected PackageInfo mPkgInfo;
|
||||
protected RestrictedSwitchPreference mBadge;
|
||||
protected RestrictedSwitchPreference mPriority;
|
||||
protected RestrictedDropDownPreference mVisibilityOverride;
|
||||
protected RestrictedSwitchPreference mImportanceToggle;
|
||||
protected LayoutPreference mBlockBar;
|
||||
protected SwitchBar mSwitchBar;
|
||||
protected FooterPreference mBlockedDesc;
|
||||
protected Preference mAppLink;
|
||||
|
||||
protected EnforcedAdmin mSuspendedAppsAdmin;
|
||||
protected boolean mDndVisualEffectsSuppressed;
|
||||
|
||||
protected NotificationChannelGroup mChannelGroup;
|
||||
protected NotificationChannelGroupWrapper mChannelGroup;
|
||||
protected NotificationChannel mChannel;
|
||||
protected NotificationBackend.AppRow mAppRow;
|
||||
protected boolean mShowLegacyChannelConfig = false;
|
||||
|
||||
protected boolean mShowLegacyChannelConfig = false;
|
||||
protected boolean mListeningToPackageRemove;
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
if (DEBUG) Log.d(TAG, "onActivityCreated mCreated=" + mCreated);
|
||||
if (mCreated) {
|
||||
Log.w(TAG, "onActivityCreated: ignoring duplicate call");
|
||||
return;
|
||||
}
|
||||
mCreated = true;
|
||||
}
|
||||
protected List<NotificationPreferenceController> mControllers = new ArrayList<>();
|
||||
protected List<Preference> mDynamicPreferences = new ArrayList<>();
|
||||
protected ImportanceListener mImportanceListener = new ImportanceListener();
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
@@ -143,7 +114,6 @@ abstract public class NotificationSettingsBase extends SettingsPreferenceFragmen
|
||||
}
|
||||
|
||||
mPm = getPackageManager();
|
||||
mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
|
||||
mNm = NotificationManager.from(mContext);
|
||||
|
||||
mPkg = args != null && args.containsKey(AppInfoBase.ARG_PACKAGE_NAME)
|
||||
@@ -187,35 +157,41 @@ abstract public class NotificationSettingsBase extends SettingsPreferenceFragmen
|
||||
return;
|
||||
}
|
||||
mAppRow = mBackend.loadAppRow(mContext, mPm, mPkgInfo);
|
||||
if (mAppRow == null) {
|
||||
Log.w(TAG, "Can't load package");
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
collectConfigActivities();
|
||||
Bundle args = getArguments();
|
||||
mChannel = (args != null && args.containsKey(Settings.EXTRA_CHANNEL_ID)) ?
|
||||
mBackend.getChannel(mPkg, mUid, args.getString(Settings.EXTRA_CHANNEL_ID)) : null;
|
||||
|
||||
mChannelGroup = (args != null && args.containsKey(Settings.EXTRA_CHANNEL_GROUP_ID)) ?
|
||||
mBackend.getGroupWithChannels(mPkg, mUid,
|
||||
NotificationChannelGroup group =
|
||||
(args != null && args.containsKey(Settings.EXTRA_CHANNEL_GROUP_ID))
|
||||
? mBackend.getGroupWithChannels(mPkg, mUid,
|
||||
args.getString(Settings.EXTRA_CHANNEL_GROUP_ID))
|
||||
: null;
|
||||
: null;
|
||||
if (group != null) {
|
||||
mChannelGroup = new NotificationChannelGroupWrapper(group);
|
||||
}
|
||||
|
||||
mSuspendedAppsAdmin = RestrictedLockUtils.checkIfApplicationIsSuspended(
|
||||
mContext, mPkg, mUserId);
|
||||
NotificationManager.Policy policy = mNm.getNotificationPolicy();
|
||||
mDndVisualEffectsSuppressed = policy == null ? false : policy.suppressedVisualEffects != 0;
|
||||
|
||||
mSuspendedAppsAdmin = RestrictedLockUtils.checkIfApplicationIsSuspended(
|
||||
mContext, mPkg, mUserId);
|
||||
}
|
||||
mShowLegacyChannelConfig = mBackend.onlyHasDefaultChannel(mAppRow.pkg, mAppRow.uid)
|
||||
|| (mChannel != null
|
||||
&& NotificationChannel.DEFAULT_CHANNEL_ID.equals(mChannel.getId()));
|
||||
|
||||
protected void setVisible(Preference p, boolean visible) {
|
||||
setVisible(getPreferenceScreen(), p, visible);
|
||||
}
|
||||
|
||||
protected void setVisible(PreferenceGroup parent, Preference p, boolean visible) {
|
||||
final boolean isVisible = parent.findPreference(p.getKey()) != null;
|
||||
if (isVisible == visible) return;
|
||||
if (visible) {
|
||||
parent.addPreference(p);
|
||||
} else {
|
||||
parent.removePreference(p);
|
||||
if (mShowLegacyChannelConfig) {
|
||||
mChannel = mBackend.getChannel(
|
||||
mAppRow.pkg, mAppRow.uid, NotificationChannel.DEFAULT_CHANNEL_ID);
|
||||
}
|
||||
if (mChannel != null && !TextUtils.isEmpty(mChannel.getGroup())) {
|
||||
group = mBackend.getGroup(mPkg, mUid, mChannel.getGroup());
|
||||
if (group != null) {
|
||||
mChannelGroup = new NotificationChannelGroupWrapper(group);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,49 +200,34 @@ abstract public class NotificationSettingsBase extends SettingsPreferenceFragmen
|
||||
getActivity().finish();
|
||||
}
|
||||
|
||||
private List<ResolveInfo> queryNotificationConfigActivities() {
|
||||
if (DEBUG) Log.d(TAG, "APP_NOTIFICATION_PREFS_CATEGORY_INTENT is "
|
||||
+ APP_NOTIFICATION_PREFS_CATEGORY_INTENT);
|
||||
protected void collectConfigActivities() {
|
||||
Intent intent = new Intent(Intent.ACTION_MAIN)
|
||||
.addCategory(Notification.INTENT_CATEGORY_NOTIFICATION_PREFERENCES)
|
||||
.setPackage(mAppRow.pkg);
|
||||
final List<ResolveInfo> resolveInfos = mPm.queryIntentActivities(
|
||||
APP_NOTIFICATION_PREFS_CATEGORY_INTENT,
|
||||
intent,
|
||||
0 //PackageManager.MATCH_DEFAULT_ONLY
|
||||
);
|
||||
return resolveInfos;
|
||||
}
|
||||
|
||||
protected void collectConfigActivities(ArrayMap<String, NotificationBackend.AppRow> rows) {
|
||||
final List<ResolveInfo> resolveInfos = queryNotificationConfigActivities();
|
||||
applyConfigActivities(rows, resolveInfos);
|
||||
}
|
||||
|
||||
private void applyConfigActivities(ArrayMap<String, NotificationBackend.AppRow> rows,
|
||||
List<ResolveInfo> resolveInfos) {
|
||||
if (DEBUG) Log.d(TAG, "Found " + resolveInfos.size() + " preference activities"
|
||||
+ (resolveInfos.size() == 0 ? " ;_;" : ""));
|
||||
for (ResolveInfo ri : resolveInfos) {
|
||||
final ActivityInfo activityInfo = ri.activityInfo;
|
||||
final ApplicationInfo appInfo = activityInfo.applicationInfo;
|
||||
final NotificationBackend.AppRow row = rows.get(appInfo.packageName);
|
||||
if (row == null) {
|
||||
if (DEBUG) Log.v(TAG, "Ignoring notification preference activity ("
|
||||
+ activityInfo.name + ") for unknown package "
|
||||
+ activityInfo.packageName);
|
||||
continue;
|
||||
}
|
||||
if (row.settingsIntent != null) {
|
||||
if (mAppRow.settingsIntent != null) {
|
||||
if (DEBUG) Log.v(TAG, "Ignoring duplicate notification preference activity ("
|
||||
+ activityInfo.name + ") for package "
|
||||
+ activityInfo.packageName);
|
||||
continue;
|
||||
}
|
||||
row.settingsIntent = new Intent(APP_NOTIFICATION_PREFS_CATEGORY_INTENT)
|
||||
mAppRow.settingsIntent = intent
|
||||
.setPackage(null)
|
||||
.setClassName(activityInfo.packageName, activityInfo.name);
|
||||
if (mChannel != null) {
|
||||
row.settingsIntent.putExtra(Notification.EXTRA_CHANNEL_ID, mChannel.getId());
|
||||
mAppRow.settingsIntent.putExtra(Notification.EXTRA_CHANNEL_ID, mChannel.getId());
|
||||
}
|
||||
if (mChannelGroup != null) {
|
||||
row.settingsIntent.putExtra(
|
||||
Notification.EXTRA_CHANNEL_GROUP_ID, mChannelGroup.getId());
|
||||
mAppRow.settingsIntent.putExtra(
|
||||
Notification.EXTRA_CHANNEL_GROUP_ID, mChannelGroup.getGroup().getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -292,134 +253,6 @@ abstract public class NotificationSettingsBase extends SettingsPreferenceFragmen
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void addAppLinkPref() {
|
||||
if (mAppRow.settingsIntent != null && mAppLink == null) {
|
||||
addPreferencesFromResource(R.xml.inapp_notification_settings);
|
||||
mAppLink = findPreference(KEY_APP_LINK);
|
||||
mAppLink.setIntent(mAppRow.settingsIntent);
|
||||
}
|
||||
}
|
||||
|
||||
protected void populateDefaultChannelPrefs() {
|
||||
if (mPkgInfo != null && mChannel != null) {
|
||||
addPreferencesFromResource(R.xml.legacy_channel_notification_settings);
|
||||
setupPriorityPref(mChannel.canBypassDnd());
|
||||
setupVisOverridePref(mChannel.getLockscreenVisibility());
|
||||
setupImportanceToggle();
|
||||
setupBadge();
|
||||
}
|
||||
mSwitchBar.setChecked(!mAppRow.banned
|
||||
&& mChannel.getImportance() != NotificationManager.IMPORTANCE_NONE);
|
||||
}
|
||||
|
||||
abstract void setupBadge();
|
||||
|
||||
abstract void updateDependents(boolean banned);
|
||||
|
||||
// 'allow sound'
|
||||
private void setupImportanceToggle() {
|
||||
mImportanceToggle = (RestrictedSwitchPreference) findPreference(KEY_ALLOW_SOUND);
|
||||
mImportanceToggle.setDisabledByAdmin(mSuspendedAppsAdmin);
|
||||
mImportanceToggle.setEnabled(isChannelConfigurable(mChannel)
|
||||
&& !mImportanceToggle.isDisabledByAdmin());
|
||||
mImportanceToggle.setChecked(mChannel.getImportance() >= IMPORTANCE_DEFAULT
|
||||
|| mChannel.getImportance() == IMPORTANCE_UNSPECIFIED);
|
||||
mImportanceToggle.setOnPreferenceChangeListener(
|
||||
new Preference.OnPreferenceChangeListener() {
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
final int importance =
|
||||
((Boolean) newValue ? IMPORTANCE_UNSPECIFIED : IMPORTANCE_LOW);
|
||||
mChannel.setImportance(importance);
|
||||
mChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
|
||||
mBackend.updateChannel(mPkg, mUid, mChannel);
|
||||
updateDependents(mChannel.getImportance() == IMPORTANCE_NONE);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void setupPriorityPref(boolean priority) {
|
||||
mPriority = (RestrictedSwitchPreference) findPreference(KEY_BYPASS_DND);
|
||||
mPriority.setDisabledByAdmin(mSuspendedAppsAdmin);
|
||||
mPriority.setEnabled(isChannelConfigurable(mChannel) && !mPriority.isDisabledByAdmin());
|
||||
mPriority.setChecked(priority);
|
||||
mPriority.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
final boolean bypassZenMode = (Boolean) newValue;
|
||||
mChannel.setBypassDnd(bypassZenMode);
|
||||
mChannel.lockFields(NotificationChannel.USER_LOCKED_PRIORITY);
|
||||
mBackend.updateChannel(mPkg, mUid, mChannel);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void setupVisOverridePref(int sensitive) {
|
||||
mVisibilityOverride =
|
||||
(RestrictedDropDownPreference) findPreference(KEY_VISIBILITY_OVERRIDE);
|
||||
ArrayList<CharSequence> entries = new ArrayList<>();
|
||||
ArrayList<CharSequence> values = new ArrayList<>();
|
||||
|
||||
mVisibilityOverride.clearRestrictedItems();
|
||||
if (getLockscreenNotificationsEnabled() && getLockscreenAllowPrivateNotifications()) {
|
||||
final String summaryShowEntry =
|
||||
getString(R.string.lock_screen_notifications_summary_show);
|
||||
final String summaryShowEntryValue =
|
||||
Integer.toString(NotificationManager.VISIBILITY_NO_OVERRIDE);
|
||||
entries.add(summaryShowEntry);
|
||||
values.add(summaryShowEntryValue);
|
||||
setRestrictedIfNotificationFeaturesDisabled(summaryShowEntry, summaryShowEntryValue,
|
||||
DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS
|
||||
| DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS);
|
||||
}
|
||||
|
||||
final String summaryHideEntry = getString(R.string.lock_screen_notifications_summary_hide);
|
||||
final String summaryHideEntryValue = Integer.toString(Notification.VISIBILITY_PRIVATE);
|
||||
entries.add(summaryHideEntry);
|
||||
values.add(summaryHideEntryValue);
|
||||
setRestrictedIfNotificationFeaturesDisabled(summaryHideEntry, summaryHideEntryValue,
|
||||
DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS);
|
||||
entries.add(getString(R.string.lock_screen_notifications_summary_disable));
|
||||
values.add(Integer.toString(Notification.VISIBILITY_SECRET));
|
||||
mVisibilityOverride.setEntries(entries.toArray(new CharSequence[entries.size()]));
|
||||
mVisibilityOverride.setEntryValues(values.toArray(new CharSequence[values.size()]));
|
||||
|
||||
if (sensitive == NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE) {
|
||||
mVisibilityOverride.setValue(Integer.toString(getGlobalVisibility()));
|
||||
} else {
|
||||
mVisibilityOverride.setValue(Integer.toString(sensitive));
|
||||
}
|
||||
mVisibilityOverride.setSummary("%s");
|
||||
|
||||
mVisibilityOverride.setOnPreferenceChangeListener(
|
||||
new Preference.OnPreferenceChangeListener() {
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
int sensitive = Integer.parseInt((String) newValue);
|
||||
if (sensitive == getGlobalVisibility()) {
|
||||
sensitive = NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE;
|
||||
}
|
||||
mChannel.setLockscreenVisibility(sensitive);
|
||||
mChannel.lockFields(NotificationChannel.USER_LOCKED_VISIBILITY);
|
||||
mBackend.updateChannel(mPkg, mUid, mChannel);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
mVisibilityOverride.setDisabledByAdmin(mSuspendedAppsAdmin);
|
||||
}
|
||||
|
||||
protected void setupBlockDesc(int summaryResId) {
|
||||
mBlockedDesc = new FooterPreference(getPrefContext());
|
||||
mBlockedDesc.setSelectable(false);
|
||||
mBlockedDesc.setTitle(summaryResId);
|
||||
mBlockedDesc.setEnabled(false);
|
||||
mBlockedDesc.setOrder(50);
|
||||
mBlockedDesc.setKey(KEY_BLOCKED_DESC);
|
||||
getPreferenceScreen().addPreference(mBlockedDesc);
|
||||
}
|
||||
|
||||
protected Preference populateSingleChannelPrefs(PreferenceGroup parent,
|
||||
final NotificationChannel channel, String summary) {
|
||||
MasterSwitchPreference channelPref = new MasterSwitchPreference(
|
||||
@@ -461,105 +294,48 @@ abstract public class NotificationSettingsBase extends SettingsPreferenceFragmen
|
||||
return channelPref;
|
||||
}
|
||||
|
||||
protected boolean checkCanBeVisible(int minImportanceVisible) {
|
||||
int importance = mChannel.getImportance();
|
||||
if (importance == NotificationManager.IMPORTANCE_UNSPECIFIED) {
|
||||
return true;
|
||||
}
|
||||
return importance >= minImportanceVisible;
|
||||
}
|
||||
|
||||
protected String getImportanceSummary(NotificationChannel channel) {
|
||||
switch (channel.getImportance()) {
|
||||
case NotificationManager.IMPORTANCE_UNSPECIFIED:
|
||||
return getContext().getString(R.string.notification_importance_unspecified);
|
||||
case NotificationManager.IMPORTANCE_NONE:
|
||||
return getContext().getString(R.string.notification_toggle_off);
|
||||
case NotificationManager.IMPORTANCE_MIN:
|
||||
return getContext().getString(R.string.notification_importance_min);
|
||||
case NotificationManager.IMPORTANCE_LOW:
|
||||
return getContext().getString(R.string.notification_importance_low);
|
||||
case NotificationManager.IMPORTANCE_DEFAULT:
|
||||
if (hasValidSound(channel)) {
|
||||
return getContext().getString(R.string.notification_importance_default);
|
||||
} else { // Silent
|
||||
return getContext().getString(R.string.notification_importance_low);
|
||||
}
|
||||
case NotificationManager.IMPORTANCE_HIGH:
|
||||
case NotificationManager.IMPORTANCE_MAX:
|
||||
default:
|
||||
if (hasValidSound(channel)) {
|
||||
return getContext().getString(R.string.notification_importance_high);
|
||||
} else { // Silent
|
||||
return getContext().getString(R.string.notification_importance_high_silent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setRestrictedIfNotificationFeaturesDisabled(CharSequence entry,
|
||||
CharSequence entryValue, int keyguardNotificationFeatures) {
|
||||
RestrictedLockUtils.EnforcedAdmin admin =
|
||||
RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
|
||||
mContext, keyguardNotificationFeatures, mUserId);
|
||||
if (admin != null) {
|
||||
RestrictedDropDownPreference.RestrictedItem item =
|
||||
new RestrictedDropDownPreference.RestrictedItem(entry, entryValue, admin);
|
||||
mVisibilityOverride.addRestrictedItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
private int getGlobalVisibility() {
|
||||
int globalVis = NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE;
|
||||
if (!getLockscreenNotificationsEnabled()) {
|
||||
globalVis = Notification.VISIBILITY_SECRET;
|
||||
} else if (!getLockscreenAllowPrivateNotifications()) {
|
||||
globalVis = Notification.VISIBILITY_PRIVATE;
|
||||
}
|
||||
return globalVis;
|
||||
}
|
||||
|
||||
private boolean getLockscreenNotificationsEnabled() {
|
||||
return Settings.Secure.getInt(getContentResolver(),
|
||||
Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0) != 0;
|
||||
}
|
||||
|
||||
private boolean getLockscreenAllowPrivateNotifications() {
|
||||
return Settings.Secure.getInt(getContentResolver(),
|
||||
Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0) != 0;
|
||||
}
|
||||
|
||||
protected boolean isLockScreenSecure() {
|
||||
if (mLockPatternUtils == null) {
|
||||
mLockPatternUtils = new LockPatternUtils(getActivity());
|
||||
}
|
||||
boolean lockscreenSecure = mLockPatternUtils.isSecure(UserHandle.myUserId());
|
||||
UserInfo parentUser = mUm.getProfileParent(UserHandle.myUserId());
|
||||
if (parentUser != null){
|
||||
lockscreenSecure |= mLockPatternUtils.isSecure(parentUser.id);
|
||||
}
|
||||
|
||||
return lockscreenSecure;
|
||||
}
|
||||
|
||||
protected boolean isChannelConfigurable(NotificationChannel channel) {
|
||||
return !channel.getId().equals(mAppRow.lockedChannelId);
|
||||
if (channel != null && mAppRow != null) {
|
||||
return !channel.getId().equals(mAppRow.lockedChannelId);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean isChannelBlockable(NotificationChannel channel) {
|
||||
if (!mAppRow.systemApp) {
|
||||
return true;
|
||||
}
|
||||
if (channel != null && mAppRow != null) {
|
||||
if (!mAppRow.systemApp) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return channel.isBlockableSystem()
|
||||
|| channel.getImportance() == NotificationManager.IMPORTANCE_NONE;
|
||||
return channel.isBlockableSystem()
|
||||
|| channel.getImportance() == NotificationManager.IMPORTANCE_NONE;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean isChannelGroupBlockable(NotificationChannelGroup group) {
|
||||
if (!mAppRow.systemApp) {
|
||||
return true;
|
||||
}
|
||||
if (group != null && mAppRow != null) {
|
||||
if (!mAppRow.systemApp) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return group.isBlocked();
|
||||
return group.isBlocked();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void setVisible(Preference p, boolean visible) {
|
||||
setVisible(getPreferenceScreen(), p, visible);
|
||||
}
|
||||
|
||||
protected void setVisible(PreferenceGroup parent, Preference p, boolean visible) {
|
||||
final boolean isVisible = parent.findPreference(p.getKey()) != null;
|
||||
if (isVisible == visible) return;
|
||||
if (visible) {
|
||||
parent.addPreference(p);
|
||||
} else {
|
||||
parent.removePreference(p);
|
||||
}
|
||||
}
|
||||
|
||||
protected void startListeningToPackageRemove() {
|
||||
@@ -604,7 +380,45 @@ abstract public class NotificationSettingsBase extends SettingsPreferenceFragmen
|
||||
return left.getId().compareTo(right.getId());
|
||||
};
|
||||
|
||||
boolean hasValidSound(NotificationChannel channel) {
|
||||
return channel.getSound() != null && !Uri.EMPTY.equals(channel.getSound());
|
||||
/**
|
||||
* These screens aren't searchable - they only make sense in the context of an app, so
|
||||
* surfacing a generic version would be impossible.
|
||||
*/
|
||||
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider() {
|
||||
@Override
|
||||
public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
|
||||
boolean enabled) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AbstractPreferenceController> getPreferenceControllers(Context context) {
|
||||
return getPreferenceControllers(context);
|
||||
}
|
||||
};
|
||||
|
||||
protected class ImportanceListener {
|
||||
protected void onImportanceChanged() {
|
||||
final PreferenceScreen screen = getPreferenceScreen();
|
||||
for (NotificationPreferenceController controller : mControllers) {
|
||||
controller.displayPreference(screen);
|
||||
}
|
||||
updatePreferenceStates();
|
||||
|
||||
boolean hideDynamicFields = false;
|
||||
if (mAppRow == null || mAppRow.banned) {
|
||||
hideDynamicFields = true;
|
||||
} else {
|
||||
if (mChannel != null) {
|
||||
hideDynamicFields = mChannel.getImportance() == IMPORTANCE_NONE;
|
||||
} else if (mChannelGroup != null) {
|
||||
hideDynamicFields = mChannelGroup.isBlocked();
|
||||
}
|
||||
}
|
||||
for (Preference preference : mDynamicPreferences) {
|
||||
setVisible(getPreferenceScreen(), preference, !hideDynamicFields);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.content.Context;
|
||||
import android.support.v7.preference.Preference;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settingslib.widget.FooterPreference;
|
||||
|
||||
public class NotificationsOffPreferenceController extends NotificationPreferenceController
|
||||
implements PreferenceControllerMixin {
|
||||
|
||||
private static final String KEY_BLOCKED_DESC = "block_desc";
|
||||
|
||||
public NotificationsOffPreferenceController(Context context) {
|
||||
super(context, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return KEY_BLOCKED_DESC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
if (mAppRow == null) {
|
||||
return false;
|
||||
}
|
||||
// Available only when other controllers are unavailable - this UI replaces the UI that
|
||||
// would give more detailed notification controls.
|
||||
return !super.isAvailable();
|
||||
}
|
||||
|
||||
public void updateState(Preference preference) {
|
||||
if (mAppRow != null) {
|
||||
if (mChannel != null) {
|
||||
preference.setTitle(R.string.channel_notifications_off_desc);
|
||||
} else if (mChannelGroup != null && mChannelGroup.getGroup() == null) {
|
||||
preference.setTitle(R.string.channel_group_notifications_off_desc);
|
||||
} else {
|
||||
preference.setTitle(R.string.app_notifications_off_desc);
|
||||
}
|
||||
}
|
||||
preference.setEnabled(false);
|
||||
preference.setSelectable(false);
|
||||
}
|
||||
}
|
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.SettingsPreferenceFragment;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
|
||||
public class SoundPreferenceController extends NotificationPreferenceController
|
||||
implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener,
|
||||
PreferenceManager.OnActivityResultListener {
|
||||
|
||||
private static final String KEY_SOUND = "ringtone";
|
||||
private final SettingsPreferenceFragment mFragment;
|
||||
private final NotificationSettingsBase.ImportanceListener mListener;
|
||||
private NotificationSoundPreference mPreference;
|
||||
protected static final int CODE = 200;
|
||||
|
||||
public SoundPreferenceController(Context context, SettingsPreferenceFragment hostFragment,
|
||||
NotificationSettingsBase.ImportanceListener importanceListener,
|
||||
NotificationBackend backend) {
|
||||
super(context, backend);
|
||||
mFragment = hostFragment;
|
||||
mListener = importanceListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return KEY_SOUND;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
if (!super.isAvailable()) {
|
||||
return false;
|
||||
}
|
||||
if (mChannel == null) {
|
||||
return false;
|
||||
}
|
||||
return checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT)
|
||||
&& !NotificationChannel.DEFAULT_CHANNEL_ID.equals(mChannel.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
|
||||
mPreference = (NotificationSoundPreference) screen.findPreference(getPreferenceKey());
|
||||
}
|
||||
|
||||
public void updateState(Preference preference) {
|
||||
if (mAppRow!= null && mChannel != null) {
|
||||
NotificationSoundPreference pref = (NotificationSoundPreference) preference;
|
||||
pref.setEnabled(mAdmin == null && isChannelConfigurable());
|
||||
pref.setRingtone(mChannel.getSound());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
if (mChannel != null) {
|
||||
mChannel.setSound((Uri) newValue, mChannel.getAudioAttributes());
|
||||
saveChannel();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handlePreferenceTreeClick(Preference preference) {
|
||||
if (KEY_SOUND.equals(preference.getKey()) && mFragment != null) {
|
||||
NotificationSoundPreference pref = (NotificationSoundPreference) preference;
|
||||
pref.onPrepareRingtonePickerIntent(pref.getIntent());
|
||||
mFragment.startActivityForResult(preference.getIntent(), CODE);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
if (CODE == requestCode) {
|
||||
if (mPreference != null) {
|
||||
mPreference.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
// the importance hasn't changed, but the importance description might as a result of
|
||||
// user's selection.
|
||||
mListener.onImportanceChanged();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected static boolean hasValidSound(NotificationChannel channel) {
|
||||
return channel != null
|
||||
&& channel.getSound() != null && !Uri.EMPTY.equals(channel.getSound());
|
||||
}
|
||||
}
|
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.os.Vibrator;
|
||||
import android.support.v7.preference.Preference;
|
||||
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settingslib.RestrictedSwitchPreference;
|
||||
|
||||
public class VibrationPreferenceController extends NotificationPreferenceController
|
||||
implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener {
|
||||
|
||||
private static final String KEY_VIBRATE = "vibrate";
|
||||
private final Vibrator mVibrator;
|
||||
|
||||
public VibrationPreferenceController(Context context, NotificationBackend backend) {
|
||||
super(context, backend);
|
||||
mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return KEY_VIBRATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
if (!super.isAvailable() || mChannel == null) {
|
||||
return false;
|
||||
}
|
||||
return checkCanBeVisible(NotificationManager.IMPORTANCE_DEFAULT)
|
||||
&& !NotificationChannel.DEFAULT_CHANNEL_ID.equals(mChannel.getId())
|
||||
&& mVibrator != null
|
||||
&& mVibrator.hasVibrator();
|
||||
}
|
||||
|
||||
public void updateState(Preference preference) {
|
||||
if (mChannel != null) {
|
||||
RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference;
|
||||
pref.setDisabledByAdmin(mAdmin);
|
||||
pref.setEnabled(!pref.isDisabledByAdmin() && isChannelConfigurable());
|
||||
pref.setChecked(mChannel.shouldVibrate());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
if (mChannel != null) {
|
||||
final boolean vibrate = (Boolean) newValue;
|
||||
mChannel.enableVibration(vibrate);
|
||||
saveChannel();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.Notification;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.content.Context;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.service.notification.NotificationListenerService;
|
||||
import android.support.v7.preference.Preference;
|
||||
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settingslib.RestrictedLockUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class VisibilityPreferenceController extends NotificationPreferenceController
|
||||
implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener {
|
||||
|
||||
private static final String TAG = "ChannelVisPrefContr";
|
||||
private static final String KEY_VISIBILITY_OVERRIDE = "visibility_override";
|
||||
private LockPatternUtils mLockPatternUtils;
|
||||
|
||||
public VisibilityPreferenceController(Context context, LockPatternUtils utils,
|
||||
NotificationBackend backend) {
|
||||
super(context, backend);
|
||||
mLockPatternUtils = utils;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return KEY_VISIBILITY_OVERRIDE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
if (!super.isAvailable()) {
|
||||
return false;
|
||||
}
|
||||
if (mChannel == null || mAppRow.banned) {
|
||||
return false;
|
||||
}
|
||||
return checkCanBeVisible(NotificationManager.IMPORTANCE_LOW) && isLockScreenSecure();
|
||||
}
|
||||
|
||||
public void updateState(Preference preference) {
|
||||
if (mChannel != null && mAppRow != null) {
|
||||
RestrictedDropDownPreference pref = (RestrictedDropDownPreference) preference;
|
||||
ArrayList<CharSequence> entries = new ArrayList<>();
|
||||
ArrayList<CharSequence> values = new ArrayList<>();
|
||||
|
||||
pref.clearRestrictedItems();
|
||||
if (getLockscreenNotificationsEnabled() && getLockscreenAllowPrivateNotifications()) {
|
||||
final String summaryShowEntry =
|
||||
mContext.getString(R.string.lock_screen_notifications_summary_show);
|
||||
final String summaryShowEntryValue =
|
||||
Integer.toString(NotificationManager.VISIBILITY_NO_OVERRIDE);
|
||||
entries.add(summaryShowEntry);
|
||||
values.add(summaryShowEntryValue);
|
||||
setRestrictedIfNotificationFeaturesDisabled(pref, summaryShowEntry,
|
||||
summaryShowEntryValue,
|
||||
DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS
|
||||
| DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS);
|
||||
}
|
||||
|
||||
final String summaryHideEntry =
|
||||
mContext.getString(R.string.lock_screen_notifications_summary_hide);
|
||||
final String summaryHideEntryValue = Integer.toString(Notification.VISIBILITY_PRIVATE);
|
||||
entries.add(summaryHideEntry);
|
||||
values.add(summaryHideEntryValue);
|
||||
setRestrictedIfNotificationFeaturesDisabled(pref,
|
||||
summaryHideEntry, summaryHideEntryValue,
|
||||
DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS);
|
||||
entries.add(mContext.getString(R.string.lock_screen_notifications_summary_disable));
|
||||
values.add(Integer.toString(Notification.VISIBILITY_SECRET));
|
||||
pref.setEntries(entries.toArray(new CharSequence[entries.size()]));
|
||||
pref.setEntryValues(values.toArray(new CharSequence[values.size()]));
|
||||
|
||||
if (mChannel.getLockscreenVisibility()
|
||||
== NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE) {
|
||||
pref.setValue(Integer.toString(getGlobalVisibility()));
|
||||
} else {
|
||||
pref.setValue(Integer.toString(mChannel.getLockscreenVisibility()));
|
||||
}
|
||||
pref.setSummary("%s");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
if (mChannel != null) {
|
||||
int sensitive = Integer.parseInt((String) newValue);
|
||||
if (sensitive == getGlobalVisibility()) {
|
||||
sensitive = NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE;
|
||||
}
|
||||
mChannel.setLockscreenVisibility(sensitive);
|
||||
mChannel.lockFields(NotificationChannel.USER_LOCKED_VISIBILITY);
|
||||
saveChannel();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void setRestrictedIfNotificationFeaturesDisabled(RestrictedDropDownPreference pref,
|
||||
CharSequence entry, CharSequence entryValue, int keyguardNotificationFeatures) {
|
||||
RestrictedLockUtils.EnforcedAdmin admin =
|
||||
RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
|
||||
mContext, keyguardNotificationFeatures, mAppRow.userId);
|
||||
if (admin != null) {
|
||||
RestrictedDropDownPreference.RestrictedItem item =
|
||||
new RestrictedDropDownPreference.RestrictedItem(entry, entryValue, admin);
|
||||
pref.addRestrictedItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
private int getGlobalVisibility() {
|
||||
int globalVis = NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE;
|
||||
if (!getLockscreenNotificationsEnabled()) {
|
||||
globalVis = Notification.VISIBILITY_SECRET;
|
||||
} else if (!getLockscreenAllowPrivateNotifications()) {
|
||||
globalVis = Notification.VISIBILITY_PRIVATE;
|
||||
}
|
||||
return globalVis;
|
||||
}
|
||||
|
||||
private boolean getLockscreenNotificationsEnabled() {
|
||||
return Settings.Secure.getInt(mContext.getContentResolver(),
|
||||
Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0) != 0;
|
||||
}
|
||||
|
||||
private boolean getLockscreenAllowPrivateNotifications() {
|
||||
return Settings.Secure.getInt(mContext.getContentResolver(),
|
||||
Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0) != 0;
|
||||
}
|
||||
|
||||
protected boolean isLockScreenSecure() {
|
||||
boolean lockscreenSecure = mLockPatternUtils.isSecure(UserHandle.myUserId());
|
||||
UserInfo parentUser = mUm.getProfileParent(UserHandle.myUserId());
|
||||
if (parentUser != null){
|
||||
lockscreenSecure |= mLockPatternUtils.isSecure(parentUser.id);
|
||||
}
|
||||
|
||||
return lockscreenSecure;
|
||||
}
|
||||
|
||||
}
|
@@ -67,7 +67,10 @@ import com.android.settings.location.LocationSettings;
|
||||
import com.android.settings.location.ScanningSettings;
|
||||
import com.android.settings.network.NetworkDashboardFragment;
|
||||
import com.android.settings.nfc.PaymentSettings;
|
||||
import com.android.settings.notification.AppNotificationSettings;
|
||||
import com.android.settings.notification.ChannelGroupNotificationSettings;
|
||||
import com.android.settings.notification.ChannelImportanceSettings;
|
||||
import com.android.settings.notification.ChannelNotificationSettings;
|
||||
import com.android.settings.notification.ConfigureNotificationSettings;
|
||||
import com.android.settings.notification.SoundSettings;
|
||||
import com.android.settings.notification.ZenModeAutomationSettings;
|
||||
@@ -173,6 +176,10 @@ public final class SearchIndexableResources {
|
||||
addIndex(LockscreenDashboardFragment.class);
|
||||
addIndex(ZenModeBehaviorSettings.class);
|
||||
addIndex(ZenModeAutomationSettings.class);
|
||||
addIndex(AppNotificationSettings.class);
|
||||
addIndex(ChannelNotificationSettings.class);
|
||||
addIndex(ChannelImportanceSettings.class);
|
||||
addIndex(ChannelGroupNotificationSettings.class);
|
||||
}
|
||||
|
||||
private SearchIndexableResources() {
|
||||
|
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2017 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.wrapper;
|
||||
|
||||
import android.app.NotificationChannelGroup;
|
||||
|
||||
/**
|
||||
* Wrapper for {@link NotificationChannelGroup} until roboletric supports O MR1.
|
||||
*/
|
||||
public class NotificationChannelGroupWrapper {
|
||||
|
||||
private final NotificationChannelGroup mGroup;
|
||||
|
||||
public NotificationChannelGroupWrapper(NotificationChannelGroup group) {
|
||||
mGroup = group;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the real group object so we can call APIs directly on it.
|
||||
*/
|
||||
public NotificationChannelGroup getGroup() {
|
||||
return mGroup;
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
if (mGroup != null) {
|
||||
return mGroup.getDescription();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setDescription(String desc) {
|
||||
if (mGroup != null) {
|
||||
mGroup.setDescription(desc);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isBlocked() {
|
||||
if (mGroup != null) {
|
||||
return mGroup.isBlocked();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setBlocked(boolean blocked) {
|
||||
if (mGroup != null) {
|
||||
mGroup.setBlocked(blocked);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user