android:value="com.android.settings.notification.AppNotificationSettings" />
</activity>
- <!-- Show channel group-level notification settings (group passed in as extras) -->
- <activity android:name="Settings$ChannelGroupNotificationSettingsActivity"
- android:exported="true">
- <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
- android:value="com.android.settings.notification.ChannelGroupNotificationSettings" />
- </activity>
-
<!-- Show channel-level notification settings (channel passed in as extras) -->
<activity android:name="Settings$ChannelNotificationSettingsActivity"
android:label="@string/notification_channel_title"
<activity
android:name=".wifi.NetworkRequestDialogActivity"
- android:theme="@style/Transparent"
+ android:theme="@style/Theme.AlertDialog"
android:excludeFromRecents="true"
android:launchMode="singleTop"
android:taskAffinity=".wifi.NetworkRequestDialogActivity"
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 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.
+ -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:visibility="gone"/>
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/wifi_item_spinner"
- android:prompt="@string/wifi_eap_method"
- android:entries="@array/wifi_eap_method" />
+ android:prompt="@string/wifi_eap_method" />
</LinearLayout>
<LinearLayout android:id="@+id/l_phase2"
<item msgid="485564189219029300">"啟用 VPN"</item>
<item msgid="7155384795265164395">"寫入桌布"</item>
<item msgid="1835836196806147034">"輔助結構"</item>
- <item msgid="5989890403088155055">"è¼\94å\8a©è\9e¢å¹\95æ\93·å\8f\96ç\95«é\9d¢"</item>
+ <item msgid="5989890403088155055">"è¼\94å\8a©è\9e¢å¹\95æ\88ªå\9c\96"</item>
<item msgid="8582699692765917557">"讀取手機狀態"</item>
<item msgid="1474039653814954902">"新增語音留言"</item>
<item msgid="7222837656938871633">"使用 SIP"</item>
<item msgid="6093344633066170692">"讀取日曆"</item>
<item msgid="1334886368750347692">"修改日曆"</item>
<item msgid="1638204101698708656">"位置"</item>
- <item msgid="2154671955760380322">"發佈通知"</item>
+ <item msgid="2154671955760380322">"發布通知"</item>
<item msgid="4282477730595931828">"位置"</item>
<item msgid="4891423912898525905">"撥打電話"</item>
<item msgid="2623604824935968113">"讀取簡訊/MMS"</item>
<item msgid="2482631530338029480">"啟用 VPN"</item>
<item msgid="1662979573471871926">"寫入桌布"</item>
<item msgid="5964768335278263478">"輔助結構"</item>
- <item msgid="2657138701132782702">"è¼\94å\8a©è\9e¢å¹\95æ\93·å\8f\96ç\95«é\9d¢"</item>
+ <item msgid="2657138701132782702">"è¼\94å\8a©è\9e¢å¹\95æ\88ªå\9c\96"</item>
<item msgid="8571369610363539266">"讀取手機狀態"</item>
<item msgid="4542463358215230845">"新增語音留言"</item>
<item msgid="864565065016166003">"使用 SIP"</item>
android:key="block_desc" />
<!-- Channels/Channel groups added here -->
+ <PreferenceCategory
+ android:key="channels"
+ android:layout="@layout/empty_view"
+ settings:allowDividerAbove="false"
+ settings:allowDividerBelow="false" />
<!-- Importance toggle -->
<com.android.settingslib.RestrictedSwitchPreference
import com.android.settings.nfc.PaymentSettings;
import com.android.settings.notification.AppBubbleNotificationSettings;
import com.android.settings.notification.AppNotificationSettings;
-import com.android.settings.notification.ChannelGroupNotificationSettings;
import com.android.settings.notification.ChannelNotificationSettings;
import com.android.settings.notification.ConfigureNotificationSettings;
import com.android.settings.notification.NotificationAccessSettings;
AppNotificationSettings.class.getName(),
NotificationAssistantPicker.class.getName(),
ChannelNotificationSettings.class.getName(),
- ChannelGroupNotificationSettings.class.getName(),
ApnSettings.class.getName(),
ApnEditor.class.getName(),
WifiCallingSettings.class.getName(),
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
+import android.provider.Settings;
import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice;
return null;
}
- // Display the contextual card only if all the following 3 conditions hold:
- // 1. The Screen Attention is enabled in Settings.
+ // Display the contextual card only if all the following 4 conditions hold:
+ // 1. The Screen Attention is available in Settings.
// 2. The device is not recently set up.
// 3. Current user hasn't opened Screen Attention's settings page before.
- if (isSettingsAvailable() && !isUserInteracted() && !isRecentlySetup()) {
+ // 4. Screen Attention is off.
+ if (isSettingsAvailable() && !isUserInteracted() && !isRecentlySetup() && !isTurnedOn()) {
final IconCompat icon = IconCompat.createWithResource(mContext,
R.drawable.ic_settings_adaptive_sleep);
final CharSequence title = mContext.getText(R.string.adaptive_sleep_title);
}
/**
+ * @return {@code true} if the feature is turned on for the device, otherwise {@code false}
+ */
+ private boolean isTurnedOn() {
+ return Settings.System.getInt(
+ mContext.getContentResolver(), Settings.System.ADAPTIVE_SLEEP, 0) != 0;
+ }
+
+ /**
* @return {@code true} if the current user has opened the Screen Attention settings page
* before, otherwise {@code false}.
*/
import static android.app.NotificationManager.IMPORTANCE_NONE;
import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
-import static com.android.settings.notification.NotificationSettingsBase.ARG_FROM_SETTINGS;
+import static com.android.settings.notification.ChannelListPreferenceController.ARG_FROM_SETTINGS;
import android.app.Application;
import android.app.NotificationChannel;
*
* Note:
* When the sent count of notification channels is the same, follow the sorting mechanism from
- * {@link com.android.settings.notification.NotificationSettingsBase#mChannelComparator}.
+ * {@link com.android.settings.notification.ChannelListPreferenceController}.
* Since slice view only shows displayable notification channels, so those deleted ones are
* excluded from the comparison here.
*/
channelArgs.putInt(AppInfoBase.ARG_PACKAGE_UID, mUid);
channelArgs.putString(AppInfoBase.ARG_PACKAGE_NAME, mPackageName);
channelArgs.putString(Settings.EXTRA_CHANNEL_ID, channel.getId());
- channelArgs.putBoolean(ARG_FROM_SETTINGS, true);
final Intent channelIntent = new SubSettingLauncher(mContext)
.setDestination(ChannelNotificationSettings.class.getName())
private int mBearerInitialVal = 0;
private String mMvnoTypeStr;
private String mMvnoMatchDataStr;
- private String[] mReadOnlyApnTypes;
+ @VisibleForTesting
+ String[] mReadOnlyApnTypes;
+ @VisibleForTesting
+ String[] mDefaultApnTypes;
private String[] mReadOnlyApnFields;
private boolean mReadOnlyApn;
private Uri mCarrierUri;
private static final int MMSPROXY_INDEX = 12;
private static final int MMSPORT_INDEX = 13;
private static final int AUTH_TYPE_INDEX = 14;
- private static final int TYPE_INDEX = 15;
+ @VisibleForTesting
+ static final int TYPE_INDEX = 15;
private static final int PROTOCOL_INDEX = 16;
@VisibleForTesting
static final int CARRIER_ENABLED_INDEX = 17;
mReadOnlyApnTypes = b.getStringArray(
CarrierConfigManager.KEY_READ_ONLY_APN_TYPES_STRING_ARRAY);
if (!ArrayUtils.isEmpty(mReadOnlyApnTypes)) {
- for (String apnType : mReadOnlyApnTypes) {
- Log.d(TAG, "onCreate: read only APN type: " + apnType);
- }
+ Log.d(TAG,
+ "onCreate: read only APN type: " + Arrays.toString(mReadOnlyApnTypes));
}
mReadOnlyApnFields = b.getStringArray(
CarrierConfigManager.KEY_READ_ONLY_APN_FIELDS_STRING_ARRAY);
+
+ mDefaultApnTypes = b.getStringArray(
+ CarrierConfigManager.KEY_APN_SETTINGS_DEFAULT_APN_TYPES_STRING_ARRAY);
+ if (!ArrayUtils.isEmpty(mDefaultApnTypes)) {
+ Log.d(TAG, "onCreate: default apn types: " + Arrays.toString(mDefaultApnTypes));
+ }
}
}
return sNotSet.equals(value) ? null : value;
}
- private String getUserEnteredApnType() {
+ @VisibleForTesting
+ String getUserEnteredApnType() {
// if user has not specified a type, map it to "ALL APN TYPES THAT ARE NOT READ-ONLY"
+ // but if user enter empty type, map it just for default
String userEnteredApnType = mApnType.getText();
if (userEnteredApnType != null) userEnteredApnType = userEnteredApnType.trim();
if ((TextUtils.isEmpty(userEnteredApnType)
|| PhoneConstants.APN_TYPE_ALL.equals(userEnteredApnType))
&& !ArrayUtils.isEmpty(mReadOnlyApnTypes)) {
+ String[] apnTypeList = PhoneConstants.APN_TYPES;
+ if (TextUtils.isEmpty(userEnteredApnType) && !ArrayUtils.isEmpty(mDefaultApnTypes)) {
+ apnTypeList = mDefaultApnTypes;
+ }
+
StringBuilder editableApnTypes = new StringBuilder();
List<String> readOnlyApnTypes = Arrays.asList(mReadOnlyApnTypes);
boolean first = true;
- for (String apnType : PhoneConstants.APN_TYPES) {
+ for (String apnType : apnTypeList) {
// add APN type if it is not read-only and is not wild-cardable
if (!readOnlyApnTypes.contains(apnType)
&& !apnType.equals(PhoneConstants.APN_TYPE_IA)
package com.android.settings.notification;
-import android.app.NotificationChannel;
-import android.app.NotificationChannelGroup;
import android.app.settings.SettingsEnums;
import android.content.Context;
-import android.os.AsyncTask;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceCategory;
-import androidx.preference.PreferenceGroup;
-import androidx.preference.PreferenceScreen;
-import androidx.preference.SwitchPreference;
-
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R;
-import com.android.settings.widget.MasterSwitchPreference;
-import com.android.settingslib.RestrictedSwitchPreference;
import com.android.settingslib.core.AbstractPreferenceController;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
import java.util.List;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceGroup;
+import androidx.preference.PreferenceScreen;
+
/** 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_ADVANCED_CATEGORY = "app_advanced";
private static String KEY_BADGE = "badge";
private static String KEY_APP_LINK = "app_link";
private static String KEY_BUBBLE = "bubble_link_pref";
private static String[] LEGACY_NON_ADVANCED_KEYS = {KEY_BADGE, KEY_APP_LINK, KEY_BUBBLE};
- private List<NotificationChannelGroup> mChannelGroupList;
-
@Override
public int getMetricsCategory() {
return SettingsEnums.NOTIFICATION_APP_NOTIFICATION;
return;
}
- if (!mShowLegacyChannelConfig) {
- // Load channel settings
- new AsyncTask<Void, Void, Void>() {
- @Override
- protected Void doInBackground(Void... unused) {
- mChannelGroupList = mBackend.getGroups(mPkg, mUid).getList();
- Collections.sort(mChannelGroupList, mChannelGroupComparator);
- return null;
- }
-
- @Override
- protected void onPostExecute(Void unused) {
- if (getHost() == null) {
- return;
- }
- populateList();
- }
- }.execute();
- }
-
for (NotificationPreferenceController controller : mControllers) {
controller.onResume(mAppRow, mChannel, mChannelGroup, mSuspendedAppsAdmin);
controller.displayPreference(getPreferenceScreen());
mControllers.add(new NotificationsOffPreferenceController(context));
mControllers.add(new DeletedChannelsPreferenceController(context, mBackend));
mControllers.add(new BubbleSummaryPreferenceController(context, mBackend));
+ mControllers.add(new ChannelListPreferenceController(context, mBackend));
return new ArrayList<>(mControllers);
}
-
- private void populateList() {
- if (!mDynamicPreferences.isEmpty()) {
- for (Preference p : mDynamicPreferences) {
- getPreferenceScreen().removePreference(p);
- }
- mDynamicPreferences.clear();
- }
- if (mChannelGroupList.isEmpty()) {
- PreferenceCategory groupCategory = new PreferenceCategory(getPrefContext());
- groupCategory.setTitle(R.string.notification_channels);
- groupCategory.setKey(KEY_GENERAL_CATEGORY);
- getPreferenceScreen().addPreference(groupCategory);
- mDynamicPreferences.add(groupCategory);
-
- Preference empty = new Preference(getPrefContext());
- empty.setTitle(R.string.no_channels);
- empty.setEnabled(false);
- groupCategory.addPreference(empty);
- } else {
- populateGroupList();
- mImportanceListener.onImportanceChanged();
- }
- }
-
- private void populateGroupList() {
- for (NotificationChannelGroup group : mChannelGroupList) {
- PreferenceCategory groupCategory = new PreferenceCategory(getPrefContext());
- groupCategory.setOrderingAsAdded(true);
- getPreferenceScreen().addPreference(groupCategory);
- mDynamicPreferences.add(groupCategory);
- if (group.getId() == null) {
- if (mChannelGroupList.size() > 1) {
- groupCategory.setTitle(R.string.notification_channels_other);
- }
- groupCategory.setKey(KEY_GENERAL_CATEGORY);
- } else {
- groupCategory.setTitle(group.getName());
- groupCategory.setKey(group.getId());
- populateGroupToggle(groupCategory, group);
- }
- if (!group.isBlocked()) {
- final List<NotificationChannel> channels = group.getChannels();
- Collections.sort(channels, mChannelComparator);
- int N = channels.size();
- for (int i = 0; i < N; i++) {
- final NotificationChannel channel = channels.get(i);
- populateSingleChannelPrefs(groupCategory, channel, group.isBlocked());
- }
- }
- }
- }
-
- protected void populateGroupToggle(final PreferenceGroup parent,
- NotificationChannelGroup group) {
- RestrictedSwitchPreference preference = new RestrictedSwitchPreference(getPrefContext());
- preference.setTitle(R.string.notification_switch_label);
- preference.setEnabled(mSuspendedAppsAdmin == null
- && isChannelGroupBlockable(group));
- preference.setChecked(!group.isBlocked());
- preference.setOnPreferenceClickListener(preference1 -> {
- final boolean allowGroup = ((SwitchPreference) preference1).isChecked();
- group.setBlocked(!allowGroup);
- mBackend.updateChannelGroup(mAppRow.pkg, mAppRow.uid, group);
-
- onGroupBlockStateChanged(group);
- return true;
- });
-
- parent.addPreference(preference);
- }
-
- private Comparator<NotificationChannelGroup> mChannelGroupComparator =
- new Comparator<NotificationChannelGroup>() {
-
- @Override
- public int compare(NotificationChannelGroup left, NotificationChannelGroup right) {
- // Non-grouped channels (in placeholder group with a null id) come last
- if (left.getId() == null && right.getId() != null) {
- return 1;
- } else if (right.getId() == null && left.getId() != null) {
- return -1;
- }
- return left.getId().compareTo(right.getId());
- }
- };
-
- protected void onGroupBlockStateChanged(NotificationChannelGroup group) {
- if (group == null) {
- return;
- }
- PreferenceGroup groupGroup = (
- PreferenceGroup) getPreferenceScreen().findPreference(group.getId());
-
- if (groupGroup != null) {
- if (group.isBlocked()) {
- List<Preference> toRemove = new ArrayList<>();
- int childCount = groupGroup.getPreferenceCount();
- for (int i = 0; i < childCount; i++) {
- Preference pref = groupGroup.getPreference(i);
- if (pref instanceof MasterSwitchPreference) {
- toRemove.add(pref);
- }
- }
- for (Preference pref : toRemove) {
- groupGroup.removePreference(pref);
- }
- } else {
- final List<NotificationChannel> channels = group.getChannels();
- Collections.sort(channels, mChannelComparator);
- int N = channels.size();
- for (int i = 0; i < N; i++) {
- final NotificationChannel channel = channels.get(i);
- populateSingleChannelPrefs(groupGroup, channel, group.isBlocked());
- }
- }
- }
- }
-
}
+++ /dev/null
-/*
- * 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.settings.SettingsEnums;
-import android.content.Context;
-import android.util.Log;
-
-import androidx.preference.Preference;
-
-import com.android.settings.R;
-import com.android.settingslib.core.AbstractPreferenceController;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-public class ChannelGroupNotificationSettings extends NotificationSettingsBase {
- private static final String TAG = "ChannelGroupSettings";
-
- @Override
- public int getMetricsCategory() {
- return SettingsEnums.NOTIFICATION_CHANNEL_GROUP;
- }
-
- @Override
- public void onResume() {
- super.onResume();
- if (mAppRow == null || mChannelGroup == null) {
- Log.w(TAG, "Missing package or uid or packageinfo or group");
- finish();
- return;
- }
-
- populateChannelList();
- for (NotificationPreferenceController controller : mControllers) {
- controller.onResume(mAppRow, mChannel, mChannelGroup, mSuspendedAppsAdmin);
- controller.displayPreference(getPreferenceScreen());
- }
- updatePreferenceStates();
- }
-
- @Override
- protected String getLogTag() {
- return TAG;
- }
-
- @Override
- protected int getPreferenceScreenResId() {
- return R.xml.notification_group_settings;
- }
-
- @Override
- protected List<AbstractPreferenceController> createPreferenceControllers(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 (!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 " +
- mDynamicPreferences.size() + ", new size " + mDynamicPreferences.size());
- for (Preference p : mDynamicPreferences) {
- getPreferenceScreen().removePreference(p);
- }
- }
- if (mChannelGroup.getChannels().isEmpty()) {
- Preference empty = new Preference(getPrefContext());
- empty.setTitle(R.string.no_channels);
- empty.setEnabled(false);
- getPreferenceScreen().addPreference(empty);
- mDynamicPreferences.add(empty);
-
- } else {
- final List<NotificationChannel> channels = mChannelGroup.getChannels();
- Collections.sort(channels, mChannelComparator);
- for (NotificationChannel channel : channels) {
- mDynamicPreferences.add(populateSingleChannelPrefs(
- getPreferenceScreen(), channel, mChannelGroup.isBlocked()));
- }
-
- }
- }
-}
--- /dev/null
+/*
+ * Copyright (C) 2019 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_LOW;
+import static android.app.NotificationManager.IMPORTANCE_NONE;
+
+import android.app.NotificationChannel;
+import android.app.NotificationChannelGroup;
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.graphics.BlendMode;
+import android.graphics.BlendModeColorFilter;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.GradientDrawable;
+import android.graphics.drawable.LayerDrawable;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.provider.Settings;
+
+import com.android.settings.R;
+import com.android.settings.Utils;
+import com.android.settings.applications.AppInfoBase;
+import com.android.settings.core.SubSettingLauncher;
+import com.android.settings.widget.MasterSwitchPreference;
+import com.android.settingslib.RestrictedSwitchPreference;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceGroup;
+import androidx.preference.SwitchPreference;
+
+public class ChannelListPreferenceController extends NotificationPreferenceController {
+
+ private static final String KEY = "channels";
+ private static String KEY_GENERAL_CATEGORY = "categories";
+ public static final String ARG_FROM_SETTINGS = "fromSettings";
+
+ private List<NotificationChannelGroup> mChannelGroupList;
+ private PreferenceCategory mPreference;
+
+ public ChannelListPreferenceController(Context context, NotificationBackend backend) {
+ super(context, backend);
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY;
+ }
+
+ @Override
+ public boolean isAvailable() {
+ if (mAppRow == null) {
+ return false;
+ }
+ if (mAppRow.banned) {
+ return false;
+ }
+ if (mChannel != null) {
+ if (mBackend.onlyHasDefaultChannel(mAppRow.pkg, mAppRow.uid)
+ || NotificationChannel.DEFAULT_CHANNEL_ID.equals(mChannel.getId())) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ mPreference = (PreferenceCategory) preference;
+ // Load channel settings
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... unused) {
+ mChannelGroupList = mBackend.getGroups(mAppRow.pkg, mAppRow.uid).getList();
+ Collections.sort(mChannelGroupList, mChannelGroupComparator);
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void unused) {
+ if (mContext == null) {
+ return;
+ }
+ populateList();
+ }
+ }.execute();
+ }
+
+ private void populateList() {
+ // TODO: if preference has children, compare with newly loaded list
+ mPreference.removeAll();
+
+ if (mChannelGroupList.isEmpty()) {
+ PreferenceCategory groupCategory = new PreferenceCategory(mContext);
+ groupCategory.setTitle(R.string.notification_channels);
+ groupCategory.setKey(KEY_GENERAL_CATEGORY);
+ mPreference.addPreference(groupCategory);
+
+ Preference empty = new Preference(mContext);
+ empty.setTitle(R.string.no_channels);
+ empty.setEnabled(false);
+ groupCategory.addPreference(empty);
+ } else {
+ populateGroupList();
+ }
+ }
+
+ private void populateGroupList() {
+ for (NotificationChannelGroup group : mChannelGroupList) {
+ PreferenceCategory groupCategory = new PreferenceCategory(mContext);
+ groupCategory.setOrderingAsAdded(true);
+ mPreference.addPreference(groupCategory);
+ if (group.getId() == null) {
+ if (mChannelGroupList.size() > 1) {
+ groupCategory.setTitle(R.string.notification_channels_other);
+ }
+ groupCategory.setKey(KEY_GENERAL_CATEGORY);
+ } else {
+ groupCategory.setTitle(group.getName());
+ groupCategory.setKey(group.getId());
+ populateGroupToggle(groupCategory, group);
+ }
+ if (!group.isBlocked()) {
+ final List<NotificationChannel> channels = group.getChannels();
+ Collections.sort(channels, mChannelComparator);
+ int N = channels.size();
+ for (int i = 0; i < N; i++) {
+ final NotificationChannel channel = channels.get(i);
+ populateSingleChannelPrefs(groupCategory, channel, group.isBlocked());
+ }
+ }
+ }
+ }
+
+ protected void populateGroupToggle(final PreferenceGroup parent,
+ NotificationChannelGroup group) {
+ RestrictedSwitchPreference preference =
+ new RestrictedSwitchPreference(mContext);
+ preference.setTitle(R.string.notification_switch_label);
+ preference.setEnabled(mAdmin == null
+ && isChannelGroupBlockable(group));
+ preference.setChecked(!group.isBlocked());
+ preference.setOnPreferenceClickListener(preference1 -> {
+ final boolean allowGroup = ((SwitchPreference) preference1).isChecked();
+ group.setBlocked(!allowGroup);
+ mBackend.updateChannelGroup(mAppRow.pkg, mAppRow.uid, group);
+
+ onGroupBlockStateChanged(group);
+ return true;
+ });
+
+ parent.addPreference(preference);
+ }
+
+ protected Preference populateSingleChannelPrefs(PreferenceGroup parent,
+ final NotificationChannel channel, final boolean groupBlocked) {
+ MasterSwitchPreference channelPref = new MasterSwitchPreference(mContext);
+ channelPref.setSwitchEnabled(mAdmin == null
+ && isChannelBlockable(channel)
+ && isChannelConfigurable(channel)
+ && !groupBlocked);
+ channelPref.setIcon(null);
+ if (channel.getImportance() > IMPORTANCE_LOW) {
+ channelPref.setIcon(getAlertingIcon());
+ }
+ channelPref.setIconSize(MasterSwitchPreference.ICON_SIZE_SMALL);
+ channelPref.setKey(channel.getId());
+ channelPref.setTitle(channel.getName());
+ channelPref.setSummary(NotificationBackend.getSentSummary(
+ mContext, mAppRow.sentByChannel.get(channel.getId()), false));
+ channelPref.setChecked(channel.getImportance() != IMPORTANCE_NONE);
+ 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, channel.getId());
+ channelArgs.putBoolean(ARG_FROM_SETTINGS, true);
+ channelPref.setIntent(new SubSettingLauncher(mContext)
+ .setDestination(ChannelNotificationSettings.class.getName())
+ .setArguments(channelArgs)
+ .setTitleRes(R.string.notification_channel_title)
+ .setSourceMetricsCategory(SettingsEnums.NOTIFICATION_APP_NOTIFICATION)
+ .toIntent());
+
+ channelPref.setOnPreferenceChangeListener(
+ (preference, o) -> {
+ boolean value = (Boolean) o;
+ int importance = value ? IMPORTANCE_LOW : IMPORTANCE_NONE;
+ channel.setImportance(importance);
+ channel.lockFields(
+ NotificationChannel.USER_LOCKED_IMPORTANCE);
+ MasterSwitchPreference channelPref1 = (MasterSwitchPreference) preference;
+ channelPref1.setIcon(null);
+ if (channel.getImportance() > IMPORTANCE_LOW) {
+ channelPref1.setIcon(getAlertingIcon());
+ }
+ toggleBehaviorIconState(channelPref1.getIcon(),
+ importance != IMPORTANCE_NONE);
+ mBackend.updateChannel(mAppRow.pkg, mAppRow.uid, channel);
+
+ return true;
+ });
+ if (parent.findPreference(channelPref.getKey()) == null) {
+ parent.addPreference(channelPref);
+ }
+ return channelPref;
+ }
+
+ private Drawable getAlertingIcon() {
+ Drawable icon = mContext.getDrawable(R.drawable.ic_notifications_alert);
+ icon.setTintList(Utils.getColorAccent(mContext));
+ return icon;
+ }
+
+ private void toggleBehaviorIconState(Drawable icon, boolean enabled) {
+ if (icon == null) return;
+
+ LayerDrawable layerDrawable = (LayerDrawable) icon;
+ GradientDrawable background =
+ (GradientDrawable) layerDrawable.findDrawableByLayerId(R.id.back);
+
+ if (background == null) return;
+
+ if (enabled) {
+ background.clearColorFilter();
+ } else {
+ background.setColorFilter(new BlendModeColorFilter(
+ mContext.getColor(R.color.material_grey_300),
+ BlendMode.SRC_IN));
+ }
+ }
+
+ protected void onGroupBlockStateChanged(NotificationChannelGroup group) {
+ if (group == null) {
+ return;
+ }
+ PreferenceGroup groupGroup = mPreference.findPreference(group.getId());
+
+ if (groupGroup != null) {
+ if (group.isBlocked()) {
+ List<Preference> toRemove = new ArrayList<>();
+ int childCount = groupGroup.getPreferenceCount();
+ for (int i = 0; i < childCount; i++) {
+ Preference pref = groupGroup.getPreference(i);
+ if (pref instanceof MasterSwitchPreference) {
+ toRemove.add(pref);
+ }
+ }
+ for (Preference pref : toRemove) {
+ groupGroup.removePreference(pref);
+ }
+ } else {
+ final List<NotificationChannel> channels = group.getChannels();
+ Collections.sort(channels, mChannelComparator);
+ int N = channels.size();
+ for (int i = 0; i < N; i++) {
+ final NotificationChannel channel = channels.get(i);
+ populateSingleChannelPrefs(groupGroup, channel, group.isBlocked());
+ }
+ }
+ }
+ }
+
+ private Comparator<NotificationChannelGroup> mChannelGroupComparator =
+ new Comparator<NotificationChannelGroup>() {
+
+ @Override
+ public int compare(NotificationChannelGroup left, NotificationChannelGroup right) {
+ // Non-grouped channels (in placeholder group with a null id) come last
+ if (left.getId() == null && right.getId() != null) {
+ return 1;
+ } else if (right.getId() == null && left.getId() != null) {
+ return -1;
+ }
+ return left.getId().compareTo(right.getId());
+ }
+ };
+
+ protected Comparator<NotificationChannel> mChannelComparator =
+ (left, right) -> {
+ if (left.isDeleted() != right.isDeleted()) {
+ return Boolean.compare(left.isDeleted(), right.isDeleted());
+ } else if (left.getId().equals(NotificationChannel.DEFAULT_CHANNEL_ID)) {
+ // Uncategorized/miscellaneous legacy channel goes last
+ return 1;
+ } else if (right.getId().equals(NotificationChannel.DEFAULT_CHANNEL_ID)) {
+ return -1;
+ }
+
+ return left.getId().compareTo(right.getId());
+ };
+}
package com.android.settings.notification;
+import static com.android.settings.notification.ChannelListPreferenceController.ARG_FROM_SETTINGS;
+
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.Intent;
}
protected boolean isChannelBlockable() {
- if (mChannel != null && mAppRow != null) {
- if (mChannel.isImportanceLockedByCriticalDeviceFunction()
- || mChannel.isImportanceLockedByOEM()) {
- return mChannel.getImportance() == IMPORTANCE_NONE;
+ return isChannelBlockable(mChannel);
+ }
+
+ protected boolean isChannelBlockable(NotificationChannel channel) {
+ if (channel != null && mAppRow != null) {
+ if (channel.isImportanceLockedByCriticalDeviceFunction()
+ || channel.isImportanceLockedByOEM()) {
+ return channel.getImportance() == IMPORTANCE_NONE;
}
- return mChannel.isBlockableSystem() || !mAppRow.systemApp
- || mChannel.getImportance() == IMPORTANCE_NONE;
+ return channel.isBlockableSystem() || !mAppRow.systemApp
+ || channel.getImportance() == IMPORTANCE_NONE;
+ }
+ return false;
+ }
+
+ protected boolean isChannelConfigurable(NotificationChannel channel) {
+ if (channel != null && mAppRow != null) {
+ return !channel.isImportanceLockedByOEM();
}
return false;
}
protected boolean isChannelGroupBlockable() {
- if (mChannelGroup != null && mAppRow != null) {
+ return isChannelGroupBlockable(mChannelGroup);
+ }
+
+ protected boolean isChannelGroupBlockable(NotificationChannelGroup group) {
+ if (group != null && mAppRow != null) {
if (!mAppRow.systemApp) {
return true;
}
- return mChannelGroup.isBlocked();
+ return group.isBlocked();
}
return false;
}
abstract public class NotificationSettingsBase extends DashboardFragment {
private static final String TAG = "NotifiSettingsBase";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- public static final String ARG_FROM_SETTINGS = "fromSettings";
protected PackageManager mPm;
protected NotificationBackend mBackend = new NotificationBackend();
protected boolean mListeningToPackageRemove;
protected List<NotificationPreferenceController> mControllers = new ArrayList<>();
- protected List<Preference> mDynamicPreferences = new ArrayList<>();
protected ImportanceListener mImportanceListener = new ImportanceListener();
protected Intent mIntent;
mSuspendedAppsAdmin = RestrictedLockUtilsInternal.checkIfApplicationIsSuspended(
mContext, mPkg, mUserId);
-
loadChannel();
loadAppRow();
loadChannelGroup();
return null;
}
- private Drawable getAlertingIcon() {
- Drawable icon = getContext().getDrawable(R.drawable.ic_notifications_alert);
- icon.setTintList(Utils.getColorAccent(getContext()));
- return icon;
- }
-
- protected Preference populateSingleChannelPrefs(PreferenceGroup parent,
- final NotificationChannel channel, final boolean groupBlocked) {
- MasterSwitchPreference channelPref = new MasterSwitchPreference(getPrefContext());
- channelPref.setSwitchEnabled(mSuspendedAppsAdmin == null
- && isChannelBlockable(channel)
- && isChannelConfigurable(channel)
- && !groupBlocked);
- channelPref.setIcon(null);
- if (channel.getImportance() > IMPORTANCE_LOW) {
- channelPref.setIcon(getAlertingIcon());
- }
- channelPref.setIconSize(MasterSwitchPreference.ICON_SIZE_SMALL);
- channelPref.setKey(channel.getId());
- channelPref.setTitle(channel.getName());
- channelPref.setSummary(NotificationBackend.getSentSummary(
- mContext, mAppRow.sentByChannel.get(channel.getId()), false));
- channelPref.setChecked(channel.getImportance() != IMPORTANCE_NONE);
- Bundle channelArgs = new Bundle();
- channelArgs.putInt(AppInfoBase.ARG_PACKAGE_UID, mUid);
- channelArgs.putString(AppInfoBase.ARG_PACKAGE_NAME, mPkg);
- channelArgs.putString(Settings.EXTRA_CHANNEL_ID, channel.getId());
- channelArgs.putBoolean(ARG_FROM_SETTINGS, true);
- channelPref.setIntent(new SubSettingLauncher(getActivity())
- .setDestination(ChannelNotificationSettings.class.getName())
- .setArguments(channelArgs)
- .setTitleRes(R.string.notification_channel_title)
- .setSourceMetricsCategory(getMetricsCategory())
- .toIntent());
-
- channelPref.setOnPreferenceChangeListener(
- (preference, o) -> {
- boolean value = (Boolean) o;
- int importance = value ? IMPORTANCE_LOW : IMPORTANCE_NONE;
- channel.setImportance(importance);
- channel.lockFields(
- NotificationChannel.USER_LOCKED_IMPORTANCE);
- MasterSwitchPreference channelPref1 = (MasterSwitchPreference) preference;
- channelPref1.setIcon(null);
- if (channel.getImportance() > IMPORTANCE_LOW) {
- channelPref1.setIcon(getAlertingIcon());
- }
- toggleBehaviorIconState(channelPref1.getIcon(),
- importance != IMPORTANCE_NONE);
- mBackend.updateChannel(mPkg, mUid, channel);
-
- return true;
- });
- if (parent.findPreference(channelPref.getKey()) == null) {
- parent.addPreference(channelPref);
- }
- return channelPref;
- }
-
- private void toggleBehaviorIconState(Drawable icon, boolean enabled) {
- if (icon == null) return;
-
- LayerDrawable layerDrawable = (LayerDrawable) icon;
- GradientDrawable background =
- (GradientDrawable) layerDrawable.findDrawableByLayerId(R.id.back);
-
- if (background == null) return;
-
- if (enabled) {
- background.clearColorFilter();
- } else {
- background.setColorFilter(new BlendModeColorFilter(
- mContext.getColor(R.color.material_grey_300),
- BlendMode.SRC_IN));
- }
- }
-
- protected boolean isChannelConfigurable(NotificationChannel channel) {
- if (channel != null && mAppRow != null) {
- return !channel.isImportanceLockedByOEM();
- }
- return false;
- }
-
- protected boolean isChannelBlockable(NotificationChannel channel) {
- if (channel != null && mAppRow != null) {
- if (!mAppRow.systemApp) {
- return true;
- }
-
- if (channel.isImportanceLockedByCriticalDeviceFunction()) {
- return false;
- }
-
- if (channel.isImportanceLockedByOEM()) {
- return false;
- }
-
- return channel.isBlockableSystem()
- || channel.getImportance() == NotificationManager.IMPORTANCE_NONE;
- }
- return false;
- }
-
- protected boolean isChannelGroupBlockable(NotificationChannelGroup group) {
- if (group != null && mAppRow != null) {
- if (!mAppRow.systemApp) {
- return true;
- }
-
- 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() {
if (mListeningToPackageRemove) {
return;
}
};
- protected Comparator<NotificationChannel> mChannelComparator =
- (left, right) -> {
- if (left.isDeleted() != right.isDeleted()) {
- return Boolean.compare(left.isDeleted(), right.isDeleted());
- } else if (left.getId().equals(NotificationChannel.DEFAULT_CHANNEL_ID)) {
- // Uncategorized/miscellaneous legacy channel goes last
- return 1;
- } else if (right.getId().equals(NotificationChannel.DEFAULT_CHANNEL_ID)) {
- return -1;
- }
-
- return left.getId().compareTo(right.getId());
- };
-
protected class ImportanceListener {
protected void onImportanceChanged() {
final PreferenceScreen screen = getPreferenceScreen();
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);
- }
}
}
}
Bundle args = new Bundle();
args.putString(AppInfoBase.ARG_PACKAGE_NAME, pkgName);
args.putInt(AppInfoBase.ARG_PACKAGE_UID, appEntry.info.uid);
- pref.setIntent(new SubSettingLauncher(mHost.getActivity())
- .setDestination(AppNotificationSettings.class.getName())
- .setTitleRes(R.string.notifications_title)
- .setArguments(args)
- .setUserHandle(new UserHandle(UserHandle.getUserId(appEntry.info.uid)))
- .setSourceMetricsCategory(
- SettingsEnums.MANAGE_APPLICATIONS_NOTIFICATIONS)
- .toIntent());
+ pref.setOnPreferenceClickListener(preference -> {
+ new SubSettingLauncher(mHost.getActivity())
+ .setDestination(AppNotificationSettings.class.getName())
+ .setTitleRes(R.string.notifications_title)
+ .setArguments(args)
+ .setUserHandle(new UserHandle(UserHandle.getUserId(appEntry.info.uid)))
+ .setSourceMetricsCategory(
+ SettingsEnums.MANAGE_APPLICATIONS_NOTIFICATIONS)
+ .launch();
+ return true;
+ });
pref.setSwitchEnabled(mNotificationBackend.isBlockable(mContext, appEntry.info));
pref.setOnPreferenceChangeListener((preference, newValue) -> {
boolean blocked = !(Boolean) newValue;
private TextView mSsidView;
private Context mContext;
- private Integer mSecurityInPosition[];
+
+ @VisibleForTesting
+ Integer mSecurityInPosition[];
private final WifiManager mWifiManager;
if ((!mAccessPoint.isSaved() && !mAccessPoint.isActive()
&& !mAccessPoint.isPasspointConfig())
|| mMode != WifiConfigUiBase.MODE_VIEW) {
- showSecurityFields();
+ showSecurityFields(true /* refreshEapMethods */, true /* refreshCertificates */);
showIpConfigFields();
showProxyFields();
final CheckBox advancedTogglebox =
return 0;
}
- private void showSecurityFields() {
+ private void showSecurityFields(boolean refreshEapMethods, boolean refreshCertificates) {
if (mAccessPointSecurity == AccessPoint.SECURITY_NONE ||
mAccessPointSecurity == AccessPoint.SECURITY_OWE ||
mAccessPointSecurity == AccessPoint.SECURITY_OWE_TRANSITION) {
if (mEapMethodSpinner == null) {
mEapMethodSpinner = (Spinner) mView.findViewById(R.id.method);
mEapMethodSpinner.setOnItemSelectedListener(this);
- if (Utils.isWifiOnly(mContext) || !mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_eap_sim_based_auth_supported)) {
- String[] eapMethods = mContext.getResources().getStringArray(
- R.array.eap_method_without_sim_auth);
- ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<String>(mContext,
- android.R.layout.simple_spinner_item, eapMethods);
- spinnerAdapter.setDropDownViewResource(
- android.R.layout.simple_spinner_dropdown_item);
- mEapMethodSpinner.setAdapter(spinnerAdapter);
- }
mPhase2Spinner = (Spinner) mView.findViewById(R.id.phase2);
mPhase2Spinner.setOnItemSelectedListener(this);
mEapCaCertSpinner = (Spinner) mView.findViewById(R.id.ca_cert);
mEapUserCertSpinner.setOnItemSelectedListener(this);
mEapIdentityView = (TextView) mView.findViewById(R.id.identity);
mEapAnonymousView = (TextView) mView.findViewById(R.id.anonymous);
+ }
- if (mAccessPoint != null && mAccessPoint.isCarrierAp()) {
- mEapMethodSpinner.setSelection(mAccessPoint.getCarrierApEapType());
+ if (refreshEapMethods) {
+ ArrayAdapter<CharSequence> eapMethodSpinnerAdapter;
+ if (mAccessPointSecurity == AccessPoint.SECURITY_EAP_SUITE_B) {
+ eapMethodSpinnerAdapter = getSpinnerAdapter(R.array.wifi_eap_method);
+ mEapMethodSpinner.setAdapter(eapMethodSpinnerAdapter);
+ // WAP3-Enterprise 192-bit only allows EAP method TLS
+ mEapMethodSpinner.setSelection(Eap.TLS);
+ mEapMethodSpinner.setEnabled(false);
+ } else if (Utils.isWifiOnly(mContext) || !mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_eap_sim_based_auth_supported)) {
+ eapMethodSpinnerAdapter = getSpinnerAdapter(
+ R.array.eap_method_without_sim_auth);
+ mEapMethodSpinner.setAdapter(eapMethodSpinnerAdapter);
+ mEapMethodSpinner.setEnabled(true);
+ } else {
+ eapMethodSpinnerAdapter = getSpinnerAdapter(R.array.wifi_eap_method);
+ mEapMethodSpinner.setAdapter(eapMethodSpinnerAdapter);
+ mEapMethodSpinner.setEnabled(true);
}
+ }
+
+ if (mAccessPointSecurity != AccessPoint.SECURITY_EAP_SUITE_B
+ && mAccessPoint != null
+ && mAccessPoint.isCarrierAp()) {
+ mEapMethodSpinner.setSelection(mAccessPoint.getCarrierApEapType());
+ }
+ if (refreshCertificates) {
loadCertificates(
mEapCaCertSpinner,
Credentials.CA_CERTIFICATE,
mDoNotProvideEapUserCertString,
false,
false);
+ }
- // Modifying an existing network
- if (mAccessPoint != null && mAccessPoint.isSaved()) {
- WifiEnterpriseConfig enterpriseConfig = mAccessPoint.getConfig().enterpriseConfig;
- int eapMethod = enterpriseConfig.getEapMethod();
- int phase2Method = enterpriseConfig.getPhase2Method();
- mEapMethodSpinner.setSelection(eapMethod);
- showEapFieldsByMethod(eapMethod);
- switch (eapMethod) {
- case Eap.PEAP:
- switch (phase2Method) {
- case Phase2.NONE:
- mPhase2Spinner.setSelection(WIFI_PEAP_PHASE2_NONE);
- break;
- case Phase2.MSCHAPV2:
- mPhase2Spinner.setSelection(WIFI_PEAP_PHASE2_MSCHAPV2);
- break;
- case Phase2.GTC:
- mPhase2Spinner.setSelection(WIFI_PEAP_PHASE2_GTC);
- break;
- case Phase2.SIM:
- mPhase2Spinner.setSelection(WIFI_PEAP_PHASE2_SIM);
- break;
- case Phase2.AKA:
- mPhase2Spinner.setSelection(WIFI_PEAP_PHASE2_AKA);
- break;
- case Phase2.AKA_PRIME:
- mPhase2Spinner.setSelection(WIFI_PEAP_PHASE2_AKA_PRIME);
- break;
- default:
- Log.e(TAG, "Invalid phase 2 method " + phase2Method);
- break;
- }
- break;
- default:
- mPhase2Spinner.setSelection(phase2Method);
- break;
- }
- if (!TextUtils.isEmpty(enterpriseConfig.getCaPath())) {
- setSelection(mEapCaCertSpinner, mUseSystemCertsString);
- } else {
- String[] caCerts = enterpriseConfig.getCaCertificateAliases();
- if (caCerts == null) {
- setSelection(mEapCaCertSpinner, mDoNotValidateEapServerString);
- } else if (caCerts.length == 1) {
- setSelection(mEapCaCertSpinner, caCerts[0]);
- } else {
- // Reload the cert spinner with an extra "multiple certificates added" item.
- loadCertificates(
- mEapCaCertSpinner,
- Credentials.CA_CERTIFICATE,
- mDoNotValidateEapServerString,
- true,
- true);
- setSelection(mEapCaCertSpinner, mMultipleCertSetString);
+ // Modifying an existing network
+ if (mAccessPoint != null && mAccessPoint.isSaved()) {
+ final WifiEnterpriseConfig enterpriseConfig = mAccessPoint.getConfig().enterpriseConfig;
+ final int eapMethod = enterpriseConfig.getEapMethod();
+ final int phase2Method = enterpriseConfig.getPhase2Method();
+ mEapMethodSpinner.setSelection(eapMethod);
+ showEapFieldsByMethod(eapMethod);
+ switch (eapMethod) {
+ case Eap.PEAP:
+ switch (phase2Method) {
+ case Phase2.NONE:
+ mPhase2Spinner.setSelection(WIFI_PEAP_PHASE2_NONE);
+ break;
+ case Phase2.MSCHAPV2:
+ mPhase2Spinner.setSelection(WIFI_PEAP_PHASE2_MSCHAPV2);
+ break;
+ case Phase2.GTC:
+ mPhase2Spinner.setSelection(WIFI_PEAP_PHASE2_GTC);
+ break;
+ case Phase2.SIM:
+ mPhase2Spinner.setSelection(WIFI_PEAP_PHASE2_SIM);
+ break;
+ case Phase2.AKA:
+ mPhase2Spinner.setSelection(WIFI_PEAP_PHASE2_AKA);
+ break;
+ case Phase2.AKA_PRIME:
+ mPhase2Spinner.setSelection(WIFI_PEAP_PHASE2_AKA_PRIME);
+ break;
+ default:
+ Log.e(TAG, "Invalid phase 2 method " + phase2Method);
+ break;
}
- }
- mEapDomainView.setText(enterpriseConfig.getDomainSuffixMatch());
- String userCert = enterpriseConfig.getClientCertificateAlias();
- if (TextUtils.isEmpty(userCert)) {
- setSelection(mEapUserCertSpinner, mDoNotProvideEapUserCertString);
+ break;
+ default:
+ mPhase2Spinner.setSelection(phase2Method);
+ break;
+ }
+ if (!TextUtils.isEmpty(enterpriseConfig.getCaPath())) {
+ setSelection(mEapCaCertSpinner, mUseSystemCertsString);
+ } else {
+ final String[] caCerts = enterpriseConfig.getCaCertificateAliases();
+ if (caCerts == null) {
+ setSelection(mEapCaCertSpinner, mDoNotValidateEapServerString);
+ } else if (caCerts.length == 1) {
+ setSelection(mEapCaCertSpinner, caCerts[0]);
} else {
- setSelection(mEapUserCertSpinner, userCert);
+ // Reload the cert spinner with an extra "multiple certificates added" item.
+ loadCertificates(
+ mEapCaCertSpinner,
+ Credentials.CA_CERTIFICATE,
+ mDoNotValidateEapServerString,
+ true,
+ true);
+ setSelection(mEapCaCertSpinner, mMultipleCertSetString);
}
- mEapIdentityView.setText(enterpriseConfig.getIdentity());
- mEapAnonymousView.setText(enterpriseConfig.getAnonymousIdentity());
+ }
+ mEapDomainView.setText(enterpriseConfig.getDomainSuffixMatch());
+ final String userCert = enterpriseConfig.getClientCertificateAlias();
+ if (TextUtils.isEmpty(userCert)) {
+ setSelection(mEapUserCertSpinner, mDoNotProvideEapUserCertString);
} else {
- mPhase2Spinner = (Spinner) mView.findViewById(R.id.phase2);
- showEapFieldsByMethod(mEapMethodSpinner.getSelectedItemPosition());
+ setSelection(mEapUserCertSpinner, userCert);
}
+ mEapIdentityView.setText(enterpriseConfig.getIdentity());
+ mEapAnonymousView.setText(enterpriseConfig.getAnonymousIdentity());
} else {
showEapFieldsByMethod(mEapMethodSpinner.getSelectedItemPosition());
}
} catch (Exception e) {
Log.e(TAG, "can't get the certificate list from KeyStore");
}
- certs.add(noCertificateString);
+
+ if (mAccessPointSecurity != AccessPoint.SECURITY_EAP_SUITE_B) {
+ certs.add(noCertificateString);
+ }
+
+ // If there are only mUnspecifiedCertString and one item to select, only shows the item
+ if (certs.size() == 2) {
+ certs.remove(mUnspecifiedCertString);
+ spinner.setEnabled(false);
+ } else {
+ spinner.setEnabled(true);
+ }
final ArrayAdapter<String> adapter = new ArrayAdapter<String>(
context, android.R.layout.simple_spinner_item,
if (parent == mSecuritySpinner) {
// Convert menu position to actual Wi-Fi security type
mAccessPointSecurity = mSecurityInPosition[position];
- showSecurityFields();
+ showSecurityFields(true /* refreshEapMethods */, true /* refreshCertificates */);
if (WifiDppUtils.isSupportEnrolleeQrCodeScanner(mContext, mAccessPointSecurity)) {
mSsidScanButton.setVisibility(View.VISIBLE);
} else {
mSsidScanButton.setVisibility(View.GONE);
}
- } else if (parent == mEapMethodSpinner || parent == mEapCaCertSpinner) {
- showSecurityFields();
+ } else if (parent == mEapMethodSpinner) {
+ showSecurityFields(false /* refreshEapMethods */, true /* refreshCertificates */);
+ } else if (parent == mEapCaCertSpinner) {
+ showSecurityFields(false /* refreshEapMethods */, false /* refreshCertificates */);
} else if (parent == mPhase2Spinner
&& mEapMethodSpinner.getSelectedItemPosition() == WIFI_EAP_METHOD_PEAP) {
showPeapFields();
((CheckBox) mView.findViewById(R.id.wifi_advanced_togglebox))
.setOnCheckedChangeListener(this);
}
+
+ private ArrayAdapter<CharSequence> getSpinnerAdapter(
+ int contentStringArrayResId) {
+ final String[] eapMethods = mContext.getResources().getStringArray(
+ contentStringArrayResId);
+ final ArrayAdapter<CharSequence> spinnerAdapter = new ArrayAdapter<>(mContext,
+ android.R.layout.simple_spinner_item, eapMethods);
+ spinnerAdapter.setDropDownViewResource(
+ android.R.layout.simple_spinner_dropdown_item);
+ return spinnerAdapter;
+ }
}
WifiDppUtils.getSecurityString(wifiConfiguration),
wifiConfiguration.getPrintableSsid(),
wifiConfiguration.preSharedKey,
- /* hiddenSsid */ false,
+ wifiConfiguration.hiddenSSID,
wifiConfiguration.networkId,
/* isHotspot */ false);
}
// Adds all Wi-Fi networks in QR code to the set of configured networks and
// connects to it if it's reachable.
- boolean hasReachableWifiNetwork = false;
+ boolean hasHiddenOrReachableWifiNetwork = false;
for (WifiConfiguration qrCodeWifiConfiguration : qrCodeWifiConfigurations) {
final int id = wifiManager.addNetwork(qrCodeWifiConfiguration);
if (id == -1) {
continue;
}
wifiManager.enableNetwork(id, /* attemptConnect */ false);
- if (isReachableWifiNetwork(qrCodeWifiConfiguration)) {
- hasReachableWifiNetwork = true;
+ // WifiTracker only contains a hidden SSID Wi-Fi network if it's saved.
+ // We can't check if a hidden SSID Wi-Fi network is reachable in advance.
+ if (qrCodeWifiConfiguration.hiddenSSID ||
+ isReachableWifiNetwork(qrCodeWifiConfiguration)) {
+ hasHiddenOrReachableWifiNetwork = true;
mEnrolleeWifiConfiguration = qrCodeWifiConfiguration;
wifiManager.connect(id,
/* listener */ WifiDppQrCodeScannerFragment.this);
}
}
- if (hasReachableWifiNetwork == false) {
+ if (!hasHiddenOrReachableWifiNetwork) {
showErrorMessageAndRestartCamera(
R.string.wifi_dpp_check_connection_try_again);
return;
if (!TextUtils.isEmpty(preSharedKey)) {
intent.putExtra(EXTRA_WIFI_PRE_SHARED_KEY, preSharedKey);
}
+ intent.putExtra(EXTRA_WIFI_HIDDEN_SSID, wifiConfiguration.hiddenSSID);
}
/**
}
final WifiNetworkConfig networkConfig = WifiNetworkConfig.getValidConfigOrNull(
selectedAccessPoint.getSecurityString(/* concise */ true),
- wifiConfig.getPrintableSsid(), wifiConfig.preSharedKey, /* hiddenSsid */ false,
+ wifiConfig.getPrintableSsid(), wifiConfig.preSharedKey, wifiConfig.hiddenSSID,
wifiConfig.networkId, /* isHotspot */ false);
if (mOnChooseNetworkListener != null) {
mOnChooseNetworkListener.onChooseNetwork(networkConfig);
com.android.settings.network.ApnSettings
com.android.settings.network.telephony.NetworkSelectSettings
com.android.settings.notification.AppNotificationSettings
-com.android.settings.notification.ChannelGroupNotificationSettings
com.android.settings.notification.ChannelNotificationSettings
com.android.settings.notification.NotificationStation
com.android.settings.notification.RedactionInterstitial$RedactionInterstitialFragment
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.Uri;
+import android.provider.Settings;
import androidx.slice.Slice;
import androidx.slice.SliceProvider;
mContext = spy(RuntimeEnvironment.application);
mContextualAdaptiveSleepSlice = spy(new ContextualAdaptiveSleepSlice(mContext));
+ Settings.System.putInt(mContext.getContentResolver(), Settings.System.ADAPTIVE_SLEEP, 0);
doReturn(mPackageManager).when(mContext).getPackageManager();
doReturn(mSharedPreferences).when(mContext).getSharedPreferences(eq(PREF), anyInt());
doReturn(true).when(mContextualAdaptiveSleepSlice).isSettingsAvailable();
assertThat(slice).isNull();
}
+
+ @Test
+ public void getSlice_ShowIfNotTurnedOn() {
+ final Slice slice = mContextualAdaptiveSleepSlice.getSlice();
+
+ assertThat(slice).isNotNull();
+ }
+
+ @Test
+ public void getSlice_DoNotShowIfTurnedOn() {
+ Settings.System.putInt(mContext.getContentResolver(), Settings.System.ADAPTIVE_SLEEP, 1);
+
+ final Slice slice = mContextualAdaptiveSleepSlice.getSlice();
+
+ assertThat(slice).isNull();
+ }
}
verify(mApnEditorUT).finish();
}
+ @Test
+ public void getUserEnteredApnType_emptyApnType_shouldReturnDefault() {
+ // case 1
+ // GIVEN read only APN types with DUN
+ String[] readOnlyApnTypes = {"dun"};
+ mApnEditorUT.mReadOnlyApnTypes = readOnlyApnTypes;
+ // GIVEN read specificApnTypeForEmptyInput with DEFAULT,DUN
+ String[] defaultApnTypes = {"default", "dun"};
+ mApnEditorUT.mDefaultApnTypes = defaultApnTypes;
+
+ // Input empty in TYPE
+ final FakeApnData apnData = new FakeApnData(APN_DATA);
+ apnData.mData[ApnEditor.TYPE_INDEX] = "";
+ mApnEditorUT.mApnData = apnData;
+ mApnEditorUT.fillUI(true /* firstTime */);
+
+ // THEN APN type should be default
+ assertThat(mApnEditorUT.getUserEnteredApnType()).isEqualTo("default");
+
+ // case 2
+ // GIVEN read only APN types with DUN
+ String[] readOnlyApnTypesCase2 = {"dun"};
+ mApnEditorUT.mReadOnlyApnTypes = readOnlyApnTypesCase2;
+ // GIVEN read specificApnTypeForEmptyInput with DEFAULT
+ String[] defaultApnTypesCase2 = {"default"};
+ mApnEditorUT.mDefaultApnTypes = defaultApnTypesCase2;
+
+ // Input empty in TYPE
+ final FakeApnData apnDataCase2 = new FakeApnData(APN_DATA);
+ apnDataCase2.mData[ApnEditor.TYPE_INDEX] = "";
+ mApnEditorUT.mApnData = apnDataCase2;
+ mApnEditorUT.fillUI(true /* firstTime */);
+
+ // THEN APN type should be default
+ assertThat(mApnEditorUT.getUserEnteredApnType()).isEqualTo("default");
+ }
+
private void initCursor() {
doReturn(2).when(mCursor).getColumnCount();
doReturn(2).when(mCursor).getInt(CURSOR_INTEGER_INDEX);
import com.android.settingslib.wifi.WifiTracker;
import com.android.settingslib.wifi.WifiTrackerFactory;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
@Config(shadows = ShadowAlertDialogCompat.class)
public class NetworkRequestDialogActivityTest {
- @Test
- public void LaunchActivity_shouldShowNetworkRequestDialog() {
+ @Before
+ public void setUp() {
// Mocks fake WifiTracker, in case of exception in NetworkRequestDialogFragment.onResume().
WifiTracker wifiTracker = mock(WifiTracker.class);
WifiTrackerFactory.setTestingWifiTracker(wifiTracker);
+ }
+ @Test
+ public void launchActivity_shouldShowNetworkRequestDialog() {
Robolectric.setupActivity(NetworkRequestDialogActivity.class);
- AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
+ final AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
assertThat(alertDialog.isShowing()).isTrue();
}
WifiConfiguration config = mController.getConfig();
assertThat(config.macRandomizationSetting).isEqualTo(WifiConfiguration.RANDOMIZATION_NONE);
}
+
+ @Test
+ public void selectSecurity_wpa3Eap192bit_eapMethodTls() {
+ final WifiManager wifiManager = mock(WifiManager.class);
+ when(wifiManager.isWpa3SuiteBSupported()).thenReturn(true);
+ mController = new TestWifiConfigController(mConfigUiBase, mView, null /* accessPoint */,
+ WifiConfigUiBase.MODE_MODIFY, wifiManager);
+ final Spinner securitySpinner = mView.findViewById(R.id.security);
+ final Spinner eapMethodSpinner = mView.findViewById(R.id.method);
+ int wpa3Eap192bitPosition = -1;
+ final int securityCount = mController.mSecurityInPosition.length;
+ for (int i = 0; i < securityCount; i++) {
+ if (mController.mSecurityInPosition[i] != null &&
+ mController.mSecurityInPosition[i] == AccessPoint.SECURITY_EAP_SUITE_B) {
+ wpa3Eap192bitPosition = i;
+ }
+ }
+
+ mController.onItemSelected(securitySpinner, null /* view */, wpa3Eap192bitPosition,
+ 0 /* id */);
+
+ final int selectedItemPosition = eapMethodSpinner.getSelectedItemPosition();
+ assertThat(eapMethodSpinner.getSelectedItem().toString()).isEqualTo("TLS");
+ }
}
--- /dev/null
+/*
+ * Copyright (C) 2019 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.wifi.dpp;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
+import android.net.wifi.WifiManager;
+
+import com.android.settingslib.wifi.AccessPoint;
+
+import java.util.BitSet;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadows.ShadowApplication;
+
+@RunWith(RobolectricTestRunner.class)
+public class WifiDppUtilsTest {
+
+ @Mock
+ private WifiManager mWifiManager;
+
+ @Mock
+ private AccessPoint mAccessPoint;
+
+ @Mock
+ private WifiConfiguration mWifiConfiguration;
+
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mContext = spy(RuntimeEnvironment.application);
+ ShadowApplication shadowApplication = ShadowApplication.getInstance();
+ shadowApplication.setSystemService(Context.WIFI_SERVICE, mWifiManager);
+ }
+
+ @Test
+ public void getConfiguratorQrCodeScannerIntentOrNull_hiddenSsidNetwork_hasHiddenSsidExtra() {
+ when(mWifiManager.isEasyConnectSupported()).thenReturn(true);
+ when(mAccessPoint.isPasspoint()).thenReturn(false);
+ when(mAccessPoint.getSecurity()).thenReturn(AccessPoint.SECURITY_PSK);
+ when(mAccessPoint.getConfig()).thenReturn(mWifiConfiguration);
+ mWifiConfiguration.SSID = "GuestNetwork";
+ mWifiConfiguration.allowedKeyManagement = new BitSet();
+ mWifiConfiguration.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
+ mWifiConfiguration.hiddenSSID = true;
+
+ Intent intent = WifiDppUtils
+ .getConfiguratorQrCodeScannerIntentOrNull(mContext, mWifiManager, mAccessPoint);
+
+ assertThat(intent.getBooleanExtra(WifiDppUtils.EXTRA_WIFI_HIDDEN_SSID, false))
+ .isEqualTo(true);
+ }
+}