Snap for 5176559 from 2602e42b65 to qt-release

Change-Id: I82a1da2ccfcc4f49ec98f0fc1bf0bdc198ffff4f
This commit is contained in:
android-build-team Robot
2018-12-12 04:04:54 +00:00
38 changed files with 1346 additions and 484 deletions

View File

@@ -0,0 +1,39 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:pathData="M7,4v3H4V4H7M9,2H2v7h7V2L9,2z"/>
<path
android:fillColor="#FF000000"
android:pathData="M15,11l-8,0l0,2l8,0l0,-2z"/>
<path
android:fillColor="#FF000000"
android:pathData="M13,2l-2,0l0,11l2,0l0,-11z"/>
<path
android:fillColor="#FF000000"
android:pathData="M22,15l-11,0l0,2l11,0l0,-2z"/>
<path
android:fillColor="#FF000000"
android:pathData="M13,17l-2,0l0,5l2,0l0,-5z"/>
<path
android:fillColor="#FF000000"
android:pathData="M17,13l-2,0l0,9l2,0l0,-9z"/>
<path
android:fillColor="#FF000000"
android:pathData="M22,19l-3,0l0,3l3,0l0,-3z"/>
<path
android:fillColor="#FF000000"
android:pathData="M5,11l-3,0l0,2l3,0l0,-2z"/>
<path
android:fillColor="#FF000000"
android:pathData="M22,11l-5,0l0,2l5,0l0,-2z"/>
<path
android:fillColor="#FF000000"
android:pathData="M20,4v3h-3V4H20M22,2h-7v7h7V2L22,2z"/>
<path
android:fillColor="#FF000000"
android:pathData="M7,17v3H4v-3H7M9,15H2v7h7V15L9,15z"/>
</vector>

View File

@@ -0,0 +1,33 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:pathData="M9,2l-7,0l0,2l7,0l0,-2z"/>
<path
android:fillColor="#FF000000"
android:pathData="M22,2l-7,0l0,2l7,0l0,-2z"/>
<path
android:fillColor="#FF000000"
android:pathData="M22,11l-20,0l0,2l20,0l0,-2z"/>
<path
android:fillColor="#FF000000"
android:pathData="M22,2l-2,0l0,7l2,0l0,-7z"/>
<path
android:fillColor="#FF000000"
android:pathData="M4,2l-2,0l0,7l2,0l0,-7z"/>
<path
android:fillColor="#FF000000"
android:pathData="M9,20l-7,0l0,2l7,0l0,-2z"/>
<path
android:fillColor="#FF000000"
android:pathData="M22,20l-7,0l0,2l7,0l0,-2z"/>
<path
android:fillColor="#FF000000"
android:pathData="M22,15l-2,0l0,7l2,0l0,-7z"/>
<path
android:fillColor="#FF000000"
android:pathData="M4,15l-2,0l0,7l2,0l0,-7z"/>
</vector>

View File

@@ -38,20 +38,13 @@
android:textAppearance="?android:attr/textAppearanceMedium"/>
<TextView
android:id="@+id/capabilities_header"
android:id="@+id/accessibility_service_warning"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="10dip"
android:textAlignment="viewStart"
android:textAppearance="?android:attr/textAppearanceMedium"/>
<LinearLayout
android:id="@+id/capabilities"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dip"/>
</LinearLayout>
</ScrollView>

View File

@@ -653,6 +653,8 @@
<string name="done">Done</string>
<!-- Button label for generic apply action [CHAR LIMIT=20] -->
<string name="apply">Apply</string>
<!-- Button label for generic share action [CHAR LIMIT=20] -->
<string name="share">Share</string>
<!-- Title of the Settings activity shown within the application itself. -->
<string name="settings_label">Settings</string>
@@ -3765,6 +3767,8 @@
<string name="lockpassword_choose_your_pattern_header_for_face">To use face authentication, set pattern</string>
<!-- Header on first screen of choose password/PIN as backup for face authentication flow. If this string cannot be translated in under 40 characters, please translate "Set face authentication backup" [CHAR LIMIT=40] -->
<string name="lockpassword_choose_your_pin_header_for_face">To use face authentication, set PIN</string>
<!-- Message on Wi-Fi Sharing screen [CHAR LIMIT=NONE] -->
<string name="wifi_sharing_message">Your Wi\u2011Fi name and password for \"<xliff:g id="SSID" example="GoogleGuest">%1$s</xliff:g>\" will be shared.</string>
<!-- Message to be used to explain the user that he needs to enter his pattern to continue a
particular operation. [CHAR LIMIT=70]-->
@@ -4826,11 +4830,12 @@
example="TalkBack">%1$s</xliff:g> affects data encryption, you need to confirm your password.
</string>
<!-- Title for the capability of an accessibility service to receive events and keys. -->
<string name="capability_title_receiveAccessibilityEvents">Observe your actions</string>
<!-- Description for the capability of an accessibility service to receive events and keys. -->
<string name="capability_desc_receiveAccessibilityEvents">Receive notifications when you\u2019re
interacting with an app.</string>
<!-- Warning that explains that accessibility services have a lot of access to user data [CHAR LIMIT=NONE] -->
<string name="accessibility_service_warning"><xliff:g id="service"
example="TalkBack">%1$s</xliff:g> is requesting full control of this device. The service
can read the screen and act on behalf of users with accessibility needs.
This level of control is not appropriate for most apps.
</string>
<!-- Title for a warning about disabling an accessibility service. [CHAR LIMIT=NONE] -->
<string name="disable_service_title">Stop <xliff:g id="service" example="TalkBack">%1$s</xliff:g>?</string>
@@ -5417,11 +5422,23 @@
<!-- Battery saver: Label for preference to indicate there is no battery saver schedule [CHAR_LIMIT=40] -->
<string name="battery_saver_auto_no_schedule">No schedule</string>
<!-- Battery saver: Label for preference to indicate there is a routine based schedule [CHAR_LIMIT=40] -->
<string name="battery_saver_auto_routine">Based on your routine</string>
<!-- Battery saver: Label for preference to indicate there is a percentage based schedule [CHAR_LIMIT=40] -->
<string name="battery_saver_auto_percentage">Based on percentage</string>
<!-- Battery saver: Summary for preference to describe what is meant by a routine based schedule [CHAR_LIMIT=NONE] -->
<string name="battery_saver_auto_routine_summary">Battery Saver turns on if your battery is likely to run out before your next typical charge</string>
<!-- Battery saver: Label for seekbar to change battery saver threshold [CHAR_LIMIT=40] -->
<string name="battery_saver_auto_percentage_summary">Will turn on at <xliff:g id="percent" example="52%">%1$s</xliff:g></string>
<!-- Battery saver: Title for battery saver schedule screen [CHAR_LIMIT=40] -->
<string name="battery_saver_schedule_settings_title">Set a schedule</string>
<!-- Battery saver: Label for seekbar to change battery saver threshold [CHAR_LIMIT=40] -->
<string name="battery_saver_seekbar_title">At <xliff:g id="percent">%1$s</xliff:g></string>
<string name="battery_saver_seekbar_title"><xliff:g id="percent">%1$s</xliff:g></string>
<!-- Battery saver: Placeholder label for seekbar to change battery saver threshold [CHAR_LIMIT=40] -->
<string name="battery_saver_seekbar_title_placeholder">Turn on</string>
@@ -7137,6 +7154,9 @@
<!-- Do not disturb: Delete text button presented in a dialog to confirm the user would like to delete the selected DND rules. [CHAR LIMIT=30] -->
<string name="zen_mode_schedule_delete">Delete</string>
<!-- Do not disturb: Edit label for button that allows user to edit the dnd schedule name. [CHAR LIMIT=30] -->
<string name="zen_mode_rule_name_edit">Edit</string>
<!-- Do not disturb: Title for the zen mode automatic rules page in settings. [CHAR LIMIT=30] -->
<string name="zen_mode_automation_settings_page_title">Schedules</string>
@@ -7907,7 +7927,7 @@
<item quantity="other"><xliff:g id="num_people" example="3">%d</xliff:g> others</item>
</plurals>
<!-- [CHAR LIMIT=20] Zen mode settings: Messages option -->
<!-- [CHAR LIMIT=40] Zen mode settings: Messages option -->
<string name="zen_mode_messages">Allow text messages</string>
<!-- Do not disturb settings, messages, events and reminders footer [CHAR LIMIT=NONE]-->
@@ -10248,7 +10268,9 @@
<!-- Message for Network connection timeout Dialog [CHAR LIMIT=NONE] -->
<string name="network_connection_timeout_dialog_message">No devices found. Make sure the device is turned on and available to connect.</string>
<!-- OK button for Network connection timeout Dialog [CHAR LIMIT=30] -->
<string name="network_connection_timeout_dialog_ok">Scan again</string>
<string name="network_connection_timeout_dialog_ok">Try again</string>
<!-- Message for Network connection error state Dialog [CHAR LIMIT=NONE] -->
<string name="network_connection_errorstate_dialog_message">Something came up. The application has cancelled the request to choose a device.</string>
<!-- Summary for bluetooth devices count in Bluetooth devices slice. [CHAR LIMIT=NONE] -->
<plurals name="show_bluetooth_devices">

View File

@@ -20,6 +20,12 @@
android:title="@string/battery_saver"
android:key="battery_saver_page">
<Preference
android:key="battery_saver_schedule"
android:fragment="com.android.settings.fuelgauge.batterysaver.BatterySaverScheduleSettings"
android:title="@string/battery_saver_schedule_settings_title"
settings:controller="com.android.settings.fuelgauge.batterysaver.BatterySaverSchedulePreferenceController"/>
<!-- Turn on automatically -->
<SwitchPreference
android:key="auto_battery_saver"

View File

@@ -41,7 +41,8 @@
<SwitchPreference
android:key="wifi_cellular_data_fallback"
android:title="@string/wifi_cellular_data_fallback_title"
android:summary="@string/wifi_cellular_data_fallback_summary" />
android:summary="@string/wifi_cellular_data_fallback_summary"
settings:controller="com.android.settings.wifi.CellularFallbackPreferenceController" />
<Preference
android:key="install_credentials"

View File

@@ -17,12 +17,17 @@
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="zen_mode_event_rule_settings"
android:title="@string/zen_mode_automatic_rule_settings_page_title">
<com.android.settingslib.widget.LayoutPreference
android:key="pref_app_header"
android:layout="@layout/settings_entity_header" />
android:layout="@layout/settings_entity_header"
settings:allowDividerBelow="true" />
<com.android.settingslib.widget.ActionButtonsPreference
android:key="zen_action_buttons" />
<com.android.settingslib.widget.LayoutPreference
android:key="zen_automatic_rule_switch"

View File

@@ -17,12 +17,17 @@
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="zen_mode_schedule_rule_settings"
android:title="@string/zen_mode_automatic_rule_settings_page_title">
<com.android.settingslib.widget.LayoutPreference
android:key="pref_app_header"
android:layout="@layout/settings_entity_header" />
android:layout="@layout/settings_entity_header"
settings:allowDividerBelow="true"/>
<com.android.settingslib.widget.ActionButtonsPreference
android:key="zen_action_buttons"/>
<com.android.settingslib.widget.LayoutPreference
android:key="zen_automatic_rule_switch"

View File

@@ -43,8 +43,8 @@ import java.util.List;
import java.util.Locale;
/**
* Utility class for creating the dialog that asks users for explicit permission to grant
* all of the requested capabilities to an accessibility service before the service is enabled
* Utility class for creating the dialog that asks users for explicit permission for an
* accessibility service to access user data before the service is enabled
*/
public class AccessibilityServiceWarning {
public static Dialog createCapabilitiesDialog(Activity parentActivity,
@@ -117,60 +117,9 @@ public class AccessibilityServiceWarning {
encryptionWarningView.setVisibility(View.GONE);
}
TextView capabilitiesHeaderView = (TextView) content.findViewById(
R.id.capabilities_header);
capabilitiesHeaderView.setText(context.getString(R.string.capabilities_list_title,
getServiceName(context, info)));
LinearLayout capabilitiesView = (LinearLayout) content.findViewById(R.id.capabilities);
// This capability is implicit for all services.
View capabilityView = inflater.inflate(
com.android.internal.R.layout.app_permission_item_old, null);
ImageView imageView = (ImageView) capabilityView.findViewById(
com.android.internal.R.id.perm_icon);
imageView.setImageDrawable(context.getDrawable(
com.android.internal.R.drawable.ic_text_dot));
TextView labelView = (TextView) capabilityView.findViewById(
com.android.internal.R.id.permission_group);
labelView.setText(context.getString(
R.string.capability_title_receiveAccessibilityEvents));
TextView descriptionView = (TextView) capabilityView.findViewById(
com.android.internal.R.id.permission_list);
descriptionView.setText(
context.getString(R.string.capability_desc_receiveAccessibilityEvents));
List<AccessibilityServiceInfo.CapabilityInfo> capabilities =
info.getCapabilityInfos(context);
capabilitiesView.addView(capabilityView);
// Service-specific capabilities.
final int capabilityCount = capabilities.size();
for (int i = 0; i < capabilityCount; i++) {
AccessibilityServiceInfo.CapabilityInfo capability = capabilities.get(i);
capabilityView = inflater.inflate(
com.android.internal.R.layout.app_permission_item_old, null);
imageView = (ImageView) capabilityView.findViewById(
com.android.internal.R.id.perm_icon);
imageView.setImageDrawable(context.getDrawable(
com.android.internal.R.drawable.ic_text_dot));
labelView = (TextView) capabilityView.findViewById(
com.android.internal.R.id.permission_group);
labelView.setText(context.getString(capability.titleResId));
descriptionView = (TextView) capabilityView.findViewById(
com.android.internal.R.id.permission_list);
descriptionView.setText(context.getString(capability.descResId));
capabilitiesView.addView(capabilityView);
}
TextView serviceWarningTextView = content.findViewById(R.id.accessibility_service_warning);
serviceWarningTextView.setText(context.getString(R.string.accessibility_service_warning,
getServiceName(context, info)));
return content;
}

View File

@@ -667,6 +667,8 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
mToggleInversionPreference.getOrder() + 1);
mToggleDisableAnimationsPreference.setOrder(
mToggleLargePointerIconPreference.getOrder() + 1);
findPreference(ACCESSIBILITY_CONTENT_TIMEOUT_PREFERENCE).setOrder(
mToggleDisableAnimationsPreference.getOrder() + 1);
mToggleInversionPreference.setSummary(R.string.summary_empty);
displayCategory.addPreference(mToggleInversionPreference);
displayCategory.addPreference(mDisplayDaltonizerPreferenceScreen);

View File

@@ -26,4 +26,5 @@ public class FeatureFlags {
public static final String MOBILE_NETWORK_V2 = "settings_mobile_network_v2";
public static final String WIFI_MAC_RANDOMIZATION = "settings_wifi_mac_randomization";
public static final String NETWORK_INTERNET_V2 = "settings_network_and_internet_v2";
public static final String WIFI_SHARING = "settings_wifi_sharing";
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright (C) 2018 The Android Open Source Project
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.android.settings.fuelgauge.batterysaver;
import android.content.ContentResolver;
import android.content.Context;
import android.os.PowerManager;
import android.provider.Settings;
import android.provider.Settings.Global;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.core.BasePreferenceController;
public class BatterySaverSchedulePreferenceController extends BasePreferenceController {
@VisibleForTesting
Preference mBatterySaverSchedulePreference;
public static final String KEY_BATTERY_SAVER_SCHEDULE = "battery_saver_schedule";
public BatterySaverSchedulePreferenceController(Context context) {
super(context, KEY_BATTERY_SAVER_SCHEDULE);
}
@Override
public String getPreferenceKey() {
return KEY_BATTERY_SAVER_SCHEDULE;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mBatterySaverSchedulePreference = screen.findPreference(KEY_BATTERY_SAVER_SCHEDULE);
}
@Override
public CharSequence getSummary() {
final ContentResolver resolver = mContext.getContentResolver();
final int mode = Settings.Global.getInt(resolver, Global.AUTOMATIC_POWER_SAVER_MODE,
PowerManager.POWER_SAVER_MODE_PERCENTAGE);
if (mode == PowerManager.POWER_SAVER_MODE_PERCENTAGE) {
final int threshold =
Settings.Global.getInt(resolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
if (threshold <= 0) {
return mContext.getText(R.string.battery_saver_auto_no_schedule);
} else {
return mContext.getString(R.string.battery_saver_auto_percentage_summary,
Utils.formatPercentage(threshold));
}
} else {
return mContext.getText(R.string.battery_saver_auto_routine);
}
}
@Override
public int getAvailabilityStatus() {
return AVAILABLE;
}
}

View File

@@ -0,0 +1,138 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.fuelgauge.batterysaver;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.View;
import androidx.preference.PreferenceScreen;
import com.android.settings.widget.RadioButtonPickerFragment;
import com.android.settings.R;
import com.android.settings.widget.RadioButtonPreference;
import com.android.settings.widget.SeekBarPreference;
import com.android.settingslib.widget.CandidateInfo;
import com.google.common.collect.Lists;
import java.util.List;
public class BatterySaverScheduleSettings extends RadioButtonPickerFragment {
private static final String KEY_NO_SCHEDULE = "key_battery_saver_no_schedule";
private static final String KEY_ROUTINE = "key_battery_saver_routine";
private static final String KEY_PERCENTAGE = "key_battery_saver_percentage";
public static final int MAX_SEEKBAR_VALUE = 15;
public static final int MIN_SEEKBAR_VALUE = 1;
public static final String KEY_BATTERY_SAVER_SEEK_BAR = "battery_saver_seek_bar";
@Override
protected int getPreferenceScreenResId() {
return R.xml.battery_saver_schedule_settings;
}
@Override
protected List<? extends CandidateInfo> getCandidates() {
Context context = getContext();
List<CandidateInfo> candidates = Lists.newArrayList();
candidates.add(new BatterySaverScheduleCandidateInfo(
context.getText(R.string.battery_saver_auto_no_schedule),
/* summary */ null,
KEY_NO_SCHEDULE,
/* enabled */ true));
candidates.add(new BatterySaverScheduleCandidateInfo(
context.getText(R.string.battery_saver_auto_routine),
context.getText(R.string.battery_saver_auto_routine_summary),
KEY_ROUTINE,
/* enabled */ true));
candidates.add(new BatterySaverScheduleCandidateInfo(
context.getText(R.string.battery_saver_auto_percentage),
/* summary */ null,
KEY_PERCENTAGE,
/* enabled */ true));
return candidates;
}
@Override
public void bindPreferenceExtra(RadioButtonPreference pref, String key, CandidateInfo info,
String defaultKey, String systemDefaultKey) {
final BatterySaverScheduleCandidateInfo candidateInfo =
(BatterySaverScheduleCandidateInfo) info;
final CharSequence summary = candidateInfo.getSummary();
if (summary != null) {
pref.setSummary(summary);
pref.setAppendixVisibility(View.GONE);
}
}
@Override
protected void addStaticPreferences(PreferenceScreen screen) {
SeekBarPreference seekbar = new SeekBarPreference(getContext());
seekbar.setMax(MAX_SEEKBAR_VALUE);
seekbar.setMin(MIN_SEEKBAR_VALUE);
seekbar.setTitle(R.string.battery_saver_seekbar_title_placeholder);
seekbar.setKey(KEY_BATTERY_SAVER_SEEK_BAR);
screen.addPreference(seekbar);
}
@Override
protected String getDefaultKey() {
return null;
}
@Override
protected boolean setDefaultKey(String key) {
return false;
}
@Override
public int getMetricsCategory() {
return 0;
}
static class BatterySaverScheduleCandidateInfo extends CandidateInfo {
private final CharSequence mLabel;
private final CharSequence mSummary;
private final String mKey;
BatterySaverScheduleCandidateInfo(CharSequence label, CharSequence summary, String key,
boolean enabled) {
super(enabled);
mLabel = label;
mKey = key;
mSummary = summary;
}
@Override
public CharSequence loadLabel() {
return mLabel;
}
@Override
public Drawable loadIcon() {
return null;
}
@Override
public String getKey() {
return mKey;
}
public CharSequence getSummary() {
return mSummary;
}
}
}

View File

@@ -0,0 +1,97 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.network;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Handler;
import android.provider.Settings;
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
import com.android.internal.telephony.TelephonyIntents;
/** Helper class for listening to changes in availability of telephony subscriptions */
public class SubscriptionsChangeListener extends ContentObserver {
public interface SubscriptionsChangeListenerClient {
void onAirplaneModeChanged(boolean airplaneModeEnabled);
void onSubscriptionsChanged();
}
private Context mContext;
private SubscriptionsChangeListenerClient mClient;
private SubscriptionManager mSubscriptionManager;
private OnSubscriptionsChangedListener mSubscriptionsChangedListener;
private Uri mAirplaneModeSettingUri;
private BroadcastReceiver mBroadcastReceiver;
public SubscriptionsChangeListener(Context context, SubscriptionsChangeListenerClient client) {
super(new Handler());
mContext = context;
mClient = client;
mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class);
mSubscriptionsChangedListener = new OnSubscriptionsChangedListener() {
@Override
public void onSubscriptionsChanged() {
subscriptionsChangedCallback();
}
};
mAirplaneModeSettingUri = Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON);
mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
subscriptionsChangedCallback();
}
};
}
public void start() {
mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionsChangedListener);
mContext.getContentResolver()
.registerContentObserver(mAirplaneModeSettingUri, false, this);
final IntentFilter radioTechnologyChangedFilter = new IntentFilter(
TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
mContext.registerReceiver(mBroadcastReceiver, radioTechnologyChangedFilter);
}
public void stop() {
mSubscriptionManager.removeOnSubscriptionsChangedListener(mSubscriptionsChangedListener);
mContext.getContentResolver().unregisterContentObserver(this);
mContext.unregisterReceiver(mBroadcastReceiver);
}
public boolean isAirplaneModeOn() {
return Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
}
private void subscriptionsChangedCallback() {
mClient.onSubscriptionsChanged();
}
@Override
public void onChange(boolean selfChange, Uri uri) {
if (uri.equals(mAirplaneModeSettingUri)) {
mClient.onAirplaneModeChanged(isAirplaneModeOn());
}
}
}

View File

@@ -76,14 +76,6 @@ public class ZenAutomaticRuleHeaderPreferenceController extends AbstractZenModeP
mController = EntityHeaderController
.newInstance(mFragment.getActivity(), mFragment,
pref.findViewById(R.id.entity_header));
mController.setEditListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ZenRuleNameDialog.show(mFragment, mRule.getName(), null,
new RuleNameChangeListener());
}
});
}
pref = mController.setIcon(getIcon())
@@ -123,20 +115,4 @@ public class ZenAutomaticRuleHeaderPreferenceController extends AbstractZenModeP
mRule = rule;
mId = id;
}
public class RuleNameChangeListener implements ZenRuleNameDialog.PositiveClickListener {
public RuleNameChangeListener() {}
@Override
public void onOk(String ruleName, Fragment parent) {
if (TextUtils.equals(ruleName, mRule.getName())) {
return;
}
mMetricsFeatureProvider.action(mContext,
MetricsProto.MetricsEvent.ACTION_ZEN_MODE_RULE_NAME_CHANGE_OK);
mRule.setName(ruleName);
mRule.setModified(true);
mBackend.updateZenRule(mId, mRule);
}
}
}

View File

@@ -20,6 +20,7 @@ import android.app.AlertDialog;
import android.app.AutomaticZenRule;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.provider.SearchIndexableResource;
import android.service.notification.ConditionProviderService;
import android.view.Menu;
@@ -44,11 +45,22 @@ import java.util.Map;
@SearchIndexable
public class ZenModeAutomationSettings extends ZenModeSettingsBase {
public static final String DELETE = "DELETE_RULE";
protected final ManagedServiceSettings.Config CONFIG = getConditionProviderConfig();
private CharSequence[] mDeleteDialogRuleNames;
private String[] mDeleteDialogRuleIds;
private boolean[] mDeleteDialogChecked;
@Override
public void onAttach(Context context) {
super.onAttach(context);
Bundle bundle = getArguments();
if (bundle != null && bundle.containsKey(DELETE)) {
mBackend.removeZenRule(bundle.getString(DELETE));
bundle.remove(DELETE);
}
}
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
ZenServiceListing serviceListing = new ZenServiceListing(getContext(), CONFIG);

View File

@@ -27,6 +27,11 @@ import android.provider.Settings;
import android.service.notification.ZenModeConfig;
import android.service.notification.ZenModeConfig.EventInfo;
import androidx.preference.DropDownPreference;
import androidx.preference.Preference;
import androidx.preference.Preference.OnPreferenceChangeListener;
import androidx.preference.PreferenceScreen;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
@@ -38,11 +43,6 @@ import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import androidx.preference.DropDownPreference;
import androidx.preference.Preference;
import androidx.preference.Preference.OnPreferenceChangeListener;
import androidx.preference.PreferenceScreen;
public class ZenModeEventRuleSettings extends ZenModeRuleSettingsBase {
private static final String KEY_CALENDAR = "calendar";
private static final String KEY_REPLY = "reply";
@@ -85,9 +85,12 @@ public class ZenModeEventRuleSettings extends ZenModeRuleSettingsBase {
List<AbstractPreferenceController> controllers = new ArrayList<>();
mHeader = new ZenAutomaticRuleHeaderPreferenceController(context, this,
getSettingsLifecycle());
mActionButtons = new ZenRuleButtonsPreferenceController(context, this,
getSettingsLifecycle());
mSwitch = new ZenAutomaticRuleSwitchPreferenceController(context, this,
getSettingsLifecycle());
controllers.add(mHeader);
controllers.add(mActionButtons);
controllers.add(mSwitch);
return controllers;
}
@@ -107,8 +110,16 @@ public class ZenModeEventRuleSettings extends ZenModeRuleSettingsBase {
mEvent.calendarId = calendar.calendarId;
}
}
mCalendar.setEntries(entries.toArray(new CharSequence[entries.size()]));
mCalendar.setEntryValues(values.toArray(new CharSequence[values.size()]));
CharSequence[] entriesArr = entries.toArray(new CharSequence[entries.size()]);
CharSequence[] valuesArr = values.toArray(new CharSequence[values.size()]);
if (!Objects.equals(mCalendar.getEntries(), entriesArr)) {
mCalendar.setEntries(entriesArr);
}
if (!Objects.equals(mCalendar.getEntryValues(), valuesArr)) {
mCalendar.setEntryValues(valuesArr);
}
}
@Override
@@ -159,8 +170,12 @@ public class ZenModeEventRuleSettings extends ZenModeRuleSettingsBase {
@Override
protected void updateControlsInternal() {
mCalendar.setValue(key(mEvent));
mReply.setValue(Integer.toString(mEvent.reply));
if (!Objects.equals(mCalendar.getValue(), key(mEvent))) {
mCalendar.setValue(key(mEvent));
}
if (!Objects.equals(mReply.getValue(), Integer.toString(mEvent.reply))) {
mReply.setValue(Integer.toString(mEvent.reply));
}
}
@Override
@@ -233,7 +248,7 @@ public class ZenModeEventRuleSettings extends ZenModeRuleSettingsBase {
private static String key(int userId, Long calendarId, String displayName) {
return EventInfo.resolveUserId(userId) + ":" + (calendarId == null ? "" : calendarId)
+ ":" + displayName;
+ ":" + (displayName == null ? "" : displayName);
}
private static final Comparator<CalendarInfo> CALENDAR_NAME = new Comparator<CalendarInfo>() {

View File

@@ -43,6 +43,7 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase {
protected String mId;
protected ZenAutomaticRuleHeaderPreferenceController mHeader;
protected ZenRuleButtonsPreferenceController mActionButtons;
protected ZenAutomaticRuleSwitchPreferenceController mSwitch;
abstract protected void onCreateInternal();
@@ -104,6 +105,10 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase {
mHeader.onResume(mRule, mId);
mHeader.displayPreference(screen);
updatePreference(mHeader);
mActionButtons.onResume(mRule, mId);
mActionButtons.displayPreference(screen);
updatePreference(mActionButtons);
}
private void updatePreference(AbstractPreferenceController controller) {
@@ -147,7 +152,8 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase {
private void toastAndFinish() {
Toast.makeText(mContext, R.string.zen_mode_rule_not_found_text, Toast.LENGTH_SHORT)
.show();
.show();
getActivity().finish();
}

View File

@@ -199,10 +199,12 @@ public class ZenModeScheduleRuleSettings extends ZenModeRuleSettingsBase {
List<AbstractPreferenceController> controllers = new ArrayList<>();
mHeader = new ZenAutomaticRuleHeaderPreferenceController(context, this,
getSettingsLifecycle());
mActionButtons = new ZenRuleButtonsPreferenceController(context, this,
getSettingsLifecycle());
mSwitch = new ZenAutomaticRuleSwitchPreferenceController(context, this,
getSettingsLifecycle());
controllers.add(mHeader);
controllers.add(mActionButtons);
controllers.add(mSwitch);
return controllers;
}

View File

@@ -52,9 +52,14 @@ abstract public class ZenModeSettingsBase extends RestrictedDashboardFragment {
}
@Override
public void onCreate(Bundle icicle) {
mContext = getActivity();
public void onAttach(Context context) {
super.onAttach(context);
mContext = context;
mBackend = ZenModeBackend.getInstance(mContext);
}
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
updateZenMode(false /*fireChanged*/);
}

View File

@@ -0,0 +1,124 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.notification;
import android.app.AutomaticZenRule;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import androidx.fragment.app.Fragment;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceScreen;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.core.SubSettingLauncher;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.widget.ActionButtonsPreference;
public class ZenRuleButtonsPreferenceController extends AbstractZenModePreferenceController
implements PreferenceControllerMixin {
public static final String KEY = "zen_action_buttons";
private AutomaticZenRule mRule;
private String mId;
private PreferenceFragmentCompat mFragment;
private ActionButtonsPreference mButtonsPref;
public ZenRuleButtonsPreferenceController(Context context, PreferenceFragmentCompat fragment,
Lifecycle lc) {
super(context, KEY, lc);
mFragment = fragment;
}
@Override
public boolean isAvailable() {
return mRule != null;
}
@Override
public void displayPreference(PreferenceScreen screen) {
if (isAvailable()) {
mButtonsPref = ((ActionButtonsPreference) screen.findPreference(KEY))
.setButton1Text(R.string.zen_mode_rule_name_edit)
.setButton1Icon(R.drawable.ic_mode_edit)
.setButton1OnClickListener(new EditRuleNameClickListener())
.setButton2Text(R.string.zen_mode_delete_rule_button)
.setButton2Icon(R.drawable.ic_settings_delete)
.setButton2OnClickListener(new DeleteRuleClickListener());
}
}
public class EditRuleNameClickListener implements View.OnClickListener {
public EditRuleNameClickListener() {}
@Override
public void onClick(View v) {
ZenRuleNameDialog.show(mFragment, mRule.getName(), null,
new ZenRuleNameDialog.PositiveClickListener() {
@Override
public void onOk(String ruleName, Fragment parent) {
if (TextUtils.equals(ruleName, mRule.getName())) {
return;
}
mMetricsFeatureProvider.action(mContext,
MetricsProto.MetricsEvent.ACTION_ZEN_MODE_RULE_NAME_CHANGE_OK);
mRule.setName(ruleName);
mRule.setModified(true);
mBackend.updateZenRule(mId, mRule);
}
});
}
}
public class DeleteRuleClickListener implements View.OnClickListener {
public DeleteRuleClickListener() {}
@Override
public void onClick(View v) {
ZenDeleteRuleDialog.show(mFragment, mRule.getName(), mId,
new ZenDeleteRuleDialog.PositiveClickListener() {
@Override
public void onOk(String id) {
Bundle bundle = new Bundle();
bundle.putString(ZenModeAutomationSettings.DELETE, id);
mMetricsFeatureProvider.action(mContext,
MetricsProto.MetricsEvent.ACTION_ZEN_DELETE_RULE_OK);
new SubSettingLauncher(mContext)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
.setDestination(ZenModeAutomationSettings.class.getName())
.setSourceMetricsCategory(MetricsProto.MetricsEvent
.NOTIFICATION_ZEN_MODE_AUTOMATION)
.setArguments(bundle)
.launch();
}
});
}
}
protected void onResume(AutomaticZenRule rule, String id) {
mRule = rule;
mId = id;
}
}

View File

@@ -44,6 +44,8 @@ public class RadioButtonPreference extends CheckBoxPreference {
}
private OnClickListener mListener = null;
private View appendix;
private int appendixVisibility = -1;
public RadioButtonPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
@@ -81,6 +83,10 @@ public class RadioButtonPreference extends CheckBoxPreference {
if (summaryContainer != null) {
summaryContainer.setVisibility(
TextUtils.isEmpty(getSummary()) ? View.GONE : View.VISIBLE);
appendix = view.findViewById(R.id.appendix);
if (appendix != null && appendixVisibility != -1) {
appendix.setVisibility(appendixVisibility);
}
}
TextView title = (TextView) view.findViewById(android.R.id.title);
@@ -89,4 +95,11 @@ public class RadioButtonPreference extends CheckBoxPreference {
title.setMaxLines(3);
}
}
public void setAppendixVisibility(int visibility) {
if (appendix != null) {
appendix.setVisibility(visibility);
}
appendixVisibility = visibility;
}
}

View File

@@ -18,62 +18,34 @@ package com.android.settings.wifi;
import android.content.Context;
import android.provider.Settings;
import android.text.TextUtils;
import androidx.preference.Preference;
import androidx.preference.SwitchPreference;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settings.core.TogglePreferenceController;
/**
* {@link AbstractPreferenceController} that controls whether we should fall back to celluar when
* CellularFallbackPreferenceController controls whether we should fall back to celluar when
* wifi is bad.
*/
public class CellularFallbackPreferenceController extends AbstractPreferenceController
implements PreferenceControllerMixin {
public class CellularFallbackPreferenceController extends TogglePreferenceController {
private static final String KEY_CELLULAR_FALLBACK = "wifi_cellular_data_fallback";
public CellularFallbackPreferenceController(Context context) {
super(context);
public CellularFallbackPreferenceController(Context context, String key) {
super(context, key);
}
@Override
public boolean isAvailable() {
return !avoidBadWifiConfig();
public int getAvailabilityStatus() {
return !avoidBadWifiConfig() ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
}
@Override
public String getPreferenceKey() {
return KEY_CELLULAR_FALLBACK;
public boolean isChecked() {
return avoidBadWifiCurrentSettings();
}
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
if (!TextUtils.equals(preference.getKey(), KEY_CELLULAR_FALLBACK)) {
return false;
}
if (!(preference instanceof SwitchPreference)) {
return false;
}
public boolean setChecked(boolean isChecked) {
// On: avoid bad wifi. Off: prompt.
String settingName = Settings.Global.NETWORK_AVOID_BAD_WIFI;
Settings.Global.putString(mContext.getContentResolver(), settingName,
((SwitchPreference) preference).isChecked() ? "1" : null);
return true;
}
@Override
public void updateState(Preference preference) {
final boolean currentSetting = avoidBadWifiCurrentSettings();
// TODO: can this ever be null? The return value of avoidBadWifiConfig() can only
// change if the resources change, but if that happens the activity will be recreated...
if (preference != null) {
SwitchPreference pref = (SwitchPreference) preference;
pref.setChecked(currentSetting);
}
return Settings.Global.putString(mContext.getContentResolver(),
Settings.Global.NETWORK_AVOID_BAD_WIFI, isChecked ? "1" : null);
}
private boolean avoidBadWifiConfig() {
@@ -85,4 +57,4 @@ public class CellularFallbackPreferenceController extends AbstractPreferenceCont
return "1".equals(Settings.Global.getString(mContext.getContentResolver(),
Settings.Global.NETWORK_AVOID_BAD_WIFI));
}
}
}

View File

@@ -85,7 +85,6 @@ public class ConfigureWifiSettings extends DashboardFragment {
controllers.add(mUseOpenWifiPreferenceController);
controllers.add(new WifiInfoPreferenceController(context, getSettingsLifecycle(),
wifiManager));
controllers.add(new CellularFallbackPreferenceController(context));
controllers.add(new WifiP2pPreferenceController(context, getSettingsLifecycle(),
wifiManager));
return controllers;

View File

@@ -44,12 +44,18 @@ import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.wifi.NetworkRequestErrorDialogFragment.ERROR_DIALOG_TYPE;
import com.android.settingslib.Utils;
import com.android.settingslib.wifi.AccessPoint;
import java.util.ArrayList;
import java.util.List;
/**
* The Fragment sets up callback {@link NetworkRequestMatchCallback} with framework. To handle most
* behaviors of the callback when requesting wifi network, except for error message. When error
* happens, {@link NetworkRequestErrorDialogFragment} will be called to display error message.
*/
public class NetworkRequestDialogFragment extends InstrumentedDialogFragment implements
DialogInterface.OnClickListener, NetworkRequestMatchCallback {
@@ -131,7 +137,7 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp
@Override
public void onCancel(@NonNull DialogInterface dialog) {
super.onCancel(dialog);
// Finishes activity when user clicks back key or outside of dialog.
// Finishes the activity when user clicks back key or outside of the dialog.
getActivity().finish();
}
@@ -166,7 +172,7 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp
switch (msg.what) {
case MESSAGE_STOP_SCAN_WIFI_LIST:
removeMessages(MESSAGE_STOP_SCAN_WIFI_LIST);
stopScanningAndPopTimeoutDialog();
stopScanningAndPopErrorDialog(ERROR_DIALOG_TYPE.TIME_OUT);
break;
default:
// Do nothing.
@@ -175,14 +181,18 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp
}
};
protected void stopScanningAndPopTimeoutDialog() {
protected void stopScanningAndPopErrorDialog(ERROR_DIALOG_TYPE type) {
// Dismisses current dialog.
dismiss();
// Throws new timeout dialog.
final NetworkRequestTimeoutDialogFragment fragment = NetworkRequestTimeoutDialogFragment
final NetworkRequestErrorDialogFragment fragment = NetworkRequestErrorDialogFragment
.newInstance();
fragment.show(getActivity().getSupportFragmentManager(), null);
final Bundle bundle = new Bundle();
bundle.putSerializable(NetworkRequestErrorDialogFragment.DIALOG_TYPE, type);
fragment.setArguments(bundle);
fragment.show(getActivity().getSupportFragmentManager(),
NetworkRequestDialogFragment.class.getSimpleName());
}
@Override
@@ -239,7 +249,7 @@ public class NetworkRequestDialogFragment extends InstrumentedDialogFragment imp
@Override
public void onAbort() {
// TODO(b/117399926): We should have a UI notify user here.
stopScanningAndPopErrorDialog(ERROR_DIALOG_TYPE.ABORT);
}
@Override

View File

@@ -0,0 +1,86 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.wifi;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
/**
* The dialog shows an error message when requesting network {@link NetworkRequestDialogFragment}.
* Contains multi-error types in {@code ERROR_DIALOG_TYPE}.
*/
public class NetworkRequestErrorDialogFragment extends InstrumentedDialogFragment {
public static final String DIALOG_TYPE = "DIALOG_ERROR_TYPE";
public enum ERROR_DIALOG_TYPE {TIME_OUT, ABORT}
public static NetworkRequestErrorDialogFragment newInstance() {
return new NetworkRequestErrorDialogFragment();
}
private NetworkRequestErrorDialogFragment() {
super();
}
@Override
public void onCancel(@NonNull DialogInterface dialog) {
super.onCancel(dialog);
// Wants to finish the activity when user clicks back key or outside of the dialog.
getActivity().finish();
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Gets error type to construct dialog. Default is TIME_OUT dialog.
ERROR_DIALOG_TYPE msgType = ERROR_DIALOG_TYPE.TIME_OUT;
if (getArguments() != null) {
msgType = (ERROR_DIALOG_TYPE) getArguments().getSerializable(DIALOG_TYPE);
}
final AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
if (msgType == ERROR_DIALOG_TYPE.TIME_OUT) {
builder.setMessage(R.string.network_connection_timeout_dialog_message)
.setPositiveButton(R.string.network_connection_timeout_dialog_ok,
(dialog, which) -> startScanningDialog())
.setNegativeButton(R.string.cancel, (dialog, which) -> getActivity().finish());
} else {
builder.setMessage(R.string.network_connection_errorstate_dialog_message)
.setPositiveButton(R.string.okay, (dialog, which) -> getActivity().finish());
}
return builder.create();
}
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.WIFI_SCANNING_NEEDED_DIALOG;
}
protected void startScanningDialog() {
final NetworkRequestDialogFragment fragment = NetworkRequestDialogFragment.newInstance();
fragment.show(getActivity().getSupportFragmentManager(),
NetworkRequestErrorDialogFragment.class.getSimpleName());
}
}

View File

@@ -1,66 +0,0 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.wifi;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import androidx.appcompat.app.AlertDialog;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
public class NetworkRequestTimeoutDialogFragment extends InstrumentedDialogFragment implements
DialogInterface.OnClickListener {
public static NetworkRequestTimeoutDialogFragment newInstance() {
NetworkRequestTimeoutDialogFragment fragment = new NetworkRequestTimeoutDialogFragment();
return fragment;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getContext())
.setMessage(R.string.network_connection_timeout_dialog_message)
.setPositiveButton(R.string.network_connection_timeout_dialog_ok, this)
.setNegativeButton(R.string.cancel, null);
return builder.create();
}
@Override
public int getMetricsCategory() {
return MetricsProto.MetricsEvent.WIFI_SCANNING_NEEDED_DIALOG;
}
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
startScanningDialog();
break;
case DialogInterface.BUTTON_NEGATIVE:
default:
// Do nothing.
break;
}
}
protected void startScanningDialog() {
NetworkRequestDialogFragment fragment = NetworkRequestDialogFragment.newInstance();
fragment.show(getActivity().getSupportFragmentManager(), null);
}
}

View File

@@ -20,6 +20,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import android.app.Activity;
import android.app.KeyguardManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -40,6 +41,7 @@ import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Handler;
import android.text.TextUtils;
import android.util.FeatureFlagUtils;
import android.util.Log;
import android.widget.ImageView;
import android.widget.Toast;
@@ -54,8 +56,11 @@ import androidx.preference.PreferenceScreen;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.core.FeatureFlags;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.widget.EntityHeaderController;
import com.android.settings.wifi.dpp.WifiDppConfiguratorActivity;
import com.android.settings.wifi.dpp.WifiDppUtils;
import com.android.settings.wifi.WifiDialog;
import com.android.settings.wifi.WifiDialog.WifiDialogListener;
import com.android.settings.wifi.WifiUtils;
@@ -280,7 +285,10 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
.setButton1Icon(R.drawable.ic_settings_delete)
.setButton1OnClickListener(view -> forgetNetwork())
.setButton2Text(R.string.wifi_sign_in_button_text)
.setButton2OnClickListener(view -> signIntoNetwork());
.setButton2OnClickListener(view -> signIntoNetwork())
.setButton3Text(R.string.share)
.setButton3Icon(R.drawable.ic_qrcode_24dp)
.setButton3OnClickListener(view -> shareNetwork());
mSignalStrengthPref = screen.findPreference(KEY_SIGNAL_STRENGTH_PREF);
mLinkSpeedPref = screen.findPreference(KEY_LINK_SPEED);
@@ -296,7 +304,7 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
mIpv6Category = (PreferenceCategory) screen.findPreference(KEY_IPV6_CATEGORY);
mIpv6AddressPref = screen.findPreference(KEY_IPV6_ADDRESSES_PREF);
mSecurityPref.setSummary(mAccessPoint.getSecurityString(false /* concise */));
mSecurityPref.setSummary(mAccessPoint.getSecurityString(/* concise */ false));
}
private void setupEntityHeader(PreferenceScreen screen) {
@@ -425,7 +433,9 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
private void updateIpLayerInfo() {
mButtonsPref.setButton2Visible(canSignIntoNetwork());
mButtonsPref.setVisible(canSignIntoNetwork() || canForgetNetwork());
mButtonsPref.setButton3Visible(isSharingNetworkEnabled());
mButtonsPref.setVisible(
canSignIntoNetwork() || canForgetNetwork() || isSharingNetworkEnabled());
if (mNetwork == null || mLinkProperties == null) {
mIpAddressPref.setVisible(false);
@@ -510,6 +520,13 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
return WifiUtils.canSignIntoNetwork(mNetworkCapabilities);
}
/**
* Returns whether the user can share the network represented by this preference with QR code.
*/
private boolean isSharingNetworkEnabled() {
return FeatureFlagUtils.isEnabled(mContext, FeatureFlags.WIFI_SHARING);
}
/**
* Forgets the wifi network associated with this preference.
*/
@@ -528,6 +545,42 @@ public class WifiDetailPreferenceController extends AbstractPreferenceController
mFragment.getActivity().finish();
}
/**
* Show QR code to share the network represented by this preference.
*/
public void launchQRCodeGenerator() {
final Intent intent = new Intent(
WifiDppConfiguratorActivity.ACTION_CONFIGURATOR_QR_CODE_GENERATOR);
intent.putExtra(WifiDppUtils.EXTRA_WIFI_SECURITY,
mAccessPoint.getSecurityString(/* concise */ false));
intent.putExtra(WifiDppUtils.EXTRA_WIFI_SSID, mAccessPoint.getSsidStr());
mContext.startActivity(intent);
}
/**
* Share the wifi network with QR code.
*/
private void shareNetwork() {
final KeyguardManager keyguardManager = (KeyguardManager) mContext.getSystemService(
Context.KEYGUARD_SERVICE);
if (keyguardManager.isKeyguardSecure()) {
// Show authentication screen to confirm credentials (pin, pattern or password) for
// the current user of the device.
final String description = String.format(
mContext.getString(R.string.wifi_sharing_message),
mAccessPoint.getSsidStr());
final Intent intent = keyguardManager.createConfirmDeviceCredentialIntent(
mContext.getString(R.string.lockpassword_confirm_your_pattern_header),
description);
if (intent != null) {
mFragment.startActivityForResult(intent,
WifiNetworkDetailsFragment.REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS);
}
} else {
launchQRCodeGenerator();
}
}
/**
* Sign in to the captive portal found on this wifi network associated with this preference.
*/

View File

@@ -17,8 +17,10 @@ package com.android.settings.wifi.details;
import static com.android.settings.wifi.WifiSettings.WIFI_DIALOG_ID;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.wifi.WifiManager;
import android.os.Bundle;
@@ -52,6 +54,8 @@ public class WifiNetworkDetailsFragment extends DashboardFragment {
private static final String TAG = "WifiNetworkDetailsFrg";
public static final int REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS = 1;
private AccessPoint mAccessPoint;
private WifiDetailPreferenceController mWifiDetailPreferenceController;
@@ -142,4 +146,14 @@ public class WifiNetworkDetailsFragment extends DashboardFragment {
return controllers;
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_CONFIRM_DEVICE_CREDENTIALS
&& resultCode == Activity.RESULT_OK) {
mWifiDetailPreferenceController.launchQRCodeGenerator();
}
}
}

View File

@@ -86,7 +86,7 @@ public class AutoBatterySeekBarPreferenceControllerTest {
mController.updateState(mPreference);
assertThat(mPreference.isVisible()).isTrue();
assertThat(mPreference.getTitle()).isEqualTo("At 20%");
assertThat(mPreference.getTitle()).isEqualTo("20%");
assertThat(mPreference.getProgress()).isEqualTo(TRIGGER_LEVEL / INTERVAL);
}

View File

@@ -0,0 +1,94 @@
/*
* Copyright (C) 2018 The Android Open Source Project
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package com.android.settings.fuelgauge.batterysaver;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.os.PowerManager;
import android.provider.Settings;
import android.provider.Settings.Global;
import androidx.preference.Preference;
import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(shadows = SettingsShadowResources.class)
public class BatterySaverSchedulePreferenceControllerTest {
private static final int TRIGGER_LEVEL = 20;
private static final int DEFAULT_LEVEL = 15;
private BatterySaverSchedulePreferenceController mController;
private Context mContext;
private Preference mPreference;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
SettingsShadowResources.overrideResource(
com.android.internal.R.integer.config_lowBatteryWarningLevel, DEFAULT_LEVEL);
mContext = RuntimeEnvironment.application;
mController = new BatterySaverSchedulePreferenceController(mContext);
mPreference = new Preference(mContext);
mController.mBatterySaverSchedulePreference = mPreference;
}
@Test
public void testPreference_lowPowerLevelZero_percentageMode_summaryNoSchedule() {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
Settings.Global.putInt(mContext.getContentResolver(),
Global.AUTOMATIC_POWER_SAVER_MODE, PowerManager.POWER_SAVER_MODE_PERCENTAGE);
mController.updateState(mPreference);
assertThat(mPreference.getSummary()).isEqualTo("No schedule");
}
@Test
public void testPreference_lowPowerLevelNonZero_percentageMode_summaryPercentage() {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, TRIGGER_LEVEL);
Settings.Global.putInt(mContext.getContentResolver(),
Global.AUTOMATIC_POWER_SAVER_MODE, PowerManager.POWER_SAVER_MODE_PERCENTAGE);
mController.updateState(mPreference);
assertThat(mPreference.getSummary()).isEqualTo("Will turn on at 20%");
}
@Test
public void testPreference_percentageRoutine_summaryRoutine() {
// It doesn't matter what this is set to for routine mode
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, TRIGGER_LEVEL);
Settings.Global.putInt(mContext.getContentResolver(),
Global.AUTOMATIC_POWER_SAVER_MODE, PowerManager.POWER_SAVER_MODE_DYNAMIC);
mController.updateState(mPreference);
assertThat(mPreference.getSummary()).isEqualTo("Based on your routine");
}
}

View File

@@ -0,0 +1,129 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.network;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.AdditionalMatchers.eq;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.ContentObserver;
import android.net.Uri;
import android.provider.Settings;
import android.telephony.SubscriptionManager;
import com.android.settings.network.SubscriptionsChangeListener.SubscriptionsChangeListenerClient;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
@RunWith(SettingsRobolectricTestRunner.class)
public class SubscriptionsChangeListenerTest {
@Mock
private SubscriptionsChangeListenerClient mClient;
@Mock
private SubscriptionManager mSubscriptionManager;
private Context mContext;
private SubscriptionsChangeListener mListener;
private Uri mAirplaneModeUri;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
mAirplaneModeUri = Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON);
}
private void initListener(boolean alsoStart) {
mListener = new SubscriptionsChangeListener(mContext, mClient);
if (alsoStart) {
mListener.start();
}
}
@Test
public void whenStartNotCalled_noListeningWasSetup() {
final ContentResolver contentResolver = mock(ContentResolver.class);
when(mContext.getContentResolver()).thenReturn(contentResolver);
initListener(false);
verify(contentResolver, never()).registerContentObserver(any(Uri.class), anyBoolean(),
any(ContentObserver.class));
verify(mSubscriptionManager, never()).addOnSubscriptionsChangedListener(any());
verify(mContext, never()).registerReceiver(any(), any());
}
@Test
public void onSubscriptionsChangedEvent_subscriptionManagerFires_eventDeliveredToUs() {
initListener(true);
final ArgumentCaptor<SubscriptionManager.OnSubscriptionsChangedListener> captor =
ArgumentCaptor.forClass(SubscriptionManager.OnSubscriptionsChangedListener.class);
verify(mSubscriptionManager).addOnSubscriptionsChangedListener(captor.capture());
captor.getValue().onSubscriptionsChanged();
verify(mClient).onSubscriptionsChanged();
}
@Test
public void onSubscriptionsChangedEvent_radioTechnologyChangedBroadcast_eventDeliveredToUs() {
initListener(true);
final ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
ArgumentCaptor.forClass(BroadcastReceiver.class);
verify(mContext).registerReceiver(broadcastReceiverCaptor.capture(), any());
broadcastReceiverCaptor.getValue().onReceive(mContext, null);
verify(mClient).onSubscriptionsChanged();
}
@Test
public void onAirplaneModeChangedEvent_becameTrue_eventFires() {
initListener(true);
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 1);
mListener.onChange(false, mAirplaneModeUri);
verify(mClient).onAirplaneModeChanged(true);
assertThat(mListener.isAirplaneModeOn()).isTrue();
}
@Test
public void onAirplaneModeChangedEvent_becameFalse_eventFires() {
initListener(true);
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0);
mListener.onChange(false, mAirplaneModeUri);
verify(mClient).onAirplaneModeChanged(false);
assertThat(mListener.isAirplaneModeOn()).isFalse();
}
}

View File

@@ -24,6 +24,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.app.Application;
import android.view.LayoutInflater;
import android.view.View;
import androidx.preference.PreferenceViewHolder;
@@ -93,4 +94,13 @@ public class RadioButtonPreferenceTest {
mPreference.onBindViewHolder(preferenceViewHolder);
assertEquals(View.GONE, summaryContainer.getVisibility());
}
@Test
public void hideAppendix_shouldBeGone() {
mPreference.setAppendixVisibility(View.GONE);
View view = LayoutInflater.from(mContext).inflate(R.layout.preference_radio, null);
PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(view);
mPreference.onBindViewHolder(holder);
assertThat(holder.findViewById(R.id.appendix).getVisibility()).isEqualTo(View.GONE);
}
}

View File

@@ -33,6 +33,7 @@ import org.mockito.MockitoAnnotations;
@RunWith(SettingsRobolectricTestRunner.class)
public class CellularFallbackPreferenceControllerTest {
private static final String KEY_CELLULAR_FALLBACK = "wifi_cellular_data_fallback";
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Context mContext;
@@ -42,7 +43,7 @@ public class CellularFallbackPreferenceControllerTest {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mController = new CellularFallbackPreferenceController(mContext);
mController = new CellularFallbackPreferenceController(mContext, KEY_CELLULAR_FALLBACK);
}
@Test

View File

@@ -17,6 +17,7 @@
package com.android.settings.wifi;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
@@ -32,213 +33,220 @@ import android.net.wifi.WifiManager;
import android.net.wifi.WifiManager.NetworkRequestUserSelectionCallback;
import android.os.Bundle;
import android.widget.Button;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.FragmentActivity;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResourcesImpl;
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
import com.android.settings.wifi.NetworkRequestErrorDialogFragment.ERROR_DIALOG_TYPE;
import com.android.settingslib.wifi.AccessPoint;
import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
import org.robolectric.shadows.ShadowLooper;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(shadows = {SettingsShadowResourcesImpl.class, ShadowAlertDialogCompat.class})
public class NetworkRequestDialogFragmentTest {
final String KEY_SSID = "key_ssid";
final String KEY_SSID = "key_ssid";
private FragmentActivity mActivity;
private NetworkRequestDialogFragment networkRequestDialogFragment;
private Context mContext;
private FragmentActivity mActivity;
private NetworkRequestDialogFragment networkRequestDialogFragment;
private Context mContext;
@Before
public void setUp() {
mActivity = Robolectric.setupActivity(FragmentActivity.class);
networkRequestDialogFragment = spy(NetworkRequestDialogFragment.newInstance());
mContext = spy(RuntimeEnvironment.application);
}
@Test
public void display_shouldShowTheDialog() {
networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), null);
AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
assertThat(alertDialog).isNotNull();
assertThat(alertDialog.isShowing()).isTrue();
}
@Test
public void clickPositiveButton_shouldCloseTheDialog() {
networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), null);
AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
assertThat(alertDialog.isShowing()).isTrue();
Button positiveButton = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE);
assertThat(positiveButton).isNotNull();
positiveButton.performClick();
assertThat(alertDialog.isShowing()).isFalse();
}
@Test
public void onResumeAndWaitTimeout_shouldCallTimeoutDialog() {
FakeNetworkRequestDialogFragment fakeFragment = new FakeNetworkRequestDialogFragment();
FakeNetworkRequestDialogFragment spyFakeFragment = spy(fakeFragment);
spyFakeFragment.show(mActivity.getSupportFragmentManager(), null);
assertThat(fakeFragment.bCalledStopAndPop).isFalse();
ShadowLooper.getShadowMainLooper().runToEndOfTasks();
assertThat(fakeFragment.bCalledStopAndPop).isTrue();
}
class FakeNetworkRequestDialogFragment extends NetworkRequestDialogFragment {
boolean bCalledStopAndPop = false;
@Override
public void stopScanningAndPopTimeoutDialog() {
bCalledStopAndPop = true;
@Before
public void setUp() {
mActivity = Robolectric.setupActivity(FragmentActivity.class);
networkRequestDialogFragment = spy(NetworkRequestDialogFragment.newInstance());
mContext = spy(RuntimeEnvironment.application);
}
}
@Test
public void onResume_shouldRegisterCallback() {
when(networkRequestDialogFragment.getContext()).thenReturn(mContext);
Context applicationContext = spy(RuntimeEnvironment.application.getApplicationContext());
when(mContext.getApplicationContext()).thenReturn(applicationContext);
WifiManager wifiManager = mock(WifiManager.class);
when(applicationContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(wifiManager);
@Test
public void display_shouldShowTheDialog() {
networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), null);
AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
assertThat(alertDialog).isNotNull();
assertThat(alertDialog.isShowing()).isTrue();
}
networkRequestDialogFragment.onResume();
@Test
public void clickPositiveButton_shouldCloseTheDialog() {
networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), null);
AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
assertThat(alertDialog.isShowing()).isTrue();
verify(wifiManager).registerNetworkRequestMatchCallback(any(), any());
}
Button positiveButton = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE);
assertThat(positiveButton).isNotNull();
@Test
public void onPause_shouldUnRegisterCallback() {
when(networkRequestDialogFragment.getContext()).thenReturn(mContext);
Context applicationContext = spy(RuntimeEnvironment.application.getApplicationContext());
when(mContext.getApplicationContext()).thenReturn(applicationContext);
WifiManager wifiManager = mock(WifiManager.class);
when(applicationContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(wifiManager);
positiveButton.performClick();
assertThat(alertDialog.isShowing()).isFalse();
}
networkRequestDialogFragment.onPause();
@Test
public void onResumeAndWaitTimeout_shouldCallTimeoutDialog() {
FakeNetworkRequestDialogFragment fakeFragment = new FakeNetworkRequestDialogFragment();
FakeNetworkRequestDialogFragment spyFakeFragment = spy(fakeFragment);
spyFakeFragment.show(mActivity.getSupportFragmentManager(), null);
verify(wifiManager).unregisterNetworkRequestMatchCallback(networkRequestDialogFragment);
}
assertThat(fakeFragment.bCalledStopAndPop).isFalse();
@Test
public void updateAccessPointList_onUserSelectionConnectSuccess_updateCorrectly() {
List<AccessPoint> accessPointList = spy(new ArrayList<>());
Bundle bundle = new Bundle();
bundle.putString(KEY_SSID, "Test AP 1");
accessPointList.add(new AccessPoint(mContext, bundle));
bundle.putString(KEY_SSID, "Test AP 2");
accessPointList.add(new AccessPoint(mContext, bundle));
bundle.putString(KEY_SSID, "Test AP 3");
accessPointList.add(new AccessPoint(mContext, bundle));
bundle.putString(KEY_SSID, "Test AP 4");
accessPointList.add(new AccessPoint(mContext, bundle));
ShadowLooper.getShadowMainLooper().runToEndOfTasks();
when(networkRequestDialogFragment.getAccessPointList()).thenReturn(accessPointList);
networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), null);
assertThat(fakeFragment.bCalledStopAndPop).isTrue();
}
// Test if config would update list.
WifiConfiguration config = new WifiConfiguration();
config.SSID = "Test AP 3";
networkRequestDialogFragment.onUserSelectionConnectSuccess(config);
class FakeNetworkRequestDialogFragment extends NetworkRequestDialogFragment {
boolean bCalledStopAndPop = false;
AccessPoint verifyAccessPoint = new AccessPoint(mContext, config);
verify(accessPointList, times(1)).set(2, verifyAccessPoint);
}
@Override
public void stopScanningAndPopErrorDialog(ERROR_DIALOG_TYPE type) {
bCalledStopAndPop = true;
}
}
@Test
public void updateAccessPointList_onUserSelectionConnectFailure_updateCorrectly() {
List<AccessPoint> accessPointList = spy(new ArrayList<>());
Bundle bundle = new Bundle();
bundle.putString(KEY_SSID, "Test AP 1");
accessPointList.add(new AccessPoint(mContext, bundle));
bundle.putString(KEY_SSID, "Test AP 2");
accessPointList.add(new AccessPoint(mContext, bundle));
bundle.putString(KEY_SSID, "Test AP 3");
accessPointList.add(new AccessPoint(mContext, bundle));
bundle.putString(KEY_SSID, "Test AP 4");
accessPointList.add(new AccessPoint(mContext, bundle));
@Test
public void onResume_shouldRegisterCallback() {
when(networkRequestDialogFragment.getContext()).thenReturn(mContext);
Context applicationContext = spy(RuntimeEnvironment.application.getApplicationContext());
when(mContext.getApplicationContext()).thenReturn(applicationContext);
WifiManager wifiManager = mock(WifiManager.class);
when(applicationContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(wifiManager);
when(networkRequestDialogFragment.getAccessPointList()).thenReturn(accessPointList);
networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), null);
networkRequestDialogFragment.onResume();
// Test if config would update list.
WifiConfiguration config = new WifiConfiguration();
config.SSID = "Test AP 3";
networkRequestDialogFragment.onUserSelectionConnectFailure(config);
verify(wifiManager).registerNetworkRequestMatchCallback(any(), any());
}
AccessPoint verifyAccessPoint = new AccessPoint(mContext, config);
verify(accessPointList, times(1)).set(2, verifyAccessPoint);
}
@Test
public void onPause_shouldUnRegisterCallback() {
when(networkRequestDialogFragment.getContext()).thenReturn(mContext);
Context applicationContext = spy(RuntimeEnvironment.application.getApplicationContext());
when(mContext.getApplicationContext()).thenReturn(applicationContext);
WifiManager wifiManager = mock(WifiManager.class);
when(applicationContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(wifiManager);
@Test
public void onUserSelectionCallbackRegistration_shouldCallSelect() {
List<AccessPoint> accessPointList = spy(new ArrayList<>());
Bundle bundle = new Bundle();
bundle.putString(KEY_SSID, "Test AP 1");
accessPointList.add(new AccessPoint(mContext, bundle));
bundle.putString(KEY_SSID, "Test AP 2");
accessPointList.add(new AccessPoint(mContext, bundle));
bundle.putString(KEY_SSID, "Test AP 3");
AccessPoint clickedAccessPoint = new AccessPoint(mContext, bundle);
accessPointList.add(clickedAccessPoint);
bundle.putString(KEY_SSID, "Test AP 4");
accessPointList.add(new AccessPoint(mContext, bundle));
when(networkRequestDialogFragment.getAccessPointList()).thenReturn(accessPointList);
networkRequestDialogFragment.onPause();
NetworkRequestUserSelectionCallback selectionCallback = mock(
NetworkRequestUserSelectionCallback.class);
AlertDialog dialog = mock(AlertDialog.class);
networkRequestDialogFragment.onUserSelectionCallbackRegistration(selectionCallback);
verify(wifiManager).unregisterNetworkRequestMatchCallback(networkRequestDialogFragment);
}
networkRequestDialogFragment.onClick(dialog, 2);
@Test
public void updateAccessPointList_onUserSelectionConnectSuccess_updateCorrectly() {
List<AccessPoint> accessPointList = spy(new ArrayList<>());
Bundle bundle = new Bundle();
bundle.putString(KEY_SSID, "Test AP 1");
accessPointList.add(new AccessPoint(mContext, bundle));
bundle.putString(KEY_SSID, "Test AP 2");
accessPointList.add(new AccessPoint(mContext, bundle));
bundle.putString(KEY_SSID, "Test AP 3");
accessPointList.add(new AccessPoint(mContext, bundle));
bundle.putString(KEY_SSID, "Test AP 4");
accessPointList.add(new AccessPoint(mContext, bundle));
verify(selectionCallback, times(1)).select(clickedAccessPoint.getConfig());
}
when(networkRequestDialogFragment.getAccessPointList()).thenReturn(accessPointList);
networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), null);
@Test
public void onMatch_shouldUpdatedList() {
// Prepares WifiManager.
when(networkRequestDialogFragment.getContext()).thenReturn(mContext);
Context applicationContext = spy(RuntimeEnvironment.application.getApplicationContext());
when(mContext.getApplicationContext()).thenReturn(applicationContext);
WifiManager wifiManager = mock(WifiManager.class);
when(applicationContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(wifiManager);
// Test if config would update list.
WifiConfiguration config = new WifiConfiguration();
config.SSID = "Test AP 3";
networkRequestDialogFragment.onUserSelectionConnectSuccess(config);
List<WifiConfiguration> wifiConfigurationList = new ArrayList<>();
WifiConfiguration config = new WifiConfiguration();
final String SSID_AP1 = "Test AP 1";
config.SSID = SSID_AP1;
wifiConfigurationList.add(config);
config = new WifiConfiguration();
final String SSID_AP2 = "Test AP 2";
config.SSID = SSID_AP2;
wifiConfigurationList.add(config);
AccessPoint verifyAccessPoint = new AccessPoint(mContext, config);
verify(accessPointList, times(1)).set(2, verifyAccessPoint);
}
// Prepares callback converted data.
List<ScanResult> scanResults = new ArrayList<>();
when(wifiManager.getAllMatchingWifiConfigs(scanResults)).thenReturn(wifiConfigurationList);
@Test
public void updateAccessPointList_onUserSelectionConnectFailure_updateCorrectly() {
List<AccessPoint> accessPointList = spy(new ArrayList<>());
Bundle bundle = new Bundle();
bundle.putString(KEY_SSID, "Test AP 1");
accessPointList.add(new AccessPoint(mContext, bundle));
bundle.putString(KEY_SSID, "Test AP 2");
accessPointList.add(new AccessPoint(mContext, bundle));
bundle.putString(KEY_SSID, "Test AP 3");
accessPointList.add(new AccessPoint(mContext, bundle));
bundle.putString(KEY_SSID, "Test AP 4");
accessPointList.add(new AccessPoint(mContext, bundle));
networkRequestDialogFragment.onMatch(scanResults);
when(networkRequestDialogFragment.getAccessPointList()).thenReturn(accessPointList);
networkRequestDialogFragment.show(mActivity.getSupportFragmentManager(), null);
List<AccessPoint> accessPointList = networkRequestDialogFragment.getAccessPointList();
assertThat(accessPointList).isNotEmpty();
assertThat(accessPointList.size()).isEqualTo(2);
assertThat(accessPointList.get(0).getSsid()).isEqualTo(SSID_AP1);
assertThat(accessPointList.get(1).getSsid()).isEqualTo(SSID_AP2);
}
// Test if config would update list.
WifiConfiguration config = new WifiConfiguration();
config.SSID = "Test AP 3";
networkRequestDialogFragment.onUserSelectionConnectFailure(config);
AccessPoint verifyAccessPoint = new AccessPoint(mContext, config);
verify(accessPointList, times(1)).set(2, verifyAccessPoint);
}
@Test
public void onUserSelectionCallbackRegistration_shouldCallSelect() {
List<AccessPoint> accessPointList = spy(new ArrayList<>());
Bundle bundle = new Bundle();
bundle.putString(KEY_SSID, "Test AP 1");
accessPointList.add(new AccessPoint(mContext, bundle));
bundle.putString(KEY_SSID, "Test AP 2");
accessPointList.add(new AccessPoint(mContext, bundle));
bundle.putString(KEY_SSID, "Test AP 3");
AccessPoint clickedAccessPoint = new AccessPoint(mContext, bundle);
accessPointList.add(clickedAccessPoint);
bundle.putString(KEY_SSID, "Test AP 4");
accessPointList.add(new AccessPoint(mContext, bundle));
when(networkRequestDialogFragment.getAccessPointList()).thenReturn(accessPointList);
NetworkRequestUserSelectionCallback selectionCallback = mock(
NetworkRequestUserSelectionCallback.class);
AlertDialog dialog = mock(AlertDialog.class);
networkRequestDialogFragment.onUserSelectionCallbackRegistration(selectionCallback);
networkRequestDialogFragment.onClick(dialog, 2);
verify(selectionCallback, times(1)).select(clickedAccessPoint.getConfig());
}
@Test
public void onMatch_shouldUpdatedList() {
// Prepares WifiManager.
when(networkRequestDialogFragment.getContext()).thenReturn(mContext);
Context applicationContext = spy(RuntimeEnvironment.application.getApplicationContext());
when(mContext.getApplicationContext()).thenReturn(applicationContext);
WifiManager wifiManager = mock(WifiManager.class);
when(applicationContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(wifiManager);
List<WifiConfiguration> wifiConfigurationList = new ArrayList<>();
WifiConfiguration config = new WifiConfiguration();
final String SSID_AP1 = "Test AP 1";
config.SSID = SSID_AP1;
wifiConfigurationList.add(config);
config = new WifiConfiguration();
final String SSID_AP2 = "Test AP 2";
config.SSID = SSID_AP2;
wifiConfigurationList.add(config);
// Prepares callback converted data.
List<ScanResult> scanResults = new ArrayList<>();
when(wifiManager.getAllMatchingWifiConfigs(scanResults)).thenReturn(wifiConfigurationList);
networkRequestDialogFragment.onMatch(scanResults);
List<AccessPoint> accessPointList = networkRequestDialogFragment.getAccessPointList();
assertThat(accessPointList).isNotEmpty();
assertThat(accessPointList.size()).isEqualTo(2);
assertThat(accessPointList.get(0).getSsid()).isEqualTo(SSID_AP1);
assertThat(accessPointList.get(1).getSsid()).isEqualTo(SSID_AP2);
}
}

View File

@@ -0,0 +1,117 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.wifi;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.internal.verification.VerificationModeFactory.times;
import android.content.DialogInterface;
import android.os.Bundle;
import android.widget.Button;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.FragmentActivity;
import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResourcesImpl;
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
import com.android.settings.wifi.NetworkRequestErrorDialogFragment.ERROR_DIALOG_TYPE;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(shadows = {SettingsShadowResourcesImpl.class, ShadowAlertDialogCompat.class})
public class NetworkRequestErrorDialogFragmentTest {
private FragmentActivity mActivity;
private NetworkRequestErrorDialogFragment mFragment;
@Before
public void setUp() {
mActivity = Robolectric.setupActivity(FragmentActivity.class);
mFragment = spy(NetworkRequestErrorDialogFragment.newInstance());
mFragment.show(mActivity.getSupportFragmentManager(), null);
}
@Test
public void display_shouldShowTimeoutDialog() {
AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
assertThat(alertDialog).isNotNull();
assertThat(alertDialog.isShowing()).isTrue();
ShadowAlertDialogCompat shadowAlertDialog = ShadowAlertDialogCompat.shadowOf(alertDialog);
assertThat(RuntimeEnvironment.application
.getString(R.string.network_connection_timeout_dialog_message))
.isEqualTo(shadowAlertDialog.getMessage());
}
@Test
public void display_shouldShowAbortDialog() {
mFragment = spy(NetworkRequestErrorDialogFragment.newInstance());
Bundle bundle = new Bundle();
bundle.putSerializable(NetworkRequestErrorDialogFragment.DIALOG_TYPE,
ERROR_DIALOG_TYPE.ABORT);
mFragment.setArguments(bundle);
mFragment.show(mActivity.getSupportFragmentManager(), null);
AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
assertThat(alertDialog).isNotNull();
assertThat(alertDialog.isShowing()).isTrue();
ShadowAlertDialogCompat shadowAlertDialog = ShadowAlertDialogCompat.shadowOf(alertDialog);
assertThat(RuntimeEnvironment.application
.getString(R.string.network_connection_errorstate_dialog_message))
.isEqualTo(shadowAlertDialog.getMessage());
}
@Test
public void clickPositiveButton_shouldCallStartScanningDialog() {
AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
assertThat(alertDialog.isShowing()).isTrue();
Button positiveButton = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE);
assertThat(positiveButton).isNotNull();
positiveButton.performClick();
verify(mFragment, times(1)).startScanningDialog();
}
@Test
public void clickNegativeButton_shouldCloseTheDialog() {
AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
assertThat(alertDialog.isShowing()).isTrue();
Button negativeButton = alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE);
assertThat(negativeButton).isNotNull();
negativeButton.performClick();
assertThat(alertDialog.isShowing()).isFalse();
}
}

View File

@@ -1,90 +0,0 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.wifi;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.internal.verification.VerificationModeFactory.times;
import android.content.DialogInterface;
import android.widget.Button;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.FragmentActivity;
import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResourcesImpl;
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(shadows = {SettingsShadowResourcesImpl.class, ShadowAlertDialogCompat.class})
public class NetworkRequestTimeoutDialogFragmentTest {
private FragmentActivity mActivity;
private NetworkRequestTimeoutDialogFragment mFragment;
@Before
public void setUp() {
mActivity = Robolectric.setupActivity(FragmentActivity.class);
mFragment = spy(NetworkRequestTimeoutDialogFragment.newInstance());
mFragment.show(mActivity.getSupportFragmentManager(), null);
}
@Test
public void display_shouldShowTheDialog() {
AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
assertThat(alertDialog).isNotNull();
assertThat(alertDialog.isShowing()).isTrue();
ShadowAlertDialogCompat shadowAlertDialog = ShadowAlertDialogCompat.shadowOf(alertDialog);
assertThat(RuntimeEnvironment.application
.getString(R.string.network_connection_timeout_dialog_message))
.isEqualTo(shadowAlertDialog.getMessage());
}
@Test
public void clickPositiveButton_shouldCallStartScanningDialog() {
AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
assertThat(alertDialog.isShowing()).isTrue();
Button positiveButton = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE);
assertThat(positiveButton).isNotNull();
positiveButton.performClick();
verify(mFragment, times(1)).startScanningDialog();
}
@Test
public void clickNegativeButton_shouldCloseTheDialog() {
AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
assertThat(alertDialog.isShowing()).isTrue();
Button negativeButton = alertDialog.getButton(DialogInterface.BUTTON_NEGATIVE);
assertThat(negativeButton).isNotNull();
negativeButton.performClick();
assertThat(alertDialog.isShowing()).isFalse();
}
}

View File

@@ -865,6 +865,12 @@ public class WifiDetailPreferenceControllerTest {
when(pref.setButton2Visible(anyBoolean())).thenReturn(pref);
when(pref.setButton2OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
when(pref.setButton3Text(anyInt())).thenReturn(pref);
when(pref.setButton3Icon(anyInt())).thenReturn(pref);
when(pref.setButton3Enabled(anyBoolean())).thenReturn(pref);
when(pref.setButton3Visible(anyBoolean())).thenReturn(pref);
when(pref.setButton3OnClickListener(any(View.OnClickListener.class))).thenReturn(pref);
return pref;
}
}