diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 3933b9ceb49..871f6092ca7 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -2973,11 +2973,16 @@
android:label="@string/settings_panel_title"
android:theme="@style/Theme.BottomDialog"
android:excludeFromRecents="true"
- android:launchMode="singleTask">
+ android:launchMode="singleTask"
+ android:exported="true">
-
+
+
+
+
+
+ android:fillColor="?android:attr/colorControlNormal" />
diff --git a/res/drawable/ic_friction_money.xml b/res/drawable/ic_friction_money.xml
index b17092144ea..fb1904aa82c 100644
--- a/res/drawable/ic_friction_money.xml
+++ b/res/drawable/ic_friction_money.xml
@@ -20,7 +20,7 @@
android:width="18dp"
android:height="18dp">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/res/layout/face_enroll_finish.xml b/res/layout/face_enroll_finish.xml
index 6b3e6ab554a..df4609826fb 100644
--- a/res/layout/face_enroll_finish.xml
+++ b/res/layout/face_enroll_finish.xml
@@ -21,8 +21,7 @@
android:id="@+id/setup_wizard_layout"
style="?attr/face_layout_theme"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- app:sucFooter="@layout/face_enroll_finish_footer">
+ android:layout_height="match_parent">
-
-
-
-
-
-
-
-
-
-
diff --git a/res/layout/face_enroll_introduction.xml b/res/layout/face_enroll_introduction.xml
index 7a5c172dac6..df3cf72fd00 100644
--- a/res/layout/face_enroll_introduction.xml
+++ b/res/layout/face_enroll_introduction.xml
@@ -18,11 +18,11 @@
+ android:layout_height="match_parent">
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/layout/face_enroll_introduction_footer.xml b/res/layout/face_enroll_introduction_footer.xml
deleted file mode 100644
index 15993f05233..00000000000
--- a/res/layout/face_enroll_introduction_footer.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/res/layout/fingerprint_enroll_enrolling_base.xml b/res/layout/fingerprint_enroll_enrolling_base.xml
index 5a2b60f5d90..6ca3fdc6e78 100644
--- a/res/layout/fingerprint_enroll_enrolling_base.xml
+++ b/res/layout/fingerprint_enroll_enrolling_base.xml
@@ -21,8 +21,7 @@
android:id="@+id/setup_wizard_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
- style="?attr/fingerprint_layout_theme"
- app:sucFooter="@layout/fingerprint_enroll_enrolling_base_footer">
+ style="?attr/fingerprint_layout_theme">
-
-
-
-
-
-
-
-
diff --git a/res/layout/fingerprint_enroll_find_sensor_base.xml b/res/layout/fingerprint_enroll_find_sensor_base.xml
index 18941a2a831..56d3ea4929d 100644
--- a/res/layout/fingerprint_enroll_find_sensor_base.xml
+++ b/res/layout/fingerprint_enroll_find_sensor_base.xml
@@ -21,8 +21,7 @@
android:id="@+id/setup_wizard_layout"
style="?attr/fingerprint_layout_theme"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- app:sucFooter="@layout/fingerprint_enroll_find_sensor_base_footer">
+ android:layout_height="match_parent">
-
-
-
-
-
-
-
-
diff --git a/res/layout/fingerprint_enroll_finish_base.xml b/res/layout/fingerprint_enroll_finish_base.xml
index 5224dabb9a1..7120d90a403 100644
--- a/res/layout/fingerprint_enroll_finish_base.xml
+++ b/res/layout/fingerprint_enroll_finish_base.xml
@@ -21,8 +21,7 @@
android:id="@+id/setup_wizard_layout"
style="?attr/fingerprint_layout_theme"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- app:sucFooter="@layout/fingerprint_enroll_finish_base_footer">
+ android:layout_height="match_parent">
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/res/layout/fingerprint_enroll_introduction.xml b/res/layout/fingerprint_enroll_introduction.xml
index 701d94a6253..adb46e5d447 100644
--- a/res/layout/fingerprint_enroll_introduction.xml
+++ b/res/layout/fingerprint_enroll_introduction.xml
@@ -21,8 +21,7 @@
style="?attr/fingerprint_layout_theme"
android:id="@+id/setup_wizard_layout"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- app:sucFooter="@layout/fingerprint_enroll_introduction_footer">
+ android:layout_height="match_parent">
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/res/layout/homepage_dismissal_view.xml b/res/layout/homepage_dismissal_view.xml
new file mode 100644
index 00000000000..e60b37510eb
--- /dev/null
+++ b/res/layout/homepage_dismissal_view.xml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/homepage_slice_half_tile.xml b/res/layout/homepage_slice_half_tile.xml
new file mode 100644
index 00000000000..7de9eb6e006
--- /dev/null
+++ b/res/layout/homepage_slice_half_tile.xml
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/homepage_slice_tile.xml b/res/layout/homepage_slice_tile.xml
index 9165abcd22c..9fa7d61ddd4 100644
--- a/res/layout/homepage_slice_tile.xml
+++ b/res/layout/homepage_slice_tile.xml
@@ -22,7 +22,7 @@
style="@style/ContextualCardStyle">
@@ -34,40 +34,7 @@
android:paddingEnd="@dimen/homepage_card_padding_end"/>
-
+
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/res/layout/panel_layout.xml b/res/layout/panel_layout.xml
index a6f62a4d589..c466ce88c3b 100644
--- a/res/layout/panel_layout.xml
+++ b/res/layout/panel_layout.xml
@@ -22,7 +22,7 @@
android:orientation="vertical">
-
-
-
-
-
-
-
-
-
-
-
diff --git a/res/layout/storage_wizard_generic.xml b/res/layout/storage_wizard_generic.xml
index 77aff9c5a00..0e7c1fdb951 100644
--- a/res/layout/storage_wizard_generic.xml
+++ b/res/layout/storage_wizard_generic.xml
@@ -19,8 +19,7 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/setup_wizard_layout"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- app:sucFooter="@layout/storage_wizard_footer">
+ android:layout_height="match_parent">
+ android:layout_height="match_parent">
+ android:layout_height="match_parent">
-
-
-
-
-
-
-
-
-
-
-
diff --git a/res/layout/zen_custom_settings_dialog.xml b/res/layout/zen_custom_settings_dialog.xml
new file mode 100644
index 00000000000..f44b2f720d7
--- /dev/null
+++ b/res/layout/zen_custom_settings_dialog.xml
@@ -0,0 +1,171 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index f95809ea3d2..e80d1514d3d 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -219,7 +219,7 @@
-
+
- 4
@@ -1081,14 +1081,14 @@
- @string/zen_mode_from_anyone
- @string/zen_mode_from_contacts
- @string/zen_mode_from_starred
- - @string/zen_mode_from_none_calls
+ - @string/zen_mode_from_none_messages
- @string/zen_mode_from_anyone
- @string/zen_mode_from_contacts
- @string/zen_mode_from_starred
- - @string/zen_mode_from_none_messages
+ - @string/zen_mode_from_none_calls
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 383506dbb1d..a88d6f6ec57 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -146,6 +146,11 @@
+
+
+
+
+
@@ -163,6 +168,4 @@
-
-
diff --git a/res/values/config.xml b/res/values/config.xml
index 7108cbde50e..82e185c8371 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -168,4 +168,7 @@
content://com.google.android.gms.nearby.fastpair/settings_slice?addr=%1$s
+
+
+
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index a6c6c37df50..a109d57de35 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -329,6 +329,9 @@
4dp
16dp
16dp
+ 12dp
+ 16dp
+ 12dp
4dp
diff --git a/res/values/strings.xml b/res/values/strings.xml
index d07cc53fe80..e435b65e04f 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -877,6 +877,12 @@
Tap to set up face authentication
Face authentication
+
+ Use accessibility setup
+
+
+
+
Cancel
@@ -6938,7 +6944,7 @@
speaker beep, speaker, volume, mute, silence, audio, music
dont don\u2019t disturb, interrupt, interruption, break
RAM
- nearby, location, history, reporting
+ nearby, location, history, reporting, GPS
account
restriction, restrict, restricted
text correction, correct, sound, vibrate, auto, language, gesture, suggest, suggestion, theme, offensive, word, type, emoji, international
@@ -7330,8 +7336,8 @@
Do Not Disturb will stay on until you turn it off
-
- Do Not Disturb was automatically turned on by a rule (%s)
+
+ Do Not Disturb was automatically turned on by a schedule (%s)
Do Not Disturb was automatically turned on by an app (%s)
@@ -7339,6 +7345,9 @@
Do Not Disturb is on for %s with custom settings.
+
+ View custom settings
+
Priority only
@@ -7402,6 +7411,17 @@
Muted, but allow %1$s, %2$s, and %3$s
+
+ Custom settings
+
+ Review schedule
+
+ Got it
+
+ Notifications
+
+ Duration
+
Messages, events & reminders
@@ -7943,6 +7963,9 @@
Create custom settings for this schedule
+
+ For \u2018%1$s\u2019
+
,\u0020
@@ -7958,9 +7981,12 @@
Calls
-
+
When Do Not Disturb is on, incoming calls are blocked. You can adjust settings to allow your friends, family, or other contacts to reach you.
+
+ For \u2018%1$s\u2019 incoming calls are blocked. You can adjust settings to allow your friends, family, or other contacts to reach you.
+
Starred contacts
@@ -7976,6 +8002,9 @@
When Do Not Disturb is on, incoming text messages are blocked. You can adjust settings to allow your friends, family, or other contacts to reach you.
+
+ For \u2018%1$s\u2019 incoming text messages are blocked. You can adjust settings to allow your friends, family, or other contacts to reach you.
+
Text messages
@@ -8039,11 +8068,11 @@
App exceptions
-
+
- No apps can override Do Not Disturb
- - 1 app can override Do Not Disturb
- - %1$d apps can override Do Not Disturb
+ - Notifications from 1 app can override Do Not Disturb
+ - Notifications from %1$d apps can override Do Not Disturb
diff --git a/res/values/themes.xml b/res/values/themes.xml
index f22d1110872..6b05a7c21aa 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -37,7 +37,6 @@
- @drawable/wifi_signal
- ?android:attr/colorAccent
- @drawable/wifi_friction
- - ?android:colorControlNormal
- @dimen/settings_side_margin
- ?android:attr/colorAccent
@@ -187,7 +186,7 @@
- @style/PreferenceTheme
- - @*android:style/ThemeOverlay.DeviceDefault.ActionBar.Accent
+ - @*android:style/ThemeOverlay.DeviceDefault.ActionBar
- @color/battery_good_color_light
diff --git a/res/xml/mobile_network_settings.xml b/res/xml/mobile_network_settings.xml
index cc914adcc0f..c6eb3e76711 100644
--- a/res/xml/mobile_network_settings.xml
+++ b/res/xml/mobile_network_settings.xml
@@ -17,7 +17,6 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="mobile_network_pref_screen"
- android:title="@string/network_settings_title"
settings:initialExpandedChildrenCount="4">
+ settings:enableCopying="true"/>
+ settings:enableCopying="true"/>
+ "com.android.settings.deviceinfo.DeviceModelPreferenceController"/>
+ "com.android.settings.deviceinfo.firmwareversion.FirmwareVersionPreferenceController"/>
+ settings:enableCopying="true"/>
+ settings:enableCopying="true"/>
+ settings:enableCopying="true"/>
+ android:selectable="false"/>
+ settings:keywords="@string/keywords_device_feedback"/>
+ settings:enableCopying="true"
+ settings:controller="com.android.settings.deviceinfo.BuildNumberPreferenceController"/>
diff --git a/res/xml/zen_mode_custom_rule_configuration.xml b/res/xml/zen_mode_custom_rule_configuration.xml
new file mode 100644
index 00000000000..c1732a3ac6a
--- /dev/null
+++ b/res/xml/zen_mode_custom_rule_configuration.xml
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/xml/zen_mode_custom_rule_settings.xml b/res/xml/zen_mode_custom_rule_settings.xml
new file mode 100644
index 00000000000..7aedd2c5e01
--- /dev/null
+++ b/res/xml/zen_mode_custom_rule_settings.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/xml/zen_mode_event_rule_settings.xml b/res/xml/zen_mode_event_rule_settings.xml
index a70b46ce30f..841fc065a85 100644
--- a/res/xml/zen_mode_event_rule_settings.xml
+++ b/res/xml/zen_mode_event_rule_settings.xml
@@ -45,4 +45,10 @@
android:title="@string/zen_mode_event_rule_reply"
android:summary="%s" />
+
+
+
diff --git a/res/xml/zen_mode_schedule_rule_settings.xml b/res/xml/zen_mode_schedule_rule_settings.xml
index 7de10b3cad9..84848541894 100644
--- a/res/xml/zen_mode_schedule_rule_settings.xml
+++ b/res/xml/zen_mode_schedule_rule_settings.xml
@@ -50,7 +50,7 @@
diff --git a/src/com/android/settings/ManualDisplayActivity.java b/src/com/android/settings/ManualDisplayActivity.java
index 8be4fee9488..8effc7b9ffe 100644
--- a/src/com/android/settings/ManualDisplayActivity.java
+++ b/src/com/android/settings/ManualDisplayActivity.java
@@ -22,7 +22,6 @@ import android.content.Intent;
import android.content.res.Resources;
import android.net.Uri;
import android.os.Bundle;
-import android.os.SystemProperties;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
@@ -35,8 +34,7 @@ import java.io.File;
public class ManualDisplayActivity extends Activity {
private static final String TAG = "SettingsManualActivity";
- private static final String DEFAULT_MANUAL_PATH = "/system/etc/MANUAL.html.gz";
- private static final String PROPERTY_MANUAL_PATH = "ro.config.manual_path";
+ private static final String MANUAL_PATH = "/system/etc/MANUAL.html.gz";
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -47,16 +45,9 @@ public class ManualDisplayActivity extends Activity {
finish(); // No manual to display for this device
}
- final String path = SystemProperties.get(PROPERTY_MANUAL_PATH, DEFAULT_MANUAL_PATH);
- if (TextUtils.isEmpty(path)) {
- Log.e(TAG, "The system property for the manual is empty");
- showErrorAndFinish();
- return;
- }
-
- final File file = new File(path);
+ final File file = new File(MANUAL_PATH);
if (!file.exists() || file.length() == 0) {
- Log.e(TAG, "Manual file " + path + " does not exist");
+ Log.e(TAG, "Manual file " + MANUAL_PATH + " does not exist");
showErrorAndFinish();
return;
}
diff --git a/src/com/android/settings/SettingsLicenseActivity.java b/src/com/android/settings/SettingsLicenseActivity.java
index 2581ed91347..6f620578ced 100644
--- a/src/com/android/settings/SettingsLicenseActivity.java
+++ b/src/com/android/settings/SettingsLicenseActivity.java
@@ -21,7 +21,6 @@ import android.content.ContentResolver;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
-import android.os.SystemProperties;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
@@ -44,8 +43,7 @@ public class SettingsLicenseActivity extends FragmentActivity implements
LoaderManager.LoaderCallbacks {
private static final String TAG = "SettingsLicenseActivity";
- private static final String DEFAULT_LICENSE_PATH = "/system/etc/NOTICE.html.gz";
- private static final String PROPERTY_LICENSE_PATH = "ro.config.license_path";
+ private static final String LICENSE_PATH = "/system/etc/NOTICE.html.gz";
private static final int LOADER_ID_LICENSE_HTML_LOADER = 0;
@@ -53,10 +51,9 @@ public class SettingsLicenseActivity extends FragmentActivity implements
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- final String licenseHtmlPath =
- SystemProperties.get(PROPERTY_LICENSE_PATH, DEFAULT_LICENSE_PATH);
- if (isFilePathValid(licenseHtmlPath)) {
- showSelectedFile(licenseHtmlPath);
+ File file = new File(LICENSE_PATH);
+ if (isFileValid(file)) {
+ showHtmlFromUri(Uri.fromFile(file));
} else {
showHtmlFromDefaultXmlFiles();
}
@@ -95,22 +92,6 @@ public class SettingsLicenseActivity extends FragmentActivity implements
}
}
- private void showSelectedFile(final String path) {
- if (TextUtils.isEmpty(path)) {
- Log.e(TAG, "The system property for the license file is empty");
- showErrorAndFinish();
- return;
- }
-
- final File file = new File(path);
- if (!isFileValid(file)) {
- Log.e(TAG, "License file " + path + " does not exist");
- showErrorAndFinish();
- return;
- }
- showHtmlFromUri(Uri.fromFile(file));
- }
-
private void showHtmlFromUri(Uri uri) {
// Kick off external viewer due to WebView security restrictions; we
// carefully point it at HTMLViewer, since it offers to decompress
@@ -139,10 +120,6 @@ public class SettingsLicenseActivity extends FragmentActivity implements
finish();
}
- private boolean isFilePathValid(final String path) {
- return !TextUtils.isEmpty(path) && isFileValid(new File(path));
- }
-
@VisibleForTesting
boolean isFileValid(final File file) {
return file.exists() && file.length() != 0;
diff --git a/src/com/android/settings/SetupWizardUtils.java b/src/com/android/settings/SetupWizardUtils.java
index 0dbb2dcef9d..1b911c72abc 100644
--- a/src/com/android/settings/SetupWizardUtils.java
+++ b/src/com/android/settings/SetupWizardUtils.java
@@ -17,7 +17,7 @@
package com.android.settings;
import android.content.Intent;
-import android.os.SystemProperties;
+import android.sysprop.SetupWizardProperties;
import androidx.annotation.VisibleForTesting;
@@ -27,13 +27,10 @@ import com.google.android.setupdesign.util.ThemeHelper;
public class SetupWizardUtils {
- @VisibleForTesting
- static final String SYSTEM_PROP_SETUPWIZARD_THEME = "setupwizard.theme";
-
public static int getTheme(Intent intent) {
String theme = intent.getStringExtra(WizardManagerHelper.EXTRA_THEME);
if (theme == null) {
- theme = SystemProperties.get(SYSTEM_PROP_SETUPWIZARD_THEME);
+ theme = SetupWizardProperties.theme().orElse("");
}
if (theme != null) {
switch (theme) {
diff --git a/src/com/android/settings/biometrics/BiometricEnrollBase.java b/src/com/android/settings/biometrics/BiometricEnrollBase.java
index 2597b297346..4b1c9bc4a3b 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollBase.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollBase.java
@@ -24,7 +24,6 @@ import android.os.Bundle;
import android.os.UserHandle;
import android.text.TextUtils;
import android.view.View;
-import android.widget.Button;
import android.widget.TextView;
import com.android.settings.R;
@@ -33,15 +32,18 @@ import com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling;
import com.android.settings.core.InstrumentedActivity;
import com.android.settings.password.ChooseLockSettingsHelper;
+import com.google.android.setupcompat.item.FooterButton;
+import com.google.android.setupcompat.template.ButtonFooterMixin;
import com.google.android.setupdesign.GlifLayout;
/**
* Base activity for all biometric enrollment steps.
*/
-public abstract class BiometricEnrollBase extends InstrumentedActivity
- implements View.OnClickListener {
- public static final String EXTRA_KEY_LAUNCHED_CONFIRM = "launched_confirm_lock";
+public abstract class BiometricEnrollBase extends InstrumentedActivity {
+ public static final String EXTRA_KEY_LAUNCHED_CONFIRM = "launched_confirm_lock";
+ public static final String EXTRA_KEY_REQUIRE_VISION = "accessibility_vision";
+ public static final String EXTRA_KEY_REQUIRE_DIVERSITY = "accessibility_diversity";
/**
* Used by the choose fingerprint wizard to indicate the wizard is
@@ -76,6 +78,7 @@ public abstract class BiometricEnrollBase extends InstrumentedActivity
protected boolean mLaunchedConfirmLock;
protected byte[] mToken;
protected int mUserId;
+ protected ButtonFooterMixin mButtonFooterMixin;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -110,10 +113,6 @@ public abstract class BiometricEnrollBase extends InstrumentedActivity
protected void initViews() {
getWindow().setStatusBarColor(Color.TRANSPARENT);
- Button nextButton = getNextButton();
- if (nextButton != null) {
- nextButton.setOnClickListener(this);
- }
}
protected GlifLayout getLayout() {
@@ -137,18 +136,14 @@ public abstract class BiometricEnrollBase extends InstrumentedActivity
setHeaderText(resId, false /* force */);
}
- protected Button getNextButton() {
- return (Button) findViewById(R.id.next_button);
- }
-
- @Override
- public void onClick(View v) {
- if (v == getNextButton()) {
- onNextButtonClick();
+ protected FooterButton getNextButton() {
+ if (mButtonFooterMixin != null) {
+ return mButtonFooterMixin.getPrimaryButton();
}
+ return null;
}
- protected void onNextButtonClick() {
+ protected void onNextButtonClick(View view) {
}
protected Intent getFingerprintEnrollingIntent() {
diff --git a/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java b/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
index 8a2a8ec21d5..0ddc1fc298c 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
@@ -22,13 +22,13 @@ import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
import android.view.View;
-import android.widget.Button;
import android.widget.TextView;
import com.android.settings.R;
import com.android.settings.password.ChooseLockGeneric;
import com.android.settings.password.ChooseLockSettingsHelper;
+import com.google.android.setupcompat.item.FooterButton;
import com.google.android.setupdesign.span.LinkSpan;
/**
@@ -70,12 +70,12 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
/**
* @return the cancel button
*/
- protected abstract Button getCancelButton();
+ protected abstract FooterButton getCancelButton();
/**
* @return the next button
*/
- protected abstract Button getNextButton();
+ protected abstract FooterButton getNextButton();
/**
* @return the error TextView
@@ -127,9 +127,6 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
setHeaderText(getHeaderResDefault());
}
- Button cancelButton = getCancelButton();
- cancelButton.setOnClickListener(v -> onCancelButtonClick());
-
mErrorText = getErrorTextView();
mUserManager = UserManager.get(this);
@@ -164,7 +161,7 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
}
@Override
- protected void onNextButtonClick() {
+ protected void onNextButtonClick(View view) {
// Lock thingy is already set up, launch directly to the next page
launchNextEnrollingActivity(mToken);
}
@@ -234,7 +231,7 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
super.onActivityResult(requestCode, resultCode, data);
}
- protected void onCancelButtonClick() {
+ protected void onCancelButtonClick(View view) {
finish();
}
diff --git a/src/com/android/settings/biometrics/BiometricsEnrollEnrolling.java b/src/com/android/settings/biometrics/BiometricsEnrollEnrolling.java
index 033fb4b5dca..7ad2d17f4c3 100644
--- a/src/com/android/settings/biometrics/BiometricsEnrollEnrolling.java
+++ b/src/com/android/settings/biometrics/BiometricsEnrollEnrolling.java
@@ -85,16 +85,9 @@ public abstract class BiometricsEnrollEnrolling extends BiometricEnrollBase
super.onBackPressed();
}
- @Override
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.skip_button:
- setResult(RESULT_SKIP);
- finish();
- break;
- default:
- super.onClick(v);
- }
+ protected void onSkipButtonClick(View view) {
+ setResult(RESULT_SKIP);
+ finish();
}
public void startEnrollment() {
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollAccessibilityToggle.java b/src/com/android/settings/biometrics/face/FaceEnrollAccessibilityToggle.java
new file mode 100644
index 00000000000..49f4f7fd660
--- /dev/null
+++ b/src/com/android/settings/biometrics/face/FaceEnrollAccessibilityToggle.java
@@ -0,0 +1,66 @@
+/*
+ * 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.biometrics.face;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.widget.LinearLayout;
+import android.widget.Switch;
+import android.widget.TextView;
+
+import com.android.settings.R;
+
+/**
+ * A layout that contains a start-justified title, and an end-justified switch.
+ */
+public class FaceEnrollAccessibilityToggle extends LinearLayout {
+
+ private Switch mSwitch;
+
+ public FaceEnrollAccessibilityToggle(Context context) {
+ this(context, null /* attrs */);
+ }
+
+ public FaceEnrollAccessibilityToggle(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public FaceEnrollAccessibilityToggle(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+
+ LayoutInflater.from(context).inflate(R.layout.face_enroll_accessibility_toggle,
+ this, true /* attachToRoot */);
+
+ final TypedArray a =
+ context.obtainStyledAttributes(attrs, R.styleable.FaceEnrollAccessibilityToggle);
+ try {
+ final CharSequence title =
+ a.getText(R.styleable.FaceEnrollAccessibilityToggle_messageText);
+ final TextView titleTextView = findViewById(R.id.title);
+ titleTextView.setText(title);
+ } finally {
+ a.recycle();
+ }
+ mSwitch = findViewById(R.id.toggle);
+ }
+
+ public boolean isChecked() {
+ return mSwitch.isChecked();
+ }
+}
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollAnimationDrawable.java b/src/com/android/settings/biometrics/face/FaceEnrollAnimationDrawable.java
index b6ad565bad2..5be7c5331d3 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollAnimationDrawable.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollAnimationDrawable.java
@@ -29,7 +29,6 @@ import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import com.android.settings.biometrics.BiometricEnrollSidecar;
-import com.android.settings.overlay.FeatureFactory;
/**
* A drawable containing the circle cutout as well as the animations.
@@ -42,17 +41,17 @@ public class FaceEnrollAnimationDrawable extends Drawable
private static final int BORDER_BOUNDS = 20;
private final Context mContext;
- private final FaceFeatureProvider.Listener mListener;
+ private final ParticleCollection.Listener mListener;
private Rect mBounds;
private final Paint mSquarePaint;
private final Paint mCircleCutoutPaint;
- private FaceFeatureProvider.EnrollingAnimation mEnrollingAnimation;
+ private ParticleCollection mParticleCollection;
private TimeAnimator mTimeAnimator;
- private final FaceFeatureProvider.Listener mAnimationListener
- = new FaceFeatureProvider.Listener() {
+ private final ParticleCollection.Listener mAnimationListener
+ = new ParticleCollection.Listener() {
@Override
public void onEnrolled() {
if (mTimeAnimator != null && mTimeAnimator.isStarted()) {
@@ -62,7 +61,7 @@ public class FaceEnrollAnimationDrawable extends Drawable
}
};
- public FaceEnrollAnimationDrawable(Context context, FaceFeatureProvider.Listener listener) {
+ public FaceEnrollAnimationDrawable(Context context, ParticleCollection.Listener listener) {
mContext = context;
mListener = listener;
@@ -78,29 +77,29 @@ public class FaceEnrollAnimationDrawable extends Drawable
@Override
public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {
- mEnrollingAnimation.onEnrollmentHelp(helpMsgId, helpString);
+ mParticleCollection.onEnrollmentHelp(helpMsgId, helpString);
}
@Override
public void onEnrollmentError(int errMsgId, CharSequence errString) {
- mEnrollingAnimation.onEnrollmentError(errMsgId, errString);
+ mParticleCollection.onEnrollmentError(errMsgId, errString);
}
@Override
public void onEnrollmentProgressChange(int steps, int remaining) {
- mEnrollingAnimation.onEnrollmentProgressChange(steps, remaining);
+ mParticleCollection.onEnrollmentProgressChange(steps, remaining);
}
@Override
protected void onBoundsChange(Rect bounds) {
mBounds = bounds;
- mEnrollingAnimation = FeatureFactory.getFactory(mContext).getFaceFeatureProvider()
- .getEnrollingAnimation(mContext, mAnimationListener, bounds, BORDER_BOUNDS);
+ mParticleCollection =
+ new ParticleCollection(mContext, mAnimationListener, bounds, BORDER_BOUNDS);
if (mTimeAnimator == null) {
mTimeAnimator = new TimeAnimator();
mTimeAnimator.setTimeListener((animation, totalTimeMs, deltaTimeMs) -> {
- mEnrollingAnimation.update(totalTimeMs, deltaTimeMs);
+ mParticleCollection.update(totalTimeMs, deltaTimeMs);
FaceEnrollAnimationDrawable.this.invalidateSelf();
});
mTimeAnimator.start();
@@ -122,7 +121,7 @@ public class FaceEnrollAnimationDrawable extends Drawable
mBounds.height() / 2 - BORDER_BOUNDS, mCircleCutoutPaint);
// Draw the animation
- mEnrollingAnimation.draw(canvas);
+ mParticleCollection.draw(canvas);
canvas.restore();
}
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollEnrolling.java b/src/com/android/settings/biometrics/face/FaceEnrollEnrolling.java
index bb46b1896f4..8cc71336fa0 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollEnrolling.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollEnrolling.java
@@ -24,17 +24,19 @@ import android.util.Log;
import android.view.View;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
-import android.widget.Button;
import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
-import com.android.settings.Utils;
+import com.android.settings.biometrics.BiometricEnrollBase;
import com.android.settings.biometrics.BiometricEnrollSidecar;
import com.android.settings.biometrics.BiometricErrorDialog;
import com.android.settings.biometrics.BiometricsEnrollEnrolling;
-import com.android.settings.password.ChooseLockSettingsHelper;
+import java.util.ArrayList;
+
+import com.google.android.setupcompat.item.FooterButton;
+import com.google.android.setupcompat.template.ButtonFooterMixin;
public class FaceEnrollEnrolling extends BiometricsEnrollEnrolling {
@@ -46,7 +48,8 @@ public class FaceEnrollEnrolling extends BiometricsEnrollEnrolling {
private Interpolator mLinearOutSlowInInterpolator;
private FaceEnrollPreviewFragment mPreviewFragment;
- private FaceFeatureProvider.Listener mListener = new FaceFeatureProvider.Listener() {
+ private ArrayList mDisabledFeatures = new ArrayList<>();
+ private ParticleCollection.Listener mListener = new ParticleCollection.Listener() {
@Override
public void onEnrolled() {
FaceEnrollEnrolling.this.launchFinish(mToken);
@@ -88,8 +91,22 @@ public class FaceEnrollEnrolling extends BiometricsEnrollEnrolling {
mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(
this, android.R.interpolator.linear_out_slow_in);
- Button skipButton = findViewById(R.id.skip_button);
- skipButton.setOnClickListener(this);
+ mButtonFooterMixin = getLayout().getMixin(ButtonFooterMixin.class);
+ mButtonFooterMixin.setSecondaryButton(
+ new FooterButton(
+ this,
+ R.string.security_settings_face_enroll_enrolling_skip,
+ this::onSkipButtonClick,
+ FooterButton.ButtonType.SKIP,
+ R.style.SuwGlifButton_Secondary)
+ );
+
+ if (!getIntent().getBooleanExtra(BiometricEnrollBase.EXTRA_KEY_REQUIRE_DIVERSITY, true)) {
+ mDisabledFeatures.add(FaceManager.FEATURE_REQUIRE_REQUIRE_DIVERSITY);
+ }
+ if (!getIntent().getBooleanExtra(BiometricEnrollBase.EXTRA_KEY_REQUIRE_VISION, true)) {
+ mDisabledFeatures.add(FaceManager.FEATURE_REQUIRE_ATTENTION);
+ }
startEnrollment();
}
@@ -114,7 +131,12 @@ public class FaceEnrollEnrolling extends BiometricsEnrollEnrolling {
@Override
protected BiometricEnrollSidecar getSidecar() {
- return new FaceEnrollSidecar();
+ final int[] disabledFeatures = new int[mDisabledFeatures.size()];
+ for (int i = 0; i < mDisabledFeatures.size(); i++) {
+ disabledFeatures[i] = mDisabledFeatures.get(i);
+ }
+
+ return new FaceEnrollSidecar(disabledFeatures);
}
@Override
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollFinish.java b/src/com/android/settings/biometrics/face/FaceEnrollFinish.java
index 7062fe36a01..f0ff5234ebe 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollFinish.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollFinish.java
@@ -17,11 +17,15 @@
package com.android.settings.biometrics.face;
import android.os.Bundle;
+import android.view.View;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.biometrics.BiometricEnrollBase;
+import com.google.android.setupcompat.item.FooterButton;
+import com.google.android.setupcompat.template.ButtonFooterMixin;
+
/**
* Activity which concludes face enrollment.
*/
@@ -32,6 +36,16 @@ public class FaceEnrollFinish extends BiometricEnrollBase {
super.onCreate(savedInstanceState);
setContentView(R.layout.face_enroll_finish);
setHeaderText(R.string.security_settings_face_enroll_finish_title);
+
+ mButtonFooterMixin = getLayout().getMixin(ButtonFooterMixin.class);
+ mButtonFooterMixin.setPrimaryButton(
+ new FooterButton(
+ this,
+ R.string.security_settings_face_enroll_done,
+ this::onNextButtonClick,
+ FooterButton.ButtonType.NEXT,
+ R.style.SuwGlifButton_Primary)
+ );
}
@Override
@@ -40,7 +54,7 @@ public class FaceEnrollFinish extends BiometricEnrollBase {
}
@Override
- public void onNextButtonClick() {
+ public void onNextButtonClick(View view) {
setResult(RESULT_FINISHED);
finish();
}
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
index b720ff4c728..a90cf5d9249 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollIntroduction.java
@@ -17,10 +17,14 @@
package com.android.settings.biometrics.face;
import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
import android.content.Intent;
import android.hardware.face.FaceManager;
import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.View;
import android.widget.Button;
+import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto;
@@ -30,6 +34,8 @@ import com.android.settings.biometrics.BiometricEnrollIntroduction;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settingslib.RestrictedLockUtilsInternal;
+import com.google.android.setupcompat.item.FooterButton;
+import com.google.android.setupcompat.template.ButtonFooterMixin;
import com.google.android.setupdesign.span.LinkSpan;
public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
@@ -37,11 +43,41 @@ public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
private static final String TAG = "FaceIntro";
private FaceManager mFaceManager;
+ private FaceEnrollAccessibilityToggle mSwitchVision;
+ private FaceEnrollAccessibilityToggle mSwitchDiversity;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mFaceManager = Utils.getFaceManagerOrNull(this);
+ final LinearLayout accessibilityLayout = findViewById(R.id.accessibility_layout);
+ final Button accessibilityButton = findViewById(R.id.accessibility_button);
+ accessibilityButton.setOnClickListener(view -> {
+ accessibilityButton.setVisibility(View.INVISIBLE);
+ accessibilityLayout.setVisibility(View.VISIBLE);
+ });
+
+ mSwitchVision = findViewById(R.id.toggle_vision);
+ mSwitchDiversity = findViewById(R.id.toggle_diversity);
+
+ mButtonFooterMixin = getLayout().getMixin(ButtonFooterMixin.class);
+ mButtonFooterMixin.setSecondaryButton(
+ new FooterButton(
+ this,
+ R.string.security_settings_face_enroll_introduction_cancel,
+ this::onCancelButtonClick,
+ FooterButton.ButtonType.SKIP,
+ R.style.SuwGlifButton_Secondary)
+ );
+
+ mButtonFooterMixin.setPrimaryButton(
+ new FooterButton(
+ this,
+ R.string.wizard_next,
+ this::onNextButtonClick,
+ FooterButton.ButtonType.NEXT,
+ R.style.SuwGlifButton_Primary)
+ );
}
@Override
@@ -71,13 +107,19 @@ public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
}
@Override
- protected Button getCancelButton() {
- return findViewById(R.id.face_cancel_button);
+ protected FooterButton getCancelButton() {
+ if (mButtonFooterMixin != null) {
+ return mButtonFooterMixin.getSecondaryButton();
+ }
+ return null;
}
@Override
- protected Button getNextButton() {
- return findViewById(R.id.face_next_button);
+ protected FooterButton getNextButton() {
+ if (mButtonFooterMixin != null) {
+ return mButtonFooterMixin.getPrimaryButton();
+ }
+ return null;
}
@Override
@@ -116,7 +158,18 @@ public class FaceEnrollIntroduction extends BiometricEnrollIntroduction {
@Override
protected Intent getEnrollingIntent() {
- return new Intent(this, FaceEnrollEnrolling.class);
+ final String flattenedString = getString(R.string.config_face_enroll);
+ final Intent intent = new Intent();
+ if (!TextUtils.isEmpty(flattenedString)) {
+ ComponentName componentName = ComponentName.unflattenFromString(flattenedString);
+ intent.setComponent(componentName);
+
+ } else {
+ intent.setClass(this, FaceEnrollEnrolling.class);
+ }
+ intent.putExtra(EXTRA_KEY_REQUIRE_VISION, mSwitchVision.isChecked());
+ intent.putExtra(EXTRA_KEY_REQUIRE_DIVERSITY, mSwitchDiversity.isChecked());
+ return intent;
}
@Override
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollPreviewFragment.java b/src/com/android/settings/biometrics/face/FaceEnrollPreviewFragment.java
index a3708751cf4..a5435845c06 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollPreviewFragment.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollPreviewFragment.java
@@ -63,7 +63,7 @@ public class FaceEnrollPreviewFragment extends InstrumentedPreferenceFragment
private CameraCaptureSession mCaptureSession;
private CaptureRequest mPreviewRequest;
private Size mPreviewSize;
- private FaceFeatureProvider.Listener mListener;
+ private ParticleCollection.Listener mListener;
// View used to contain the circular cutout and enrollment animation drawable
private ImageView mCircleView;
@@ -75,8 +75,8 @@ public class FaceEnrollPreviewFragment extends InstrumentedPreferenceFragment
private FaceSquareTextureView mTextureView;
// Listener sent to the animation drawable
- private final FaceFeatureProvider.Listener mAnimationListener
- = new FaceFeatureProvider.Listener() {
+ private final ParticleCollection.Listener mAnimationListener
+ = new ParticleCollection.Listener() {
@Override
public void onEnrolled() {
mListener.onEnrolled();
@@ -234,7 +234,7 @@ public class FaceEnrollPreviewFragment extends InstrumentedPreferenceFragment
mAnimationDrawable.onEnrollmentProgressChange(steps, remaining);
}
- public void setListener(FaceFeatureProvider.Listener listener) {
+ public void setListener(ParticleCollection.Listener listener) {
mListener = listener;
}
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollSidecar.java b/src/com/android/settings/biometrics/face/FaceEnrollSidecar.java
index 2433fcb7892..75195305093 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollSidecar.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollSidecar.java
@@ -24,13 +24,22 @@ import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricEnrollSidecar;
+import java.util.ArrayList;
+import java.util.Arrays;
+
/**
* Sidecar fragment to handle the state around face enrollment
*/
public class FaceEnrollSidecar extends BiometricEnrollSidecar {
+ private final int[] mDisabledFeatures;
+
private FaceManager mFaceManager;
+ public FaceEnrollSidecar(int[] disabledFeatures) {
+ mDisabledFeatures = Arrays.copyOf(disabledFeatures, disabledFeatures.length);
+ }
+
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
@@ -43,9 +52,9 @@ public class FaceEnrollSidecar extends BiometricEnrollSidecar {
if (mUserId != UserHandle.USER_NULL) {
mFaceManager.setActiveUser(mUserId);
}
- // TODO: Send the list of disabled features
+
mFaceManager.enroll(mToken, mEnrollmentCancel,
- mEnrollmentCallback, new int[0] /* disabledFeatures */);
+ mEnrollmentCallback, mDisabledFeatures);
}
private FaceManager.EnrollmentCallback mEnrollmentCallback
diff --git a/src/com/android/settings/biometrics/face/FaceFeatureProvider.java b/src/com/android/settings/biometrics/face/FaceFeatureProvider.java
deleted file mode 100644
index e2f62d3a9af..00000000000
--- a/src/com/android/settings/biometrics/face/FaceFeatureProvider.java
+++ /dev/null
@@ -1,42 +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.biometrics.face;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Rect;
-
-/**
- * Feature provider for face authentication.
- */
-public interface FaceFeatureProvider {
-
- interface EnrollingAnimation {
- void onEnrollmentHelp(int helpMsgId, CharSequence helpString);
- void onEnrollmentError(int errMsgId, CharSequence errString);
- void onEnrollmentProgressChange(int steps, int remaining);
- void draw(Canvas canvas);
- void update(long t, long dt);
- }
-
- interface Listener {
- void onEnrolled();
- }
-
- EnrollingAnimation getEnrollingAnimation(Context context, Listener listener, Rect bounds,
- int borderWidth);
-}
diff --git a/src/com/android/settings/biometrics/face/FaceFeatureProviderImpl.java b/src/com/android/settings/biometrics/face/FaceFeatureProviderImpl.java
deleted file mode 100644
index 3f656696afa..00000000000
--- a/src/com/android/settings/biometrics/face/FaceFeatureProviderImpl.java
+++ /dev/null
@@ -1,28 +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.biometrics.face;
-
-import android.content.Context;
-import android.graphics.Rect;
-
-public class FaceFeatureProviderImpl implements FaceFeatureProvider {
- @Override
- public EnrollingAnimation getEnrollingAnimation(Context context, Listener listener, Rect bounds,
- int borderWidth) {
- return new ParticleCollection(context, listener, bounds, borderWidth);
- }
-}
diff --git a/src/com/android/settings/biometrics/face/ParticleCollection.java b/src/com/android/settings/biometrics/face/ParticleCollection.java
index b345ab5f945..399beec3abd 100644
--- a/src/com/android/settings/biometrics/face/ParticleCollection.java
+++ b/src/com/android/settings/biometrics/face/ParticleCollection.java
@@ -35,7 +35,7 @@ import java.util.List;
* are updated/drawn in a special order so that the overlap is correct during the final completion
* effect.
*/
-public class ParticleCollection implements FaceFeatureProviderImpl.EnrollingAnimation {
+public class ParticleCollection implements BiometricEnrollSidecar.Listener {
private static final String TAG = "AnimationController";
@@ -49,7 +49,11 @@ public class ParticleCollection implements FaceFeatureProviderImpl.EnrollingAnim
private final List mParticleList;
private final List mPrimariesInProgress; // primary particles not done animating yet
private int mState;
- private FaceFeatureProvider.Listener mListener;
+ private Listener mListener;
+
+ public interface Listener {
+ void onEnrolled();
+ }
private final AnimationParticle.Listener mParticleListener = new AnimationParticle.Listener() {
@Override
@@ -68,8 +72,7 @@ public class ParticleCollection implements FaceFeatureProviderImpl.EnrollingAnim
}
};
- public ParticleCollection(Context context, FaceFeatureProvider.Listener listener, Rect bounds,
- int borderWidth) {
+ public ParticleCollection(Context context, Listener listener, Rect bounds, int borderWidth) {
mParticleList = new ArrayList<>();
mListener = listener;
@@ -100,14 +103,12 @@ public class ParticleCollection implements FaceFeatureProviderImpl.EnrollingAnim
updateState(STATE_STARTED);
}
- @Override
public void update(long t, long dt) {
for (int i = 0; i < mParticleList.size(); i++) {
mParticleList.get(i).update(t, dt);
}
}
- @Override
public void draw(Canvas canvas) {
for (int i = 0; i < mParticleList.size(); i++) {
mParticleList.get(i).draw(canvas);
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
index fb6a221de2e..5953c10e500 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
@@ -35,7 +35,6 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
-import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
@@ -48,6 +47,9 @@ import com.android.settings.biometrics.BiometricErrorDialog;
import com.android.settings.biometrics.BiometricsEnrollEnrolling;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+import com.google.android.setupcompat.item.FooterButton;
+import com.google.android.setupcompat.template.ButtonFooterMixin;
+
/**
* Activity which handles the actual enrolling for fingerprint.
*/
@@ -135,8 +137,15 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
mProgressBar = (ProgressBar) findViewById(R.id.fingerprint_progress_bar);
mVibrator = getSystemService(Vibrator.class);
- Button skipButton = findViewById(R.id.skip_button);
- skipButton.setOnClickListener(this);
+ mButtonFooterMixin = getLayout().getMixin(ButtonFooterMixin.class);
+ mButtonFooterMixin.setSecondaryButton(
+ new FooterButton(
+ this,
+ R.string.security_settings_fingerprint_enroll_enrolling_skip,
+ this::onSkipButtonClick,
+ FooterButton.ButtonType.SKIP,
+ R.style.SuwGlifButton_Secondary)
+ );
final LayerDrawable fingerprintDrawable = (LayerDrawable) mProgressBar.getBackground();
mIconAnimationDrawable = (AnimatedVectorDrawable)
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java
index 0772c666d47..b8a0f40834e 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensor.java
@@ -20,7 +20,6 @@ import android.content.Intent;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle;
import android.view.View;
-import android.widget.Button;
import androidx.annotation.Nullable;
@@ -30,6 +29,8 @@ import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricEnrollBase;
import com.android.settings.biometrics.BiometricEnrollSidecar.Listener;
import com.android.settings.password.ChooseLockSettingsHelper;
+import com.google.android.setupcompat.item.FooterButton;
+import com.google.android.setupcompat.template.ButtonFooterMixin;
/**
* Activity explaining the fingerprint sensor location for fingerprint enrollment.
@@ -46,8 +47,15 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getContentView());
- Button skipButton = findViewById(R.id.skip_button);
- skipButton.setOnClickListener(this);
+ mButtonFooterMixin = getLayout().getMixin(ButtonFooterMixin.class);
+ mButtonFooterMixin.setSecondaryButton(
+ new FooterButton(
+ this,
+ R.string.skip_label,
+ this::onSkipButtonClick,
+ FooterButton.ButtonType.SKIP,
+ R.style.SuwGlifButton_Secondary)
+ );
setHeaderText(R.string.security_settings_fingerprint_enroll_find_sensor_title);
@@ -120,18 +128,7 @@ public class FingerprintEnrollFindSensor extends BiometricEnrollBase {
}
}
- @Override
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.skip_button:
- onSkipButtonClick();
- break;
- default:
- super.onClick(v);
- }
- }
-
- protected void onSkipButtonClick() {
+ protected void onSkipButtonClick(View view) {
setResult(RESULT_SKIP);
finish();
}
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinish.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinish.java
index db6b5bcfdf8..76f1d1fa033 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinish.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinish.java
@@ -20,13 +20,15 @@ import android.content.Intent;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle;
import android.view.View;
-import android.widget.Button;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricEnrollBase;
+import com.google.android.setupcompat.item.FooterButton;
+import com.google.android.setupcompat.template.ButtonFooterMixin;
+
/**
* Activity which concludes fingerprint enrollment.
*/
@@ -39,13 +41,32 @@ public class FingerprintEnrollFinish extends BiometricEnrollBase {
super.onCreate(savedInstanceState);
setContentView(R.layout.fingerprint_enroll_finish);
setHeaderText(R.string.security_settings_fingerprint_enroll_finish_title);
+
+ mButtonFooterMixin = getLayout().getMixin(ButtonFooterMixin.class);
+ mButtonFooterMixin.setSecondaryButton(
+ new FooterButton(
+ this,
+ R.string.fingerprint_enroll_button_add,
+ null,
+ FooterButton.ButtonType.SKIP,
+ R.style.SuwGlifButton_Secondary)
+ );
+
+ mButtonFooterMixin.setPrimaryButton(
+ new FooterButton(
+ this,
+ R.string.security_settings_fingerprint_enroll_done,
+ this::onNextButtonClick,
+ FooterButton.ButtonType.NEXT,
+ R.style.SuwGlifButton_Primary)
+ );
}
@Override
protected void onResume() {
super.onResume();
- Button addButton = (Button) findViewById(R.id.add_another_button);
+ FooterButton addButton = mButtonFooterMixin.getSecondaryButton();
final FingerprintManager fpm = Utils.getFingerprintManagerOrNull(this);
boolean hideAddAnother = false;
@@ -59,22 +80,18 @@ public class FingerprintEnrollFinish extends BiometricEnrollBase {
// Don't show "Add" button if too many fingerprints already added
addButton.setVisibility(View.INVISIBLE);
} else {
- addButton.setOnClickListener(this);
+ addButton.setOnClickListener(this::onAddAnotherButtonClick);
}
}
@Override
- protected void onNextButtonClick() {
+ protected void onNextButtonClick(View view) {
setResult(RESULT_FINISHED);
finish();
}
- @Override
- public void onClick(View v) {
- if (v.getId() == R.id.add_another_button) {
- startActivityForResult(getFingerprintEnrollingIntent(), REQUEST_ADD_ANOTHER);
- }
- super.onClick(v);
+ private void onAddAnotherButtonClick(View view) {
+ startActivityForResult(getFingerprintEnrollingIntent(), REQUEST_ADD_ANOTHER);
}
@Override
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
index 61c67a5e3fb..4eca87d4bf9 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroduction.java
@@ -22,7 +22,6 @@ import android.content.Intent;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle;
import android.util.Log;
-import android.widget.Button;
import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto;
@@ -33,6 +32,8 @@ import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settingslib.HelpUtils;
import com.android.settingslib.RestrictedLockUtilsInternal;
+import com.google.android.setupcompat.item.FooterButton;
+import com.google.android.setupcompat.template.ButtonFooterMixin;
import com.google.android.setupdesign.span.LinkSpan;
public class FingerprintEnrollIntroduction extends BiometricEnrollIntroduction {
@@ -45,6 +46,25 @@ public class FingerprintEnrollIntroduction extends BiometricEnrollIntroduction {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mFingerprintManager = Utils.getFingerprintManagerOrNull(this);
+
+ mButtonFooterMixin = getLayout().getMixin(ButtonFooterMixin.class);
+ mButtonFooterMixin.setSecondaryButton(
+ new FooterButton(
+ this,
+ R.string.security_settings_face_enroll_introduction_cancel,
+ this::onCancelButtonClick,
+ FooterButton.ButtonType.SKIP,
+ R.style.SuwGlifButton_Secondary)
+ );
+
+ mButtonFooterMixin.setPrimaryButton(
+ new FooterButton(
+ this,
+ R.string.wizard_next,
+ this::onNextButtonClick,
+ FooterButton.ButtonType.NEXT,
+ R.style.SuwGlifButton_Primary)
+ );
}
@Override
@@ -74,13 +94,19 @@ public class FingerprintEnrollIntroduction extends BiometricEnrollIntroduction {
}
@Override
- protected Button getCancelButton() {
- return findViewById(R.id.fingerprint_cancel_button);
+ protected FooterButton getCancelButton() {
+ if (mButtonFooterMixin != null) {
+ return mButtonFooterMixin.getSecondaryButton();
+ }
+ return null;
}
@Override
- protected Button getNextButton() {
- return findViewById(R.id.fingerprint_next_button);
+ protected FooterButton getNextButton() {
+ if (mButtonFooterMixin != null) {
+ return mButtonFooterMixin.getPrimaryButton();
+ }
+ return null;
}
@Override
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintSuggestionActivity.java b/src/com/android/settings/biometrics/fingerprint/FingerprintSuggestionActivity.java
index f5fe92b7bcd..704ed13be1d 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintSuggestionActivity.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintSuggestionActivity.java
@@ -19,19 +19,21 @@ package com.android.settings.biometrics.fingerprint;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.hardware.fingerprint.FingerprintManager;
-import android.widget.Button;
import com.android.settings.R;
import com.android.settings.Utils;
+import com.google.android.setupcompat.item.FooterButton;
+
public class FingerprintSuggestionActivity extends SetupFingerprintEnrollIntroduction {
@Override
protected void initViews() {
super.initViews();
- final Button cancelButton = findViewById(R.id.fingerprint_cancel_button);
- cancelButton.setText(R.string.security_settings_fingerprint_enroll_introduction_cancel);
+ final FooterButton cancelButton = getCancelButton();
+ cancelButton.setText(
+ this, R.string.security_settings_fingerprint_enroll_introduction_cancel);
}
@Override
diff --git a/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollFindSensor.java b/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollFindSensor.java
index 8ab92523095..5f1a240bdce 100644
--- a/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollFindSensor.java
+++ b/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollFindSensor.java
@@ -22,6 +22,7 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.UserHandle;
+import android.view.View;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
@@ -53,7 +54,7 @@ public class SetupFingerprintEnrollFindSensor extends FingerprintEnrollFindSenso
}
@Override
- protected void onSkipButtonClick() {
+ protected void onSkipButtonClick(View view) {
new SkipFingerprintDialog().show(getSupportFragmentManager());
}
diff --git a/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollFinish.java b/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollFinish.java
index 49eac16bfe8..6afbb84ecd5 100644
--- a/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollFinish.java
+++ b/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollFinish.java
@@ -25,6 +25,8 @@ import com.android.settings.R;
import com.android.settings.SetupWizardUtils;
import com.android.settings.password.ChooseLockSettingsHelper;
+import com.google.android.setupcompat.item.FooterButton;
+
public class SetupFingerprintEnrollFinish extends FingerprintEnrollFinish {
@Override
@@ -41,8 +43,8 @@ public class SetupFingerprintEnrollFinish extends FingerprintEnrollFinish {
@Override
protected void initViews() {
super.initViews();
- Button nextButton = findViewById(R.id.next_button);
- nextButton.setText(R.string.next_label);
+ FooterButton nextButton = getNextButton();
+ nextButton.setText(this, R.string.next_label);
}
@Override
diff --git a/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollIntroduction.java b/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollIntroduction.java
index 08f5c7e061b..a74bbbad962 100644
--- a/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollIntroduction.java
@@ -23,7 +23,7 @@ import android.content.Intent;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.storage.StorageManager;
-import android.widget.Button;
+import android.view.View;
import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -34,6 +34,8 @@ import com.android.settings.password.ChooseLockGeneric.ChooseLockGenericFragment
import com.android.settings.password.SetupChooseLockGeneric;
import com.android.settings.password.SetupSkipDialog;
+import com.google.android.setupcompat.item.FooterButton;
+
public class SetupFingerprintEnrollIntroduction extends FingerprintEnrollIntroduction {
private static final String KEY_LOCK_SCREEN_PRESENT = "wasLockScreenPresent";
private boolean mAlreadyHadLockScreenSetup = false;
@@ -84,13 +86,13 @@ public class SetupFingerprintEnrollIntroduction extends FingerprintEnrollIntrodu
description.setText(
R.string.security_settings_fingerprint_enroll_introduction_message_setup);
- Button nextButton = getNextButton();
+ FooterButton nextButton = getNextButton();
nextButton.setText(
- R.string.security_settings_fingerprint_enroll_introduction_continue_setup);
+ this, R.string.security_settings_fingerprint_enroll_introduction_continue_setup);
- final Button cancelButton = (Button) findViewById(R.id.fingerprint_cancel_button);
+ final FooterButton cancelButton = getCancelButton();
cancelButton.setText(
- R.string.security_settings_fingerprint_enroll_introduction_cancel_setup);
+ this, R.string.security_settings_fingerprint_enroll_introduction_cancel_setup);
}
@Override
@@ -116,7 +118,7 @@ public class SetupFingerprintEnrollIntroduction extends FingerprintEnrollIntrodu
}
@Override
- protected void onCancelButtonClick() {
+ protected void onCancelButtonClick(View view) {
if (isKeyguardSecure()) {
// If the keyguard is already set up securely (maybe the user added a backup screen
// lock and skipped fingerprint), return RESULT_SKIP directly.
diff --git a/src/com/android/settings/connecteddevice/usb/ConnectedUsbDeviceUpdater.java b/src/com/android/settings/connecteddevice/usb/ConnectedUsbDeviceUpdater.java
index befdf29f378..0be1438407a 100644
--- a/src/com/android/settings/connecteddevice/usb/ConnectedUsbDeviceUpdater.java
+++ b/src/com/android/settings/connecteddevice/usb/ConnectedUsbDeviceUpdater.java
@@ -15,9 +15,12 @@
*/
package com.android.settings.connecteddevice.usb;
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SINK;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SOURCE;
+
import android.content.Context;
import android.hardware.usb.UsbManager;
-import android.hardware.usb.UsbPort;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
@@ -43,7 +46,7 @@ public class ConnectedUsbDeviceUpdater {
UsbConnectionBroadcastReceiver.UsbConnectionListener mUsbConnectionListener =
(connected, functions, powerRole, dataRole) -> {
if (connected) {
- mUsbPreference.setSummary(getSummary(dataRole == UsbPort.DATA_ROLE_DEVICE
+ mUsbPreference.setSummary(getSummary(dataRole == DATA_ROLE_DEVICE
? functions : UsbManager.FUNCTION_NONE, powerRole));
mDevicePreferenceCallback.onDeviceAdded(mUsbPreference);
} else {
@@ -100,7 +103,7 @@ public class ConnectedUsbDeviceUpdater {
public static int getSummary(long functions, int power) {
switch (power) {
- case UsbPort.POWER_ROLE_SINK:
+ case POWER_ROLE_SINK:
if (functions == UsbManager.FUNCTION_MTP) {
return R.string.usb_summary_file_transfers;
} else if (functions == UsbManager.FUNCTION_RNDIS) {
@@ -112,7 +115,7 @@ public class ConnectedUsbDeviceUpdater {
} else {
return R.string.usb_summary_charging_only;
}
- case UsbPort.POWER_ROLE_SOURCE:
+ case POWER_ROLE_SOURCE:
if (functions == UsbManager.FUNCTION_MTP) {
return R.string.usb_summary_file_transfers_power;
} else if (functions == UsbManager.FUNCTION_RNDIS) {
diff --git a/src/com/android/settings/connecteddevice/usb/UsbBackend.java b/src/com/android/settings/connecteddevice/usb/UsbBackend.java
index f68a4a07f43..556f76d5531 100644
--- a/src/com/android/settings/connecteddevice/usb/UsbBackend.java
+++ b/src/com/android/settings/connecteddevice/usb/UsbBackend.java
@@ -15,6 +15,13 @@
*/
package com.android.settings.connecteddevice.usb;
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_NONE;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SOURCE;
+import static android.service.usb.UsbPortStatusProto.DATA_ROLE_HOST;
+import static android.service.usb.UsbPortStatusProto.DATA_ROLE_NONE;
+import static android.service.usb.UsbPortStatusProto.POWER_ROLE_SINK;
+
import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -27,6 +34,8 @@ import android.os.UserManager;
import androidx.annotation.VisibleForTesting;
+import java.util.List;
+
/**
* Provides access to underlying system USB functionality.
*/
@@ -96,30 +105,30 @@ public class UsbBackend {
public int getPowerRole() {
updatePorts();
- return mPortStatus == null ? UsbPort.POWER_ROLE_NONE : mPortStatus.getCurrentPowerRole();
+ return mPortStatus == null ? POWER_ROLE_NONE : mPortStatus.getCurrentPowerRole();
}
public int getDataRole() {
updatePorts();
- return mPortStatus == null ? UsbPort.DATA_ROLE_NONE : mPortStatus.getCurrentDataRole();
+ return mPortStatus == null ? DATA_ROLE_NONE : mPortStatus.getCurrentDataRole();
}
public void setPowerRole(int role) {
int newDataRole = getDataRole();
if (!areAllRolesSupported()) {
switch (role) {
- case UsbPort.POWER_ROLE_SINK:
- newDataRole = UsbPort.DATA_ROLE_DEVICE;
+ case POWER_ROLE_SINK:
+ newDataRole = DATA_ROLE_DEVICE;
break;
- case UsbPort.POWER_ROLE_SOURCE:
- newDataRole = UsbPort.DATA_ROLE_HOST;
+ case POWER_ROLE_SOURCE:
+ newDataRole = DATA_ROLE_HOST;
break;
default:
- newDataRole = UsbPort.DATA_ROLE_NONE;
+ newDataRole = DATA_ROLE_NONE;
}
}
if (mPort != null) {
- mUsbManager.setPortRoles(mPort, role, newDataRole);
+ mPort.setRoles(role, newDataRole);
}
}
@@ -127,31 +136,27 @@ public class UsbBackend {
int newPowerRole = getPowerRole();
if (!areAllRolesSupported()) {
switch (role) {
- case UsbPort.DATA_ROLE_DEVICE:
- newPowerRole = UsbPort.POWER_ROLE_SINK;
+ case DATA_ROLE_DEVICE:
+ newPowerRole = POWER_ROLE_SINK;
break;
- case UsbPort.DATA_ROLE_HOST:
- newPowerRole = UsbPort.POWER_ROLE_SOURCE;
+ case DATA_ROLE_HOST:
+ newPowerRole = POWER_ROLE_SOURCE;
break;
default:
- newPowerRole = UsbPort.POWER_ROLE_NONE;
+ newPowerRole = POWER_ROLE_NONE;
}
}
if (mPort != null) {
- mUsbManager.setPortRoles(mPort, newPowerRole, role);
+ mPort.setRoles(newPowerRole, role);
}
}
public boolean areAllRolesSupported() {
return mPort != null && mPortStatus != null
- && mPortStatus
- .isRoleCombinationSupported(UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_DEVICE)
- && mPortStatus
- .isRoleCombinationSupported(UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_HOST)
- && mPortStatus
- .isRoleCombinationSupported(UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_DEVICE)
- && mPortStatus
- .isRoleCombinationSupported(UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_HOST);
+ && mPortStatus.isRoleCombinationSupported(POWER_ROLE_SINK, DATA_ROLE_DEVICE)
+ && mPortStatus.isRoleCombinationSupported(POWER_ROLE_SINK, DATA_ROLE_HOST)
+ && mPortStatus.isRoleCombinationSupported(POWER_ROLE_SOURCE, DATA_ROLE_DEVICE)
+ && mPortStatus.isRoleCombinationSupported(POWER_ROLE_SOURCE, DATA_ROLE_HOST);
}
public static String usbFunctionsToString(long functions) {
@@ -205,17 +210,14 @@ public class UsbBackend {
private void updatePorts() {
mPort = null;
mPortStatus = null;
- UsbPort[] ports = mUsbManager.getPorts();
- if (ports == null) {
- return;
- }
+ List ports = mUsbManager.getPorts();
// For now look for a connected port, in the future we should identify port in the
// notification and pick based on that.
- final int N = ports.length;
+ final int N = ports.size();
for (int i = 0; i < N; i++) {
- UsbPortStatus status = mUsbManager.getPortStatus(ports[i]);
+ UsbPortStatus status = ports.get(i).getStatus();
if (status.isConnected()) {
- mPort = ports[i];
+ mPort = ports.get(i);
mPortStatus = status;
break;
}
diff --git a/src/com/android/settings/connecteddevice/usb/UsbConnectionBroadcastReceiver.java b/src/com/android/settings/connecteddevice/usb/UsbConnectionBroadcastReceiver.java
index 1d43371a02c..beb23757e60 100644
--- a/src/com/android/settings/connecteddevice/usb/UsbConnectionBroadcastReceiver.java
+++ b/src/com/android/settings/connecteddevice/usb/UsbConnectionBroadcastReceiver.java
@@ -49,8 +49,8 @@ public class UsbConnectionBroadcastReceiver extends BroadcastReceiver implements
mUsbBackend = backend;
mFunctions = UsbManager.FUNCTION_NONE;
- mDataRole = UsbPort.DATA_ROLE_NONE;
- mPowerRole = UsbPort.POWER_ROLE_NONE;
+ mDataRole = UsbPortStatus.DATA_ROLE_NONE;
+ mPowerRole = UsbPortStatus.POWER_ROLE_NONE;
}
@Override
diff --git a/src/com/android/settings/connecteddevice/usb/UsbDetailsDataRoleController.java b/src/com/android/settings/connecteddevice/usb/UsbDetailsDataRoleController.java
index 84576b14252..a584c11fa06 100644
--- a/src/com/android/settings/connecteddevice/usb/UsbDetailsDataRoleController.java
+++ b/src/com/android/settings/connecteddevice/usb/UsbDetailsDataRoleController.java
@@ -16,6 +16,10 @@
package com.android.settings.connecteddevice.usb;
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE;
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_HOST;
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_NONE;
+
import android.content.Context;
import android.hardware.usb.UsbPort;
@@ -55,23 +59,23 @@ public class UsbDetailsDataRoleController extends UsbDetailsController
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreferenceCategory = (PreferenceCategory) screen.findPreference(getPreferenceKey());
- mHostPref = makeRadioPreference(UsbBackend.dataRoleToString(UsbPort.DATA_ROLE_HOST),
+ mHostPref = makeRadioPreference(UsbBackend.dataRoleToString(DATA_ROLE_HOST),
R.string.usb_control_host);
- mDevicePref = makeRadioPreference(UsbBackend.dataRoleToString(UsbPort.DATA_ROLE_DEVICE),
+ mDevicePref = makeRadioPreference(UsbBackend.dataRoleToString(DATA_ROLE_DEVICE),
R.string.usb_control_device);
}
@Override
protected void refresh(boolean connected, long functions, int powerRole, int dataRole) {
- if (dataRole == UsbPort.DATA_ROLE_DEVICE) {
+ if (dataRole == DATA_ROLE_DEVICE) {
mDevicePref.setChecked(true);
mHostPref.setChecked(false);
mPreferenceCategory.setEnabled(true);
- } else if (dataRole == UsbPort.DATA_ROLE_HOST) {
+ } else if (dataRole == DATA_ROLE_HOST) {
mDevicePref.setChecked(false);
mHostPref.setChecked(true);
mPreferenceCategory.setEnabled(true);
- } else if (!connected || dataRole == UsbPort.DATA_ROLE_NONE){
+ } else if (!connected || dataRole == DATA_ROLE_NONE){
mPreferenceCategory.setEnabled(false);
if (mNextRolePref == null) {
// Disconnected with no operation pending, so clear subtexts
@@ -80,7 +84,7 @@ public class UsbDetailsDataRoleController extends UsbDetailsController
}
}
- if (mNextRolePref != null && dataRole != UsbPort.DATA_ROLE_NONE) {
+ if (mNextRolePref != null && dataRole != DATA_ROLE_NONE) {
if (UsbBackend.dataRoleFromString(mNextRolePref.getKey()) == dataRole) {
// Clear switching text if switch succeeded
mNextRolePref.setSummary("");
diff --git a/src/com/android/settings/connecteddevice/usb/UsbDetailsFunctionsController.java b/src/com/android/settings/connecteddevice/usb/UsbDetailsFunctionsController.java
index f74dc0f5c5f..283e56bd9a0 100644
--- a/src/com/android/settings/connecteddevice/usb/UsbDetailsFunctionsController.java
+++ b/src/com/android/settings/connecteddevice/usb/UsbDetailsFunctionsController.java
@@ -16,6 +16,7 @@
package com.android.settings.connecteddevice.usb;
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE;
import static android.net.ConnectivityManager.TETHERING_USB;
import android.content.Context;
@@ -88,7 +89,7 @@ public class UsbDetailsFunctionsController extends UsbDetailsController
@Override
protected void refresh(boolean connected, long functions, int powerRole, int dataRole) {
- if (!connected || dataRole != UsbPort.DATA_ROLE_DEVICE) {
+ if (!connected || dataRole != DATA_ROLE_DEVICE) {
mProfilesContainer.setEnabled(false);
} else {
// Functions are only available in device mode
diff --git a/src/com/android/settings/connecteddevice/usb/UsbDetailsPowerRoleController.java b/src/com/android/settings/connecteddevice/usb/UsbDetailsPowerRoleController.java
index 30314f6e2ca..b59890aa61e 100644
--- a/src/com/android/settings/connecteddevice/usb/UsbDetailsPowerRoleController.java
+++ b/src/com/android/settings/connecteddevice/usb/UsbDetailsPowerRoleController.java
@@ -16,8 +16,13 @@
package com.android.settings.connecteddevice.usb;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_NONE;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SINK;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SOURCE;
+
import android.content.Context;
import android.hardware.usb.UsbPort;
+import android.hardware.usb.UsbPortStatus;
import androidx.preference.Preference;
import androidx.preference.Preference.OnPreferenceClickListener;
@@ -40,16 +45,16 @@ public class UsbDetailsPowerRoleController extends UsbDetailsController
private int mNextPowerRole;
private final Runnable mFailureCallback = () -> {
- if (mNextPowerRole != UsbPort.POWER_ROLE_NONE) {
+ if (mNextPowerRole != POWER_ROLE_NONE) {
mSwitchPreference.setSummary(R.string.usb_switching_failed);
- mNextPowerRole = UsbPort.POWER_ROLE_NONE;
+ mNextPowerRole = POWER_ROLE_NONE;
}
};
public UsbDetailsPowerRoleController(Context context, UsbDetailsFragment fragment,
UsbBackend backend) {
super(context, fragment, backend);
- mNextPowerRole = UsbPort.POWER_ROLE_NONE;
+ mNextPowerRole = POWER_ROLE_NONE;
}
@Override
@@ -70,20 +75,21 @@ public class UsbDetailsPowerRoleController extends UsbDetailsController
} else if (connected && mUsbBackend.areAllRolesSupported()){
mFragment.getPreferenceScreen().addPreference(mPreferenceCategory);
}
- if (powerRole == UsbPort.POWER_ROLE_SOURCE) {
+ if (powerRole == POWER_ROLE_SOURCE) {
mSwitchPreference.setChecked(true);
mPreferenceCategory.setEnabled(true);
- } else if (powerRole == UsbPort.POWER_ROLE_SINK) {
+ } else if (powerRole == POWER_ROLE_SINK) {
mSwitchPreference.setChecked(false);
mPreferenceCategory.setEnabled(true);
- } else if (!connected || powerRole == UsbPort.POWER_ROLE_NONE){
+ } else if (!connected || powerRole == POWER_ROLE_NONE){
mPreferenceCategory.setEnabled(false);
- if (mNextPowerRole == UsbPort.POWER_ROLE_NONE) {
+ if (mNextPowerRole == POWER_ROLE_NONE) {
mSwitchPreference.setSummary("");
}
}
- if (mNextPowerRole != UsbPort.POWER_ROLE_NONE && powerRole != UsbPort.POWER_ROLE_NONE) {
+ if (mNextPowerRole != POWER_ROLE_NONE
+ && powerRole != POWER_ROLE_NONE) {
if (mNextPowerRole == powerRole) {
// Clear switching text if switch succeeded
mSwitchPreference.setSummary("");
@@ -91,16 +97,16 @@ public class UsbDetailsPowerRoleController extends UsbDetailsController
// Set failure text if switch failed
mSwitchPreference.setSummary(R.string.usb_switching_failed);
}
- mNextPowerRole = UsbPort.POWER_ROLE_NONE;
+ mNextPowerRole = POWER_ROLE_NONE;
mHandler.removeCallbacks(mFailureCallback);
}
}
@Override
public boolean onPreferenceClick(Preference preference) {
- int newRole = mSwitchPreference.isChecked() ? UsbPort.POWER_ROLE_SOURCE
- : UsbPort.POWER_ROLE_SINK;
- if (mUsbBackend.getPowerRole() != newRole && mNextPowerRole == UsbPort.POWER_ROLE_NONE
+ int newRole = mSwitchPreference.isChecked() ? POWER_ROLE_SOURCE
+ : POWER_ROLE_SINK;
+ if (mUsbBackend.getPowerRole() != newRole && mNextPowerRole == POWER_ROLE_NONE
&& !Utils.isMonkeyRunning()) {
mUsbBackend.setPowerRole(newRole);
diff --git a/src/com/android/settings/core/InstrumentedPreferenceFragment.java b/src/com/android/settings/core/InstrumentedPreferenceFragment.java
index cafef00cf6f..f5f245fad66 100644
--- a/src/com/android/settings/core/InstrumentedPreferenceFragment.java
+++ b/src/com/android/settings/core/InstrumentedPreferenceFragment.java
@@ -22,6 +22,7 @@ import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.XmlRes;
+import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.overlay.FeatureFactory;
@@ -78,6 +79,14 @@ public abstract class InstrumentedPreferenceFragment extends ObservablePreferenc
updateActivityTitleWithScreenTitle(getPreferenceScreen());
}
+ @Override
+ public T findPreference(CharSequence key) {
+ if (key == null) {
+ return null;
+ }
+ return super.findPreference(key);
+ }
+
protected final Context getPrefContext() {
return getPreferenceManager().getContext();
}
diff --git a/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java b/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java
index 65492d5b054..5883e2173d5 100644
--- a/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java
@@ -16,7 +16,11 @@
package com.android.settings.deviceinfo;
+import static android.content.Context.CLIPBOARD_SERVICE;
+
import android.app.Activity;
+import android.content.ClipData;
+import android.content.ClipboardManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -29,34 +33,30 @@ import android.text.TextUtils;
import android.widget.Toast;
import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.Utils;
+import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.InstrumentedPreferenceFragment;
-import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.password.ChooseLockSettingsHelper;
+import com.android.settings.slices.Copyable;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtilsInternal;
-import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
-import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
-import com.android.settingslib.core.lifecycle.events.OnResume;
+import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.development.DevelopmentSettingsEnabler;
-public class BuildNumberPreferenceController extends AbstractPreferenceController implements
- PreferenceControllerMixin, LifecycleObserver, OnResume {
+public class BuildNumberPreferenceController extends BasePreferenceController implements Copyable,
+ LifecycleObserver, OnStart {
static final int TAPS_TO_BE_A_DEVELOPER = 7;
static final int REQUEST_CONFIRM_PASSWORD_FOR_DEV_PREF = 100;
- private static final String KEY_BUILD_NUMBER = "build_number";
-
- private final Activity mActivity;
- private final InstrumentedPreferenceFragment mFragment;
+ private Activity mActivity;
+ private InstrumentedPreferenceFragment mFragment;
private final UserManager mUm;
private final MetricsFeatureProvider mMetricsFeatureProvider;
@@ -66,44 +66,28 @@ public class BuildNumberPreferenceController extends AbstractPreferenceControlle
private int mDevHitCountdown;
private boolean mProcessingLastDevHit;
- public BuildNumberPreferenceController(Context context, Activity activity,
- InstrumentedPreferenceFragment fragment, Lifecycle lifecycle) {
- super(context);
- mActivity = activity;
- mFragment = fragment;
+ public BuildNumberPreferenceController(Context context, String key) {
+ super(context, key);
mUm = (UserManager) context.getSystemService(Context.USER_SERVICE);
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
- if (lifecycle != null) {
- lifecycle.addObserver(this);
+ }
+
+ public void setHost(InstrumentedPreferenceFragment fragment) {
+ mFragment = fragment;
+ mActivity = fragment.getActivity();
+ }
+
+ @Override
+ public CharSequence getSummary() {
+ try {
+ return BidiFormatter.getInstance().unicodeWrap(Build.DISPLAY);
+ } catch (Exception e) {
+ return mContext.getText(R.string.device_info_default);
}
}
@Override
- public void displayPreference(PreferenceScreen screen) {
- super.displayPreference(screen);
- final Preference preference = screen.findPreference(KEY_BUILD_NUMBER);
- if (preference != null) {
- try {
- preference.setSummary(BidiFormatter.getInstance().unicodeWrap(Build.DISPLAY));
- preference.setEnabled(true);
- } catch (Exception e) {
- preference.setSummary(R.string.device_info_default);
- }
- }
- }
-
- @Override
- public String getPreferenceKey() {
- return KEY_BUILD_NUMBER;
- }
-
- @Override
- public boolean isAvailable() {
- return true;
- }
-
- @Override
- public void onResume() {
+ public void onStart() {
mDebuggingFeaturesDisallowedAdmin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
mContext, UserManager.DISALLOW_DEBUGGING_FEATURES, UserHandle.myUserId());
mDebuggingFeaturesDisallowedBySystem = RestrictedLockUtilsInternal.hasBaseUserRestriction(
@@ -113,9 +97,31 @@ public class BuildNumberPreferenceController extends AbstractPreferenceControlle
mDevHitToast = null;
}
+ @Override
+ public int getAvailabilityStatus() {
+ return AVAILABLE;
+ }
+
+ @Override
+ public boolean isSliceable() {
+ return true;
+ }
+
+ @Override
+ public void copy() {
+ final ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(
+ CLIPBOARD_SERVICE);
+ final ClipData clip = ClipData.newPlainText("text", getSummary());
+ clipboard.setPrimaryClip(clip);
+
+ final String toast = mContext.getString(R.string.copyable_slice_toast,
+ mContext.getText(R.string.build_number));
+ Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show();
+ }
+
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
- if (!TextUtils.equals(preference.getKey(), KEY_BUILD_NUMBER)) {
+ if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
return false;
}
if (Utils.isMonkeyRunning()) {
diff --git a/src/com/android/settings/deviceinfo/StorageWizardBase.java b/src/com/android/settings/deviceinfo/StorageWizardBase.java
index 50c908acc8d..9950d3ffaa0 100644
--- a/src/com/android/settings/deviceinfo/StorageWizardBase.java
+++ b/src/com/android/settings/deviceinfo/StorageWizardBase.java
@@ -35,7 +35,6 @@ import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
-import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
@@ -45,6 +44,8 @@ import androidx.fragment.app.FragmentActivity;
import com.android.settings.R;
import com.android.settingslib.Utils;
+import com.google.android.setupcompat.item.FooterButton;
+import com.google.android.setupcompat.template.ButtonFooterMixin;
import com.google.android.setupdesign.GlifLayout;
import java.text.NumberFormat;
@@ -62,8 +63,9 @@ public abstract class StorageWizardBase extends FragmentActivity {
protected VolumeInfo mVolume;
protected DiskInfo mDisk;
- private Button mBack;
- private Button mNext;
+ private ButtonFooterMixin mButtonFooterMixin;
+ private FooterButton mBack;
+ private FooterButton mNext;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -92,8 +94,25 @@ public abstract class StorageWizardBase extends FragmentActivity {
public void setContentView(@LayoutRes int layoutResID) {
super.setContentView(layoutResID);
- mBack = requireViewById(R.id.storage_back_button);
- mNext = requireViewById(R.id.storage_next_button);
+ mButtonFooterMixin = getGlifLayout().getMixin(ButtonFooterMixin.class);
+ mButtonFooterMixin.setSecondaryButton(
+ new FooterButton(
+ this,
+ R.string.wizard_back,
+ this::onNavigateBack,
+ FooterButton.ButtonType.OTHER,
+ R.style.SuwGlifButton_Secondary)
+ );
+ mButtonFooterMixin.setPrimaryButton(
+ new FooterButton(
+ this,
+ R.string.wizard_next,
+ this::onNavigateNext,
+ FooterButton.ButtonType.NEXT,
+ R.style.SuwGlifButton_Primary)
+ );
+ mBack = mButtonFooterMixin.getSecondaryButton();
+ mNext = mButtonFooterMixin.getPrimaryButton();
setIcon(com.android.internal.R.drawable.ic_sd_card_48dp);
}
@@ -104,11 +123,11 @@ public abstract class StorageWizardBase extends FragmentActivity {
super.onDestroy();
}
- protected Button getBackButton() {
+ protected FooterButton getBackButton() {
return mBack;
}
- protected Button getNextButton() {
+ protected FooterButton getNextButton() {
return mNext;
}
diff --git a/src/com/android/settings/deviceinfo/StorageWizardInit.java b/src/com/android/settings/deviceinfo/StorageWizardInit.java
index 51dd74bdb3e..907f58c6160 100644
--- a/src/com/android/settings/deviceinfo/StorageWizardInit.java
+++ b/src/com/android/settings/deviceinfo/StorageWizardInit.java
@@ -30,7 +30,6 @@ import com.android.settings.R;
import com.android.settings.overlay.FeatureFactory;
public class StorageWizardInit extends StorageWizardBase {
- private Button mExternal;
private Button mInternal;
private boolean mIsPermittedToAdopt;
@@ -49,7 +48,6 @@ public class StorageWizardInit extends StorageWizardBase {
setHeaderText(R.string.storage_wizard_init_v2_title, getDiskShortDescription());
- mExternal = requireViewById(R.id.storage_wizard_init_external);
mInternal = requireViewById(R.id.storage_wizard_init_internal);
setBackButtonText(R.string.storage_wizard_init_v2_later);
diff --git a/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java b/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java
index 8b21f0d9633..19b69759f2c 100644
--- a/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java
+++ b/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java
@@ -64,6 +64,8 @@ public class MyDeviceInfoFragment extends DashboardFragment
private static final String LOG_TAG = "MyDeviceInfoFragment";
private static final String KEY_MY_DEVICE_INFO_HEADER = "my_device_info_header";
+ private BuildNumberPreferenceController mBuildNumberPreferenceController;
+
@Override
public int getMetricsCategory() {
return MetricsEvent.DEVICEINFO;
@@ -79,6 +81,8 @@ public class MyDeviceInfoFragment extends DashboardFragment
super.onAttach(context);
use(FirmwareVersionPreferenceController.class).setHost(this /*parent*/);
use(DeviceModelPreferenceController.class).setHost(this /* parent */);
+ mBuildNumberPreferenceController = use(BuildNumberPreferenceController.class);
+ mBuildNumberPreferenceController.setHost(this /* parent */);
}
@Override
@@ -126,17 +130,13 @@ public class MyDeviceInfoFragment extends DashboardFragment
controllers.add(new ManualPreferenceController(context));
controllers.add(new FeedbackPreferenceController(fragment, context));
controllers.add(new FccEquipmentIdPreferenceController(context));
- controllers.add(
- new BuildNumberPreferenceController(context, activity, fragment, lifecycle));
controllers.add(new UptimePreferenceController(context, lifecycle));
return controllers;
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
- final BuildNumberPreferenceController buildNumberPreferenceController =
- use(BuildNumberPreferenceController.class);
- if (buildNumberPreferenceController.onActivityResult(requestCode, resultCode, data)) {
+ if (mBuildNumberPreferenceController.onActivityResult(requestCode, resultCode, data)) {
return;
}
super.onActivityResult(requestCode, resultCode, data);
diff --git a/src/com/android/settings/fuelgauge/BatteryUtils.java b/src/com/android/settings/fuelgauge/BatteryUtils.java
index c0712842706..6f779535943 100644
--- a/src/com/android/settings/fuelgauge/BatteryUtils.java
+++ b/src/com/android/settings/fuelgauge/BatteryUtils.java
@@ -449,12 +449,14 @@ public class BatteryUtils {
final BatteryStats stats = statsHelper.getStats();
BatteryInfo batteryInfo;
- final Estimate estimate;
+ Estimate estimate = null;
// Get enhanced prediction if available
if (mPowerUsageFeatureProvider != null &&
mPowerUsageFeatureProvider.isEnhancedBatteryPredictionEnabled(mContext)) {
estimate = mPowerUsageFeatureProvider.getEnhancedBatteryPrediction(mContext);
- } else {
+ }
+
+ if (estimate == null) {
estimate = new Estimate(
PowerUtil.convertUsToMs(stats.computeBatteryTimeRemaining(elapsedRealtimeUs)),
false /* isBasedOnUsage */,
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProvider.java b/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProvider.java
index 5ebc924bdec..b1e9d33e682 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProvider.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProvider.java
@@ -16,24 +16,21 @@
package com.android.settings.homepage.contextualcards;
-import android.content.Context;
-
import java.util.List;
/** Feature provider for the contextual card feature. */
public interface ContextualCardFeatureProvider {
/** Homepage displays. */
- void logHomepageDisplay(Context context, long latency);
+ void logHomepageDisplay(long latency);
/** When user clicks dismiss in contextual card */
- void logContextualCardDismiss(Context context, ContextualCard card);
+ void logContextualCardDismiss(ContextualCard card);
/** After ContextualCardManager decides which cards will be displayed/hidden */
- void logContextualCardDisplay(Context context, List showedCards,
+ void logContextualCardDisplay(List showedCards,
List hiddenCards);
/** When user clicks toggle/title area of a contextual card. */
- void logContextualCardClick(Context context, ContextualCard card, int row,
- int tapTarget);
+ void logContextualCardClick(ContextualCard card, int row, int tapTarget);
}
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImpl.java b/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImpl.java
index dc295fc1f94..12590ff8487 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImpl.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImpl.java
@@ -51,6 +51,9 @@ public class ContextualCardFeatureProviderImpl implements ContextualCardFeatureP
// contextual card name
private static final String EXTRA_CONTEXTUALCARD_NAME = "name";
+ // contextual card uri
+ private static final String EXTRA_CONTEXTUALCARD_URI = "uri";
+
// contextual card score
private static final String EXTRA_CONTEXTUALCARD_SCORE = "score";
@@ -84,51 +87,59 @@ public class ContextualCardFeatureProviderImpl implements ContextualCardFeatureP
// Click slider
private static final int TARGET_SLIDER = 3;
+ private final Context mContext;
+
+ public ContextualCardFeatureProviderImpl(Context context) {
+ mContext = context;
+ }
+
@Override
- public void logHomepageDisplay(Context context, long latency) {
- sendBroadcast(context, new Intent()
+ public void logHomepageDisplay(long latency) {
+ sendBroadcast(new Intent()
.putExtra(EXTRA_CONTEXTUALCARD_ACTION_TYPE, CONTEXTUAL_HOME_SHOW)
.putExtra(EXTRA_LATENCY, latency));
}
@Override
- public void logContextualCardDismiss(Context context, ContextualCard card) {
+ public void logContextualCardDismiss(ContextualCard card) {
final Intent intent = new Intent();
intent.putExtra(EXTRA_CONTEXTUALCARD_ACTION_TYPE, CONTEXTUAL_CARD_DISMISS);
intent.putExtra(EXTRA_CONTEXTUALCARD_NAME, card.getName());
+ intent.putExtra(EXTRA_CONTEXTUALCARD_URI, card.getSliceUri().toString());
intent.putExtra(EXTRA_CONTEXTUALCARD_SCORE, card.getRankingScore());
- sendBroadcast(context, intent);
+ sendBroadcast(intent);
}
@Override
- public void logContextualCardDisplay(Context context, List visibleCards,
+ public void logContextualCardDisplay(List visibleCards,
List hiddenCards) {
final Intent intent = new Intent();
intent.putExtra(EXTRA_CONTEXTUALCARD_ACTION_TYPE, CONTEXTUAL_CARD_SHOW);
intent.putExtra(EXTRA_CONTEXTUALCARD_VISIBLE, serialize(visibleCards));
intent.putExtra(EXTRA_CONTEXTUALCARD_HIDDEN, serialize(hiddenCards));
- sendBroadcast(context, intent);
+ sendBroadcast(intent);
}
@Override
- public void logContextualCardClick(Context context, ContextualCard card, int row,
+ public void logContextualCardClick(ContextualCard card, int row,
int actionType) {
final Intent intent = new Intent();
intent.putExtra(EXTRA_CONTEXTUALCARD_ACTION_TYPE, CONTEXTUAL_CARD_CLICK);
intent.putExtra(EXTRA_CONTEXTUALCARD_NAME, card.getName());
+ intent.putExtra(EXTRA_CONTEXTUALCARD_URI, card.getSliceUri().toString());
intent.putExtra(EXTRA_CONTEXTUALCARD_SCORE, card.getRankingScore());
intent.putExtra(EXTRA_CONTEXTUALCARD_ROW, row);
intent.putExtra(EXTRA_CONTEXTUALCARD_TAP_TARGET, actionTypeToTapTarget(actionType));
- sendBroadcast(context, intent);
+ sendBroadcast(intent);
}
@VisibleForTesting
- void sendBroadcast(final Context context, final Intent intent) {
- intent.setPackage(context.getString(R.string.config_settingsintelligence_package_name));
- final String action = context.getString(R.string.config_settingsintelligence_log_action);
+ void sendBroadcast(final Intent intent) {
+ intent.setPackage(mContext.getString(R.string.config_settingsintelligence_package_name));
+ final String action = mContext.getString(R.string.config_settingsintelligence_log_action);
if (!TextUtils.isEmpty(action)) {
intent.setAction(action);
- context.sendBroadcastAsUser(intent, UserHandle.ALL);
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
}
}
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
index 71b262de7d7..88478e3d065 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
@@ -21,7 +21,7 @@ import static android.app.slice.Slice.HINT_ERROR;
import static androidx.slice.widget.SliceLiveData.SUPPORTED_SPECS;
import static com.android.settings.slices.CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI;
-import static com.android.settings.slices.CustomSliceRegistry.WIFI_SLICE_URI;
+import static com.android.settings.slices.CustomSliceRegistry.CONTEXTUAL_WIFI_SLICE_URI;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
@@ -149,10 +149,10 @@ public class ContextualCardLoader extends AsyncLoaderCompat
// Two large cards
return visibleCards;
} finally {
+ //TODO(b/121196921): Should not call this if user click dismiss
final ContextualCardFeatureProvider contextualCardFeatureProvider =
- FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider();
- contextualCardFeatureProvider.logContextualCardDisplay(mContext, visibleCards,
- hiddenCards);
+ FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider(mContext);
+ contextualCardFeatureProvider.logContextualCardDisplay(visibleCards, hiddenCards);
}
}
@@ -204,7 +204,7 @@ public class ContextualCardLoader extends AsyncLoaderCompat
}
private boolean isLargeCard(ContextualCard card) {
- return card.getSliceUri().equals(WIFI_SLICE_URI)
+ return card.getSliceUri().equals(CONTEXTUAL_WIFI_SLICE_URI)
|| card.getSliceUri().equals(BLUETOOTH_DEVICES_SLICE_URI);
}
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
index 9c06beb7ebc..067de7ccf3a 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardManager.java
@@ -201,8 +201,8 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo
.collect(groupingBy(ContextualCard::getCardType)));
}
final long totalTime = System.currentTimeMillis() - mStartTime;
- FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider()
- .logHomepageDisplay(mContext, totalTime);
+ FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider(mContext)
+ .logHomepageDisplay(totalTime);
mIsFirstLaunch = false;
}
diff --git a/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java b/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
index d5500fb37e3..57970433150 100644
--- a/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
+++ b/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProvider.java
@@ -34,8 +34,8 @@ public class SettingsContextualCardProvider extends ContextualCardProvider {
public ContextualCardList getContextualCards() {
final ContextualCard wifiCard =
ContextualCard.newBuilder()
- .setSliceUri(CustomSliceRegistry.WIFI_SLICE_URI.toString())
- .setCardName(CustomSliceRegistry.WIFI_SLICE_URI.toString())
+ .setSliceUri(CustomSliceRegistry.CONTEXTUAL_WIFI_SLICE_URI.toString())
+ .setCardName(CustomSliceRegistry.CONTEXTUAL_WIFI_SLICE_URI.toString())
.setCardCategory(ContextualCard.Category.IMPORTANT)
.build();
final ContextualCard connectedDeviceCard =
diff --git a/src/com/android/settings/homepage/contextualcards/slices/BatteryFixSlice.java b/src/com/android/settings/homepage/contextualcards/slices/BatteryFixSlice.java
index 41c27575fd1..ab1b4c90327 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/BatteryFixSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/BatteryFixSlice.java
@@ -98,10 +98,10 @@ public class BatteryFixSlice implements CustomSliceable {
ListBuilder.ICON_IMAGE,
batteryTip.getTitle(mContext));
sliceBuilder.addRow(new RowBuilder()
+ .setTitleItem(icon, ListBuilder.ICON_IMAGE)
.setTitle(batteryTip.getTitle(mContext))
.setSubtitle(batteryTip.getSummary(mContext))
- .setPrimaryAction(primaryAction)
- .addEndItem(icon, ListBuilder.ICON_IMAGE));
+ .setPrimaryAction(primaryAction));
break;
}
}
@@ -144,9 +144,9 @@ public class BatteryFixSlice implements CustomSliceable {
final SliceAction primaryAction = SliceAction.createDeeplink(getPrimaryAction(), icon,
ListBuilder.ICON_IMAGE, title);
sliceBuilder.addRow(new RowBuilder()
+ .setTitleItem(icon, ListBuilder.ICON_IMAGE)
.setTitle(title)
- .setPrimaryAction(primaryAction)
- .addEndItem(icon, ListBuilder.ICON_IMAGE))
+ .setPrimaryAction(primaryAction))
.setIsError(isError);
return sliceBuilder.build();
}
diff --git a/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java b/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java
index ad8d4a644aa..6a7527482ae 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSlice.java
@@ -46,6 +46,7 @@ import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.CustomSliceable;
+import com.android.settings.slices.SliceBroadcastReceiver;
import com.android.settings.slices.SliceBuilderUtils;
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
@@ -59,19 +60,22 @@ import java.util.stream.Collectors;
public class BluetoothDevicesSlice implements CustomSliceable {
- /**
- * TODO(b/114807655): Contextual Home Page - Connected Device
- * Re-design sorting for new rule:
- * Sorting rule: Audio Streaming > Last connected > Recently connected.
- */
- private static final Comparator COMPARATOR
- = Comparator.naturalOrder();
+ @VisibleForTesting
+ static final String BLUETOOTH_DEVICE_HASH_CODE = "bluetooth_device_hash_code";
/**
* Add the "Pair new device" in the end of slice, when the number of Bluetooth devices is less
* than {@link #DEFAULT_EXPANDED_ROW_COUNT}.
*/
- private static final int DEFAULT_EXPANDED_ROW_COUNT = 3;
+ @VisibleForTesting
+ static final int DEFAULT_EXPANDED_ROW_COUNT = 3;
+
+ /**
+ * Refer {@link com.android.settings.bluetooth.BluetoothDevicePreference#compareTo} to sort the
+ * Bluetooth devices by {@link CachedBluetoothDevice}.
+ */
+ private static final Comparator COMPARATOR
+ = Comparator.naturalOrder();
private static final String TAG = "BluetoothDevicesSlice";
@@ -109,12 +113,11 @@ public class BluetoothDevicesSlice implements CustomSliceable {
final SliceAction primarySliceAction = SliceAction.createDeeplink(primaryActionIntent, icon,
ListBuilder.ICON_IMAGE, title);
final ListBuilder listBuilder =
- new ListBuilder(mContext, CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI,
- ListBuilder.INFINITY)
+ new ListBuilder(mContext, getUri(), ListBuilder.INFINITY)
.setAccentColor(Utils.getColorAccentDefaultColor(mContext));
// Get row builders by Bluetooth devices.
- final List rows = getBluetoothRowBuilder(primarySliceAction);
+ final List rows = getBluetoothRowBuilder();
// Return a header with IsError flag, if no Bluetooth devices.
if (rows.isEmpty()) {
@@ -125,15 +128,18 @@ public class BluetoothDevicesSlice implements CustomSliceable {
.build();
}
- // According the number of Bluetooth devices to set sub title of header.
+ // Get displayable device count.
+ final int deviceCount = Math.min(rows.size(), DEFAULT_EXPANDED_ROW_COUNT);
+
+ // According to the displayable device count to set sub title of header.
listBuilder.setHeader(new ListBuilder.HeaderBuilder()
.setTitle(title)
- .setSubtitle(getSubTitle(rows.size()))
+ .setSubtitle(getSubTitle(deviceCount))
.setPrimaryAction(primarySliceAction));
- // Add bluetooth device rows.
- for (ListBuilder.RowBuilder rowBuilder : rows) {
- listBuilder.addRow(rowBuilder);
+ // According to the displayable device count to add bluetooth device rows.
+ for (int i = 0; i < deviceCount; i++) {
+ listBuilder.addRow(rows.get(i));
}
// Add "Pair new device" if need.
@@ -154,11 +160,19 @@ public class BluetoothDevicesSlice implements CustomSliceable {
screenTitle,
MetricsProto.MetricsEvent.SLICE)
.setClassName(mContext.getPackageName(), SubSettings.class.getName())
- .setData(CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI);
+ .setData(getUri());
}
@Override
public void onNotifyChange(Intent intent) {
+ // Activate available media device.
+ final int bluetoothDeviceHashCode = intent.getIntExtra(BLUETOOTH_DEVICE_HASH_CODE, -1);
+ for (CachedBluetoothDevice cachedBluetoothDevice : getConnectedBluetoothDevices()) {
+ if (cachedBluetoothDevice.hashCode() == bluetoothDeviceHashCode) {
+ cachedBluetoothDevice.setActive();
+ return;
+ }
+ }
}
@Override
@@ -167,10 +181,10 @@ public class BluetoothDevicesSlice implements CustomSliceable {
}
@VisibleForTesting
- List getBluetoothDevices() {
+ List getConnectedBluetoothDevices() {
final List bluetoothDeviceList = new ArrayList<>();
- // If Bluetooth is disable, skip to get the bluetooth devices.
+ // If Bluetooth is disable, skip to get the Bluetooth devices.
if (!BluetoothAdapter.getDefaultAdapter().isEnabled()) {
Log.i(TAG, "Cannot get Bluetooth devices, Bluetooth is disabled.");
return bluetoothDeviceList;
@@ -188,12 +202,13 @@ public class BluetoothDevicesSlice implements CustomSliceable {
/**
* TODO(b/114807655): Contextual Home Page - Connected Device
- * Re-design to get all Bluetooth devices and sort them by new rule:
- * Sorting rule: Audio Streaming > Last connected > Recently connected.
+ * It's under discussion for including available media devices and currently connected
+ * devices from Bluetooth. Will update the devices list or remove TODO later.
*/
- // Get connected Bluetooth devices and sort them.
- return cachedDevices.stream().filter(device -> device.isConnected()).sorted(
- COMPARATOR).collect(Collectors.toList());
+ // Get available media device list and sort them.
+ return cachedDevices.stream()
+ .filter(device -> device.isConnected() && device.isConnectedA2dpDevice())
+ .sorted(COMPARATOR).collect(Collectors.toList());
}
@VisibleForTesting
@@ -226,27 +241,35 @@ public class BluetoothDevicesSlice implements CustomSliceable {
}
}
- private List getBluetoothRowBuilder(SliceAction primarySliceAction) {
+ private List getBluetoothRowBuilder() {
+ // According to Bluetooth devices to create row builders.
final List bluetoothRows = new ArrayList<>();
-
- /**
- * TODO(b/114807655): Contextual Home Page - Connected Device
- * Re-design to do action "activating" in primary action.
- */
- // According Bluetooth device to create row builders.
- final List bluetoothDevices = getBluetoothDevices();
+ final List bluetoothDevices = getConnectedBluetoothDevices();
for (CachedBluetoothDevice bluetoothDevice : bluetoothDevices) {
bluetoothRows.add(new ListBuilder.RowBuilder()
.setTitleItem(getBluetoothDeviceIcon(bluetoothDevice), ListBuilder.ICON_IMAGE)
.setTitle(bluetoothDevice.getName())
.setSubtitle(bluetoothDevice.getConnectionSummary())
- .setPrimaryAction(primarySliceAction)
+ .setPrimaryAction(buildBluetoothDeviceAction(bluetoothDevice))
.addEndItem(buildBluetoothDetailDeepLinkAction(bluetoothDevice)));
}
return bluetoothRows;
}
+ private SliceAction buildBluetoothDeviceAction(CachedBluetoothDevice bluetoothDevice) {
+ // Send broadcast to activate available media device.
+ final Intent intent = new Intent(getUri().toString())
+ .setClass(mContext, SliceBroadcastReceiver.class)
+ .putExtra(BLUETOOTH_DEVICE_HASH_CODE, bluetoothDevice.hashCode());
+
+ return SliceAction.create(
+ PendingIntent.getBroadcast(mContext, bluetoothDevice.hashCode(), intent, 0),
+ getBluetoothDeviceIcon(bluetoothDevice),
+ ListBuilder.ICON_IMAGE,
+ bluetoothDevice.getName());
+ }
+
private SliceAction buildBluetoothDetailDeepLinkAction(CachedBluetoothDevice bluetoothDevice) {
return SliceAction.createDeeplink(
getBluetoothDetailIntent(bluetoothDevice),
diff --git a/src/com/android/settings/homepage/contextualcards/slices/LowStorageSlice.java b/src/com/android/settings/homepage/contextualcards/slices/LowStorageSlice.java
index e0f31165c5f..03e430160b3 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/LowStorageSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/LowStorageSlice.java
@@ -119,15 +119,10 @@ public class LowStorageSlice implements CustomSliceable {
PendingIntent.getActivity(mContext, 0, getIntent(), 0), icon,
ListBuilder.ICON_IMAGE, title);
- /**
- * TODO(b/114808204): Contextual Home Page - "Low Storage"
- * Slices doesn't support "Icon on the left" in header. Now we intend to start with Icon
- * right aligned. Will update the icon to left until Slices support it.
- */
return new RowBuilder()
+ .setTitleItem(icon, ListBuilder.ICON_IMAGE)
.setTitle(title)
.setSubtitle(summary)
- .addEndItem(icon, ListBuilder.ICON_IMAGE)
.setPrimaryAction(primarySliceAction);
}
}
\ No newline at end of file
diff --git a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardController.java b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardController.java
index 8720a3ce488..eb062e8629f 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardController.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardController.java
@@ -70,8 +70,8 @@ public class SliceContextualCardController implements ContextualCardController {
});
showFeedbackDialog(card);
final ContextualCardFeatureProvider contextualCardFeatureProvider =
- FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider();
- contextualCardFeatureProvider.logContextualCardDismiss(mContext, card);
+ FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider(mContext);
+ contextualCardFeatureProvider.logContextualCardDismiss(card);
}
@Override
diff --git a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java
index 172c3b27845..7ca6e9aad84 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java
@@ -132,6 +132,7 @@ public class SliceContextualCardRenderer implements ContextualCardRenderer,
cardHolder.sliceView.setOnSliceActionListener(this);
// Customize slice view for Settings
+ cardHolder.sliceView.showTitleItems(true);
if (card.isLargeCard()) {
cardHolder.sliceView.showHeaderDivider(true);
cardHolder.sliceView.showActionDividers(true);
@@ -173,8 +174,9 @@ public class SliceContextualCardRenderer implements ContextualCardRenderer,
if (sliceItem.getSlice().getUri().toString().startsWith(
card.getSliceUri().toString())) {
ContextualCardFeatureProvider contexualCardFeatureProvider =
- FeatureFactory.getFactory(mContext).getContextualCardFeatureProvider();
- contexualCardFeatureProvider.logContextualCardClick(mContext, card,
+ FeatureFactory.getFactory(mContext)
+ .getContextualCardFeatureProvider(mContext);
+ contexualCardFeatureProvider.logContextualCardClick(card,
eventInfo.rowIndex, eventInfo.actionType);
break;
}
@@ -194,7 +196,7 @@ public class SliceContextualCardRenderer implements ContextualCardRenderer,
public SliceViewHolder(View view) {
super(view);
sliceView = view.findViewById(R.id.slice_view);
- viewFlipper = view.findViewById(R.id.viewFlipper);
+ viewFlipper = view.findViewById(R.id.view_flipper);
}
public void resetCard() {
diff --git a/src/com/android/settings/location/LocationSettings.java b/src/com/android/settings/location/LocationSettings.java
index 41123402039..78a15411703 100644
--- a/src/com/android/settings/location/LocationSettings.java
+++ b/src/com/android/settings/location/LocationSettings.java
@@ -16,7 +16,6 @@
package com.android.settings.location;
-import android.app.Activity;
import android.content.Context;
import android.location.SettingInjectorService;
import android.os.Bundle;
@@ -29,7 +28,6 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.dashboard.DashboardFragment;
-import com.android.settings.dashboard.SummaryLoader;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settings.widget.SwitchBar;
@@ -103,12 +101,8 @@ public class LocationSettings extends DashboardFragment {
static void addPreferencesSorted(List prefs, PreferenceGroup container) {
// If there's some items to display, sort the items and add them to the container.
- Collections.sort(prefs, new Comparator() {
- @Override
- public int compare(Preference lhs, Preference rhs) {
- return lhs.getTitle().toString().compareTo(rhs.getTitle().toString());
- }
- });
+ Collections.sort(prefs,
+ Comparator.comparing(lhs -> lhs.getTitle().toString()));
for (Preference entry : prefs) {
container.addPreference(entry);
}
diff --git a/src/com/android/settings/network/ApnSettings.java b/src/com/android/settings/network/ApnSettings.java
index 261d88915a2..2b47c70fdd1 100755
--- a/src/com/android/settings/network/ApnSettings.java
+++ b/src/com/android/settings/network/ApnSettings.java
@@ -277,7 +277,7 @@ public class ApnSettings extends RestrictedSettingsFragment {
private void fillList() {
final int subId = mSubscriptionInfo != null ? mSubscriptionInfo.getSubscriptionId()
: SubscriptionManager.INVALID_SUBSCRIPTION_ID;
- final Uri simApnUri = Uri.withAppendedPath(Telephony.Carriers.SIM_APN_LIST,
+ final Uri simApnUri = Uri.withAppendedPath(Telephony.Carriers.SIM_APN_URI,
String.valueOf(subId));
StringBuilder where = new StringBuilder("NOT (type='ia' AND (apn=\"\" OR apn IS NULL)) AND "
+ "user_visible!=0");
diff --git a/src/com/android/settings/network/SubscriptionsPreferenceController.java b/src/com/android/settings/network/SubscriptionsPreferenceController.java
index 9e55341a7d3..bf6d39c3d00 100644
--- a/src/com/android/settings/network/SubscriptionsPreferenceController.java
+++ b/src/com/android/settings/network/SubscriptionsPreferenceController.java
@@ -20,10 +20,13 @@ import static androidx.lifecycle.Lifecycle.Event.ON_PAUSE;
import static androidx.lifecycle.Lifecycle.Event.ON_RESUME;
import android.content.Context;
+import android.content.Intent;
+import android.provider.Settings;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import com.android.settings.R;
+import com.android.settings.network.telephony.MobileNetworkActivity;
import com.android.settingslib.core.AbstractPreferenceController;
import java.util.Map;
@@ -125,7 +128,7 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
mSubscriptionPreferences = new ArrayMap<>();
int order = mStartOrder;
- for (SubscriptionInfo info : SubscriptionUtil.getAvailableSubscriptions(mManager) ) {
+ for (SubscriptionInfo info : SubscriptionUtil.getAvailableSubscriptions(mManager)) {
final int subId = info.getSubscriptionId();
Preference pref = existingPrefs.remove(subId);
if (pref == null) {
@@ -139,8 +142,9 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
// TODO(asargent) - set summary here to indicate default for calls/sms and data
pref.setOnPreferenceClickListener(clickedPref -> {
- // TODO(asargent) - make this start MobileNetworkActivity once we've
- // added support for it to take a subscription id
+ final Intent intent = new Intent(mContext, MobileNetworkActivity.class);
+ intent.putExtra(Settings.EXTRA_SUB_ID, subId);
+ mContext.startActivity(intent);
return true;
});
diff --git a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java
index b323f910af5..d2ec162a423 100644
--- a/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java
+++ b/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java
@@ -126,7 +126,6 @@ public class EnabledNetworkModePreferenceController extends BasePreferenceContro
private void updatePreferenceEntries(ListPreference preference) {
final int phoneType = mTelephonyManager.getPhoneType();
- final Resources resources = mContext.getResources();
final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(mSubId);
if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
final int lteForced = android.provider.Settings.Global.getInt(
@@ -216,6 +215,7 @@ public class EnabledNetworkModePreferenceController extends BasePreferenceContro
}
private void updatePreferenceValueAndSummary(ListPreference preference, int networkMode) {
+ preference.setValue(Integer.toString(networkMode));
switch (networkMode) {
case TelephonyManager.NETWORK_MODE_TDSCDMA_WCDMA:
case TelephonyManager.NETWORK_MODE_TDSCDMA_GSM_WCDMA:
diff --git a/src/com/android/settings/network/telephony/MobileNetworkActivity.java b/src/com/android/settings/network/telephony/MobileNetworkActivity.java
index 9f3dfb28f2a..c101db4b095 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkActivity.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkActivity.java
@@ -25,7 +25,6 @@ import android.os.Bundle;
import android.provider.Settings;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
-import android.util.Log;
import android.view.Menu;
import android.view.View;
@@ -43,14 +42,12 @@ import com.android.settings.core.SettingsBaseActivity;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
import java.util.List;
import java.util.Objects;
public class MobileNetworkActivity extends SettingsBaseActivity {
- private static final String TAG = "MobileSettingsActivity";
+ private static final String TAG = "MobileNetworkActivity";
@VisibleForTesting
static final String MOBILE_SETTINGS_TAG = "mobile_settings:";
@VisibleForTesting
@@ -94,6 +91,13 @@ public class MobileNetworkActivity extends SettingsBaseActivity {
actionBar.setDisplayHomeAsUpEnabled(true);
}
+ // Set the title to the name of the subscription. If we don't have subscription info, the
+ // title will just default to the label for this activity that's already specified in
+ // AndroidManifest.xml.
+ final SubscriptionInfo subscription = getSubscription();
+ if (subscription != null) {
+ setTitle(subscription.getDisplayName());
+ }
updateSubscriptions(savedInstanceState);
}
@@ -136,25 +140,41 @@ public class MobileNetworkActivity extends SettingsBaseActivity {
}
/**
- * Get the current subId to display. First check whether intent has {@link
- * Settings#EXTRA_SUB_ID}. If not, just display first one in list
- * since it is already sorted by sim slot.
+ * Get the current subscription to display. First check whether intent has {@link
+ * Settings#EXTRA_SUB_ID} and if so find the subscription with that id. If not, just return the
+ * first one in the mSubscriptionInfos list since it is already sorted by sim slot.
*/
@VisibleForTesting
- int getSubscriptionId() {
+ SubscriptionInfo getSubscription() {
final Intent intent = getIntent();
if (intent != null) {
final int subId = intent.getIntExtra(Settings.EXTRA_SUB_ID, SUB_ID_NULL);
- if (subId != SUB_ID_NULL && mSubscriptionManager.isActiveSubscriptionId(subId)) {
- return subId;
+ if (subId != SUB_ID_NULL) {
+ for (SubscriptionInfo subscription :
+ mSubscriptionManager.getAvailableSubscriptionInfoList()) {
+ if (subscription.getSubscriptionId() == subId) {
+ return subscription;
+ }
+ }
}
}
if (CollectionUtils.isEmpty(mSubscriptionInfos)) {
- return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ return null;
}
+ return mSubscriptionInfos.get(0);
+ }
- return mSubscriptionInfos.get(0).getSubscriptionId();
+ /**
+ * Get the current subId to display.
+ */
+ @VisibleForTesting
+ int getSubscriptionId() {
+ final SubscriptionInfo subscription = getSubscription();
+ if (subscription != null) {
+ return subscription.getSubscriptionId();
+ }
+ return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
}
@VisibleForTesting
diff --git a/src/com/android/settings/notification/AbstractZenCustomRulePreferenceController.java b/src/com/android/settings/notification/AbstractZenCustomRulePreferenceController.java
new file mode 100644
index 00000000000..409eec62ece
--- /dev/null
+++ b/src/com/android/settings/notification/AbstractZenCustomRulePreferenceController.java
@@ -0,0 +1,61 @@
+/*
+ * 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.os.Bundle;
+
+import androidx.preference.Preference;
+
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+abstract class AbstractZenCustomRulePreferenceController extends
+ AbstractZenModePreferenceController implements PreferenceControllerMixin {
+
+ String mId;
+ AutomaticZenRule mRule;
+
+ AbstractZenCustomRulePreferenceController(Context context, String key,
+ Lifecycle lifecycle) {
+ super(context, key, lifecycle);
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ if (mId != null) {
+ mRule = mBackend.getAutomaticZenRule(mId);
+ }
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return mRule != null;
+ }
+
+ public void onResume(AutomaticZenRule rule, String id) {
+ mId = id;
+ mRule = rule;
+ }
+
+ Bundle createBundle() {
+ Bundle bundle = new Bundle();
+ bundle.putString(ZenCustomRuleSettings.RULE_ID, mId);
+ return bundle;
+ }
+}
diff --git a/src/com/android/settings/notification/AbstractZenModePreferenceController.java b/src/com/android/settings/notification/AbstractZenModePreferenceController.java
index 383934a236c..0e45e58c62d 100644
--- a/src/com/android/settings/notification/AbstractZenModePreferenceController.java
+++ b/src/com/android/settings/notification/AbstractZenModePreferenceController.java
@@ -50,7 +50,7 @@ abstract public class AbstractZenModePreferenceController extends
@VisibleForTesting
protected SettingObserver mSettingObserver;
- private final String KEY;
+ final String KEY;
final private NotificationManager mNotificationManager;
protected static ZenModeConfigWrapper mZenModeConfigWrapper;
protected MetricsFeatureProvider mMetricsFeatureProvider;
diff --git a/src/com/android/settings/notification/VolumeSeekBarPreference.java b/src/com/android/settings/notification/VolumeSeekBarPreference.java
index 2ef33d4ab04..13f630004d1 100644
--- a/src/com/android/settings/notification/VolumeSeekBarPreference.java
+++ b/src/com/android/settings/notification/VolumeSeekBarPreference.java
@@ -80,6 +80,11 @@ public class VolumeSeekBarPreference extends SeekBarPreference {
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
}
+ @Override
+ public boolean isSelectable() {
+ return false;
+ }
+
public void setStream(int stream) {
mStream = stream;
setMax(mAudioManager.getStreamMaxVolume(mStream));
diff --git a/src/com/android/settings/notification/ZenCustomRuleBlockedEffectsSettings.java b/src/com/android/settings/notification/ZenCustomRuleBlockedEffectsSettings.java
new file mode 100644
index 00000000000..3f75a20ff45
--- /dev/null
+++ b/src/com/android/settings/notification/ZenCustomRuleBlockedEffectsSettings.java
@@ -0,0 +1,81 @@
+/*
+ * 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.content.Context;
+import android.os.Bundle;
+import android.service.notification.ZenPolicy;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.R;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ZenCustomRuleBlockedEffectsSettings extends ZenCustomRuleSettingsBase {
+
+ @Override
+ public void onCreate(Bundle bundle) {
+ super.onCreate(bundle);
+ mFooterPreferenceMixin.createFooterPreference().setTitle(
+ R.string.zen_mode_blocked_effects_footer);
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.zen_mode_block_settings;
+ }
+
+ @Override
+ protected List createPreferenceControllers(Context context) {
+ mControllers = new ArrayList<>();
+ mControllers.add(new ZenRuleVisEffectPreferenceController(context, getSettingsLifecycle(),
+ "zen_effect_intent", ZenPolicy.VISUAL_EFFECT_FULL_SCREEN_INTENT,
+ MetricsEvent.ACTION_ZEN_BLOCK_FULL_SCREEN_INTENTS, null));
+ mControllers.add(new ZenRuleVisEffectPreferenceController(context, getSettingsLifecycle(),
+ "zen_effect_light", ZenPolicy.VISUAL_EFFECT_LIGHTS,
+ MetricsEvent.ACTION_ZEN_BLOCK_LIGHT, null));
+ mControllers.add(new ZenRuleVisEffectPreferenceController(context, getSettingsLifecycle(),
+ "zen_effect_peek", ZenPolicy.VISUAL_EFFECT_PEEK,
+ MetricsEvent.ACTION_ZEN_BLOCK_PEEK, null));
+ mControllers.add(new ZenRuleVisEffectPreferenceController(context, getSettingsLifecycle(),
+ "zen_effect_status", ZenPolicy.VISUAL_EFFECT_STATUS_BAR,
+ MetricsEvent.ACTION_ZEN_BLOCK_STATUS,
+ new int[] {ZenPolicy.VISUAL_EFFECT_NOTIFICATION_LIST}));
+ mControllers.add(new ZenRuleVisEffectPreferenceController(context, getSettingsLifecycle(),
+ "zen_effect_badge", ZenPolicy.VISUAL_EFFECT_BADGE,
+ MetricsEvent.ACTION_ZEN_BLOCK_BADGE, null));
+ mControllers.add(new ZenRuleVisEffectPreferenceController(context, getSettingsLifecycle(),
+ "zen_effect_ambient", ZenPolicy.VISUAL_EFFECT_AMBIENT,
+ MetricsEvent.ACTION_ZEN_BLOCK_AMBIENT, null));
+ mControllers.add(new ZenRuleVisEffectPreferenceController(context, getSettingsLifecycle(),
+ "zen_effect_list", ZenPolicy.VISUAL_EFFECT_NOTIFICATION_LIST,
+ MetricsEvent.ACTION_ZEN_BLOCK_NOTIFICATION_LIST, null));
+ return mControllers;
+ }
+
+ @Override
+ String getPreferenceCategoryKey() {
+ return null;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsEvent.ZEN_CUSTOM_RULE_VIS_EFFECTS;
+ }
+}
diff --git a/src/com/android/settings/notification/ZenCustomRuleCallsSettings.java b/src/com/android/settings/notification/ZenCustomRuleCallsSettings.java
new file mode 100644
index 00000000000..808264e0ad5
--- /dev/null
+++ b/src/com/android/settings/notification/ZenCustomRuleCallsSettings.java
@@ -0,0 +1,81 @@
+/*
+ * 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.content.Context;
+import android.os.Bundle;
+import android.service.notification.ZenPolicy;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.R;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.widget.FooterPreference;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ZenCustomRuleCallsSettings extends ZenCustomRuleSettingsBase {
+ private static final String CALLS_KEY = "zen_mode_calls";
+ private static final String REPEAT_CALLERS_KEY = "zen_mode_repeat_callers";
+ private static final String STARRED_CONTACTS_KEY = "zen_mode_starred_contacts_callers";
+ private static final String PREFERENCE_CATEGORY_KEY = "zen_mode_settings_category_calls";
+
+ @Override
+ public void onCreate(Bundle bundle) {
+ super.onCreate(bundle);
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return com.android.settings.R.xml.zen_mode_calls_settings;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsProto.MetricsEvent.ZEN_CUSTOM_RULE_CALLS;
+ }
+
+ @Override
+ protected List createPreferenceControllers(Context context) {
+ mControllers = new ArrayList<>();
+ mControllers.add(new ZenRuleCallsPreferenceController(context, CALLS_KEY,
+ getSettingsLifecycle()));
+ mControllers.add(new ZenRuleRepeatCallersPreferenceController(context,
+ REPEAT_CALLERS_KEY, getSettingsLifecycle(), context.getResources()
+ .getInteger(com.android.internal.R.integer.config_zen_repeat_callers_threshold)));
+ mControllers.add(new ZenRuleStarredContactsPreferenceController(context,
+ getSettingsLifecycle(), ZenPolicy.PRIORITY_CATEGORY_CALLS, STARRED_CONTACTS_KEY));
+ return mControllers;
+ }
+
+ @Override
+ String getPreferenceCategoryKey() {
+ return PREFERENCE_CATEGORY_KEY;
+ }
+
+ @Override
+ public void updatePreferences() {
+ super.updatePreferences();
+ PreferenceScreen screen = getPreferenceScreen();
+ Preference footerPreference = screen.findPreference(FooterPreference.KEY_FOOTER);
+ footerPreference.setTitle(mContext.getResources().getString(
+ R.string.zen_mode_custom_calls_footer, mRule.getName()));
+ }
+}
diff --git a/src/com/android/settings/notification/ZenCustomRuleConfigSettings.java b/src/com/android/settings/notification/ZenCustomRuleConfigSettings.java
new file mode 100644
index 00000000000..fd8ce2be2e1
--- /dev/null
+++ b/src/com/android/settings/notification/ZenCustomRuleConfigSettings.java
@@ -0,0 +1,160 @@
+/*
+ * 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.NotificationManager;
+import android.content.Context;
+import android.os.Bundle;
+import android.service.notification.ZenPolicy;
+
+import androidx.preference.Preference;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.R;
+import com.android.settings.core.SubSettingLauncher;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ZenCustomRuleConfigSettings extends ZenCustomRuleSettingsBase {
+ private static final String CALLS_KEY = "zen_rule_calls_settings";
+ private static final String MESSAGES_KEY = "zen_rule_messages_settings";
+ private static final String ALARMS_KEY = "zen_rule_alarms";
+ private static final String MEDIA_KEY = "zen_rule_media";
+ private static final String SYSTEM_KEY = "zen_rule_system";
+ private static final String REMINDERS_KEY = "zen_rule_reminders";
+ private static final String EVENTS_KEY = "zen_rule_events";
+ private static final String NOTIFICATIONS_KEY = "zen_rule_notifications";
+ private static final String PREFERENCE_CATEGORY_KEY = "zen_custom_rule_configuration_category";
+
+ private Preference mCallsPreference;
+ private Preference mMessagesPreference;
+ private Preference mNotificationsPreference;
+ private ZenModeSettings.SummaryBuilder mSummaryBuilder;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ mSummaryBuilder = new ZenModeSettings.SummaryBuilder(mContext);
+
+ mCallsPreference = getPreferenceScreen().findPreference(CALLS_KEY);
+ mCallsPreference.setOnPreferenceClickListener(
+ new Preference.OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ new SubSettingLauncher(mContext)
+ .setDestination(ZenCustomRuleCallsSettings.class.getName())
+ .setArguments(createZenRuleBundle())
+ .setSourceMetricsCategory(MetricsEvent.ZEN_CUSTOM_RULE_CALLS)
+ .launch();
+ return true;
+ }
+ });
+
+ mMessagesPreference = getPreferenceScreen().findPreference(MESSAGES_KEY);
+ mMessagesPreference.setOnPreferenceClickListener(
+ new Preference.OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ new SubSettingLauncher(mContext)
+ .setDestination(ZenCustomRuleMessagesSettings.class.getName())
+ .setArguments(createZenRuleBundle())
+ .setSourceMetricsCategory(MetricsEvent.ZEN_CUSTOM_RULE_MESSAGES)
+ .launch();
+ return true;
+ }
+ });
+
+ mNotificationsPreference = getPreferenceScreen().findPreference(NOTIFICATIONS_KEY);
+ mNotificationsPreference.setOnPreferenceClickListener(
+ new Preference.OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ new SubSettingLauncher(mContext)
+ .setDestination(ZenCustomRuleNotificationsSettings.class.getName())
+ .setArguments(createZenRuleBundle())
+ .setSourceMetricsCategory
+ (MetricsEvent.ZEN_CUSTOM_RULE_NOTIFICATION_RESTRICTIONS)
+ .launch();
+ return true;
+ }
+ });
+
+ updateSummaries();
+ }
+
+ @Override
+ public void onZenModeConfigChanged() {
+ super.onZenModeConfigChanged();
+ updateSummaries();
+ }
+
+ /**
+ * Updates summaries of preferences without preference controllers
+ */
+ private void updateSummaries() {
+ NotificationManager.Policy noManPolicy = mBackend.toNotificationPolicy(
+ mRule.getZenPolicy());
+
+ mCallsPreference.setSummary(mSummaryBuilder.getCallsSettingSummary(noManPolicy));
+ mMessagesPreference.setSummary(mSummaryBuilder.getMessagesSettingSummary(noManPolicy));
+ mNotificationsPreference.setSummary(mSummaryBuilder.getBlockedEffectsSummary(noManPolicy));
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.zen_mode_custom_rule_configuration;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsEvent.ZEN_CUSTOM_RULE_SOUND_SETTINGS;
+ }
+
+ @Override
+ protected List createPreferenceControllers(Context context) {
+ mControllers = new ArrayList<>();
+ mControllers.add(new ZenRuleCustomSwitchPreferenceController(context,
+ getSettingsLifecycle(), ALARMS_KEY, ZenPolicy.PRIORITY_CATEGORY_ALARMS,
+ MetricsEvent.ACTION_ZEN_ALLOW_ALARMS));
+ mControllers.add(new ZenRuleCustomSwitchPreferenceController(context,
+ getSettingsLifecycle(), MEDIA_KEY, ZenPolicy.PRIORITY_CATEGORY_MEDIA,
+ MetricsEvent.ACTION_ZEN_ALLOW_MEDIA));
+ mControllers.add(new ZenRuleCustomSwitchPreferenceController(context,
+ getSettingsLifecycle(), SYSTEM_KEY, ZenPolicy.PRIORITY_CATEGORY_SYSTEM,
+ MetricsEvent.ACTION_ZEN_ALLOW_SYSTEM));
+ mControllers.add(new ZenRuleCustomSwitchPreferenceController(context,
+ getSettingsLifecycle(), REMINDERS_KEY, ZenPolicy.PRIORITY_CATEGORY_REMINDERS,
+ MetricsEvent.ACTION_ZEN_ALLOW_REMINDERS));
+ mControllers.add(new ZenRuleCustomSwitchPreferenceController(context,
+ getSettingsLifecycle(), EVENTS_KEY, ZenPolicy.PRIORITY_CATEGORY_EVENTS,
+ MetricsEvent.ACTION_ZEN_ALLOW_EVENTS));
+ return mControllers;
+ }
+
+ @Override
+ String getPreferenceCategoryKey() {
+ return PREFERENCE_CATEGORY_KEY;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ updateSummaries();
+ }
+}
diff --git a/src/com/android/settings/notification/ZenCustomRuleMessagesSettings.java b/src/com/android/settings/notification/ZenCustomRuleMessagesSettings.java
new file mode 100644
index 00000000000..8db2824efaf
--- /dev/null
+++ b/src/com/android/settings/notification/ZenCustomRuleMessagesSettings.java
@@ -0,0 +1,72 @@
+/*
+ * 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.content.Context;
+import android.service.notification.ZenPolicy;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.R;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.widget.FooterPreference;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ZenCustomRuleMessagesSettings extends ZenCustomRuleSettingsBase {
+ private static final String MESSAGES_KEY = "zen_mode_messages";
+ private static final String STARRED_CONTACTS_KEY = "zen_mode_starred_contacts_messages";
+ private static final String PREFERENCE_CATEGORY_KEY = "zen_mode_settings_category_messages";
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return com.android.settings.R.xml.zen_mode_messages_settings;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsProto.MetricsEvent.ZEN_CUSTOM_RULE_MESSAGES;
+ }
+
+ @Override
+ protected List createPreferenceControllers(Context context) {
+ mControllers = new ArrayList<>();
+ mControllers.add(new ZenRuleMessagesPreferenceController(context, MESSAGES_KEY,
+ getSettingsLifecycle()));
+ mControllers.add(new ZenRuleStarredContactsPreferenceController(context,
+ getSettingsLifecycle(), ZenPolicy.PRIORITY_CATEGORY_MESSAGES,
+ STARRED_CONTACTS_KEY));
+ return mControllers;
+ }
+
+ @Override
+ String getPreferenceCategoryKey() {
+ return PREFERENCE_CATEGORY_KEY;
+ }
+
+ @Override
+ public void updatePreferences() {
+ super.updatePreferences();
+ PreferenceScreen screen = getPreferenceScreen();
+ Preference footerPreference = screen.findPreference(FooterPreference.KEY_FOOTER);
+ footerPreference.setTitle(mContext.getResources().getString(
+ R.string.zen_mode_custom_messages_footer, mRule.getName()));
+ }
+}
diff --git a/src/com/android/settings/notification/ZenCustomRuleNotificationsSettings.java b/src/com/android/settings/notification/ZenCustomRuleNotificationsSettings.java
new file mode 100644
index 00000000000..a23bc6dd7c7
--- /dev/null
+++ b/src/com/android/settings/notification/ZenCustomRuleNotificationsSettings.java
@@ -0,0 +1,63 @@
+/*
+ * 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.content.Context;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.R;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.widget.FooterPreference;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ZenCustomRuleNotificationsSettings extends ZenCustomRuleSettingsBase {
+ private static final String VIS_EFFECTS_ALL_KEY = "zen_mute_notifications";
+ private static final String VIS_EFFECTS_NONE_KEY = "zen_hide_notifications";
+ private static final String VIS_EFFECTS_CUSTOM_KEY = "zen_custom";
+ private static final String PREFERENCE_CATEGORY_KEY = "restrict_category";
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.zen_mode_restrict_notifications_settings;
+ }
+
+ @Override
+ protected List createPreferenceControllers(Context context) {
+ mControllers = new ArrayList<>();
+ mControllers.add(new ZenRuleVisEffectsAllPreferenceController(
+ context, getSettingsLifecycle(), VIS_EFFECTS_ALL_KEY));
+ mControllers.add(new ZenRuleVisEffectsNonePreferenceController(
+ context, getSettingsLifecycle(), VIS_EFFECTS_NONE_KEY));
+ mControllers.add(new ZenRuleVisEffectsCustomPreferenceController(
+ context, getSettingsLifecycle(), VIS_EFFECTS_CUSTOM_KEY));
+ mControllers.add(new ZenRuleNotifFooterPreferenceController(context, getSettingsLifecycle(),
+ FooterPreference.KEY_FOOTER));
+ return mControllers;
+ }
+
+ @Override
+ String getPreferenceCategoryKey() {
+ return PREFERENCE_CATEGORY_KEY;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsProto.MetricsEvent.ZEN_CUSTOM_RULE_NOTIFICATION_RESTRICTIONS;
+ }
+}
diff --git a/src/com/android/settings/notification/ZenCustomRuleSettings.java b/src/com/android/settings/notification/ZenCustomRuleSettings.java
new file mode 100644
index 00000000000..ebd63064ccd
--- /dev/null
+++ b/src/com/android/settings/notification/ZenCustomRuleSettings.java
@@ -0,0 +1,57 @@
+/*
+ * 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.content.Context;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.R;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ZenCustomRuleSettings extends ZenCustomRuleSettingsBase {
+ private static final String RULE_DEFAULT_POLICY_KEY = "zen_custom_rule_setting_default";
+ private static final String CUSTOM_RULE_POLICY_KEY = "zen_custom_rule_setting";
+ private static final String PREFERENCE_CATEGORY_KEY = "zen_custom_rule_category";
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.zen_mode_custom_rule_settings;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsProto.MetricsEvent.ZEN_CUSTOM_RULE_SETTINGS;
+ }
+
+ @Override
+ protected List createPreferenceControllers(Context context) {
+ mControllers = new ArrayList<>();
+ mControllers.add(new ZenRuleDefaultPolicyPreferenceController(
+ context, getSettingsLifecycle(), RULE_DEFAULT_POLICY_KEY));
+ mControllers.add(new ZenRuleCustomPolicyPreferenceController(
+ context, getSettingsLifecycle(), CUSTOM_RULE_POLICY_KEY));
+ return mControllers;
+ }
+
+ @Override
+ String getPreferenceCategoryKey() {
+ return PREFERENCE_CATEGORY_KEY;
+ }
+}
diff --git a/src/com/android/settings/notification/ZenCustomRuleSettingsBase.java b/src/com/android/settings/notification/ZenCustomRuleSettingsBase.java
new file mode 100644
index 00000000000..94b0b7b9903
--- /dev/null
+++ b/src/com/android/settings/notification/ZenCustomRuleSettingsBase.java
@@ -0,0 +1,103 @@
+/*
+ * 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.os.Bundle;
+import android.util.Log;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+import java.util.ArrayList;
+import java.util.List;
+
+abstract class ZenCustomRuleSettingsBase extends ZenModeSettingsBase {
+ static final String TAG = "ZenCustomRuleSettings";
+ static final String RULE_ID = "RULE_ID";
+
+ String mId;
+ AutomaticZenRule mRule;
+ List mControllers = new ArrayList<>();
+
+ /**
+ * @return null if no preference category exists
+ */
+ abstract String getPreferenceCategoryKey();
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ Bundle bundle = getArguments();
+ if (bundle != null && bundle.containsKey(RULE_ID)) {
+ mId = bundle.getString(RULE_ID);
+ mRule = mBackend.getAutomaticZenRule(mId);
+ } else {
+ Log.d(TAG, "Rule id required to set custom dnd rule config settings");
+ this.finish();
+ }
+ }
+
+ @Override
+ public void onZenModeConfigChanged() {
+ super.onZenModeConfigChanged();
+ updatePreferences();
+ }
+
+ public void updatePreferences() {
+ mRule = mBackend.getAutomaticZenRule(mId);
+ final PreferenceScreen screen = getPreferenceScreen();
+ String categoryKey = getPreferenceCategoryKey();
+ if (categoryKey != null) {
+ Preference prefCategory = screen.findPreference(categoryKey);
+ if (prefCategory != null) {
+ prefCategory.setTitle(mContext.getResources().getString(
+ com.android.settings.R.string.zen_mode_custom_behavior_category_title,
+ mRule.getName()));
+ }
+ }
+
+ for (AbstractPreferenceController controller : mControllers) {
+ AbstractZenCustomRulePreferenceController zenRuleController =
+ (AbstractZenCustomRulePreferenceController) controller;
+ zenRuleController.onResume(mRule, mId);
+ zenRuleController.displayPreference(screen);
+ updatePreference(zenRuleController);
+ }
+ }
+
+ @Override
+ public int getHelpResource() {
+ return R.string.help_uri_interruptions;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ updatePreferences();
+ }
+
+ Bundle createZenRuleBundle() {
+ Bundle bundle = new Bundle();
+ bundle.putString(RULE_ID, mId);
+ return bundle;
+ }
+}
diff --git a/src/com/android/settings/notification/ZenModeBackend.java b/src/com/android/settings/notification/ZenModeBackend.java
index a75f51c423d..4c9cebe8451 100644
--- a/src/com/android/settings/notification/ZenModeBackend.java
+++ b/src/com/android/settings/notification/ZenModeBackend.java
@@ -23,15 +23,20 @@ import android.app.ActivityManager;
import android.app.AutomaticZenRule;
import android.app.NotificationManager;
import android.content.Context;
+import android.database.Cursor;
+import android.icu.text.ListFormatter;
import android.net.Uri;
+import android.provider.ContactsContract;
import android.provider.Settings;
import android.service.notification.ZenModeConfig;
+import android.service.notification.ZenPolicy;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
import com.android.settings.R;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
@@ -116,7 +121,7 @@ public class ZenModeBackend {
return (mPolicy.priorityCategories & categoryType) != 0;
}
- protected int getNewPriorityCategories(boolean allow, int categoryType) {
+ protected int getNewDefaultPriorityCategories(boolean allow, int categoryType) {
int priorityCategories = mPolicy.priorityCategories;
if (allow) {
priorityCategories |= categoryType;
@@ -135,7 +140,8 @@ public class ZenModeBackend {
}
protected int getPriorityMessageSenders() {
- if (isPriorityCategoryEnabled(NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES)) {
+ if (isPriorityCategoryEnabled(
+ NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES)) {
return mPolicy.priorityMessageSenders;
}
return SOURCE_NONE;
@@ -151,7 +157,7 @@ public class ZenModeBackend {
}
protected void saveSoundPolicy(int category, boolean allow) {
- int priorityCategories = getNewPriorityCategories(allow, category);
+ int priorityCategories = getNewDefaultPriorityCategories(allow, category);
savePolicy(priorityCategories, mPolicy.priorityCallSenders,
mPolicy.priorityMessageSenders, mPolicy.suppressedVisualEffects);
}
@@ -163,6 +169,7 @@ public class ZenModeBackend {
mNotificationManager.setNotificationPolicy(mPolicy);
}
+
private int getNewSuppressedEffects(boolean suppress, int effectType) {
int effects = mPolicy.suppressedVisualEffects;
@@ -202,7 +209,7 @@ public class ZenModeBackend {
priorityMessagesSenders = allowSendersFrom;
}
- savePolicy(getNewPriorityCategories(allowSenders, category),
+ savePolicy(getNewDefaultPriorityCategories(allowSenders, category),
priorityCallSenders, priorityMessagesSenders, mPolicy.suppressedVisualEffects);
if (ZenModeSettingsBase.DEBUG) Log.d(TAG, "onPrefChange allow" +
@@ -236,6 +243,20 @@ public class ZenModeBackend {
return categorySenders;
}
+ protected static String getKeyFromZenPolicySetting(int contactType) {
+ switch (contactType) {
+ case ZenPolicy.PEOPLE_TYPE_ANYONE:
+ return ZEN_MODE_FROM_ANYONE;
+ case ZenPolicy.PEOPLE_TYPE_CONTACTS:
+ return ZEN_MODE_FROM_CONTACTS;
+ case ZenPolicy.PEOPLE_TYPE_STARRED:
+ return ZEN_MODE_FROM_STARRED;
+ case ZenPolicy.PEOPLE_TYPE_NONE:
+ default:
+ return ZEN_MODE_FROM_NONE;
+ }
+ }
+
protected static String getKeyFromSetting(int contactType) {
switch (contactType) {
case NotificationManager.Policy.PRIORITY_SENDERS_ANY:
@@ -288,6 +309,50 @@ public class ZenModeBackend {
}
}
+ protected int getContactsCallsSummary(ZenPolicy policy) {
+ int peopleType = policy.getPriorityCallSenders();
+ switch (peopleType) {
+ case ZenPolicy.PEOPLE_TYPE_ANYONE:
+ return R.string.zen_mode_from_anyone;
+ case ZenPolicy.PEOPLE_TYPE_CONTACTS:
+ return R.string.zen_mode_from_contacts;
+ case ZenPolicy.PEOPLE_TYPE_STARRED:
+ return R.string.zen_mode_from_starred;
+ case ZenPolicy.PEOPLE_TYPE_NONE:
+ default:
+ return R.string.zen_mode_from_none_calls;
+ }
+ }
+
+ protected int getContactsMessagesSummary(ZenPolicy policy) {
+ int peopleType = policy.getPriorityMessageSenders();
+ switch (peopleType) {
+ case ZenPolicy.PEOPLE_TYPE_ANYONE:
+ return R.string.zen_mode_from_anyone;
+ case ZenPolicy.PEOPLE_TYPE_CONTACTS:
+ return R.string.zen_mode_from_contacts;
+ case ZenPolicy.PEOPLE_TYPE_STARRED:
+ return R.string.zen_mode_from_starred;
+ case ZenPolicy.PEOPLE_TYPE_NONE:
+ default:
+ return R.string.zen_mode_from_none_messages;
+ }
+ }
+
+ protected static int getZenPolicySettingFromPrefKey(String key) {
+ switch (key) {
+ case ZEN_MODE_FROM_ANYONE:
+ return ZenPolicy.PEOPLE_TYPE_ANYONE;
+ case ZEN_MODE_FROM_CONTACTS:
+ return ZenPolicy.PEOPLE_TYPE_CONTACTS;
+ case ZEN_MODE_FROM_STARRED:
+ return ZenPolicy.PEOPLE_TYPE_STARRED;
+ case ZEN_MODE_FROM_NONE:
+ default:
+ return ZenPolicy.PEOPLE_TYPE_NONE;
+ }
+ }
+
protected static int getSettingFromPrefKey(String key) {
switch (key) {
case ZEN_MODE_FROM_ANYONE:
@@ -318,6 +383,40 @@ public class ZenModeBackend {
}
}
+ ZenPolicy setDefaultZenPolicy(ZenPolicy zenPolicy) {
+ int calls;
+ if (mPolicy.allowCalls()) {
+ calls = ZenModeConfig.getZenPolicySenders(mPolicy.allowCallsFrom());
+ } else {
+ calls = ZenPolicy.PEOPLE_TYPE_NONE;
+ }
+
+ int messages;
+ if (mPolicy.allowMessages()) {
+ messages = ZenModeConfig.getZenPolicySenders(mPolicy.allowMessagesFrom());
+ } else {
+ messages = ZenPolicy.PEOPLE_TYPE_NONE;
+ }
+
+ return new ZenPolicy.Builder(zenPolicy)
+ .allowAlarms(mPolicy.allowAlarms())
+ .allowCalls(calls)
+ .allowEvents(mPolicy.allowEvents())
+ .allowMedia(mPolicy.allowMedia())
+ .allowMessages(messages)
+ .allowReminders(mPolicy.allowReminders())
+ .allowRepeatCallers(mPolicy.allowRepeatCallers())
+ .allowSystem(mPolicy.allowSystem())
+ .showFullScreenIntent(mPolicy.showFullScreenIntents())
+ .showLights(mPolicy.showLights())
+ .showInAmbientDisplay(mPolicy.showAmbient())
+ .showInNotificationList(mPolicy.showInNotificationList())
+ .showBadges(mPolicy.showBadges())
+ .showPeeking(mPolicy.showPeeking())
+ .showStatusBarIcons(mPolicy.showStatusBarIcons())
+ .build();
+ }
+
protected Map.Entry[] getAutomaticZenRules() {
Map ruleMap =
NotificationManager.from(mContext).getAutomaticZenRules();
@@ -338,6 +437,70 @@ public class ZenModeBackend {
return mDefaultRuleIds;
}
+ NotificationManager.Policy toNotificationPolicy(ZenPolicy policy) {
+ ZenModeConfig config = new ZenModeConfig();
+ return config.toNotificationPolicy(policy);
+ }
+
+ @VisibleForTesting
+ List getStarredContacts(Cursor cursor) {
+ List starredContacts = new ArrayList<>();
+ if (cursor != null && cursor.moveToFirst()) {
+ do {
+ String contact = cursor.getString(0);
+ if (contact != null) {
+ starredContacts.add(contact);
+ }
+ } while (cursor.moveToNext());
+ }
+ return starredContacts;
+ }
+
+ private List getStarredContacts() {
+ Cursor cursor = null;
+ try {
+ cursor = queryData();
+ return getStarredContacts(cursor);
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
+ }
+ }
+
+ public String getStarredContactsSummary() {
+ List starredContacts = getStarredContacts();
+ int numStarredContacts = starredContacts.size();
+
+ List displayContacts = new ArrayList<>();
+
+ if (numStarredContacts == 0) {
+ displayContacts.add(mContext.getString(R.string.zen_mode_from_none));
+ } else {
+ for (int i = 0; i < 2 && i < numStarredContacts; i++) {
+ displayContacts.add(starredContacts.get(i));
+ }
+
+ if (numStarredContacts == 3) {
+ displayContacts.add(starredContacts.get(2));
+ } else if (numStarredContacts > 2) {
+ displayContacts.add(mContext.getResources().getQuantityString(
+ R.plurals.zen_mode_starred_contacts_summary_additional_contacts,
+ numStarredContacts - 2, numStarredContacts - 2));
+ }
+ }
+
+ // values in displayContacts must not be null
+ return ListFormatter.getInstance().format(displayContacts);
+ }
+
+ private Cursor queryData() {
+ return mContext.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,
+ new String[]{ContactsContract.Contacts.DISPLAY_NAME_PRIMARY},
+ ContactsContract.Data.STARRED + "=1", null,
+ ContactsContract.Data.TIMES_CONTACTED);
+ }
+
@VisibleForTesting
public static final Comparator> RULE_COMPARATOR =
new Comparator>() {
diff --git a/src/com/android/settings/notification/ZenModeRuleSettingsBase.java b/src/com/android/settings/notification/ZenModeRuleSettingsBase.java
index e573884181a..46162a8f170 100644
--- a/src/com/android/settings/notification/ZenModeRuleSettingsBase.java
+++ b/src/com/android/settings/notification/ZenModeRuleSettingsBase.java
@@ -30,13 +30,15 @@ import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
-import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settings.core.SubSettingLauncher;
public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase {
protected static final String TAG = ZenModeSettingsBase.TAG;
protected static final boolean DEBUG = ZenModeSettingsBase.DEBUG;
+ private final String CUSTOM_BEHAVIOR_KEY = "zen_custom_setting";
+
protected Context mContext;
protected boolean mDisableListeners;
protected AutomaticZenRule mRule;
@@ -45,6 +47,7 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase {
protected ZenAutomaticRuleHeaderPreferenceController mHeader;
protected ZenRuleButtonsPreferenceController mActionButtons;
protected ZenAutomaticRuleSwitchPreferenceController mSwitch;
+ protected Preference mCustomBehaviorPreference;
abstract protected void onCreateInternal();
abstract protected boolean setRule(AutomaticZenRule rule);
@@ -75,6 +78,21 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase {
}
super.onCreate(icicle);
+ mCustomBehaviorPreference = getPreferenceScreen().findPreference(CUSTOM_BEHAVIOR_KEY);
+ mCustomBehaviorPreference.setOnPreferenceClickListener(
+ new Preference.OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ Bundle bundle = new Bundle();
+ bundle.putString(ZenCustomRuleSettings.RULE_ID, mId);
+ new SubSettingLauncher(mContext)
+ .setDestination(ZenCustomRuleSettings.class.getName())
+ .setArguments(bundle)
+ .setSourceMetricsCategory(0) // TODO
+ .launch();
+ return true;
+ }
+ });
onCreateInternal();
}
@@ -84,7 +102,9 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase {
if (isUiRestricted()) {
return;
}
- updateControls();
+ if (!refreshRuleOrFinish()) {
+ updateControls();
+ }
}
@Override
@@ -111,22 +131,6 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase {
updatePreference(mActionButtons);
}
- private void updatePreference(AbstractPreferenceController controller) {
- final PreferenceScreen screen = getPreferenceScreen();
- if (!controller.isAvailable()) {
- return;
- }
- final String key = controller.getPreferenceKey();
-
- final Preference preference = screen.findPreference(key);
- if (preference == null) {
- Log.d(TAG, String.format("Cannot find preference with key %s in Controller %s",
- key, controller.getClass().getSimpleName()));
- return;
- }
- controller.updateState(preference);
- }
-
protected void updateRule(Uri newConditionId) {
mRule.setConditionId(newConditionId);
mBackend.updateZenRule(mId, mRule);
@@ -165,6 +169,11 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase {
mDisableListeners = true;
updateControlsInternal();
updateHeader();
+ if (mRule.getZenPolicy() == null) {
+ mCustomBehaviorPreference.setSummary(R.string.zen_mode_custom_behavior_summary_default);
+ } else {
+ mCustomBehaviorPreference.setSummary(R.string.zen_mode_custom_behavior_summary);
+ }
mDisableListeners = false;
}
}
diff --git a/src/com/android/settings/notification/ZenModeSettings.java b/src/com/android/settings/notification/ZenModeSettings.java
index a3f59c680d5..bdf80a6180a 100644
--- a/src/com/android/settings/notification/ZenModeSettings.java
+++ b/src/com/android/settings/notification/ZenModeSettings.java
@@ -90,7 +90,8 @@ public class ZenModeSettings extends ZenModeSettingsBase {
controllers.add(new ZenModeDurationPreferenceController(context, lifecycle));
controllers.add(new ZenModeAutomationPreferenceController(context));
controllers.add(new ZenModeButtonPreferenceController(context, lifecycle, fragmentManager));
- controllers.add(new ZenModeSettingsFooterPreferenceController(context, lifecycle));
+ controllers.add(new ZenModeSettingsFooterPreferenceController(context, lifecycle,
+ fragmentManager));
return controllers;
}
diff --git a/src/com/android/settings/notification/ZenModeSettingsBase.java b/src/com/android/settings/notification/ZenModeSettingsBase.java
index b9a14eec1ce..3f538794836 100644
--- a/src/com/android/settings/notification/ZenModeSettingsBase.java
+++ b/src/com/android/settings/notification/ZenModeSettingsBase.java
@@ -26,7 +26,11 @@ import android.provider.Settings;
import android.provider.Settings.Global;
import android.util.Log;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
import com.android.settings.dashboard.RestrictedDashboardFragment;
+import com.android.settingslib.core.AbstractPreferenceController;
abstract public class ZenModeSettingsBase extends RestrictedDashboardFragment {
protected static final String TAG = "ZenModeSettings";
@@ -121,4 +125,20 @@ abstract public class ZenModeSettingsBase extends RestrictedDashboardFragment {
}
}
}
+
+ void updatePreference(AbstractPreferenceController controller) {
+ final PreferenceScreen screen = getPreferenceScreen();
+ if (!controller.isAvailable()) {
+ return;
+ }
+ final String key = controller.getPreferenceKey();
+
+ final Preference preference = screen.findPreference(key);
+ if (preference == null) {
+ Log.d(TAG, String.format("Cannot find preference with key %s in Controller %s",
+ key, controller.getClass().getSimpleName()));
+ return;
+ }
+ controller.updateState(preference);
+ }
}
diff --git a/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceController.java b/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceController.java
index f69eac749fa..7c2464c1bb3 100644
--- a/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceController.java
+++ b/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceController.java
@@ -16,17 +16,29 @@
package com.android.settings.notification;
+import android.app.Dialog;
import android.app.NotificationManager;
import android.content.Context;
+import android.content.DialogInterface;
import android.icu.text.ListFormatter;
import android.net.Uri;
+import android.os.Bundle;
import android.provider.Settings;
import android.service.notification.ZenModeConfig;
-import android.util.Log;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.FragmentManager;
import androidx.preference.Preference;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
+import com.android.settings.core.SubSettingLauncher;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+import com.android.settings.utils.AnnotationSpan;
import com.android.settingslib.core.lifecycle.Lifecycle;
import java.util.ArrayList;
@@ -34,11 +46,13 @@ import java.util.List;
import java.util.Objects;
public class ZenModeSettingsFooterPreferenceController extends AbstractZenModePreferenceController {
+ static final String KEY = "footer_preference";
+ private FragmentManager mFragment;
- protected static final String KEY = "footer_preference";
-
- public ZenModeSettingsFooterPreferenceController(Context context, Lifecycle lifecycle) {
+ public ZenModeSettingsFooterPreferenceController(Context context, Lifecycle lifecycle,
+ FragmentManager fragment) {
super(context, KEY, lifecycle);
+ mFragment = fragment;
}
@Override
@@ -70,7 +84,7 @@ public class ZenModeSettingsFooterPreferenceController extends AbstractZenModePr
}
}
- protected String getFooterText() {
+ protected CharSequence getFooterText() {
ZenModeConfig config = getZenModeConfig();
NotificationManager.Policy appliedPolicy = mBackend.getConsolidatedPolicy();
@@ -88,15 +102,25 @@ public class ZenModeSettingsFooterPreferenceController extends AbstractZenModePr
if (rulesNames.size() > 0) {
String rules = ListFormatter.getInstance().format(rulesNames);
if (!rules.isEmpty()) {
- return mContext.getString(R.string.zen_mode_settings_dnd_custom_settings_footer,
- rules);
+ final AnnotationSpan.LinkInfo linkInfo = new AnnotationSpan.LinkInfo(
+ AnnotationSpan.LinkInfo.DEFAULT_ANNOTATION, new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ showCustomSettingsDialog();
+ }
+ });
+ return TextUtils.concat(mContext.getResources().getString(
+ R.string.zen_mode_settings_dnd_custom_settings_footer, rules),
+ AnnotationSpan.linkify(mContext.getResources().getText(
+ R.string.zen_mode_settings_dnd_custom_settings_footer_link),
+ linkInfo));
}
}
}
- return getFooterUsingDefaultPolicy(config);
+ return getDefaultPolicyFooter(config);
}
- private String getFooterUsingDefaultPolicy(ZenModeConfig config) {
+ private String getDefaultPolicyFooter(ZenModeConfig config) {
String footerText = "";
long latestEndTime = -1;
@@ -162,4 +186,101 @@ public class ZenModeSettingsFooterPreferenceController extends AbstractZenModePr
}
return zenRules;
}
+
+ private void showCustomSettingsDialog() {
+ ZenCustomSettingsDialog dialog = new ZenCustomSettingsDialog();
+ dialog.setNotificationPolicy(mBackend.getConsolidatedPolicy());
+ dialog.show(mFragment, ZenCustomSettingsDialog.class.getName());
+ }
+
+ public static class ZenCustomSettingsDialog extends InstrumentedDialogFragment {
+ private String KEY_POLICY = "policy";
+ private NotificationManager.Policy mPolicy;
+ private ZenModeSettings.SummaryBuilder mSummaryBuilder;
+
+ public void setNotificationPolicy(NotificationManager.Policy policy) {
+ mPolicy = policy;
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ Context context = getActivity();
+ if (savedInstanceState != null) {
+ NotificationManager.Policy policy = savedInstanceState.getParcelable(KEY_POLICY);
+ if (policy != null) {
+ mPolicy = policy;
+ }
+ }
+
+ mSummaryBuilder = new ZenModeSettings.SummaryBuilder(context);
+
+ AlertDialog customSettingsDialog = new AlertDialog.Builder(context)
+ .setTitle(R.string.zen_custom_settings_dialog_title)
+ .setNeutralButton(R.string.zen_custom_settings_dialog_review_schedule,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog,
+ int which) {
+ new SubSettingLauncher(context)
+ .setDestination(
+ ZenModeAutomationSettings.class.getName())
+ .setSourceMetricsCategory(
+ MetricsEvent.NOTIFICATION_ZEN_MODE_AUTOMATION)
+ .launch();
+ }
+ })
+ .setPositiveButton(R.string.zen_custom_settings_dialog_ok, null)
+ .setView(LayoutInflater.from(context).inflate(context.getResources().getLayout(
+ R.layout.zen_custom_settings_dialog), null, false))
+ .create();
+
+ customSettingsDialog.setOnShowListener(new DialogInterface.OnShowListener() {
+ @Override
+ public void onShow(DialogInterface dialog) {
+ TextView allowCallsText = customSettingsDialog.findViewById(
+ R.id.zen_custom_settings_dialog_calls_allow);
+ TextView allowMessagesText = customSettingsDialog.findViewById(
+ R.id.zen_custom_settings_dialog_messages_allow);
+ TextView allowAlarmsText = customSettingsDialog.findViewById(
+ R.id.zen_custom_settings_dialog_alarms_allow);
+ TextView allowMediaText = customSettingsDialog.findViewById(
+ R.id.zen_custom_settings_dialog_media_allow);
+ TextView allowSystemText = customSettingsDialog.findViewById(
+ R.id.zen_custom_settings_dialog_system_allow);
+ TextView allowRemindersText = customSettingsDialog.findViewById(
+ R.id.zen_custom_settings_dialog_reminders_allow);
+ TextView allowEventsText = customSettingsDialog.findViewById(
+ R.id.zen_custom_settings_dialog_events_allow);
+ TextView notificationsText = customSettingsDialog.findViewById(
+ R.id.zen_custom_settings_dialog_show_notifications);
+
+ allowCallsText.setText(mSummaryBuilder.getCallsSettingSummary(mPolicy));
+ allowMessagesText.setText(mSummaryBuilder.getMessagesSettingSummary(mPolicy));
+ allowAlarmsText.setText(getAllowRes(mPolicy.allowAlarms()));
+ allowMediaText.setText(getAllowRes(mPolicy.allowMedia()));
+ allowSystemText.setText(getAllowRes(mPolicy.allowSystem()));
+ allowRemindersText.setText(getAllowRes(mPolicy.allowReminders()));
+ allowEventsText.setText(getAllowRes(mPolicy.allowEvents()));
+ notificationsText.setText(mSummaryBuilder.getBlockedEffectsSummary(mPolicy));
+ }
+ });
+
+ return customSettingsDialog;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsEvent.ZEN_CUSTOM_SETTINGS_DIALOG;
+ }
+
+ private int getAllowRes(boolean allow) {
+ return allow ? R.string.zen_mode_sound_summary_on : R.string.zen_mode_sound_summary_off;
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putParcelable(KEY_POLICY, mPolicy);
+ }
+ }
}
diff --git a/src/com/android/settings/notification/ZenModeStarredContactsPreferenceController.java b/src/com/android/settings/notification/ZenModeStarredContactsPreferenceController.java
index 66c2ddd2db4..e5982ebd1a6 100644
--- a/src/com/android/settings/notification/ZenModeStarredContactsPreferenceController.java
+++ b/src/com/android/settings/notification/ZenModeStarredContactsPreferenceController.java
@@ -23,25 +23,15 @@ import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_STARRED;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
-import android.database.Cursor;
-import android.icu.text.ListFormatter;
import android.provider.Contacts;
-import android.provider.ContactsContract;
-import com.android.settings.R;
-import com.android.settingslib.core.lifecycle.Lifecycle;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
public class ZenModeStarredContactsPreferenceController extends
AbstractZenModePreferenceController implements Preference.OnPreferenceClickListener {
-
- protected static String KEY;
private Preference mPreference;
private final int mPriorityCategory;
private final PackageManager mPackageManager;
@@ -52,8 +42,6 @@ public class ZenModeStarredContactsPreferenceController extends
public ZenModeStarredContactsPreferenceController(Context context, Lifecycle lifecycle, int
priorityCategory, String key) {
super(context, key, lifecycle);
- KEY = key;
-
mPriorityCategory = priorityCategory;
mPackageManager = mContext.getPackageManager();
@@ -96,29 +84,7 @@ public class ZenModeStarredContactsPreferenceController extends
@Override
public CharSequence getSummary() {
- List starredContacts = getStarredContacts();
- int numStarredContacts = starredContacts.size();
-
- List displayContacts = new ArrayList<>();
-
- if (numStarredContacts == 0) {
- displayContacts.add(mContext.getString(R.string.zen_mode_from_none));
- } else {
- for (int i = 0; i < 2 && i < numStarredContacts; i++) {
- displayContacts.add(starredContacts.get(i));
- }
-
- if (numStarredContacts == 3) {
- displayContacts.add(starredContacts.get(2));
- } else if (numStarredContacts > 2) {
- displayContacts.add(mContext.getResources().getQuantityString(
- R.plurals.zen_mode_starred_contacts_summary_additional_contacts,
- numStarredContacts - 2, numStarredContacts - 2));
- }
- }
-
- // values in displayContacts must not be null
- return ListFormatter.getInstance().format(displayContacts);
+ return mBackend.getStarredContactsSummary();
}
@Override
@@ -131,39 +97,6 @@ public class ZenModeStarredContactsPreferenceController extends
return true;
}
- @VisibleForTesting
- List getStarredContacts(Cursor cursor) {
- List starredContacts = new ArrayList<>();
- if (cursor.moveToFirst()) {
- do {
- String contact = cursor.getString(0);
- if (contact != null) {
- starredContacts.add(contact);
- }
- } while (cursor.moveToNext());
- }
- return starredContacts;
- }
-
- private List getStarredContacts() {
- Cursor cursor = null;
- try {
- cursor = queryData();
- return getStarredContacts(cursor);
- } finally {
- if (cursor != null) {
- cursor.close();
- }
- }
- }
-
- private Cursor queryData() {
- return mContext.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,
- new String[]{ContactsContract.Contacts.DISPLAY_NAME_PRIMARY},
- ContactsContract.Data.STARRED + "=1", null,
- ContactsContract.Data.TIMES_CONTACTED);
- }
-
private boolean isIntentValid() {
return mStarredContactsIntent.resolveActivity(mPackageManager) != null
|| mFallbackIntent.resolveActivity(mPackageManager) != null;
diff --git a/src/com/android/settings/notification/ZenRuleCallsPreferenceController.java b/src/com/android/settings/notification/ZenRuleCallsPreferenceController.java
new file mode 100644
index 00000000000..b27c5feb0e0
--- /dev/null
+++ b/src/com/android/settings/notification/ZenRuleCallsPreferenceController.java
@@ -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.notification;
+
+import android.content.Context;
+import android.service.notification.ZenPolicy;
+import android.text.TextUtils;
+import android.util.Pair;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.ListPreference;
+import androidx.preference.Preference;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+public class ZenRuleCallsPreferenceController extends AbstractZenCustomRulePreferenceController
+ implements Preference.OnPreferenceChangeListener {
+
+ private final String[] mListValues;
+
+ public ZenRuleCallsPreferenceController(Context context, String key, Lifecycle lifecycle) {
+ super(context, key, lifecycle);
+ mListValues = context.getResources().getStringArray(
+ com.android.settings.R.array.zen_mode_contacts_values);
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ updateFromContactsValue(preference);
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object selectedContactsFrom) {
+ int allowCalls = ZenModeBackend.getZenPolicySettingFromPrefKey(
+ selectedContactsFrom.toString());
+ mMetricsFeatureProvider.action(mContext, MetricsProto.MetricsEvent.ACTION_ZEN_ALLOW_CALLS,
+ Pair.create(MetricsProto.MetricsEvent.FIELD_ZEN_TOGGLE_EXCEPTION, allowCalls),
+ Pair.create(MetricsProto.MetricsEvent.FIELD_ZEN_RULE_ID, mId));
+ mRule.setZenPolicy(new ZenPolicy.Builder(mRule.getZenPolicy())
+ .allowCalls(allowCalls)
+ .build());
+ mBackend.updateZenRule(mId, mRule);
+ updateFromContactsValue(preference);
+ return true;
+ }
+
+ private void updateFromContactsValue(Preference preference) {
+ if (mRule == null || mRule.getZenPolicy() == null) {
+ return;
+ }
+ ListPreference listPreference = (ListPreference) preference;
+ listPreference.setSummary(mBackend.getContactsCallsSummary(mRule.getZenPolicy()));
+ final String currentVal = ZenModeBackend.getKeyFromZenPolicySetting(
+ mRule.getZenPolicy().getPriorityCallSenders());
+ listPreference.setValue(mListValues[getIndexOfSendersValue(currentVal)]);
+
+ }
+
+ @VisibleForTesting
+ protected int getIndexOfSendersValue(String currentVal) {
+ int index = 3; // defaults to "none" based on R.array.zen_mode_contacts_values
+ for (int i = 0; i < mListValues.length; i++) {
+ if (TextUtils.equals(currentVal, mListValues[i])) {
+ return i;
+ }
+ }
+
+ return index;
+ }
+}
diff --git a/src/com/android/settings/notification/ZenRuleCustomPolicyPreferenceController.java b/src/com/android/settings/notification/ZenRuleCustomPolicyPreferenceController.java
new file mode 100644
index 00000000000..39de0eb65ee
--- /dev/null
+++ b/src/com/android/settings/notification/ZenRuleCustomPolicyPreferenceController.java
@@ -0,0 +1,81 @@
+/*
+ * 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.content.Context;
+import android.service.notification.ZenPolicy;
+import android.util.Log;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.core.SubSettingLauncher;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+public class ZenRuleCustomPolicyPreferenceController extends
+ AbstractZenCustomRulePreferenceController {
+
+ private ZenCustomRadioButtonPreference mPreference;
+
+ public ZenRuleCustomPolicyPreferenceController(Context context, Lifecycle lifecycle,
+ String key) {
+ super(context, key, lifecycle);
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPreference = (ZenCustomRadioButtonPreference) screen.findPreference(getPreferenceKey());
+
+ mPreference.setOnGearClickListener(p -> {
+ setCustomPolicy();
+ launchCustomSettings();
+
+ });
+
+ mPreference.setOnRadioButtonClickListener(p -> {
+ setCustomPolicy();
+ launchCustomSettings();
+ });
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ if (mId == null || mRule == null) {
+ return;
+ }
+
+ mPreference.setChecked(mRule.getZenPolicy() != null);
+ }
+
+ private void setCustomPolicy() {
+ if (mRule.getZenPolicy() == null) {
+ mRule.setZenPolicy(mBackend.setDefaultZenPolicy(new ZenPolicy()));
+ mBackend.updateZenRule(mId, mRule);
+ }
+ }
+
+ private void launchCustomSettings() {
+ new SubSettingLauncher(mContext)
+ .setDestination(ZenCustomRuleConfigSettings.class.getName())
+ .setArguments(createBundle())
+ .setSourceMetricsCategory(MetricsProto.MetricsEvent.ZEN_CUSTOM_RULE_SOUND_SETTINGS)
+ .launch();
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/notification/ZenRuleCustomSwitchPreferenceController.java b/src/com/android/settings/notification/ZenRuleCustomSwitchPreferenceController.java
new file mode 100644
index 00000000000..804469e37d9
--- /dev/null
+++ b/src/com/android/settings/notification/ZenRuleCustomSwitchPreferenceController.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import android.content.Context;
+import android.service.notification.ZenPolicy;
+import android.util.Log;
+import android.util.Pair;
+
+import androidx.preference.Preference;
+import androidx.preference.SwitchPreference;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+public class ZenRuleCustomSwitchPreferenceController extends
+ AbstractZenCustomRulePreferenceController implements Preference.OnPreferenceChangeListener {
+
+ private @ZenPolicy.PriorityCategory int mCategory;
+ private int mMetricsCategory;
+
+ public ZenRuleCustomSwitchPreferenceController(Context context, Lifecycle lifecycle,
+ String key, @ZenPolicy.PriorityCategory int category, int metricsCategory) {
+ super(context, key, lifecycle);
+ mCategory = category;
+ mMetricsCategory = metricsCategory;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ if (mRule == null || mRule.getZenPolicy() == null) {
+ return;
+ }
+
+ SwitchPreference pref = (SwitchPreference) preference;
+ pref.setChecked(mRule.getZenPolicy().isCategoryAllowed(mCategory, false));
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ final boolean allow = (Boolean) newValue;
+ if (ZenModeSettingsBase.DEBUG) {
+ Log.d(TAG, KEY + " onPrefChange mRule=" + mRule + " mCategory=" + mCategory
+ + " allow=" + allow);
+ }
+ mMetricsFeatureProvider.action(mContext, mMetricsCategory,
+ Pair.create(MetricsProto.MetricsEvent.FIELD_ZEN_TOGGLE_EXCEPTION, allow ? 1 : 0),
+ Pair.create(MetricsProto.MetricsEvent.FIELD_ZEN_RULE_ID, mId));
+ mRule.setZenPolicy(new ZenPolicy.Builder(mRule.getZenPolicy())
+ .allowCategory(mCategory, allow)
+ .build());
+ mBackend.updateZenRule(mId, mRule);
+ return true;
+ }
+}
diff --git a/src/com/android/settings/notification/ZenRuleDefaultPolicyPreferenceController.java b/src/com/android/settings/notification/ZenRuleDefaultPolicyPreferenceController.java
new file mode 100644
index 00000000000..857d8534c23
--- /dev/null
+++ b/src/com/android/settings/notification/ZenRuleDefaultPolicyPreferenceController.java
@@ -0,0 +1,60 @@
+/*
+ * 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.content.Context;
+import android.util.Pair;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+public class ZenRuleDefaultPolicyPreferenceController extends
+ AbstractZenCustomRulePreferenceController implements PreferenceControllerMixin {
+
+ private ZenCustomRadioButtonPreference mPreference;
+
+ public ZenRuleDefaultPolicyPreferenceController(Context context, Lifecycle lifecycle,
+ String key) {
+ super(context, key, lifecycle);
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPreference = (ZenCustomRadioButtonPreference) screen.findPreference(getPreferenceKey());
+
+ mPreference.setOnRadioButtonClickListener(p -> {
+ mRule.setZenPolicy(null);
+ mBackend.updateZenRule(mId, mRule);
+ });
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ if (mId == null || mRule == null) {
+ return;
+ }
+ mMetricsFeatureProvider.action(mContext, MetricsEvent.ZEN_CUSTOM_RULE_DEFAULT_SETTINGS,
+ Pair.create(MetricsEvent.FIELD_ZEN_RULE_ID, mId));
+ mPreference.setChecked(mRule.getZenPolicy() == null);
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/notification/ZenRuleMessagesPreferenceController.java b/src/com/android/settings/notification/ZenRuleMessagesPreferenceController.java
new file mode 100644
index 00000000000..010e152344f
--- /dev/null
+++ b/src/com/android/settings/notification/ZenRuleMessagesPreferenceController.java
@@ -0,0 +1,87 @@
+/*
+ * 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.content.Context;
+import android.service.notification.ZenPolicy;
+import android.text.TextUtils;
+import android.util.Pair;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.ListPreference;
+import androidx.preference.Preference;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+public class ZenRuleMessagesPreferenceController extends AbstractZenCustomRulePreferenceController
+ implements Preference.OnPreferenceChangeListener {
+
+ private final String[] mListValues;
+
+ public ZenRuleMessagesPreferenceController(Context context, String key, Lifecycle lifecycle) {
+ super(context, key, lifecycle);
+ mListValues = context.getResources().getStringArray(
+ com.android.settings.R.array.zen_mode_contacts_values);
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ updateFromContactsValue(preference);
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object selectedContactsFrom) {
+ int allowMessages = ZenModeBackend.getZenPolicySettingFromPrefKey(
+ selectedContactsFrom.toString());
+ mMetricsFeatureProvider.action(mContext,
+ MetricsProto.MetricsEvent.ACTION_ZEN_ALLOW_MESSAGES,
+ Pair.create(MetricsProto.MetricsEvent.FIELD_ZEN_TOGGLE_EXCEPTION, allowMessages),
+ Pair.create(MetricsProto.MetricsEvent.FIELD_ZEN_RULE_ID, mId));
+ mRule.setZenPolicy(new ZenPolicy.Builder(mRule.getZenPolicy())
+ .allowMessages(allowMessages)
+ .build());
+ mBackend.updateZenRule(mId, mRule);
+ updateFromContactsValue(preference);
+ return true;
+ }
+
+ private void updateFromContactsValue(Preference preference) {
+ if (mRule == null || mRule.getZenPolicy() == null) {
+ return;
+ }
+ ListPreference listPreference = (ListPreference) preference;
+ listPreference.setSummary(mBackend.getContactsMessagesSummary(mRule.getZenPolicy()));
+ final String currentVal = ZenModeBackend.getKeyFromZenPolicySetting(
+ mRule.getZenPolicy().getPriorityMessageSenders());
+ listPreference.setValue(mListValues[getIndexOfSendersValue(currentVal)]);
+
+ }
+
+ @VisibleForTesting
+ protected int getIndexOfSendersValue(String currentVal) {
+ int index = 3; // defaults to "none" based on R.array.zen_mode_contacts_values
+ for (int i = 0; i < mListValues.length; i++) {
+ if (TextUtils.equals(currentVal, mListValues[i])) {
+ return i;
+ }
+ }
+
+ return index;
+ }
+}
diff --git a/src/com/android/settings/notification/ZenRuleNotifFooterPreferenceController.java b/src/com/android/settings/notification/ZenRuleNotifFooterPreferenceController.java
new file mode 100644
index 00000000000..678bf90edaf
--- /dev/null
+++ b/src/com/android/settings/notification/ZenRuleNotifFooterPreferenceController.java
@@ -0,0 +1,60 @@
+/*
+ * 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.content.Context;
+
+import androidx.preference.Preference;
+
+import com.android.settings.R;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+public class ZenRuleNotifFooterPreferenceController extends
+ AbstractZenCustomRulePreferenceController {
+
+ public ZenRuleNotifFooterPreferenceController(Context context, Lifecycle lifecycle,
+ String key) {
+ super(context, key, lifecycle);
+ }
+
+ @Override
+ public boolean isAvailable() {
+ if (!super.isAvailable() || mRule.getZenPolicy() == null) {
+ return false;
+ }
+
+
+ return mRule.getZenPolicy().shouldHideAllVisualEffects()
+ || mRule.getZenPolicy().shouldShowAllVisualEffects();
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ if (mRule == null || mRule.getZenPolicy() == null) {
+ return;
+ }
+
+ if (mRule.getZenPolicy().shouldShowAllVisualEffects()) {
+ preference.setTitle(R.string.zen_mode_restrict_notifications_mute_footer);
+ } else if (mRule.getZenPolicy().shouldHideAllVisualEffects()) {
+ preference.setTitle(R.string.zen_mode_restrict_notifications_hide_footer);
+ } else {
+ preference.setTitle(null);
+ }
+ }
+}
diff --git a/src/com/android/settings/notification/ZenRuleRepeatCallersPreferenceController.java b/src/com/android/settings/notification/ZenRuleRepeatCallersPreferenceController.java
new file mode 100644
index 00000000000..1161bec195f
--- /dev/null
+++ b/src/com/android/settings/notification/ZenRuleRepeatCallersPreferenceController.java
@@ -0,0 +1,91 @@
+/*
+ * 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.content.Context;
+import android.service.notification.ZenPolicy;
+import android.util.Log;
+import android.util.Pair;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+public class ZenRuleRepeatCallersPreferenceController extends
+ AbstractZenCustomRulePreferenceController implements Preference.OnPreferenceChangeListener {
+
+ private final int mRepeatCallersThreshold;
+
+ public ZenRuleRepeatCallersPreferenceController(Context context,
+ String key, Lifecycle lifecycle, int repeatCallersThreshold) {
+ super(context, key, lifecycle);
+ mRepeatCallersThreshold = repeatCallersThreshold;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ setRepeatCallerSummary(screen.findPreference(KEY));
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ if (mRule == null || mRule.getZenPolicy() == null) {
+ return;
+ }
+
+ SwitchPreference pref = (SwitchPreference) preference;
+ boolean anyCallersCanBypassDnd = mRule.getZenPolicy().getPriorityCallSenders()
+ == ZenPolicy.PEOPLE_TYPE_ANYONE;
+
+ // if any caller can bypass dnd then repeat callers preference is disabled
+ if (anyCallersCanBypassDnd) {
+ pref.setEnabled(false);
+ pref.setChecked(true);
+ } else {
+ pref.setEnabled(true);
+ pref.setChecked(mRule.getZenPolicy().getPriorityCategoryRepeatCallers()
+ == ZenPolicy.STATE_ALLOW);
+ }
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ final boolean allow = (Boolean) newValue;
+ if (ZenModeSettingsBase.DEBUG) {
+ Log.d(TAG, KEY + " onPrefChange mRule=" + mRule + " mCategory="
+ + ZenPolicy.PRIORITY_CATEGORY_REPEAT_CALLERS + " allow=" + allow);
+ }
+ mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_ZEN_ALLOW_REPEAT_CALLS,
+ Pair.create(MetricsEvent.FIELD_ZEN_TOGGLE_EXCEPTION, allow ? 1 : 0),
+ Pair.create(MetricsEvent.FIELD_ZEN_RULE_ID, mId));
+ mRule.setZenPolicy(new ZenPolicy.Builder(mRule.getZenPolicy())
+ .allowRepeatCallers(allow)
+ .build());
+ mBackend.updateZenRule(mId, mRule);
+ return true;
+ }
+
+ private void setRepeatCallerSummary(Preference preference) {
+ preference.setSummary(mContext.getString(
+ com.android.settings.R.string.zen_mode_repeat_callers_summary,
+ mRepeatCallersThreshold));
+ }
+}
diff --git a/src/com/android/settings/notification/ZenRuleStarredContactsPreferenceController.java b/src/com/android/settings/notification/ZenRuleStarredContactsPreferenceController.java
new file mode 100644
index 00000000000..8a227a17ec6
--- /dev/null
+++ b/src/com/android/settings/notification/ZenRuleStarredContactsPreferenceController.java
@@ -0,0 +1,103 @@
+/*
+ * 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.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.provider.Contacts;
+import android.service.notification.ZenPolicy;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+public class ZenRuleStarredContactsPreferenceController extends
+ AbstractZenCustomRulePreferenceController implements Preference.OnPreferenceClickListener {
+
+ private Preference mPreference;
+ private final @ZenPolicy.PriorityCategory int mPriorityCategory;
+ private final PackageManager mPackageManager;
+
+ private Intent mStarredContactsIntent;
+ private Intent mFallbackIntent;
+
+ public ZenRuleStarredContactsPreferenceController(Context context, Lifecycle lifecycle,
+ @ZenPolicy.PriorityCategory int priorityCategory, String key) {
+ super(context, key, lifecycle);
+ mPriorityCategory = priorityCategory;
+ mPackageManager = mContext.getPackageManager();
+
+ mStarredContactsIntent = new Intent(Contacts.Intents.UI.LIST_STARRED_ACTION);
+
+ mFallbackIntent = new Intent(Intent.ACTION_MAIN);
+ mFallbackIntent.addCategory(Intent.CATEGORY_APP_CONTACTS);
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPreference = screen.findPreference(KEY);
+
+ if (mPreference != null) {
+ mPreference.setOnPreferenceClickListener(this);
+ }
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY;
+ }
+
+ @Override
+ public boolean isAvailable() {
+ if (!super.isAvailable() || mRule.getZenPolicy() == null || !isIntentValid()) {
+ return false;
+ }
+
+ if (mPriorityCategory == ZenPolicy.PRIORITY_CATEGORY_CALLS) {
+ return mRule.getZenPolicy().getPriorityCallSenders() == ZenPolicy.PEOPLE_TYPE_STARRED;
+ } else if (mPriorityCategory == ZenPolicy.PRIORITY_CATEGORY_MESSAGES) {
+ return mRule.getZenPolicy().getPriorityMessageSenders()
+ == ZenPolicy.PEOPLE_TYPE_STARRED;
+ } else {
+ // invalid category
+ return false;
+ }
+ }
+
+ @Override
+ public CharSequence getSummary() {
+ return mBackend.getStarredContactsSummary();
+ }
+
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ if (mStarredContactsIntent.resolveActivity(mPackageManager) != null) {
+ mContext.startActivity(mStarredContactsIntent);
+ } else {
+ mContext.startActivity(mFallbackIntent);
+ }
+ return true;
+ }
+
+ private boolean isIntentValid() {
+ return mStarredContactsIntent.resolveActivity(mPackageManager) != null
+ || mFallbackIntent.resolveActivity(mPackageManager) != null;
+ }
+}
diff --git a/src/com/android/settings/notification/ZenRuleVisEffectPreferenceController.java b/src/com/android/settings/notification/ZenRuleVisEffectPreferenceController.java
new file mode 100644
index 00000000000..94b82347984
--- /dev/null
+++ b/src/com/android/settings/notification/ZenRuleVisEffectPreferenceController.java
@@ -0,0 +1,104 @@
+/*
+ * 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.content.Context;
+import android.service.notification.ZenPolicy;
+import android.util.Log;
+import android.util.Pair;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.CheckBoxPreference;
+import androidx.preference.Preference;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.widget.DisabledCheckBoxPreference;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+public class ZenRuleVisEffectPreferenceController extends AbstractZenCustomRulePreferenceController
+ implements Preference.OnPreferenceChangeListener {
+
+ private final int mMetricsCategory;
+
+ @VisibleForTesting protected @ZenPolicy.VisualEffect int mEffect;
+
+ // if any of these effects are suppressed, this effect must be too
+ @VisibleForTesting protected @ZenPolicy.VisualEffect int[] mParentSuppressedEffects;
+
+ public ZenRuleVisEffectPreferenceController(Context context, Lifecycle lifecycle, String key,
+ @ZenPolicy.VisualEffect int visualEffect, int metricsCategory,
+ @ZenPolicy.VisualEffect int[] parentSuppressedEffects) {
+ super(context, key, lifecycle);
+ mEffect = visualEffect;
+ mMetricsCategory = metricsCategory;
+ mParentSuppressedEffects = parentSuppressedEffects;
+ }
+
+ @Override
+ public boolean isAvailable() {
+ if (!super.isAvailable()) {
+ return false;
+ }
+
+ if (mEffect == ZenPolicy.VISUAL_EFFECT_LIGHTS) {
+ return mContext.getResources()
+ .getBoolean(com.android.internal.R.bool.config_intrusiveNotificationLed);
+ }
+ return true;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ if (mRule == null || mRule.getZenPolicy() == null) {
+ return;
+ }
+
+ boolean suppressed = !mRule.getZenPolicy().isVisualEffectAllowed(mEffect, false);
+ boolean parentSuppressed = false;
+ if (mParentSuppressedEffects != null) {
+ for (@ZenPolicy.VisualEffect int parentEffect : mParentSuppressedEffects) {
+ if (!mRule.getZenPolicy().isVisualEffectAllowed(parentEffect, true)) {
+ parentSuppressed = true;
+ }
+ }
+ }
+ if (parentSuppressed) {
+ ((CheckBoxPreference) preference).setChecked(parentSuppressed);
+ onPreferenceChange(preference, parentSuppressed);
+ ((DisabledCheckBoxPreference) preference).enableCheckbox(false);
+ } else {
+ ((DisabledCheckBoxPreference) preference).enableCheckbox(true);
+ ((CheckBoxPreference) preference).setChecked(suppressed);
+ }
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ final boolean suppressEffect = (Boolean) newValue;
+ mMetricsFeatureProvider.action(mContext, mMetricsCategory,
+ Pair.create(MetricsProto.MetricsEvent.FIELD_ZEN_TOGGLE_EXCEPTION,
+ suppressEffect ? 1 : 0),
+ Pair.create(MetricsProto.MetricsEvent.FIELD_ZEN_RULE_ID, mId));
+
+ mRule.setZenPolicy(new ZenPolicy.Builder(mRule.getZenPolicy())
+ .showVisualEffect(mEffect, !suppressEffect)
+ .build());
+ mBackend.updateZenRule(mId, mRule);
+ return true;
+ }
+}
diff --git a/src/com/android/settings/notification/ZenRuleVisEffectsAllPreferenceController.java b/src/com/android/settings/notification/ZenRuleVisEffectsAllPreferenceController.java
new file mode 100644
index 00000000000..9ddd624e421
--- /dev/null
+++ b/src/com/android/settings/notification/ZenRuleVisEffectsAllPreferenceController.java
@@ -0,0 +1,64 @@
+/*
+ * 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.content.Context;
+import android.service.notification.ZenPolicy;
+import android.util.Log;
+import android.util.Pair;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+public class ZenRuleVisEffectsAllPreferenceController extends
+ AbstractZenCustomRulePreferenceController implements PreferenceControllerMixin {
+
+ private ZenCustomRadioButtonPreference mPreference;
+
+ public ZenRuleVisEffectsAllPreferenceController(Context context, Lifecycle lifecycle,
+ String key) {
+ super(context, key, lifecycle);
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPreference = (ZenCustomRadioButtonPreference) screen.findPreference(getPreferenceKey());
+
+ mPreference.setOnRadioButtonClickListener(p -> {
+ mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_ZEN_SOUND_ONLY,
+ Pair.create(MetricsEvent.FIELD_ZEN_RULE_ID, mId));
+ mRule.setZenPolicy(new ZenPolicy.Builder(mRule.getZenPolicy())
+ .showAllVisualEffects()
+ .build());
+ mBackend.updateZenRule(mId, mRule);
+ });
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ if (mId == null || mRule == null || mRule.getZenPolicy() == null) {
+ return;
+ }
+ mPreference.setChecked(mRule.getZenPolicy().shouldShowAllVisualEffects());
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/notification/ZenRuleVisEffectsCustomPreferenceController.java b/src/com/android/settings/notification/ZenRuleVisEffectsCustomPreferenceController.java
new file mode 100644
index 00000000000..64dd71c004f
--- /dev/null
+++ b/src/com/android/settings/notification/ZenRuleVisEffectsCustomPreferenceController.java
@@ -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.notification;
+
+import android.content.Context;
+import android.util.Pair;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.core.SubSettingLauncher;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+public class ZenRuleVisEffectsCustomPreferenceController extends
+ AbstractZenCustomRulePreferenceController implements PreferenceControllerMixin {
+
+ private ZenCustomRadioButtonPreference mPreference;
+
+ public ZenRuleVisEffectsCustomPreferenceController(Context context, Lifecycle lifecycle,
+ String key) {
+ super(context, key, lifecycle);
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPreference = (ZenCustomRadioButtonPreference) screen.findPreference(getPreferenceKey());
+
+ mPreference.setOnGearClickListener(p -> {
+ launchCustomSettings();
+
+ });
+
+ mPreference.setOnRadioButtonClickListener(p -> {
+ launchCustomSettings();
+ });
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ if (mId == null || mRule == null || mRule.getZenPolicy() == null) {
+ return;
+ }
+
+ mPreference.setChecked(!mRule.getZenPolicy().shouldHideAllVisualEffects()
+ && !mRule.getZenPolicy().shouldShowAllVisualEffects());
+ }
+
+ private void launchCustomSettings() {
+ mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_ZEN_SHOW_CUSTOM,
+ Pair.create(MetricsEvent.FIELD_ZEN_RULE_ID, mId));
+ new SubSettingLauncher(mContext)
+ .setDestination(ZenCustomRuleBlockedEffectsSettings.class.getName())
+ .setArguments(createBundle())
+ .setSourceMetricsCategory(MetricsEvent.ZEN_CUSTOM_RULE_VIS_EFFECTS)
+ .launch();
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/notification/ZenRuleVisEffectsNonePreferenceController.java b/src/com/android/settings/notification/ZenRuleVisEffectsNonePreferenceController.java
new file mode 100644
index 00000000000..4f98924c5f8
--- /dev/null
+++ b/src/com/android/settings/notification/ZenRuleVisEffectsNonePreferenceController.java
@@ -0,0 +1,65 @@
+/*
+ * 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.content.Context;
+import android.service.notification.ZenPolicy;
+import android.util.Log;
+import android.util.Pair;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+public class ZenRuleVisEffectsNonePreferenceController extends
+ AbstractZenCustomRulePreferenceController implements PreferenceControllerMixin {
+
+ private ZenCustomRadioButtonPreference mPreference;
+
+ public ZenRuleVisEffectsNonePreferenceController(Context context, Lifecycle lifecycle,
+ String key) {
+ super(context, key, lifecycle);
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPreference = (ZenCustomRadioButtonPreference) screen.findPreference(getPreferenceKey());
+
+ mPreference.setOnRadioButtonClickListener(p -> {
+ mMetricsFeatureProvider.action(mContext, MetricsEvent.ACTION_ZEN_SOUND_AND_VIS_EFFECTS,
+ Pair.create(MetricsEvent.FIELD_ZEN_RULE_ID, mId));
+ mRule.setZenPolicy(new ZenPolicy.Builder(mRule.getZenPolicy())
+ .hideAllVisualEffects()
+ .build());
+ mBackend.updateZenRule(mId, mRule);
+ });
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ if (mId == null || mRule == null || mRule.getZenPolicy() == null) {
+ return;
+ }
+
+ mPreference.setChecked(mRule.getZenPolicy().shouldHideAllVisualEffects());
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/overlay/FeatureFactory.java b/src/com/android/settings/overlay/FeatureFactory.java
index 76962b2658a..1d12c959180 100644
--- a/src/com/android/settings/overlay/FeatureFactory.java
+++ b/src/com/android/settings/overlay/FeatureFactory.java
@@ -23,7 +23,6 @@ import android.util.Log;
import com.android.settings.R;
import com.android.settings.accounts.AccountFeatureProvider;
import com.android.settings.applications.ApplicationFeatureProvider;
-import com.android.settings.biometrics.face.FaceFeatureProvider;
import com.android.settings.bluetooth.BluetoothFeatureProvider;
import com.android.settings.dashboard.DashboardFeatureProvider;
import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
@@ -111,9 +110,7 @@ public abstract class FeatureFactory {
public abstract PanelFeatureProvider getPanelFeatureProvider();
- public abstract ContextualCardFeatureProvider getContextualCardFeatureProvider();
-
- public abstract FaceFeatureProvider getFaceFeatureProvider();
+ public abstract ContextualCardFeatureProvider getContextualCardFeatureProvider(Context context);
public abstract BluetoothFeatureProvider getBluetoothFeatureProvider(Context context);
diff --git a/src/com/android/settings/overlay/FeatureFactoryImpl.java b/src/com/android/settings/overlay/FeatureFactoryImpl.java
index 50b9f8f3e50..ff40158814b 100644
--- a/src/com/android/settings/overlay/FeatureFactoryImpl.java
+++ b/src/com/android/settings/overlay/FeatureFactoryImpl.java
@@ -28,8 +28,6 @@ import com.android.settings.accounts.AccountFeatureProvider;
import com.android.settings.accounts.AccountFeatureProviderImpl;
import com.android.settings.applications.ApplicationFeatureProvider;
import com.android.settings.applications.ApplicationFeatureProviderImpl;
-import com.android.settings.biometrics.face.FaceFeatureProvider;
-import com.android.settings.biometrics.face.FaceFeatureProviderImpl;
import com.android.settings.bluetooth.BluetoothFeatureProvider;
import com.android.settings.bluetooth.BluetoothFeatureProviderImpl;
import com.android.settings.connecteddevice.dock.DockUpdaterFeatureProviderImpl;
@@ -82,7 +80,6 @@ public class FeatureFactoryImpl extends FeatureFactory {
private AccountFeatureProvider mAccountFeatureProvider;
private PanelFeatureProvider mPanelFeatureProvider;
private ContextualCardFeatureProvider mContextualCardFeatureProvider;
- private FaceFeatureProvider mFaceFeatureProvider;
private BluetoothFeatureProvider mBluetoothFeatureProvider;
@Override
@@ -231,21 +228,14 @@ public class FeatureFactoryImpl extends FeatureFactory {
}
@Override
- public ContextualCardFeatureProvider getContextualCardFeatureProvider() {
+ public ContextualCardFeatureProvider getContextualCardFeatureProvider(Context context) {
if (mContextualCardFeatureProvider == null) {
- mContextualCardFeatureProvider = new ContextualCardFeatureProviderImpl();
+ mContextualCardFeatureProvider = new ContextualCardFeatureProviderImpl(
+ context.getApplicationContext());
}
return mContextualCardFeatureProvider;
}
- @Override
- public FaceFeatureProvider getFaceFeatureProvider() {
- if (mFaceFeatureProvider == null) {
- mFaceFeatureProvider = new FaceFeatureProviderImpl();
- }
- return mFaceFeatureProvider;
- }
-
@Override
public BluetoothFeatureProvider getBluetoothFeatureProvider(Context context) {
if (mBluetoothFeatureProvider == null) {
diff --git a/src/com/android/settings/panel/PanelFeatureProviderImpl.java b/src/com/android/settings/panel/PanelFeatureProviderImpl.java
index 503a5c37b6f..ade2ffdc946 100644
--- a/src/com/android/settings/panel/PanelFeatureProviderImpl.java
+++ b/src/com/android/settings/panel/PanelFeatureProviderImpl.java
@@ -17,15 +17,16 @@
package com.android.settings.panel;
import android.content.Context;
+import android.provider.Settings;
public class PanelFeatureProviderImpl implements PanelFeatureProvider {
@Override
public PanelContent getPanel(Context context, String panelType) {
switch (panelType) {
- case SettingsPanelActivity.PANEL_TYPE_WIFI:
+ case Settings.Panel.ACTION_INTERNET_CONNECTIVITY:
return InternetConnectivityPanel.create(context);
- case SettingsPanelActivity.PANEL_TYPE_VOLUME:
+ case Settings.Panel.ACTION_VOLUME:
return VolumePanel.create(context);
}
diff --git a/src/com/android/settings/panel/PanelFragment.java b/src/com/android/settings/panel/PanelFragment.java
index e61b8f8429e..7655be8f006 100644
--- a/src/com/android/settings/panel/PanelFragment.java
+++ b/src/com/android/settings/panel/PanelFragment.java
@@ -69,7 +69,7 @@ public class PanelFragment extends Fragment {
mPanelSlices = view.findViewById(R.id.panel_parent_layout);
mSeeMoreButton = view.findViewById(R.id.see_more);
mDoneButton = view.findViewById(R.id.done);
- mTitleView = view.findViewById(R.id.title);
+ mTitleView = view.findViewById(R.id.panel_title);
final Bundle arguments = getArguments();
final String panelType = arguments.getString(SettingsPanelActivity.KEY_PANEL_TYPE_ARGUMENT);
diff --git a/src/com/android/settings/panel/SettingsPanelActivity.java b/src/com/android/settings/panel/SettingsPanelActivity.java
index 09bead4c52e..ffe94f88acb 100644
--- a/src/com/android/settings/panel/SettingsPanelActivity.java
+++ b/src/com/android/settings/panel/SettingsPanelActivity.java
@@ -16,11 +16,9 @@
package com.android.settings.panel;
-import android.content.ComponentName;
import android.content.Intent;
import android.os.Bundle;
-import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
import android.view.Window;
@@ -35,8 +33,6 @@ import com.android.settings.R;
/**
* Dialog Activity to host Settings Slices.
- *
- * TODO link to action / framework API
*/
public class SettingsPanelActivity extends FragmentActivity {
@@ -47,28 +43,10 @@ public class SettingsPanelActivity extends FragmentActivity {
*/
public static final String KEY_PANEL_TYPE_ARGUMENT = "PANEL_TYPE_ARGUMENT";
-
- // TODO (b/117804442) move to framework
- public static final String EXTRA_PANEL_TYPE = "com.android.settings.panel.extra";
-
- // TODO (b/117804442) move to framework
- public static final String PANEL_TYPE_WIFI = "wifi_panel";
-
- // TODO (b/117804442) move to framework
- public static final String PANEL_TYPE_VOLUME = "volume_panel";
-
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- final ComponentName callingActivityName = getCallingActivity();
-
- if (callingActivityName == null) {
- Log.e(TAG, "Must start with startActivityForResult. Closing.");
- finish();
- return;
- }
-
final Intent callingIntent = getIntent();
if (callingIntent == null) {
Log.e(TAG, "Null intent, closing Panel Activity");
@@ -76,12 +54,6 @@ public class SettingsPanelActivity extends FragmentActivity {
return;
}
- final String typeExtra = callingIntent.getStringExtra(EXTRA_PANEL_TYPE);
- if (TextUtils.isEmpty(typeExtra)) {
- Log.e(TAG, "No intent passed, closing Panel Activity");
- return;
- }
-
setContentView(R.layout.settings_panel);
// Move the window to the bottom of screen, and make it take up the entire screen width.
@@ -90,9 +62,8 @@ public class SettingsPanelActivity extends FragmentActivity {
window.setLayout(WindowManager.LayoutParams.MATCH_PARENT,
WindowManager.LayoutParams.WRAP_CONTENT);
-
final Bundle bundle = new Bundle();
- bundle.putString(KEY_PANEL_TYPE_ARGUMENT, typeExtra);
+ bundle.putString(KEY_PANEL_TYPE_ARGUMENT, callingIntent.getAction());
final PanelFragment panelFragment = new PanelFragment();
panelFragment.setArguments(bundle);
diff --git a/src/com/android/settings/slices/CustomSliceManager.java b/src/com/android/settings/slices/CustomSliceManager.java
index 4a9de15d841..bb47df28622 100644
--- a/src/com/android/settings/slices/CustomSliceManager.java
+++ b/src/com/android/settings/slices/CustomSliceManager.java
@@ -32,7 +32,8 @@ import com.android.settings.homepage.contextualcards.slices.BatteryFixSlice;
import com.android.settings.homepage.contextualcards.slices.BluetoothDevicesSlice;
import com.android.settings.homepage.contextualcards.slices.LowStorageSlice;
import com.android.settings.location.LocationSlice;
-import com.android.settings.wifi.WifiSlice;
+import com.android.settings.wifi.slice.ContextualWifiSlice;
+import com.android.settings.wifi.slice.WifiSlice;
import java.util.Map;
import java.util.WeakHashMap;
@@ -107,6 +108,7 @@ public class CustomSliceManager {
mUriMap.put(CustomSliceRegistry.BATTERY_FIX_SLICE_URI, BatteryFixSlice.class);
mUriMap.put(CustomSliceRegistry.BATTERY_INFO_SLICE_URI, BatterySlice.class);
mUriMap.put(CustomSliceRegistry.BLUETOOTH_DEVICES_SLICE_URI, BluetoothDevicesSlice.class);
+ mUriMap.put(CustomSliceRegistry.CONTEXTUAL_WIFI_SLICE_URI, ContextualWifiSlice.class);
mUriMap.put(CustomSliceRegistry.DATA_USAGE_SLICE_URI, DataUsageSlice.class);
mUriMap.put(CustomSliceRegistry.DEVICE_INFO_SLICE_URI, DeviceInfoSlice.class);
mUriMap.put(CustomSliceRegistry.EMERGENCY_INFO_SLICE_URI, EmergencyInfoSlice.class);
diff --git a/src/com/android/settings/slices/CustomSliceRegistry.java b/src/com/android/settings/slices/CustomSliceRegistry.java
index 1b8cffef509..bdf8b35ebda 100644
--- a/src/com/android/settings/slices/CustomSliceRegistry.java
+++ b/src/com/android/settings/slices/CustomSliceRegistry.java
@@ -80,6 +80,17 @@ public class CustomSliceRegistry {
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
.appendPath("bluetooth_devices")
.build();
+
+ /**
+ * Backing Uri for the Wifi Slice.
+ */
+ public static final Uri CONTEXTUAL_WIFI_SLICE_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSlicesContract.AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath("contextual_wifi")
+ .build();
+
/**
* Backing Uri for the Data usage Slice.
*/
@@ -216,6 +227,7 @@ public class CustomSliceRegistry {
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
.appendPath(KEY_WIFI)
.build();
+
/**
* Backing Uri for the Zen Mode Slice.
*/
diff --git a/src/com/android/settings/widget/SeekBarPreference.java b/src/com/android/settings/widget/SeekBarPreference.java
index 2c57bb31a94..f4d2aac83d4 100644
--- a/src/com/android/settings/widget/SeekBarPreference.java
+++ b/src/com/android/settings/widget/SeekBarPreference.java
@@ -91,6 +91,11 @@ public class SeekBarPreference extends RestrictedPreference
notifyChanged();
}
+ @Override
+ public boolean isSelectable() {
+ return false;
+ }
+
@Override
public void onBindViewHolder(PreferenceViewHolder view) {
super.onBindViewHolder(view);
diff --git a/src/com/android/settings/wifi/WifiDialogActivity.java b/src/com/android/settings/wifi/WifiDialogActivity.java
index 9ef6a39a028..c32bcf3d0c6 100644
--- a/src/com/android/settings/wifi/WifiDialogActivity.java
+++ b/src/com/android/settings/wifi/WifiDialogActivity.java
@@ -38,6 +38,8 @@ public class WifiDialogActivity extends Activity implements WifiDialog.WifiDialo
private static final String TAG = "WifiDialogActivity";
+ public static final String KEY_ACCESS_POINT_STATE = "access_point_state";
+
/**
* Boolean extra indicating whether this activity should connect to an access point on the
* caller's behalf. If this is set to false, the caller should check
@@ -46,9 +48,8 @@ public class WifiDialogActivity extends Activity implements WifiDialog.WifiDialo
*/
@VisibleForTesting
static final String KEY_CONNECT_FOR_CALLER = "connect_for_caller";
- static final String KEY_ACCESS_POINT_STATE = "access_point_state";
- private static final String KEY_WIFI_CONFIGURATION = "wifi_configuration";
+ private static final String KEY_WIFI_CONFIGURATION = "wifi_configuration";
private static final int RESULT_CONNECTED = RESULT_FIRST_USER;
private static final int RESULT_FORGET = RESULT_FIRST_USER + 1;
diff --git a/src/com/android/settings/wifi/dpp/WifiDppUtils.java b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
index 3275695c307..cc75d441dce 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppUtils.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
@@ -58,25 +58,7 @@ public class WifiDppUtils {
/** The data corresponding to {@code WifiConfiguration} hiddenSSID */
public static final String EXTRA_WIFI_HIDDEN_SSID = "hiddenSsid";
- /**
- * Acceptable QR code string may be a standard W-Fi DPP bootstrapping information or the Wi-Fi
- * Network config format described in
- * https://github.com/zxing/zxing/wiki/Barcode-Contents#wi-fi-network-config-android-ios-11
- *
- * Wi-Fi Network config format example:
- *
- * WIFI:T:WPA;S:mynetwork;P:mypass;;
- *
- * parameter Example Description
- * T WPA Authentication type; can be WEP or WPA, or 'nopass' for no password. Or,
- * omit for no password.
- * S mynetwork Network SSID. Required. Enclose in double quotes if it is an ASCII name,
- * but could be interpreted as hex (i.e. "ABCD")
- * P mypass Password, ignored if T is "nopass" (in which case it may be omitted).
- * Enclose in double quotes if it is an ASCII name, but could be interpreted as
- * hex (i.e. "ABCD")
- * H true Optional. True if the network SSID is hidden.
- */
+ /** @see WifiQrCode */
public static final String EXTRA_QR_CODE = "qrCode";
/**
diff --git a/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java b/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java
index 439de988c0f..bb64e050532 100644
--- a/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java
+++ b/src/com/android/settings/wifi/dpp/WifiNetworkConfig.java
@@ -19,15 +19,20 @@ package com.android.settings.wifi.dpp;
import android.content.Intent;
import android.text.TextUtils;
+import androidx.annotation.Keep;
+
/**
- * Contains the Wi-Fi Network config parameters described in
- * https://github.com/zxing/zxing/wiki/Barcode-Contents#wi-fi-network-config-android-ios-11
+ * Wraps the parameters of ZXing reader library's Wi-Fi Network config format.
+ * Please check {@code WifiQrCode} for detail of the format.
*
* Checks below members of {@code WifiDppUtils} for more information.
* EXTRA_WIFI_SECURITY / EXTRA_WIFI_SSID / EXTRA_WIFI_PRE_SHARED_KEY / EXTRA_WIFI_HIDDEN_SSID /
* EXTRA_QR_CODE
*/
public class WifiNetworkConfig {
+ // Ignores password if security is NO_PASSWORD or absent
+ public static final String NO_PASSWORD = "nopass";
+
private String mSecurity;
private String mSsid;
private String mPreSharedKey;
@@ -42,9 +47,18 @@ public class WifiNetworkConfig {
}
public WifiNetworkConfig(WifiNetworkConfig config) {
- mSecurity = new String(config.mSecurity);
- mSsid = new String(config.mSsid);
- mPreSharedKey = new String(config.mPreSharedKey);
+ if (config.mSecurity != null) {
+ mSecurity = new String(config.mSecurity);
+ }
+
+ if (config.mSsid != null) {
+ mSsid = new String(config.mSsid);
+ }
+
+ if (config.mPreSharedKey != null) {
+ mPreSharedKey = new String(config.mPreSharedKey);
+ }
+
mHiddenSsid = config.mHiddenSsid;
}
@@ -69,12 +83,13 @@ public class WifiNetworkConfig {
String preSharedKey = intent.getStringExtra(WifiDppUtils.EXTRA_WIFI_PRE_SHARED_KEY);
boolean hiddenSsid = intent.getBooleanExtra(WifiDppUtils.EXTRA_WIFI_HIDDEN_SSID, false);
- if (!isValidConfig(security, ssid, hiddenSsid)) {
- return null;
- }
+ return getValidConfigOrNull(security, ssid, preSharedKey, hiddenSsid);
+ }
- if (ssid == null) {
- ssid = "";
+ public static WifiNetworkConfig getValidConfigOrNull(String security, String ssid,
+ String preSharedKey, boolean hiddenSsid) {
+ if (!isValidConfig(security, ssid, preSharedKey, hiddenSsid)) {
+ return null;
}
return new WifiNetworkConfig(security, ssid, preSharedKey, hiddenSsid);
@@ -84,13 +99,17 @@ public class WifiNetworkConfig {
if (config == null) {
return false;
} else {
- return isValidConfig(config.mSecurity, config.mSsid, config.mHiddenSsid);
+ return isValidConfig(config.mSecurity, config.mSsid, config.mPreSharedKey,
+ config.mHiddenSsid);
}
}
- public static boolean isValidConfig(String security, String ssid, boolean hiddenSsid) {
- if (TextUtils.isEmpty(security)) {
- return false;
+ public static boolean isValidConfig(String security, String ssid, String preSharedKey,
+ boolean hiddenSsid) {
+ if (!TextUtils.isEmpty(security) && !NO_PASSWORD.equals(security)) {
+ if (TextUtils.isEmpty(preSharedKey)) {
+ return false;
+ }
}
if (!hiddenSsid && TextUtils.isEmpty(ssid)) {
@@ -100,18 +119,22 @@ public class WifiNetworkConfig {
return true;
}
+ @Keep
public String getSecurity() {
- return new String(mSecurity);
+ return mSecurity;
}
+ @Keep
public String getSsid() {
- return new String(mSsid);
+ return mSsid;
}
+ @Keep
public String getPreSharedKey() {
- return new String(mPreSharedKey);
+ return mPreSharedKey;
}
+ @Keep
public boolean getHiddenSsid() {
return mHiddenSsid;
}
diff --git a/src/com/android/settings/wifi/dpp/WifiQrCode.java b/src/com/android/settings/wifi/dpp/WifiQrCode.java
new file mode 100644
index 00000000000..ebc39c371cb
--- /dev/null
+++ b/src/com/android/settings/wifi/dpp/WifiQrCode.java
@@ -0,0 +1,223 @@
+/*
+ * 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.dpp;
+
+import android.content.Intent;
+import android.text.TextUtils;
+
+import androidx.annotation.Keep;
+import androidx.annotation.VisibleForTesting;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Supports to parse 2 types of QR code
+ *
+ * 1. Standard Wi-Fi DPP bootstrapping information or
+ * 2. ZXing reader library's Wi-Fi Network config format described in
+ * https://github.com/zxing/zxing/wiki/Barcode-Contents#wi-fi-network-config-android-ios-11
+ *
+ * ZXing reader library's Wi-Fi Network config format example:
+ *
+ * WIFI:T:WPA;S:mynetwork;P:mypass;;
+ *
+ * parameter Example Description
+ * T WPA Authentication type; can be WEP or WPA, or 'nopass' for no password. Or,
+ * omit for no password.
+ * S mynetwork Network SSID. Required. Enclose in double quotes if it is an ASCII name,
+ * but could be interpreted as hex (i.e. "ABCD")
+ * P mypass Password, ignored if T is "nopass" (in which case it may be omitted).
+ * Enclose in double quotes if it is an ASCII name, but could be interpreted as
+ * hex (i.e. "ABCD")
+ * H true Optional. True if the network SSID is hidden.
+ *
+ */
+@Keep
+public class WifiQrCode {
+ public static final String SCHEME_DPP = "DPP";
+ public static final String SCHEME_ZXING_WIFI_NETWORK_CONFIG = "WIFI";
+ public static final String PREFIX_DPP = "DPP:";
+ public static final String PREFIX_ZXING_WIFI_NETWORK_CONFIG = "WIFI:";
+
+ public static final String PREFIX_DPP_PUBLIC_KEY = "K:";
+ public static final String PREFIX_DPP_INFORMATION = "I:";
+
+ public static final String PREFIX_ZXING_SECURITY = "T:";
+ public static final String PREFIX_ZXING_SSID = "S:";
+ public static final String PREFIX_ZXING_PASSWORD = "P:";
+ public static final String PREFIX_ZXING_HIDDEN_SSID = "H:";
+
+ public static final String SUFFIX_QR_CODE = ";";
+
+ private String mQrCode;
+
+ /**
+ * SCHEME_DPP for standard Wi-Fi device provision protocol; SCHEME_ZXING_WIFI_NETWORK_CONFIG
+ * for ZXing reader library' Wi-Fi Network config format
+ */
+ private String mScheme;
+
+ // Data from parsed Wi-Fi DPP QR code
+ private String mPublicKey;
+ private String mInformation;
+
+ // Data from parsed ZXing reader library's Wi-Fi Network config format
+ private WifiNetworkConfig mWifiNetworkConfig;
+
+ @Keep
+ public WifiQrCode(String qrCode) throws IllegalArgumentException {
+ if (TextUtils.isEmpty(qrCode)) {
+ throw new IllegalArgumentException("Empty QR code");
+ }
+
+ mQrCode = qrCode;
+
+ if (qrCode.startsWith(PREFIX_DPP)) {
+ mScheme = SCHEME_DPP;
+ parseWifiDppQrCode(qrCode);
+ } else if (qrCode.startsWith(PREFIX_ZXING_WIFI_NETWORK_CONFIG)) {
+ mScheme = SCHEME_ZXING_WIFI_NETWORK_CONFIG;
+ parseZxingWifiQrCode(qrCode);
+ } else {
+ throw new IllegalArgumentException("Invalid scheme");
+ }
+ }
+
+ /** Parses Wi-Fi DPP QR code string */
+ private void parseWifiDppQrCode(String qrCode) throws IllegalArgumentException {
+ String publicKey = getSubStringOrNull(qrCode, PREFIX_DPP_PUBLIC_KEY, SUFFIX_QR_CODE);
+ if (TextUtils.isEmpty(publicKey)) {
+ throw new IllegalArgumentException("Invalid format");
+ }
+ mPublicKey = publicKey;
+
+ mInformation = getSubStringOrNull(qrCode, PREFIX_DPP_INFORMATION, SUFFIX_QR_CODE);
+ }
+
+ /** Parses ZXing reader library's Wi-Fi Network config format */
+ private void parseZxingWifiQrCode(String qrCode) throws IllegalArgumentException {
+ String security = getSubStringOrNull(qrCode, PREFIX_ZXING_SECURITY, SUFFIX_QR_CODE);
+ String ssid = getSubStringOrNull(qrCode, PREFIX_ZXING_SSID, SUFFIX_QR_CODE);
+ String password = getSubStringOrNull(qrCode, PREFIX_ZXING_PASSWORD, SUFFIX_QR_CODE);
+ String hiddenSsidString = getSubStringOrNull(qrCode, PREFIX_ZXING_HIDDEN_SSID,
+ SUFFIX_QR_CODE);
+ boolean hiddenSsid = "true".equalsIgnoreCase(hiddenSsidString);
+
+ //"\", ";", "," and ":" are escaped with a backslash "\", should remove at first
+ security = removeBackSlash(security);
+ ssid = removeBackSlash(ssid);
+ password = removeBackSlash(password);
+
+ mWifiNetworkConfig = WifiNetworkConfig.getValidConfigOrNull(security, ssid, password,
+ hiddenSsid);
+
+ if (mWifiNetworkConfig == null) {
+ throw new IllegalArgumentException("Invalid format");
+ }
+ }
+
+ /**
+ * Gets the substring between prefix & suffix from input.
+ *
+ * @param prefix the string before the returned substring
+ * @param suffix the string after the returned substring
+ * @return null if not exists, non-null otherwise
+ */
+ private static String getSubStringOrNull(String input, String prefix, String suffix) {
+ StringBuilder sb = new StringBuilder();
+ String regex = sb.append(prefix).append("(.*?)").append(suffix).toString();
+ Pattern pattern = Pattern.compile(regex);
+ Matcher matcher = pattern.matcher(input);
+
+ if (!matcher.find()) {
+ return null;
+ }
+
+ String target = matcher.group(1);
+ if (TextUtils.isEmpty(target)) {
+ return null;
+ }
+
+ return target;
+ }
+
+ @Keep
+ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+ protected static String removeBackSlash(String input) {
+ if (input == null) {
+ return null;
+ }
+
+ StringBuilder sb = new StringBuilder();
+ boolean backSlash = false;
+ for (char ch : input.toCharArray()) {
+ if (ch != '\\') {
+ sb.append(ch);
+ backSlash = false;
+ } else {
+ if (backSlash) {
+ sb.append(ch);
+ backSlash = false;
+ continue;
+ }
+
+ backSlash = true;
+ }
+ }
+
+ return sb.toString();
+ }
+
+ @Keep
+ public String getQrCode() {
+ return mQrCode;
+ }
+
+ /**
+ * Uses to check type of QR code
+ *
+ * SCHEME_DPP for standard Wi-Fi device provision protocol; SCHEME_ZXING_WIFI_NETWORK_CONFIG
+ * for ZXing reader library' Wi-Fi Network config format
+ */
+ @Keep
+ public String getScheme() {
+ return mScheme;
+ }
+
+ /** Available when {@code getScheme()} returns SCHEME_DPP */
+ @Keep
+ public String getPublicKey() {
+ return mPublicKey;
+ }
+
+ /** May be available when {@code getScheme()} returns SCHEME_DPP */
+ @Keep
+ public String getInformation() {
+ return mInformation;
+ }
+
+ /** Available when {@code getScheme()} returns SCHEME_ZXING_WIFI_NETWORK_CONFIG */
+ @Keep
+ public WifiNetworkConfig getWifiNetworkConfig() {
+ if (mWifiNetworkConfig == null) {
+ return null;
+ }
+
+ return new WifiNetworkConfig(mWifiNetworkConfig);
+ }
+}
diff --git a/src/com/android/settings/wifi/slice/ContextualWifiSlice.java b/src/com/android/settings/wifi/slice/ContextualWifiSlice.java
new file mode 100644
index 00000000000..fa8c2678e29
--- /dev/null
+++ b/src/com/android/settings/wifi/slice/ContextualWifiSlice.java
@@ -0,0 +1,61 @@
+/*
+ * 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.slice;
+
+import android.content.Context;
+import android.net.Uri;
+import android.net.wifi.WifiSsid;
+import android.text.TextUtils;
+import android.util.Log;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.slice.Slice;
+
+import com.android.settings.slices.CustomSliceRegistry;
+import com.android.settings.slices.CustomSliceable;
+
+/**
+ * {@link CustomSliceable} for Wi-Fi, used by contextual homepage.
+ */
+public class ContextualWifiSlice extends WifiSlice {
+
+ private static final String TAG = "ContextualWifiSlice";
+ @VisibleForTesting
+ boolean mPreviouslyDisplayed;
+
+ public ContextualWifiSlice(Context context) {
+ super(context);
+ }
+
+ @Override
+ public Uri getUri() {
+ return CustomSliceRegistry.CONTEXTUAL_WIFI_SLICE_URI;
+ }
+
+ @Override
+ public Slice getSlice() {
+ if (!mPreviouslyDisplayed && !TextUtils.equals(getActiveSSID(), WifiSsid.NONE)) {
+ Log.d(TAG, "Wifi is connected, no point showing any suggestion.");
+ return null;
+ }
+ // Set mPreviouslyDisplayed to true - we will show *something* on the screen. So we should
+ // keep showing this card to keep UI stable, even if wifi connects to a network later.
+ mPreviouslyDisplayed = true;
+
+ return super.getSlice();
+ }
+}
diff --git a/src/com/android/settings/wifi/WifiSlice.java b/src/com/android/settings/wifi/slice/WifiSlice.java
similarity index 95%
rename from src/com/android/settings/wifi/WifiSlice.java
rename to src/com/android/settings/wifi/slice/WifiSlice.java
index 9f05783421f..4d3a95ad217 100644
--- a/src/com/android/settings/wifi/WifiSlice.java
+++ b/src/com/android/settings/wifi/slice/WifiSlice.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.settings.wifi;
+package com.android.settings.wifi.slice;
import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
import static android.provider.SettingsSlicesContract.KEY_WIFI;
@@ -46,6 +46,8 @@ import com.android.settings.core.SubSettingLauncher;
import com.android.settings.slices.CustomSliceable;
import com.android.settings.slices.SliceBackgroundWorker;
import com.android.settings.slices.SliceBuilderUtils;
+import com.android.settings.wifi.WifiDialogActivity;
+import com.android.settings.wifi.WifiSettings;
import com.android.settings.wifi.details.WifiNetworkDetailsFragment;
import com.android.settingslib.wifi.AccessPoint;
import com.android.settingslib.wifi.WifiTracker;
@@ -54,15 +56,15 @@ import java.util.ArrayList;
import java.util.List;
/**
- * Utility class to build a Wifi Slice, and handle all associated actions.
+ * {@link CustomSliceable} for Wi-Fi, used by generic clients.
*/
public class WifiSlice implements CustomSliceable {
@VisibleForTesting
static final int DEFAULT_EXPANDED_ROW_COUNT = 3;
+ protected final WifiManager mWifiManager;
private final Context mContext;
- private final WifiManager mWifiManager;
public WifiSlice(Context context) {
mContext = context;
@@ -77,6 +79,7 @@ public class WifiSlice implements CustomSliceable {
@Override
public Slice getSlice() {
final boolean isWifiEnabled = isWifiEnabled();
+
final IconCompat icon = IconCompat.createWithResource(mContext,
R.drawable.ic_settings_wireless);
final String title = mContext.getString(R.string.wifi_settings);
@@ -208,6 +211,13 @@ public class WifiSlice implements CustomSliceable {
return intent;
}
+ protected String getActiveSSID() {
+ if (mWifiManager.getWifiState() != WifiManager.WIFI_STATE_ENABLED) {
+ return WifiSsid.NONE;
+ }
+ return WifiInfo.removeDoubleQuotes(mWifiManager.getConnectionInfo().getSSID());
+ }
+
private boolean isWifiEnabled() {
switch (mWifiManager.getWifiState()) {
case WifiManager.WIFI_STATE_ENABLED:
@@ -221,8 +231,7 @@ public class WifiSlice implements CustomSliceable {
private CharSequence getSummary() {
switch (mWifiManager.getWifiState()) {
case WifiManager.WIFI_STATE_ENABLED:
- final String ssid = WifiInfo.removeDoubleQuotes(mWifiManager.getConnectionInfo()
- .getSSID());
+ final String ssid = getActiveSSID();
if (TextUtils.equals(ssid, WifiSsid.NONE)) {
return mContext.getText(R.string.disconnected);
}
diff --git a/tests/robotests/assets/grandfather_not_implementing_index_provider b/tests/robotests/assets/grandfather_not_implementing_index_provider
index ab06f751c77..447de0049df 100644
--- a/tests/robotests/assets/grandfather_not_implementing_index_provider
+++ b/tests/robotests/assets/grandfather_not_implementing_index_provider
@@ -54,6 +54,12 @@ com.android.settings.notification.NotificationStation
com.android.settings.notification.RedactionInterstitial$RedactionInterstitialFragment
com.android.settings.notification.ZenModeEventRuleSettings
com.android.settings.notification.ZenModeScheduleRuleSettings
+com.android.settings.notification.ZenCustomRuleNotificationsSettings
+com.android.settings.notification.ZenCustomRuleCallsSettings
+com.android.settings.notification.ZenCustomRuleConfigSettings
+com.android.settings.notification.ZenCustomRuleSettings
+com.android.settings.notification.ZenCustomRuleBlockedEffectsSettings
+com.android.settings.notification.ZenCustomRuleMessagesSettings
com.android.settings.password.ChooseLockGeneric$ChooseLockGenericFragment
com.android.settings.password.SetupChooseLockGeneric$InternalActivity$InternalSetupChooseLockGenericFragment
com.android.settings.password.SetupChooseLockGeneric$SetupChooseLockGenericFragment
diff --git a/tests/robotests/res/layout-mcc999/fingerprint_enroll_find_sensor.xml b/tests/robotests/res/layout-mcc999/fingerprint_enroll_find_sensor.xml
index 50e2a379894..83eb781fb92 100644
--- a/tests/robotests/res/layout-mcc999/fingerprint_enroll_find_sensor.xml
+++ b/tests/robotests/res/layout-mcc999/fingerprint_enroll_find_sensor.xml
@@ -21,8 +21,7 @@
android:id="@+id/setup_wizard_layout"
style="?attr/fingerprint_layout_theme"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- app:sucFooter="@layout/fingerprint_enroll_find_sensor_base_footer">
+ android:layout_height="match_parent">
broadcastReceiverCaptor =
- ArgumentCaptor.forClass(BroadcastReceiver.class);
- verify(mContext).registerReceiver(broadcastReceiverCaptor.capture(), any());
- BroadcastReceiver br = broadcastReceiverCaptor.getValue();
- br.onReceive(mContext, intent);
+ for (BroadcastReceiver receiver : mShadowApplication.getReceiversForIntent(intent)) {
+ receiver.onReceive(mContext, intent);
+ }
}
private List generateHearingAidDeviceList() {
diff --git a/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultBrowserPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultBrowserPreferenceControllerTest.java
index 7bfd299fb20..03b3867848d 100644
--- a/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultBrowserPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/defaultapps/DefaultBrowserPreferenceControllerTest.java
@@ -109,10 +109,16 @@ public class DefaultBrowserPreferenceControllerTest {
doReturn(null).when(spyController).getDefaultAppIcon();
final List resolveInfos = new ArrayList<>();
final CharSequence PACKAGE_NAME = "com.test.package";
- final ResolveInfo info1 = spy(createResolveInfo(PACKAGE_NAME.toString()));
- when(info1.loadLabel(mPackageManager)).thenReturn(PACKAGE_NAME);
+
+ // This ResolveInfo will return a non-null label from loadLabel.
+ final ResolveInfo info1 = createResolveInfo(PACKAGE_NAME.toString());
+ info1.nonLocalizedLabel = PACKAGE_NAME;
resolveInfos.add(info1);
- resolveInfos.add(createResolveInfo(PACKAGE_NAME.toString()));
+
+ // This ResolveInfo will return a null label from loadLabel.
+ final ResolveInfo info2 = createResolveInfo(PACKAGE_NAME.toString());
+ resolveInfos.add(info2);
+
when(mPackageManager.getDefaultBrowserPackageNameAsUser(anyInt())).thenReturn(null);
when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
.thenReturn(resolveInfos);
diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensorTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensorTest.java
index d6adb5c78ef..67c03d56b79 100644
--- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensorTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFindSensorTest.java
@@ -37,6 +37,9 @@ import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.ShadowUtils;
+import com.google.android.setupcompat.PartnerCustomizationLayout;
+import com.google.android.setupcompat.template.ButtonFooterMixin;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -133,8 +136,8 @@ public class FingerprintEnrollFindSensorTest {
@Test
public void clickSkip_shouldReturnResultSkip() {
- Button skipButton = mActivity.findViewById(R.id.skip_button);
- skipButton.performClick();
+ PartnerCustomizationLayout layout = mActivity.findViewById(R.id.setup_wizard_layout);
+ layout.getMixin(ButtonFooterMixin.class).getSecondaryButtonView().performClick();
ShadowActivity shadowActivity = Shadows.shadowOf(mActivity);
assertThat(shadowActivity.getResultCode()).named("result code")
diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSuggestionActivityTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSuggestionActivityTest.java
index 76dc736fa13..82124f91d1c 100644
--- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSuggestionActivityTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSuggestionActivityTest.java
@@ -31,6 +31,9 @@ import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
import com.android.settings.testutils.shadow.ShadowUserManager;
+import com.google.android.setupcompat.PartnerCustomizationLayout;
+import com.google.android.setupcompat.template.ButtonFooterMixin;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -62,7 +65,10 @@ public class FingerprintSuggestionActivityTest {
mController.create().resume();
- final Button cancelButton = mController.get().findViewById(R.id.fingerprint_cancel_button);
+ PartnerCustomizationLayout layout =
+ mController.get().findViewById(R.id.setup_wizard_layout);
+ final Button cancelButton =
+ layout.getMixin(ButtonFooterMixin.class).getSecondaryButtonView();
assertThat(cancelButton.getText().toString()).isEqualTo("Cancel");
assertThat(cancelButton.getVisibility()).named("Cancel visible").isEqualTo(View.VISIBLE);
cancelButton.performClick();
diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollFindSensorTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollFindSensorTest.java
index 7e971496aa7..b112c8a5f13 100644
--- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollFindSensorTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollFindSensorTest.java
@@ -32,6 +32,9 @@ import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
import com.android.settings.testutils.shadow.ShadowUtils;
+import com.google.android.setupcompat.PartnerCustomizationLayout;
+import com.google.android.setupcompat.template.ButtonFooterMixin;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -71,8 +74,8 @@ public class SetupFingerprintEnrollFindSensorTest {
Robolectric.buildActivity(SetupFingerprintEnrollFindSensor.class,
intent).setup().get();
- final Button skipButton = activity.findViewById(R.id.skip_button);
- skipButton.performClick();
+ PartnerCustomizationLayout layout = activity.findViewById(R.id.setup_wizard_layout);
+ layout.getMixin(ButtonFooterMixin.class).getSecondaryButtonView().performClick();
final AlertDialog alertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();
assertThat(alertDialog).isNotNull();
diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollIntroductionTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollIntroductionTest.java
index d9d9197f22a..12bf1e2ca9a 100644
--- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollIntroductionTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/SetupFingerprintEnrollIntroductionTest.java
@@ -37,6 +37,9 @@ import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
import com.android.settings.testutils.shadow.ShadowStorageManager;
import com.android.settings.testutils.shadow.ShadowUserManager;
+import com.google.android.setupcompat.PartnerCustomizationLayout;
+import com.google.android.setupcompat.template.ButtonFooterMixin;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -83,7 +86,10 @@ public class SetupFingerprintEnrollIntroductionTest {
mController.create().resume();
- final Button skipButton = mController.get().findViewById(R.id.fingerprint_cancel_button);
+ PartnerCustomizationLayout layout =
+ mController.get().findViewById(R.id.setup_wizard_layout);
+ final Button skipButton =
+ layout.getMixin(ButtonFooterMixin.class).getSecondaryButtonView();
assertThat(skipButton.getVisibility()).named("Skip visible").isEqualTo(View.VISIBLE);
skipButton.performClick();
@@ -99,7 +105,10 @@ public class SetupFingerprintEnrollIntroductionTest {
mController.create().resume();
- final Button skipButton = mController.get().findViewById(R.id.fingerprint_cancel_button);
+ PartnerCustomizationLayout layout =
+ mController.get().findViewById(R.id.setup_wizard_layout);
+ final Button skipButton =
+ layout.getMixin(ButtonFooterMixin.class).getSecondaryButtonView();
assertThat(skipButton.getVisibility()).named("Skip visible").isEqualTo(View.VISIBLE);
skipButton.performClick();
@@ -141,7 +150,9 @@ public class SetupFingerprintEnrollIntroductionTest {
getShadowKeyguardManager().setIsKeyguardSecure(false);
SetupFingerprintEnrollIntroduction activity = mController.create().resume().get();
- final Button skipButton = activity.findViewById(R.id.fingerprint_cancel_button);
+ PartnerCustomizationLayout layout = activity.findViewById(R.id.setup_wizard_layout);
+ final Button skipButton =
+ layout.getMixin(ButtonFooterMixin.class).getSecondaryButtonView();
getShadowKeyguardManager().setIsKeyguardSecure(true);
skipButton.performClick();
@@ -156,7 +167,9 @@ public class SetupFingerprintEnrollIntroductionTest {
getShadowKeyguardManager().setIsKeyguardSecure(true);
SetupFingerprintEnrollIntroduction activity = mController.create().resume().get();
- final Button skipButton = activity.findViewById(R.id.fingerprint_cancel_button);
+ PartnerCustomizationLayout layout = activity.findViewById(R.id.setup_wizard_layout);
+ final Button skipButton =
+ layout.getMixin(ButtonFooterMixin.class).getSecondaryButtonView();
skipButton.performClick();
ShadowActivity shadowActivity = Shadows.shadowOf(activity);
@@ -199,8 +212,9 @@ public class SetupFingerprintEnrollIntroductionTest {
SetupFingerprintEnrollIntroduction activity = mController.get();
- final Button nextButton = activity.findViewById(R.id.fingerprint_next_button);
- nextButton.performClick();
+ PartnerCustomizationLayout layout = activity.findViewById(R.id.setup_wizard_layout);
+ layout.getMixin(ButtonFooterMixin.class).getPrimaryButtonView().performClick();
+
ShadowActivity shadowActivity = Shadows.shadowOf(activity);
IntentForResult startedActivity = shadowActivity.getNextStartedActivityForResult();
diff --git a/tests/robotests/src/com/android/settings/bluetooth/RemoteDeviceNameDialogFragmentTest.java b/tests/robotests/src/com/android/settings/bluetooth/RemoteDeviceNameDialogFragmentTest.java
index bd7f79e96ee..c8467b2a57e 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/RemoteDeviceNameDialogFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/RemoteDeviceNameDialogFragmentTest.java
@@ -38,7 +38,6 @@ import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
@@ -80,7 +79,6 @@ public class RemoteDeviceNameDialogFragmentTest {
return (AlertDialog) ShadowDialog.getLatestDialog();
}
- @Ignore("b/119592320")
@Test
public void deviceNameDisplayIsCorrect() {
String deviceName = "ABC Corp Headphones";
@@ -96,7 +94,6 @@ public class RemoteDeviceNameDialogFragmentTest {
assertThat(negativeButton.isEnabled()).isTrue();
}
- @Ignore("b/119592320")
@Test
public void deviceNameEditSucceeds() {
String deviceNameInitial = "ABC Corp Headphones";
@@ -119,7 +116,6 @@ public class RemoteDeviceNameDialogFragmentTest {
verify(mCachedDevice).setName(deviceNameModified);
}
- @Ignore("b/119592320")
@Test
public void deviceNameEditThenCancelDoesntRename() {
String deviceNameInitial = "ABC Corp Headphones";
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/usb/ConnectedUsbDeviceUpdaterTest.java b/tests/robotests/src/com/android/settings/connecteddevice/usb/ConnectedUsbDeviceUpdaterTest.java
index b698b3aa366..7c6a305c18a 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/usb/ConnectedUsbDeviceUpdaterTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/usb/ConnectedUsbDeviceUpdaterTest.java
@@ -15,6 +15,11 @@
*/
package com.android.settings.connecteddevice.usb;
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE;
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_NONE;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_NONE;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SINK;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.verify;
@@ -22,7 +27,6 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.hardware.usb.UsbManager;
-import android.hardware.usb.UsbPort;
import com.android.settings.R;
import com.android.settings.connecteddevice.DevicePreferenceCallback;
@@ -78,7 +82,7 @@ public class ConnectedUsbDeviceUpdaterTest {
public void initUsbPreference_usbConnected_preferenceAdded() {
mDeviceUpdater.initUsbPreference(mContext);
mDeviceUpdater.mUsbConnectionListener.onUsbConnectionChanged(true /* connected */,
- UsbManager.FUNCTION_NONE, UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_DEVICE);
+ UsbManager.FUNCTION_NONE, POWER_ROLE_SINK, DATA_ROLE_DEVICE);
verify(mDevicePreferenceCallback).onDeviceAdded(mDeviceUpdater.mUsbPreference);
}
@@ -87,7 +91,7 @@ public class ConnectedUsbDeviceUpdaterTest {
public void initUsbPreference_usbDisconnected_preferenceRemoved() {
mDeviceUpdater.initUsbPreference(mContext);
mDeviceUpdater.mUsbConnectionListener.onUsbConnectionChanged(false /* connected */,
- UsbManager.FUNCTION_NONE, UsbPort.POWER_ROLE_NONE, UsbPort.DATA_ROLE_NONE);
+ UsbManager.FUNCTION_NONE, POWER_ROLE_NONE, DATA_ROLE_NONE);
verify(mDevicePreferenceCallback).onDeviceRemoved(mDeviceUpdater.mUsbPreference);
}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbBackendTest.java b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbBackendTest.java
index 333d2b6cc52..4e5897da3ed 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbBackendTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbBackendTest.java
@@ -16,6 +16,11 @@
package com.android.settings.connecteddevice.usb;
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE;
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_HOST;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SINK;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SOURCE;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Answers.RETURNS_DEEP_STUBS;
@@ -40,6 +45,8 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
+import java.util.Collections;
+
@RunWith(RobolectricTestRunner.class)
public class UsbBackendTest {
@@ -64,9 +71,9 @@ public class UsbBackendTest {
when((Object) mContext.getSystemService(UsbManager.class)).thenReturn(mUsbManager);
when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
.thenReturn(mConnectivityManager);
- when(mUsbManager.getPorts()).thenReturn(new UsbPort[] {mUsbPort});
+ when(mUsbManager.getPorts()).thenReturn(Collections.singletonList(mUsbPort));
when(mUsbPortStatus.isConnected()).thenReturn(true);
- when(mUsbManager.getPortStatus(mUsbPort)).thenReturn(mUsbPortStatus);
+ when(mUsbPort.getStatus()).thenReturn(mUsbPortStatus);
}
@Test
@@ -74,22 +81,22 @@ public class UsbBackendTest {
final UsbBackend usbBackend = new UsbBackend(mContext, mUserManager);
when(mUsbPortStatus
- .isRoleCombinationSupported(UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_DEVICE))
+ .isRoleCombinationSupported(POWER_ROLE_SINK, DATA_ROLE_DEVICE))
.thenReturn(true);
when(mUsbPortStatus
- .isRoleCombinationSupported(UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_HOST))
+ .isRoleCombinationSupported(POWER_ROLE_SINK, DATA_ROLE_HOST))
.thenReturn(true);
when(mUsbPortStatus
- .isRoleCombinationSupported(UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_DEVICE))
+ .isRoleCombinationSupported(POWER_ROLE_SOURCE, DATA_ROLE_DEVICE))
.thenReturn(true);
when(mUsbPortStatus
- .isRoleCombinationSupported(UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_HOST))
+ .isRoleCombinationSupported(POWER_ROLE_SOURCE, DATA_ROLE_HOST))
.thenReturn(true);
- when(mUsbPortStatus.getCurrentPowerRole()).thenReturn(UsbPort.POWER_ROLE_SINK);
+ when(mUsbPortStatus.getCurrentPowerRole()).thenReturn(POWER_ROLE_SINK);
- usbBackend.setDataRole(UsbPort.DATA_ROLE_HOST);
+ usbBackend.setDataRole(DATA_ROLE_HOST);
- verify(mUsbManager).setPortRoles(mUsbPort, UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_HOST);
+ verify(mUsbPort).setRoles(POWER_ROLE_SINK, DATA_ROLE_HOST);
}
@Test
@@ -97,17 +104,16 @@ public class UsbBackendTest {
final UsbBackend usbBackend = new UsbBackend(mContext, mUserManager);
when(mUsbPortStatus
- .isRoleCombinationSupported(UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_DEVICE))
+ .isRoleCombinationSupported(POWER_ROLE_SINK, DATA_ROLE_DEVICE))
.thenReturn(true);
when(mUsbPortStatus
- .isRoleCombinationSupported(UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_HOST))
+ .isRoleCombinationSupported(POWER_ROLE_SOURCE, DATA_ROLE_HOST))
.thenReturn(true);
- when(mUsbPortStatus.getCurrentPowerRole()).thenReturn(UsbPort.POWER_ROLE_SINK);
+ when(mUsbPortStatus.getCurrentPowerRole()).thenReturn(POWER_ROLE_SINK);
- usbBackend.setDataRole(UsbPort.DATA_ROLE_HOST);
+ usbBackend.setDataRole(DATA_ROLE_HOST);
- verify(mUsbManager)
- .setPortRoles(mUsbPort, UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_HOST);
+ verify(mUsbPort).setRoles(POWER_ROLE_SOURCE, DATA_ROLE_HOST);
}
@Test
@@ -115,23 +121,22 @@ public class UsbBackendTest {
final UsbBackend usbBackend = new UsbBackend(mContext, mUserManager);
when(mUsbPortStatus
- .isRoleCombinationSupported(UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_DEVICE))
+ .isRoleCombinationSupported(POWER_ROLE_SINK, DATA_ROLE_DEVICE))
.thenReturn(true);
when(mUsbPortStatus
- .isRoleCombinationSupported(UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_HOST))
+ .isRoleCombinationSupported(POWER_ROLE_SINK, DATA_ROLE_HOST))
.thenReturn(true);
when(mUsbPortStatus
- .isRoleCombinationSupported(UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_DEVICE))
+ .isRoleCombinationSupported(POWER_ROLE_SOURCE, DATA_ROLE_DEVICE))
.thenReturn(true);
when(mUsbPortStatus
- .isRoleCombinationSupported(UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_HOST))
+ .isRoleCombinationSupported(POWER_ROLE_SOURCE, DATA_ROLE_HOST))
.thenReturn(true);
- when(mUsbPortStatus.getCurrentDataRole()).thenReturn(UsbPort.DATA_ROLE_DEVICE);
+ when(mUsbPortStatus.getCurrentDataRole()).thenReturn(DATA_ROLE_DEVICE);
- usbBackend.setPowerRole(UsbPort.POWER_ROLE_SOURCE);
+ usbBackend.setPowerRole(POWER_ROLE_SOURCE);
- verify(mUsbManager)
- .setPortRoles(mUsbPort, UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_DEVICE);
+ verify(mUsbPort).setRoles(POWER_ROLE_SOURCE, DATA_ROLE_DEVICE);
}
@Test
@@ -139,17 +144,16 @@ public class UsbBackendTest {
final UsbBackend usbBackend = new UsbBackend(mContext, mUserManager);
when(mUsbPortStatus
- .isRoleCombinationSupported(UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_DEVICE))
+ .isRoleCombinationSupported(POWER_ROLE_SINK, DATA_ROLE_DEVICE))
.thenReturn(true);
when(mUsbPortStatus
- .isRoleCombinationSupported(UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_HOST))
+ .isRoleCombinationSupported(POWER_ROLE_SOURCE, DATA_ROLE_HOST))
.thenReturn(true);
- when(mUsbPortStatus.getCurrentDataRole()).thenReturn(UsbPort.DATA_ROLE_DEVICE);
+ when(mUsbPortStatus.getCurrentDataRole()).thenReturn(DATA_ROLE_DEVICE);
- usbBackend.setPowerRole(UsbPort.POWER_ROLE_SOURCE);
+ usbBackend.setPowerRole(POWER_ROLE_SOURCE);
- verify(mUsbManager)
- .setPortRoles(mUsbPort, UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_HOST);
+ verify(mUsbPort).setRoles(POWER_ROLE_SOURCE, DATA_ROLE_HOST);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbConnectionBroadcastReceiverTest.java b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbConnectionBroadcastReceiverTest.java
index 1689ee7344d..1da97f5d520 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbConnectionBroadcastReceiverTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbConnectionBroadcastReceiverTest.java
@@ -15,6 +15,11 @@
*/
package com.android.settings.connecteddevice.usb;
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE;
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_NONE;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_NONE;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SINK;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.verify;
@@ -22,7 +27,6 @@ import static org.mockito.Mockito.verify;
import android.content.Context;
import android.content.Intent;
import android.hardware.usb.UsbManager;
-import android.hardware.usb.UsbPort;
import android.hardware.usb.UsbPortStatus;
import org.junit.Before;
@@ -63,7 +67,7 @@ public class UsbConnectionBroadcastReceiverTest {
mReceiver.onReceive(mContext, intent);
verify(mListener).onUsbConnectionChanged(true /* connected */, UsbManager.FUNCTION_NONE,
- UsbPort.POWER_ROLE_NONE, UsbPort.DATA_ROLE_NONE);
+ POWER_ROLE_NONE, DATA_ROLE_NONE);
}
@Test
@@ -75,7 +79,7 @@ public class UsbConnectionBroadcastReceiverTest {
mReceiver.onReceive(mContext, intent);
verify(mListener).onUsbConnectionChanged(false /* connected */, UsbManager.FUNCTION_NONE,
- UsbPort.POWER_ROLE_NONE, UsbPort.DATA_ROLE_NONE);
+ POWER_ROLE_NONE, DATA_ROLE_NONE);
}
@Test
@@ -89,21 +93,21 @@ public class UsbConnectionBroadcastReceiverTest {
mReceiver.onReceive(mContext, intent);
verify(mListener).onUsbConnectionChanged(true /* connected */, UsbManager.FUNCTION_MTP,
- UsbPort.POWER_ROLE_NONE, UsbPort.DATA_ROLE_NONE);
+ POWER_ROLE_NONE, DATA_ROLE_NONE);
}
@Test
public void onReceive_usbPortStatus_invokeCallback() {
final Intent intent = new Intent();
intent.setAction(UsbManager.ACTION_USB_PORT_CHANGED);
- final UsbPortStatus status = new UsbPortStatus(0, UsbPort.POWER_ROLE_SINK,
- UsbPort.DATA_ROLE_DEVICE, 0);
+ final UsbPortStatus status = new UsbPortStatus(0, POWER_ROLE_SINK,
+ DATA_ROLE_DEVICE, 0);
intent.putExtra(UsbManager.EXTRA_PORT_STATUS, status);
mReceiver.onReceive(mContext, intent);
verify(mListener).onUsbConnectionChanged(false /* connected */, UsbManager.FUNCTION_NONE,
- UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_DEVICE);
+ POWER_ROLE_SINK, DATA_ROLE_DEVICE);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsDataRoleControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsDataRoleControllerTest.java
index 3eda3d1ea70..91e680b9342 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsDataRoleControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsDataRoleControllerTest.java
@@ -16,6 +16,12 @@
package com.android.settings.connecteddevice.usb;
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE;
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_HOST;
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_NONE;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_NONE;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SINK;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyLong;
@@ -24,7 +30,6 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.hardware.usb.UsbManager;
-import android.hardware.usb.UsbPort;
import android.os.Handler;
import androidx.fragment.app.FragmentActivity;
@@ -92,11 +97,11 @@ public class UsbDetailsDataRoleControllerTest {
public void displayRefresh_deviceRole_shouldCheckDevice() {
mDetailsDataRoleController.displayPreference(mScreen);
- mDetailsDataRoleController.refresh(true, UsbManager.FUNCTION_NONE, UsbPort.POWER_ROLE_SINK,
- UsbPort.DATA_ROLE_DEVICE);
+ mDetailsDataRoleController.refresh(true, UsbManager.FUNCTION_NONE, POWER_ROLE_SINK,
+ DATA_ROLE_DEVICE);
- final RadioButtonPreference devicePref = getRadioPreference(UsbPort.DATA_ROLE_DEVICE);
- final RadioButtonPreference hostPref = getRadioPreference(UsbPort.DATA_ROLE_HOST);
+ final RadioButtonPreference devicePref = getRadioPreference(DATA_ROLE_DEVICE);
+ final RadioButtonPreference hostPref = getRadioPreference(DATA_ROLE_HOST);
assertThat(devicePref.isChecked()).isTrue();
assertThat(hostPref.isChecked()).isFalse();
}
@@ -105,11 +110,11 @@ public class UsbDetailsDataRoleControllerTest {
public void displayRefresh_hostRole_shouldCheckHost() {
mDetailsDataRoleController.displayPreference(mScreen);
- mDetailsDataRoleController.refresh(true, UsbManager.FUNCTION_NONE, UsbPort.POWER_ROLE_SINK,
- UsbPort.DATA_ROLE_HOST);
+ mDetailsDataRoleController.refresh(true, UsbManager.FUNCTION_NONE, POWER_ROLE_SINK,
+ DATA_ROLE_HOST);
- final RadioButtonPreference devicePref = getRadioPreference(UsbPort.DATA_ROLE_DEVICE);
- final RadioButtonPreference hostPref = getRadioPreference(UsbPort.DATA_ROLE_HOST);
+ final RadioButtonPreference devicePref = getRadioPreference(DATA_ROLE_DEVICE);
+ final RadioButtonPreference hostPref = getRadioPreference(DATA_ROLE_HOST);
assertThat(devicePref.isChecked()).isFalse();
assertThat(hostPref.isChecked()).isTrue();
}
@@ -118,8 +123,8 @@ public class UsbDetailsDataRoleControllerTest {
public void displayRefresh_disconnected_shouldDisable() {
mDetailsDataRoleController.displayPreference(mScreen);
- mDetailsDataRoleController.refresh(false, UsbManager.FUNCTION_NONE, UsbPort.POWER_ROLE_SINK,
- UsbPort.DATA_ROLE_DEVICE);
+ mDetailsDataRoleController.refresh(false, UsbManager.FUNCTION_NONE, POWER_ROLE_SINK,
+ DATA_ROLE_DEVICE);
assertThat(mPreference.isEnabled()).isFalse();
}
@@ -127,12 +132,12 @@ public class UsbDetailsDataRoleControllerTest {
@Test
public void onClickDevice_hostEnabled_shouldSetDevice() {
mDetailsDataRoleController.displayPreference(mScreen);
- when(mUsbBackend.getDataRole()).thenReturn(UsbPort.DATA_ROLE_HOST);
+ when(mUsbBackend.getDataRole()).thenReturn(DATA_ROLE_HOST);
- final RadioButtonPreference devicePref = getRadioPreference(UsbPort.DATA_ROLE_DEVICE);
+ final RadioButtonPreference devicePref = getRadioPreference(DATA_ROLE_DEVICE);
devicePref.performClick();
- verify(mUsbBackend).setDataRole(UsbPort.DATA_ROLE_DEVICE);
+ verify(mUsbBackend).setDataRole(DATA_ROLE_DEVICE);
assertThat(devicePref.getSummary())
.isEqualTo(mContext.getString(R.string.usb_switching));
}
@@ -140,50 +145,50 @@ public class UsbDetailsDataRoleControllerTest {
@Test
public void onClickDeviceTwice_hostEnabled_shouldSetDeviceOnce() {
mDetailsDataRoleController.displayPreference(mScreen);
- when(mUsbBackend.getDataRole()).thenReturn(UsbPort.DATA_ROLE_HOST);
+ when(mUsbBackend.getDataRole()).thenReturn(DATA_ROLE_HOST);
- final RadioButtonPreference devicePref = getRadioPreference(UsbPort.DATA_ROLE_DEVICE);
+ final RadioButtonPreference devicePref = getRadioPreference(DATA_ROLE_DEVICE);
devicePref.performClick();
assertThat(devicePref.getSummary())
.isEqualTo(mContext.getString(R.string.usb_switching));
devicePref.performClick();
- verify(mUsbBackend).setDataRole(UsbPort.DATA_ROLE_DEVICE);
+ verify(mUsbBackend).setDataRole(DATA_ROLE_DEVICE);
}
@Test
public void onClickDeviceAndRefresh_success_shouldClearSubtext() {
mDetailsDataRoleController.displayPreference(mScreen);
- when(mUsbBackend.getDataRole()).thenReturn(UsbPort.DATA_ROLE_HOST);
+ when(mUsbBackend.getDataRole()).thenReturn(DATA_ROLE_HOST);
- final RadioButtonPreference devicePref = getRadioPreference(UsbPort.DATA_ROLE_DEVICE);
+ final RadioButtonPreference devicePref = getRadioPreference(DATA_ROLE_DEVICE);
devicePref.performClick();
- verify(mUsbBackend).setDataRole(UsbPort.DATA_ROLE_DEVICE);
+ verify(mUsbBackend).setDataRole(DATA_ROLE_DEVICE);
assertThat(devicePref.getSummary())
.isEqualTo(mContext.getString(R.string.usb_switching));
mDetailsDataRoleController.refresh(false /* connected */, UsbManager.FUNCTION_NONE,
- UsbPort.POWER_ROLE_NONE, UsbPort.DATA_ROLE_NONE);
+ POWER_ROLE_NONE, DATA_ROLE_NONE);
mDetailsDataRoleController.refresh(true /* connected */, UsbManager.FUNCTION_NONE,
- UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_DEVICE);
+ POWER_ROLE_SINK, DATA_ROLE_DEVICE);
assertThat(devicePref.getSummary()).isEqualTo("");
}
@Test
public void onClickDeviceAndRefresh_failed_shouldShowFailureText() {
mDetailsDataRoleController.displayPreference(mScreen);
- when(mUsbBackend.getDataRole()).thenReturn(UsbPort.DATA_ROLE_HOST);
+ when(mUsbBackend.getDataRole()).thenReturn(DATA_ROLE_HOST);
- final RadioButtonPreference devicePref = getRadioPreference(UsbPort.DATA_ROLE_DEVICE);
+ final RadioButtonPreference devicePref = getRadioPreference(DATA_ROLE_DEVICE);
devicePref.performClick();
- verify(mUsbBackend).setDataRole(UsbPort.DATA_ROLE_DEVICE);
+ verify(mUsbBackend).setDataRole(DATA_ROLE_DEVICE);
assertThat(devicePref.getSummary())
.isEqualTo(mContext.getString(R.string.usb_switching));
mDetailsDataRoleController.refresh(false /* connected */, UsbManager.FUNCTION_NONE,
- UsbPort.POWER_ROLE_NONE, UsbPort.DATA_ROLE_NONE);
+ POWER_ROLE_NONE, DATA_ROLE_NONE);
mDetailsDataRoleController.refresh(true /* connected */, UsbManager.FUNCTION_NONE,
- UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_HOST);
+ POWER_ROLE_SINK, DATA_ROLE_HOST);
assertThat(devicePref.getSummary())
.isEqualTo(mContext.getString(R.string.usb_switching_failed));
}
@@ -191,18 +196,18 @@ public class UsbDetailsDataRoleControllerTest {
@Test
public void onClickDevice_timedOut_shouldShowFailureText() {
mDetailsDataRoleController.displayPreference(mScreen);
- when(mUsbBackend.getDataRole()).thenReturn(UsbPort.DATA_ROLE_HOST);
+ when(mUsbBackend.getDataRole()).thenReturn(DATA_ROLE_HOST);
- final RadioButtonPreference devicePref = getRadioPreference(UsbPort.DATA_ROLE_DEVICE);
+ final RadioButtonPreference devicePref = getRadioPreference(DATA_ROLE_DEVICE);
devicePref.performClick();
- verify(mUsbBackend).setDataRole(UsbPort.DATA_ROLE_DEVICE);
+ verify(mUsbBackend).setDataRole(DATA_ROLE_DEVICE);
ArgumentCaptor captor = ArgumentCaptor.forClass(Runnable.class);
verify(mHandler).postDelayed(captor.capture(), anyLong());
assertThat(devicePref.getSummary())
.isEqualTo(mContext.getString(R.string.usb_switching));
mDetailsDataRoleController.refresh(false /* connected */, UsbManager.FUNCTION_NONE,
- UsbPort.POWER_ROLE_NONE, UsbPort.DATA_ROLE_NONE);
+ POWER_ROLE_NONE, DATA_ROLE_NONE);
captor.getValue().run();
assertThat(devicePref.getSummary())
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsFunctionsControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsFunctionsControllerTest.java
index fc93a58e677..11fa61342d0 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsFunctionsControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsFunctionsControllerTest.java
@@ -16,6 +16,8 @@
package com.android.settings.connecteddevice.usb;
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SINK;
import static android.net.ConnectivityManager.TETHERING_USB;
import static com.google.common.truth.Truth.assertThat;
@@ -105,8 +107,8 @@ public class UsbDetailsFunctionsControllerTest {
when(mUsbBackend.areFunctionsSupported(anyLong())).thenReturn(true);
mDetailsFunctionsController.displayPreference(mScreen);
- mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_NONE, UsbPort.POWER_ROLE_SINK,
- UsbPort.DATA_ROLE_DEVICE);
+ mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_NONE, POWER_ROLE_SINK,
+ DATA_ROLE_DEVICE);
List prefs = getRadioPreferences();
Iterator iter = UsbDetailsFunctionsController.FUNCTIONS_MAP.keySet().iterator();
@@ -120,7 +122,7 @@ public class UsbDetailsFunctionsControllerTest {
when(mUsbBackend.areFunctionsSupported(anyLong())).thenReturn(true);
mDetailsFunctionsController.refresh(false, UsbManager.FUNCTION_NONE,
- UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_DEVICE);
+ POWER_ROLE_SINK, DATA_ROLE_DEVICE);
assertThat(mPreferenceCategory.isEnabled()).isFalse();
}
@@ -131,8 +133,8 @@ public class UsbDetailsFunctionsControllerTest {
when(mUsbBackend.areFunctionsSupported(UsbManager.FUNCTION_PTP)).thenReturn(false);
when(mUsbBackend.areFunctionsSupported(UsbManager.FUNCTION_RNDIS)).thenReturn(false);
- mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_NONE, UsbPort.POWER_ROLE_SINK,
- UsbPort.DATA_ROLE_DEVICE);
+ mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_NONE, POWER_ROLE_SINK,
+ DATA_ROLE_DEVICE);
List prefs = getRadioPreferences();
assertThat(prefs.size()).isEqualTo(1);
assertThat(prefs.get(0).getKey())
@@ -143,8 +145,8 @@ public class UsbDetailsFunctionsControllerTest {
public void displayRefresh_mtpEnabled_shouldCheckSwitches() {
when(mUsbBackend.areFunctionsSupported(anyLong())).thenReturn(true);
- mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_MTP, UsbPort.POWER_ROLE_SINK,
- UsbPort.DATA_ROLE_DEVICE);
+ mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_MTP, POWER_ROLE_SINK,
+ DATA_ROLE_DEVICE);
List prefs = getRadioPreferences();
assertThat(prefs.get(0).getKey())
@@ -156,8 +158,8 @@ public class UsbDetailsFunctionsControllerTest {
public void onClickMtp_noneEnabled_shouldEnableMtp() {
when(mUsbBackend.areFunctionsSupported(anyLong())).thenReturn(true);
- mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_NONE, UsbPort.POWER_ROLE_SINK,
- UsbPort.DATA_ROLE_DEVICE);
+ mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_NONE, POWER_ROLE_SINK,
+ DATA_ROLE_DEVICE);
when(mUsbBackend.getCurrentFunctions()).thenReturn(UsbManager.FUNCTION_NONE);
List prefs = getRadioPreferences();
prefs.get(0).performClick();
@@ -165,8 +167,8 @@ public class UsbDetailsFunctionsControllerTest {
assertThat(prefs.get(0).getKey())
.isEqualTo(UsbBackend.usbFunctionsToString(UsbManager.FUNCTION_MTP));
verify(mUsbBackend).setCurrentFunctions(UsbManager.FUNCTION_MTP);
- mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_MTP, UsbPort.POWER_ROLE_SINK,
- UsbPort.DATA_ROLE_DEVICE);
+ mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_MTP, POWER_ROLE_SINK,
+ DATA_ROLE_DEVICE);
assertThat(prefs.get(0).isChecked()).isTrue();
}
@@ -174,8 +176,8 @@ public class UsbDetailsFunctionsControllerTest {
public void onClickMtp_ptpEnabled_shouldEnableMtp() {
when(mUsbBackend.areFunctionsSupported(anyLong())).thenReturn(true);
- mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_PTP, UsbPort.POWER_ROLE_SINK,
- UsbPort.DATA_ROLE_DEVICE);
+ mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_PTP, POWER_ROLE_SINK,
+ DATA_ROLE_DEVICE);
when(mUsbBackend.getCurrentFunctions()).thenReturn(UsbManager.FUNCTION_PTP);
List prefs = getRadioPreferences();
prefs.get(0).performClick();
@@ -183,8 +185,8 @@ public class UsbDetailsFunctionsControllerTest {
assertThat(prefs.get(0).getKey())
.isEqualTo(UsbBackend.usbFunctionsToString(UsbManager.FUNCTION_MTP));
verify(mUsbBackend).setCurrentFunctions(UsbManager.FUNCTION_MTP);
- mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_MTP, UsbPort.POWER_ROLE_SINK,
- UsbPort.DATA_ROLE_DEVICE);
+ mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_MTP, POWER_ROLE_SINK,
+ DATA_ROLE_DEVICE);
assertThat(prefs.get(0).isChecked()).isTrue();
assertThat(prefs.get(3).getKey())
.isEqualTo(UsbBackend.usbFunctionsToString(UsbManager.FUNCTION_PTP));
@@ -195,8 +197,8 @@ public class UsbDetailsFunctionsControllerTest {
public void onClickNone_mtpEnabled_shouldDisableMtp() {
when(mUsbBackend.areFunctionsSupported(anyLong())).thenReturn(true);
- mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_MTP, UsbPort.POWER_ROLE_SINK,
- UsbPort.DATA_ROLE_DEVICE);
+ mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_MTP, POWER_ROLE_SINK,
+ DATA_ROLE_DEVICE);
when(mUsbBackend.getCurrentFunctions()).thenReturn(UsbManager.FUNCTION_MTP);
List prefs = getRadioPreferences();
prefs.get(4).performClick();
@@ -204,8 +206,8 @@ public class UsbDetailsFunctionsControllerTest {
assertThat(prefs.get(4).getKey())
.isEqualTo(UsbBackend.usbFunctionsToString(UsbManager.FUNCTION_NONE));
verify(mUsbBackend).setCurrentFunctions(UsbManager.FUNCTION_NONE);
- mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_NONE, UsbPort.POWER_ROLE_SINK,
- UsbPort.DATA_ROLE_DEVICE);
+ mDetailsFunctionsController.refresh(true, UsbManager.FUNCTION_NONE, POWER_ROLE_SINK,
+ DATA_ROLE_DEVICE);
assertThat(prefs.get(0).isChecked()).isFalse();
}
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsHeaderControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsHeaderControllerTest.java
index d72214f1afd..280b8d4c7ca 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsHeaderControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsHeaderControllerTest.java
@@ -16,6 +16,9 @@
package com.android.settings.connecteddevice.usb;
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SINK;
+
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -101,8 +104,8 @@ public class UsbDetailsHeaderControllerTest {
@Test
public void displayRefresh_charging_shouldSetHeader() {
mDetailsHeaderController.displayPreference(mScreen);
- mDetailsHeaderController.refresh(true, UsbManager.FUNCTION_NONE, UsbPort.POWER_ROLE_SINK,
- UsbPort.DATA_ROLE_DEVICE);
+ mDetailsHeaderController.refresh(true, UsbManager.FUNCTION_NONE, POWER_ROLE_SINK,
+ DATA_ROLE_DEVICE);
verify(mHeaderController).setLabel(mContext.getString(R.string.usb_pref));
verify(mHeaderController).setIcon(argThat((ArgumentMatcher) t -> {
DrawableTestHelper.assertDrawableResId(t, R.drawable.ic_usb);
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsPowerRoleControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsPowerRoleControllerTest.java
index b16a4536321..aa62741eae0 100644
--- a/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsPowerRoleControllerTest.java
+++ b/tests/robotests/src/com/android/settings/connecteddevice/usb/UsbDetailsPowerRoleControllerTest.java
@@ -16,6 +16,13 @@
package com.android.settings.connecteddevice.usb;
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE;
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_HOST;
+import static android.hardware.usb.UsbPortStatus.DATA_ROLE_NONE;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_NONE;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SINK;
+import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SOURCE;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyLong;
@@ -25,7 +32,6 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.hardware.usb.UsbManager;
-import android.hardware.usb.UsbPort;
import android.os.Handler;
import androidx.fragment.app.FragmentActivity;
@@ -95,8 +101,8 @@ public class UsbDetailsPowerRoleControllerTest {
mDetailsPowerRoleController.displayPreference(mScreen);
when(mUsbBackend.areAllRolesSupported()).thenReturn(true);
- mDetailsPowerRoleController.refresh(true, UsbManager.FUNCTION_NONE, UsbPort.POWER_ROLE_SINK,
- UsbPort.DATA_ROLE_DEVICE);
+ mDetailsPowerRoleController.refresh(true, UsbManager.FUNCTION_NONE, POWER_ROLE_SINK,
+ DATA_ROLE_DEVICE);
SwitchPreference pref = getPreference();
assertThat(pref.isChecked()).isFalse();
@@ -108,7 +114,7 @@ public class UsbDetailsPowerRoleControllerTest {
when(mUsbBackend.areAllRolesSupported()).thenReturn(true);
mDetailsPowerRoleController.refresh(true, UsbManager.FUNCTION_NONE,
- UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_HOST);
+ POWER_ROLE_SOURCE, DATA_ROLE_HOST);
SwitchPreference pref = getPreference();
assertThat(pref.isChecked()).isTrue();
@@ -120,7 +126,7 @@ public class UsbDetailsPowerRoleControllerTest {
when(mUsbBackend.areAllRolesSupported()).thenReturn(true);
mDetailsPowerRoleController.refresh(false, UsbManager.FUNCTION_NONE,
- UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_DEVICE);
+ POWER_ROLE_SINK, DATA_ROLE_DEVICE);
assertThat(mPreference.isEnabled()).isFalse();
assertThat((Preference) mScreen.findPreference(
@@ -132,8 +138,8 @@ public class UsbDetailsPowerRoleControllerTest {
mDetailsPowerRoleController.displayPreference(mScreen);
when(mUsbBackend.areAllRolesSupported()).thenReturn(false);
- mDetailsPowerRoleController.refresh(true, UsbManager.FUNCTION_NONE, UsbPort.POWER_ROLE_SINK,
- UsbPort.DATA_ROLE_DEVICE);
+ mDetailsPowerRoleController.refresh(true, UsbManager.FUNCTION_NONE, POWER_ROLE_SINK,
+ DATA_ROLE_DEVICE);
assertThat((Preference) mScreen.findPreference(
mDetailsPowerRoleController.getPreferenceKey())).isNull();
@@ -142,12 +148,12 @@ public class UsbDetailsPowerRoleControllerTest {
@Test
public void onClick_sink_shouldSetSource() {
mDetailsPowerRoleController.displayPreference(mScreen);
- when(mUsbBackend.getPowerRole()).thenReturn(UsbPort.POWER_ROLE_SINK);
+ when(mUsbBackend.getPowerRole()).thenReturn(POWER_ROLE_SINK);
SwitchPreference pref = getPreference();
pref.performClick();
- verify(mUsbBackend).setPowerRole(UsbPort.POWER_ROLE_SOURCE);
+ verify(mUsbBackend).setPowerRole(POWER_ROLE_SOURCE);
assertThat(pref.getSummary())
.isEqualTo(mContext.getString(R.string.usb_switching));
}
@@ -155,7 +161,7 @@ public class UsbDetailsPowerRoleControllerTest {
@Test
public void onClickTwice_sink_shouldSetSourceOnce() {
mDetailsPowerRoleController.displayPreference(mScreen);
- when(mUsbBackend.getPowerRole()).thenReturn(UsbPort.POWER_ROLE_SINK);
+ when(mUsbBackend.getPowerRole()).thenReturn(POWER_ROLE_SINK);
SwitchPreference pref = getPreference();
pref.performClick();
@@ -163,42 +169,42 @@ public class UsbDetailsPowerRoleControllerTest {
assertThat(pref.getSummary())
.isEqualTo(mContext.getString(R.string.usb_switching));
pref.performClick();
- verify(mUsbBackend, times(1)).setPowerRole(UsbPort.POWER_ROLE_SOURCE);
+ verify(mUsbBackend, times(1)).setPowerRole(POWER_ROLE_SOURCE);
}
@Test
public void onClickDeviceAndRefresh_success_shouldClearSubtext() {
mDetailsPowerRoleController.displayPreference(mScreen);
- when(mUsbBackend.getPowerRole()).thenReturn(UsbPort.POWER_ROLE_SINK);
+ when(mUsbBackend.getPowerRole()).thenReturn(POWER_ROLE_SINK);
SwitchPreference pref = getPreference();
pref.performClick();
- verify(mUsbBackend).setPowerRole(UsbPort.POWER_ROLE_SOURCE);
+ verify(mUsbBackend).setPowerRole(POWER_ROLE_SOURCE);
assertThat(pref.getSummary())
.isEqualTo(mContext.getString(R.string.usb_switching));
mDetailsPowerRoleController.refresh(false /* connected */, UsbManager.FUNCTION_NONE,
- UsbPort.POWER_ROLE_NONE, UsbPort.DATA_ROLE_NONE);
+ POWER_ROLE_NONE, DATA_ROLE_NONE);
mDetailsPowerRoleController.refresh(true /* connected */, UsbManager.FUNCTION_NONE,
- UsbPort.POWER_ROLE_SOURCE, UsbPort.DATA_ROLE_DEVICE);
+ POWER_ROLE_SOURCE, DATA_ROLE_DEVICE);
assertThat(pref.getSummary()).isEqualTo("");
}
@Test
public void onClickDeviceAndRefresh_failed_shouldShowFailureText() {
mDetailsPowerRoleController.displayPreference(mScreen);
- when(mUsbBackend.getPowerRole()).thenReturn(UsbPort.POWER_ROLE_SINK);
+ when(mUsbBackend.getPowerRole()).thenReturn(POWER_ROLE_SINK);
SwitchPreference pref = getPreference();
pref.performClick();
- verify(mUsbBackend).setPowerRole(UsbPort.POWER_ROLE_SOURCE);
+ verify(mUsbBackend).setPowerRole(POWER_ROLE_SOURCE);
assertThat(pref.getSummary())
.isEqualTo(mContext.getString(R.string.usb_switching));
mDetailsPowerRoleController.refresh(false /* connected */, UsbManager.FUNCTION_NONE,
- UsbPort.POWER_ROLE_NONE, UsbPort.DATA_ROLE_NONE);
+ POWER_ROLE_NONE, DATA_ROLE_NONE);
mDetailsPowerRoleController.refresh(true /* connected */, UsbManager.FUNCTION_NONE,
- UsbPort.POWER_ROLE_SINK, UsbPort.DATA_ROLE_DEVICE);
+ POWER_ROLE_SINK, DATA_ROLE_DEVICE);
assertThat(pref.getSummary())
.isEqualTo(mContext.getString(R.string.usb_switching_failed));
}
@@ -206,18 +212,18 @@ public class UsbDetailsPowerRoleControllerTest {
@Test
public void onClickDevice_timedOut_shouldShowFailureText() {
mDetailsPowerRoleController.displayPreference(mScreen);
- when(mUsbBackend.getPowerRole()).thenReturn(UsbPort.POWER_ROLE_SINK);
+ when(mUsbBackend.getPowerRole()).thenReturn(POWER_ROLE_SINK);
SwitchPreference pref = getPreference();
pref.performClick();
- verify(mUsbBackend).setPowerRole(UsbPort.POWER_ROLE_SOURCE);
+ verify(mUsbBackend).setPowerRole(POWER_ROLE_SOURCE);
ArgumentCaptor captor = ArgumentCaptor.forClass(Runnable.class);
verify(mHandler).postDelayed(captor.capture(), anyLong());
assertThat(pref.getSummary())
.isEqualTo(mContext.getString(R.string.usb_switching));
mDetailsPowerRoleController.refresh(false /* connected */, UsbManager.FUNCTION_NONE,
- UsbPort.POWER_ROLE_NONE, UsbPort.DATA_ROLE_NONE);
+ POWER_ROLE_NONE, DATA_ROLE_NONE);
captor.getValue().run();
assertThat(pref.getSummary())
.isEqualTo(mContext.getString(R.string.usb_switching_failed));
diff --git a/tests/robotests/src/com/android/settings/development/qstile/DevelopmentTilePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/qstile/DevelopmentTilePreferenceControllerTest.java
index 8b006fcdabd..dc466dff80d 100644
--- a/tests/robotests/src/com/android/settings/development/qstile/DevelopmentTilePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/qstile/DevelopmentTilePreferenceControllerTest.java
@@ -19,6 +19,7 @@ package com.android.settings.development.qstile;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -40,7 +41,6 @@ import com.android.internal.statusbar.IStatusBarService;
import com.android.settings.R;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -52,6 +52,8 @@ import org.robolectric.Shadows;
import org.robolectric.shadows.ShadowPackageManager;
import org.robolectric.util.ReflectionHelpers;
+import java.util.Arrays;
+
@RunWith(RobolectricTestRunner.class)
public class DevelopmentTilePreferenceControllerTest {
@@ -83,7 +85,6 @@ public class DevelopmentTilePreferenceControllerTest {
}
@Test
- @Ignore("b/119829673")
public void display_hasTileService_shouldDisplay() {
final Intent tileProbe = new Intent(TileService.ACTION_QS_TILE)
.setPackage(mContext.getPackageName());
@@ -92,11 +93,11 @@ public class DevelopmentTilePreferenceControllerTest {
info.serviceInfo.name = "abc";
info.serviceInfo.icon = R.drawable.ic_settings_24dp;
info.serviceInfo.packageName = mContext.getPackageName();
- mShadowPackageManager.addResolveInfoForIntent(tileProbe, info);
+ mShadowPackageManager.setResolveInfosForIntent(tileProbe, Arrays.asList(info));
mController.displayPreference(mScreen);
- verify(mScreen).addPreference(any(Preference.class));
+ verify(mScreen, atLeastOnce()).addPreference(any(Preference.class));
}
@Test
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java
index 5fb17470c6e..8fae45c584c 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java
@@ -16,22 +16,22 @@
package com.android.settings.deviceinfo;
+import static android.content.Context.CLIPBOARD_SERVICE;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Answers.RETURNS_DEEP_STUBS;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import android.app.Activity;
+import android.content.ClipboardManager;
import android.content.Context;
-import android.os.Build;
import android.os.Process;
import android.os.UserManager;
import android.provider.Settings;
-import android.text.BidiFormatter;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.Preference;
@@ -61,6 +61,8 @@ import org.robolectric.shadows.ShadowUserManager;
@Config(shadows = ShadowUtils.class)
public class BuildNumberPreferenceControllerTest {
+ private static final String KEY_BUILD_NUMBER = "build_number";
+
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Activity mActivity;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
@@ -86,8 +88,8 @@ public class BuildNumberPreferenceControllerTest {
mFactory = FakeFeatureFactory.setupForTest();
mLifecycleOwner = () -> mLifecycle;
mLifecycle = new Lifecycle(mLifecycleOwner);
- mController =
- new BuildNumberPreferenceController(mContext, mActivity, mFragment, mLifecycle);
+ mController = new BuildNumberPreferenceController(mContext, KEY_BUILD_NUMBER);
+ mController.setHost(mFragment);
mPreference = new Preference(mContext);
mPreference.setKey(mController.getPreferenceKey());
@@ -101,15 +103,6 @@ public class BuildNumberPreferenceControllerTest {
ShadowUtils.reset();
}
- @Test
- public void displayPref_shouldAlwaysDisplay() {
- mController.displayPreference(mScreen);
-
- verify((Preference) mScreen.findPreference(mController.getPreferenceKey()))
- .setSummary(BidiFormatter.getInstance().unicodeWrap(Build.DISPLAY));
- verify(mScreen, never()).removePreference(any(Preference.class));
- }
-
@Test
public void handlePrefTreeClick_onlyHandleBuildNumberPref() {
assertThat(mController.handlePreferenceTreeClick(mock(Preference.class))).isFalse();
@@ -198,8 +191,6 @@ public class BuildNumberPreferenceControllerTest {
@Test
public void onActivityResult_confirmPasswordRequestCompleted_enableDevPref() {
mShadowUserManager.setIsAdminUser(true);
- mController =
- new BuildNumberPreferenceController(mContext, mActivity, mFragment, mLifecycle);
final boolean activityResultHandled = mController.onActivityResult(
BuildNumberPreferenceController.REQUEST_CONFIRM_PASSWORD_FOR_DEV_PREF,
@@ -209,4 +200,14 @@ public class BuildNumberPreferenceControllerTest {
assertThat(activityResultHandled).isTrue();
assertThat(DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext)).isTrue();
}
+
+ @Test
+ public void copy_shouldCopyBuildNumberToClipboard() {
+ mController.copy();
+
+ final ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(
+ CLIPBOARD_SERVICE);
+ final CharSequence data = clipboard.getPrimaryClip().getItemAt(0).getText();
+ assertThat(data.toString()).isEqualTo(mController.getSummary());
+ }
}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragmentTest.java b/tests/robotests/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragmentTest.java
index fefad5ec6f5..90dcf718268 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragmentTest.java
@@ -104,12 +104,7 @@ public class MyDeviceInfoFragmentTest {
public void onActivityResult_shouldCallBuildNumberPreferenceController() {
final BuildNumberPreferenceController controller =
mock(BuildNumberPreferenceController.class);
- final Map> preferenceControllers =
- new ArrayMap<>();
- final List controllerList = new ArrayList<>();
- controllerList.add(controller);
- preferenceControllers.put(BuildNumberPreferenceController.class, controllerList);
- ReflectionHelpers.setField(mSettings, "mPreferenceControllers", preferenceControllers);
+ ReflectionHelpers.setField(mSettings, "mBuildNumberPreferenceController", controller);
final int requestCode = 1;
final int resultCode = 2;
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java
index 7c455bbdd7b..a60460b8ce2 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java
@@ -27,6 +27,7 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
@@ -38,7 +39,10 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.AppOpsManager;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
@@ -75,6 +79,8 @@ import java.util.List;
@RunWith(RobolectricTestRunner.class)
public class BatteryUtilsTest {
+ private static final String TAG = "BatteryUtilsTest";
+
// unit that used to converted ms to us
private static final long UNIT = 1000;
private static final long TIME_STATE_TOP = 1500 * UNIT;
@@ -160,6 +166,7 @@ public class BatteryUtilsTest {
private FakeFeatureFactory mFeatureFactory;
private PowerUsageFeatureProvider mProvider;
private List mUsageList;
+ private Context mContext;
@Before
public void setUp() throws PackageManager.NameNotFoundException {
@@ -214,10 +221,10 @@ public class BatteryUtilsTest {
mIdleBatterySipper.drainType = BatterySipper.DrainType.IDLE;
mIdleBatterySipper.totalPowerMah = BATTERY_IDLE_USAGE;
- final Context shadowContext = spy(RuntimeEnvironment.application);
- doReturn(mPackageManager).when(shadowContext).getPackageManager();
- doReturn(mAppOpsManager).when(shadowContext).getSystemService(Context.APP_OPS_SERVICE);
- mBatteryUtils = spy(new BatteryUtils(shadowContext));
+ mContext = spy(RuntimeEnvironment.application);
+ doReturn(mPackageManager).when(mContext).getPackageManager();
+ doReturn(mAppOpsManager).when(mContext).getSystemService(Context.APP_OPS_SERVICE);
+ mBatteryUtils = spy(new BatteryUtils(mContext));
mBatteryUtils.mPowerUsageFeatureProvider = mProvider;
doReturn(0L).when(mBatteryUtils)
.getForegroundServiceTotalTimeUs(any(BatteryStats.Uid.class), anyLong());
@@ -710,4 +717,15 @@ public class BatteryUtilsTest {
verify(mAppOpsManager, never()).setMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID,
PACKAGE_NAME, AppOpsManager.MODE_ALLOWED);
}
+
+ @Test
+ public void getBatteryInfo_providerNull_shouldNotCrash() {
+ when(mProvider.isEnhancedBatteryPredictionEnabled(mContext)).thenReturn(true);
+ when(mProvider.getEnhancedBatteryPrediction(mContext)).thenReturn(null);
+ when(mContext.registerReceiver(nullable(BroadcastReceiver.class),
+ any(IntentFilter.class))).thenReturn(new Intent());
+
+ //Should not crash
+ assertThat(mBatteryUtils.getBatteryInfo(mBatteryStatsHelper, TAG)).isNotNull();
+ }
}
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImplTest.java
index f1bb3ed4d49..2db7f3fcb21 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardFeatureProviderImplTest.java
@@ -49,13 +49,13 @@ public class ContextualCardFeatureProviderImplTest {
@Before
public void setUp() {
mContext = spy(RuntimeEnvironment.application);
- mImpl = new ContextualCardFeatureProviderImpl();
+ mImpl = new ContextualCardFeatureProviderImpl(mContext);
}
@Test
public void sendBroadcast_emptyAction_notSendBroadcast() {
final Intent intent = new Intent();
- mImpl.sendBroadcast(mContext, intent);
+ mImpl.sendBroadcast(intent);
verify(mContext, never()).sendBroadcastAsUser(intent, UserHandle.ALL);
}
@@ -64,7 +64,7 @@ public class ContextualCardFeatureProviderImplTest {
@Config(qualifiers = "mcc999")
public void sendBroadcast_hasAction_sendBroadcast() {
final Intent intent = new Intent();
- mImpl.sendBroadcast(mContext, intent);
+ mImpl.sendBroadcast(intent);
verify(mContext).sendBroadcastAsUser(intent, UserHandle.ALL);
}
@@ -72,7 +72,7 @@ public class ContextualCardFeatureProviderImplTest {
@Test
@Config(qualifiers = "mcc999")
public void logContextualCardDisplay_hasAction_sendBroadcast() {
- mImpl.logContextualCardDisplay(mContext, new ArrayList<>(), new ArrayList<>());
+ mImpl.logContextualCardDisplay(new ArrayList<>(), new ArrayList<>());
verify(mContext).sendBroadcastAsUser(any(Intent.class), any());
}
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
index 101ca75ec2d..c62a6bbbfdb 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/ContextualCardLoaderTest.java
@@ -145,7 +145,7 @@ public class ContextualCardLoaderTest {
cards.add(new ContextualCard.Builder()
.setName("test_wifi")
.setCardType(ContextualCard.CardType.SLICE)
- .setSliceUri(CustomSliceRegistry.WIFI_SLICE_URI)
+ .setSliceUri(CustomSliceRegistry.CONTEXTUAL_WIFI_SLICE_URI)
.build());
cards.add(new ContextualCard.Builder()
.setName("test_flashlight")
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java
index 8f36ea59652..d4b67f51ef1 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/SettingsContextualCardProviderTest.java
@@ -70,11 +70,12 @@ public class SettingsContextualCardProviderTest {
}
@Test
- public void getContextualCards_wifiSlice_shouldGetCorrectCategory() {
+ public void getContextualCards_wifiSlice_shouldGetImportantCategory() {
final ContextualCardList cards = mProvider.getContextualCards();
ContextualCard wifiCard = null;
for (ContextualCard card : cards.getCardList()) {
- if (card.getSliceUri().equals(CustomSliceRegistry.WIFI_SLICE_URI.toString())) {
+ if (card.getSliceUri().equals(
+ CustomSliceRegistry.CONTEXTUAL_WIFI_SLICE_URI.toString())) {
wifiCard = card;
}
}
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSliceTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSliceTest.java
index 51e8cc852ce..12ae7077c60 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSliceTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/BluetoothDevicesSliceTest.java
@@ -16,11 +16,15 @@
package com.android.settings.homepage.contextualcards.slices;
+import static android.app.slice.Slice.HINT_LIST_ITEM;
+import static android.app.slice.SliceItem.FORMAT_SLICE;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.PendingIntent;
@@ -33,6 +37,7 @@ import androidx.slice.Slice;
import androidx.slice.SliceItem;
import androidx.slice.SliceMetadata;
import androidx.slice.SliceProvider;
+import androidx.slice.core.SliceQuery;
import androidx.slice.widget.SliceLiveData;
import com.android.settings.R;
@@ -54,6 +59,7 @@ import java.util.List;
@RunWith(RobolectricTestRunner.class)
public class BluetoothDevicesSliceTest {
+ private static final String BLUETOOTH_MOCK_ADDRESS = "00:11:00:11:00:11";
private static final String BLUETOOTH_MOCK_SUMMARY = "BluetoothSummary";
private static final String BLUETOOTH_MOCK_TITLE = "BluetoothTitle";
@@ -95,8 +101,8 @@ public class BluetoothDevicesSliceTest {
@Test
public void getSlice_hasBluetoothDevices_shouldHaveBluetoothDevicesTitle() {
- mockBluetoothDeviceList();
- doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getBluetoothDevices();
+ mockBluetoothDeviceList(1);
+ doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getConnectedBluetoothDevices();
final Slice slice = mBluetoothDevicesSlice.getSlice();
@@ -106,8 +112,8 @@ public class BluetoothDevicesSliceTest {
@Test
public void getSlice_hasBluetoothDevices_shouldMatchBluetoothMockTitle() {
- mockBluetoothDeviceList();
- doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getBluetoothDevices();
+ mockBluetoothDeviceList(1);
+ doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getConnectedBluetoothDevices();
final Slice slice = mBluetoothDevicesSlice.getSlice();
@@ -117,8 +123,8 @@ public class BluetoothDevicesSliceTest {
@Test
public void getSlice_hasBluetoothDevices_shouldHavePairNewDevice() {
- mockBluetoothDeviceList();
- doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getBluetoothDevices();
+ mockBluetoothDeviceList(1);
+ doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getConnectedBluetoothDevices();
final Slice slice = mBluetoothDevicesSlice.getSlice();
@@ -129,7 +135,7 @@ public class BluetoothDevicesSliceTest {
@Test
public void getSlice_noBluetoothDevices_shouldHaveNoBluetoothDevicesTitle() {
- doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getBluetoothDevices();
+ doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getConnectedBluetoothDevices();
final Slice slice = mBluetoothDevicesSlice.getSlice();
@@ -139,7 +145,7 @@ public class BluetoothDevicesSliceTest {
@Test
public void getSlice_noBluetoothDevices_shouldNotHavePairNewDevice() {
- doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getBluetoothDevices();
+ doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getConnectedBluetoothDevices();
final Slice slice = mBluetoothDevicesSlice.getSlice();
@@ -148,10 +154,53 @@ public class BluetoothDevicesSliceTest {
mContext.getString(R.string.bluetooth_pairing_pref_title))).isFalse();
}
- private void mockBluetoothDeviceList() {
+ @Test
+ public void getSlice_exceedDefaultRowCount_shouldOnlyShowDefaultRows() {
+ mockBluetoothDeviceList(BluetoothDevicesSlice.DEFAULT_EXPANDED_ROW_COUNT + 1);
+ doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getConnectedBluetoothDevices();
+
+ final Slice slice = mBluetoothDevicesSlice.getSlice();
+
+ // Get the number of RowBuilders from Slice.
+ final int rows = SliceQuery.findAll(slice, FORMAT_SLICE, HINT_LIST_ITEM, null).size();
+ assertThat(rows).isEqualTo(BluetoothDevicesSlice.DEFAULT_EXPANDED_ROW_COUNT);
+ }
+
+ @Test
+ public void getSlice_exceedDefaultRowCount_shouldContainDefaultCountInSubTitle() {
+ mockBluetoothDeviceList(BluetoothDevicesSlice.DEFAULT_EXPANDED_ROW_COUNT + 1);
+ doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getConnectedBluetoothDevices();
+
+ final Slice slice = mBluetoothDevicesSlice.getSlice();
+
+ final SliceMetadata metadata = SliceMetadata.from(mContext, slice);
+ assertThat(metadata.getSubtitle()).isEqualTo(
+ mContext.getResources().getQuantityString(R.plurals.show_bluetooth_devices,
+ BluetoothDevicesSlice.DEFAULT_EXPANDED_ROW_COUNT,
+ BluetoothDevicesSlice.DEFAULT_EXPANDED_ROW_COUNT));
+ }
+
+ @Test
+ public void onNotifyChange_mediaDevice_shouldActivateDevice() {
+ mockBluetoothDeviceList(1);
+ doReturn(mBluetoothDeviceList).when(mBluetoothDevicesSlice).getConnectedBluetoothDevices();
+ final Intent intent = new Intent().putExtra(
+ BluetoothDevicesSlice.BLUETOOTH_DEVICE_HASH_CODE,
+ mCachedBluetoothDevice.hashCode());
+
+ mBluetoothDevicesSlice.onNotifyChange(intent);
+
+ verify(mCachedBluetoothDevice).setActive();
+ }
+
+ private void mockBluetoothDeviceList(int deviceCount) {
doReturn(BLUETOOTH_MOCK_TITLE).when(mCachedBluetoothDevice).getName();
doReturn(BLUETOOTH_MOCK_SUMMARY).when(mCachedBluetoothDevice).getConnectionSummary();
- mBluetoothDeviceList.add(mCachedBluetoothDevice);
+ doReturn(BLUETOOTH_MOCK_ADDRESS).when(mCachedBluetoothDevice).getAddress();
+ doReturn(true).when(mCachedBluetoothDevice).isConnectedA2dpDevice();
+ for (int i = 0; i < deviceCount; i++) {
+ mBluetoothDeviceList.add(mCachedBluetoothDevice);
+ }
}
private boolean hasTitle(SliceMetadata metadata, String title) {
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardControllerTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardControllerTest.java
index 5bc36985d4b..7e1a32c81f4 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardControllerTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardControllerTest.java
@@ -91,8 +91,7 @@ public class SliceContextualCardControllerTest {
cr.close();
assertThat(qryDismissed).isEqualTo(1);
- verify(mFeatureFactory.mContextualCardFeatureProvider).logContextualCardDismiss(
- mContext, card);
+ verify(mFeatureFactory.mContextualCardFeatureProvider).logContextualCardDismiss(card);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java
index 3407ee3679d..0b87525b6bd 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java
@@ -128,7 +128,7 @@ public class SliceContextualCardRendererTest {
public void longClick_shouldFlipCard() {
final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
final View card = viewHolder.itemView.findViewById(R.id.slice_view);
- final ViewFlipper viewFlipper = viewHolder.itemView.findViewById(R.id.viewFlipper);
+ final ViewFlipper viewFlipper = viewHolder.itemView.findViewById(R.id.view_flipper);
final View dismissalView = viewHolder.itemView.findViewById(R.id.dismissal_view);
mRenderer.bindView(viewHolder, buildContextualCard(TEST_SLICE_URI));
@@ -153,7 +153,7 @@ public class SliceContextualCardRendererTest {
final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
final View card = viewHolder.itemView.findViewById(R.id.slice_view);
final Button btnKeep = viewHolder.itemView.findViewById(R.id.keep);
- final ViewFlipper viewFlipper = viewHolder.itemView.findViewById(R.id.viewFlipper);
+ final ViewFlipper viewFlipper = viewHolder.itemView.findViewById(R.id.view_flipper);
mRenderer.bindView(viewHolder, buildContextualCard(TEST_SLICE_URI));
card.performLongClick();
@@ -212,7 +212,7 @@ public class SliceContextualCardRendererTest {
public void onStop_cardIsFlipped_shouldFlipBack() {
final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
final View card = viewHolder.itemView.findViewById(R.id.slice_view);
- final ViewFlipper viewFlipper = viewHolder.itemView.findViewById(R.id.viewFlipper);
+ final ViewFlipper viewFlipper = viewHolder.itemView.findViewById(R.id.view_flipper);
mRenderer.bindView(viewHolder, buildContextualCard(TEST_SLICE_URI));
card.performLongClick();
diff --git a/tests/robotests/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java
index 016a885d517..70536997493 100644
--- a/tests/robotests/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/SubscriptionsPreferenceControllerTest.java
@@ -16,33 +16,40 @@
package com.android.settings.network;
+import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.Activity;
import android.content.Context;
+import android.content.Intent;
import android.provider.Settings;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import com.android.settingslib.core.lifecycle.Lifecycle;
+import org.junit.After;
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.Robolectric;
import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.Preference;
@@ -70,7 +77,7 @@ public class SubscriptionsPreferenceControllerTest {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mContext = spy(RuntimeEnvironment.application);
+ mContext = spy(Robolectric.setupActivity(Activity.class));
mLifecycleOwner = () -> mLifecycle;
mLifecycle = new Lifecycle(mLifecycleOwner);
when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
@@ -83,6 +90,11 @@ public class SubscriptionsPreferenceControllerTest {
KEY, 5);
}
+ @After
+ public void tearDown() {
+ SubscriptionUtil.setAvailableSubscriptionsForTesting(null);
+ }
+
@Test
public void isAvailable_oneSubscription_availableFalse() {
SubscriptionUtil.setAvailableSubscriptionsForTesting(
@@ -215,4 +227,57 @@ public class SubscriptionsPreferenceControllerTest {
verify(mPreferenceCategory, times(3)).addPreference(captor.capture());
assertThat(captor.getValue().getTitle()).isEqualTo("sub3");
}
+
+
+ /**
+ * Helper to create a specified number of subscriptions, display them, and then click on one and
+ * verify that the intent fires and has the right subscription id extra.
+ *
+ * @param subscriptionCount the number of subscriptions
+ * @param selectedPrefIndex index of the subscription to click on
+ */
+ private void runPreferenceClickTest(int subscriptionCount, int selectedPrefIndex) {
+ final ArrayList subscriptions = new ArrayList<>();
+ for (int i = 0; i < subscriptionCount; i++) {
+ final SubscriptionInfo sub = mock(SubscriptionInfo.class);
+ doReturn(i + 1).when(sub).getSubscriptionId();
+ subscriptions.add(sub);
+ }
+ SubscriptionUtil.setAvailableSubscriptionsForTesting(subscriptions);
+ mController.displayPreference(mScreen);
+ final ArgumentCaptor prefCaptor = ArgumentCaptor.forClass(Preference.class);
+ verify(mPreferenceCategory, times(subscriptionCount)).addPreference(prefCaptor.capture());
+ final List prefs = prefCaptor.getAllValues();
+ final Preference pref = prefs.get(selectedPrefIndex);
+ pref.getOnPreferenceClickListener().onPreferenceClick(pref);
+ final ArgumentCaptor intentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(mContext).startActivity(intentCaptor.capture());
+ final Intent intent = intentCaptor.getValue();
+ assertThat(intent).isNotNull();
+ assertThat(intent.hasExtra(Settings.EXTRA_SUB_ID)).isTrue();
+ final int subIdFromIntent = intent.getIntExtra(Settings.EXTRA_SUB_ID,
+ INVALID_SUBSCRIPTION_ID);
+ assertThat(subIdFromIntent).isEqualTo(
+ subscriptions.get(selectedPrefIndex).getSubscriptionId());
+ }
+
+ @Test
+ public void twoPreferences_firstPreferenceClicked_correctIntentFires() {
+ runPreferenceClickTest(2, 0);
+ }
+
+ @Test
+ public void twoPreferences_secondPreferenceClicked_correctIntentFires() {
+ runPreferenceClickTest(2, 1);
+ }
+
+ @Test
+ public void threePreferences_secondPreferenceClicked_correctIntentFires() {
+ runPreferenceClickTest(3, 1);
+ }
+
+ @Test
+ public void threePreferences_thirdPreferenceClicked_correctIntentFires() {
+ runPreferenceClickTest(3, 2);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/network/VpnPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/VpnPreferenceControllerTest.java
index 5144877cb24..89d0465fab2 100644
--- a/tests/robotests/src/com/android/settings/network/VpnPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/VpnPreferenceControllerTest.java
@@ -34,6 +34,7 @@ import android.net.IConnectivityManager;
import android.net.NetworkRequest;
import android.os.IBinder;
import android.os.UserHandle;
+import android.os.ServiceManager;
import android.provider.SettingsSlicesContract;
import androidx.lifecycle.LifecycleOwner;
@@ -50,7 +51,6 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-import org.robolectric.shadows.ShadowServiceManager;
@RunWith(RobolectricTestRunner.class)
public class VpnPreferenceControllerTest {
@@ -78,7 +78,7 @@ public class VpnPreferenceControllerTest {
.thenReturn(mConnectivityManager);
when(mBinder.queryLocalInterface("android.net.IConnectivityManager"))
.thenReturn(mConnectivityManagerService);
- ShadowServiceManager.addService(Context.CONNECTIVITY_SERVICE, mBinder);
+ ServiceManager.addService(Context.CONNECTIVITY_SERVICE, mBinder);
when(mScreen.findPreference(anyString())).thenReturn(mPreference);
mController = spy(new VpnPreferenceController(mContext));
diff --git a/tests/robotests/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceControllerTest.java
index 9b8a3e379f5..ba8be908c79 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceControllerTest.java
@@ -124,6 +124,18 @@ public class EnabledNetworkModePreferenceControllerTest {
assertThat(mPreference.getSummary()).isEqualTo("3G");
}
+ @Test
+ public void updateState_updateByNetworkMode_useDefaultValue() {
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.PREFERRED_NETWORK_MODE + SUB_ID,
+ TelephonyManager.NETWORK_MODE_LTE_GSM_WCDMA);
+
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.getValue()).isEqualTo(
+ String.valueOf(TelephonyManager.NETWORK_MODE_LTE_GSM_WCDMA));
+ }
+
@Test
public void onPreferenceChange_updateSuccess() {
doReturn(true).when(mTelephonyManager).setPreferredNetworkType(SUB_ID,
diff --git a/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkActivityTest.java b/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkActivityTest.java
index f13746c13f2..29472f54b85 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkActivityTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkActivityTest.java
@@ -143,6 +143,9 @@ public class MobileNetworkActivityTest {
final Intent intent = new Intent();
intent.putExtra(Settings.EXTRA_SUB_ID, CURRENT_SUB_ID);
doReturn(intent).when(mMobileNetworkActivity).getIntent();
+ mSubscriptionInfos.add(mSubscriptionInfo);
+ mSubscriptionInfos.add(mSubscriptionInfo2);
+ doReturn(mSubscriptionInfos).when(mSubscriptionManager).getAvailableSubscriptionInfoList();
doReturn(true).when(mSubscriptionManager).isActiveSubscriptionId(CURRENT_SUB_ID);
assertThat(mMobileNetworkActivity.getSubscriptionId()).isEqualTo(CURRENT_SUB_ID);
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeBackendTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeBackendTest.java
index 6169f92ddc9..6cf19a629a5 100644
--- a/tests/robotests/src/com/android/settings/notification/ZenModeBackendTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ZenModeBackendTest.java
@@ -1,26 +1,58 @@
package com.android.settings.notification;
+import static com.google.common.truth.Truth.assertThat;
+
import static junit.framework.Assert.assertEquals;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
import android.app.AutomaticZenRule;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.database.Cursor;
import android.provider.Settings;
import android.service.notification.ZenModeConfig;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadows.ShadowApplication;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
-import org.robolectric.RobolectricTestRunner;
@RunWith(RobolectricTestRunner.class)
public class ZenModeBackendTest {
+ @Mock
+ private NotificationManager mNotificationManager;
private static final String GENERIC_RULE_NAME = "test";
private static final String DEFAULT_ID_1 = ZenModeConfig.EVENTS_DEFAULT_RULE_ID;
private static final String DEFAULT_ID_2 = ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID;
+ private Context mContext;
+ private ZenModeBackend mBackend;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ ShadowApplication shadowApplication = ShadowApplication.getInstance();
+ shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
+
+ mContext = RuntimeEnvironment.application;
+ mBackend = new ZenModeBackend(mContext);
+ }
+
@Test
public void updateState_checkRuleOrderingDescending() {
final int NUM_RULES = 4;
@@ -63,6 +95,39 @@ public class ZenModeBackendTest {
}
}
+ @Test
+ public void updateSummary_nullCursorValues() {
+ Cursor testCursorWithNullValues = createMockCursor(3);
+ when(testCursorWithNullValues.getString(0)).thenReturn(null);
+
+ // expected - no null values
+ List contacts = mBackend.getStarredContacts(testCursorWithNullValues);
+ for (String contact : contacts) {
+ assertThat(contact).isNotNull();
+ }
+ }
+
+ private Cursor createMockCursor(int size) {
+ Cursor mockCursor = mock(Cursor.class);
+ when(mockCursor.moveToFirst()).thenReturn(true);
+
+ doAnswer(new Answer() {
+ int count = 0;
+
+ @Override
+ public Boolean answer(InvocationOnMock invocation) throws Throwable {
+ if (count < size) {
+ count++;
+ return true;
+ }
+ return false;
+ }
+
+ }).when(mockCursor).moveToNext();
+
+ return mockCursor;
+ }
+
private Map.Entry[] populateAutoZenRulesAscendingCreationTime(
int numRules, boolean addDefaultRules) {
Map ruleMap = new HashMap<>();
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeMessagesPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeMessagesPreferenceControllerTest.java
index 5589caefa0f..808766da22e 100644
--- a/tests/robotests/src/com/android/settings/notification/ZenModeMessagesPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ZenModeMessagesPreferenceControllerTest.java
@@ -17,12 +17,16 @@
package com.android.settings.notification;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.NotificationManager;
import android.content.Context;
+import androidx.preference.Preference;
+
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
@@ -67,11 +71,10 @@ public final class ZenModeMessagesPreferenceControllerTest {
assertTrue(mController.isAvailable());
}
-// TODO: (b/111475013 - beverlyt) set messages summary
-// @Test
-// public void testHasSummary() {
-// Preference pref = mock(Preference.class);
-// mController.updateState(pref);
-// verify(pref).setSummary(any());
-// }
+ @Test
+ public void testHasSummary() {
+ Preference pref = mock(Preference.class);
+ mController.updateState(pref);
+ verify(pref).setSummary(any());
+ }
}
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceControllerTest.java
index 516d98f1f0a..345186852c2 100644
--- a/tests/robotests/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ZenModeSettingsFooterPreferenceControllerTest.java
@@ -22,9 +22,8 @@ import static android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
import static android.provider.Settings.Global.ZEN_MODE_NO_INTERRUPTIONS;
import static android.provider.Settings.Global.ZEN_MODE_OFF;
-import static org.junit.Assert.assertTrue;
-
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -40,6 +39,7 @@ import android.service.notification.ZenModeConfig;
import android.service.notification.ZenModeConfig.ZenRule;
import android.util.ArrayMap;
+import androidx.fragment.app.FragmentManager;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
@@ -92,8 +92,8 @@ public class ZenModeSettingsFooterPreferenceControllerTest {
mContentResolver = RuntimeEnvironment.application.getContentResolver();
when(mNotificationManager.getZenModeConfig()).thenReturn(mZenModeConfig);
- mController =
- new ZenModeSettingsFooterPreferenceController(mContext, mock(Lifecycle.class));
+ mController = new ZenModeSettingsFooterPreferenceController(mContext, mock(Lifecycle.class),
+ mock(FragmentManager.class));
ReflectionHelpers.setField(mZenModeConfig, AUTOMATIC_RULES_FIELD, mInjectedAutomaticRules);
ReflectionHelpers.setField(mController, "mZenModeConfigWrapper", mConfigWrapper);
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeStarredContactsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeStarredContactsPreferenceControllerTest.java
index db551a2f8ff..fd6e63943ca 100644
--- a/tests/robotests/src/com/android/settings/notification/ZenModeStarredContactsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ZenModeStarredContactsPreferenceControllerTest.java
@@ -30,7 +30,6 @@ import android.app.NotificationManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.database.Cursor;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
@@ -49,7 +48,6 @@ import org.robolectric.RuntimeEnvironment;
import org.robolectric.shadows.ShadowApplication;
import org.robolectric.util.ReflectionHelpers;
-import java.util.List;
@RunWith(RobolectricTestRunner.class)
public class ZenModeStarredContactsPreferenceControllerTest {
@@ -156,18 +154,6 @@ public class ZenModeStarredContactsPreferenceControllerTest {
assertThat(mMessagesController.isAvailable()).isTrue();
}
- @Test
- public void updateSummary_nullCursorValues() {
- Cursor testCursorWithNullValues = createMockCursor(3);
- when(testCursorWithNullValues.getString(0)).thenReturn(null);
-
- // expected - no null values
- List contacts = mMessagesController.getStarredContacts(testCursorWithNullValues);
- for (String contact : contacts) {
- assertThat(contact).isNotNull();
- }
- }
-
@Test
public void nullPreference_displayPreference() {
when(mPreferenceScreen.findPreference(mMessagesController.getPreferenceKey()))
@@ -176,25 +162,4 @@ public class ZenModeStarredContactsPreferenceControllerTest {
// should not throw a null pointer
mMessagesController.displayPreference(mPreferenceScreen);
}
-
- private Cursor createMockCursor(int size) {
- Cursor mockCursor = mock(Cursor.class);
- when(mockCursor.moveToFirst()).thenReturn(true);
-
- doAnswer(new Answer() {
- int count = 0;
-
- @Override
- public Boolean answer(InvocationOnMock invocation) {
- if (count < size) {
- count++;
- return true;
- }
- return false;
- }
-
- }).when(mockCursor).moveToNext();
-
- return mockCursor;
- }
}
diff --git a/tests/robotests/src/com/android/settings/notification/ZenRuleCustomPolicyPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenRuleCustomPolicyPreferenceControllerTest.java
new file mode 100644
index 00000000000..5d3a6017c9e
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/ZenRuleCustomPolicyPreferenceControllerTest.java
@@ -0,0 +1,90 @@
+/*
+ * 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 static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.NotificationManager;
+import android.content.Context;
+import android.service.notification.ZenPolicy;
+
+import androidx.preference.PreferenceScreen;
+
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+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;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(RobolectricTestRunner.class)
+public class ZenRuleCustomPolicyPreferenceControllerTest extends
+ ZenRuleCustomPrefContrTestBase {
+
+ @Mock
+ private ZenModeBackend mBackend;
+ @Mock
+ private NotificationManager mNotificationManager;
+ @Mock
+ private ZenCustomRadioButtonPreference mockPref;
+ @Mock
+ private PreferenceScreen mScreen;
+
+ private Context mContext;
+ private ZenRuleCustomPolicyPreferenceController mController;
+
+ @Override
+ AbstractZenCustomRulePreferenceController getController() {
+ return mController;
+ }
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ ShadowApplication shadowApplication = ShadowApplication.getInstance();
+ shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
+
+ mContext = RuntimeEnvironment.application;
+ mController = new ZenRuleCustomPolicyPreferenceController(mContext, mock(Lifecycle.class),
+ PREF_KEY);
+ ReflectionHelpers.setField(mController, "mBackend", mBackend);
+ when(mBackend.getAutomaticZenRule(RULE_ID)).thenReturn(mRule);
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mockPref);
+ mController.displayPreference(mScreen);
+ }
+
+ @Test
+ public void updateState_nullZenPolicy() {
+ updateControllerZenPolicy(null);
+ mController.updateState(mockPref);
+ verify(mockPref).setChecked(false);
+ }
+
+ @Test
+ public void updateState_hasZenPolicy() {
+ updateControllerZenPolicy(new ZenPolicy.Builder().build());
+ mController.updateState(mockPref);
+ verify(mockPref).setChecked(true);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/ZenRuleCustomPrefContrTestBase.java b/tests/robotests/src/com/android/settings/notification/ZenRuleCustomPrefContrTestBase.java
new file mode 100644
index 00000000000..10472a5b695
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/ZenRuleCustomPrefContrTestBase.java
@@ -0,0 +1,40 @@
+/*
+ * 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.app.NotificationManager;
+import android.service.notification.ZenPolicy;
+
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+abstract class ZenRuleCustomPrefContrTestBase {
+ public static final String RULE_ID = "test_rule_id";
+ public static final String PREF_KEY = "main_pref";
+
+ AutomaticZenRule mRule = new AutomaticZenRule("test", null, null, null, null,
+ NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+
+ abstract AbstractZenCustomRulePreferenceController getController();
+
+ void updateControllerZenPolicy(ZenPolicy policy) {
+ mRule.setZenPolicy(policy);
+ getController().onResume(mRule, RULE_ID);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/ZenRuleCustomSwitchPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenRuleCustomSwitchPreferenceControllerTest.java
new file mode 100644
index 00000000000..e15eb605936
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/ZenRuleCustomSwitchPreferenceControllerTest.java
@@ -0,0 +1,108 @@
+/*
+ * 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 static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.NotificationManager;
+import android.content.Context;
+import android.service.notification.ZenPolicy;
+
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+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;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(RobolectricTestRunner.class)
+public class ZenRuleCustomSwitchPreferenceControllerTest extends ZenRuleCustomPrefContrTestBase {
+ private ZenRuleCustomSwitchPreferenceController mController;
+
+ @Mock
+ private ZenModeBackend mBackend;
+ @Mock
+ private NotificationManager mNotificationManager;
+ @Mock
+ private SwitchPreference mockPref;
+ @Mock
+ private NotificationManager.Policy mPolicy;
+ @Mock
+ private PreferenceScreen mPreferenceScreen;
+
+ private Context mContext;
+
+ @Override
+ AbstractZenCustomRulePreferenceController getController() {
+ return mController;
+ }
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ ShadowApplication shadowApplication = ShadowApplication.getInstance();
+ shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
+
+ mContext = RuntimeEnvironment.application;
+ when(mNotificationManager.getNotificationPolicy()).thenReturn(mPolicy);
+ mController = new ZenRuleCustomSwitchPreferenceController(mContext, mock(Lifecycle.class),
+ PREF_KEY, ZenPolicy.PRIORITY_CATEGORY_ALARMS, 0);
+ ReflectionHelpers.setField(mController, "mBackend", mBackend);
+
+ when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
+ .thenReturn(mockPref);
+ mController.displayPreference(mPreferenceScreen);
+ }
+
+ @Test
+ public void onPreferenceChanged_enable() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .allowMedia(false)
+ .allowAlarms(false)
+ .build());
+ mController.onPreferenceChange(mockPref, true);
+ mRule.setZenPolicy(new ZenPolicy.Builder()
+ .allowMedia(false)
+ .allowAlarms(true)
+ .build());
+ verify(mBackend).updateZenRule(RULE_ID, mRule);
+ }
+
+ @Test
+ public void onPreferenceChanged_disable() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .allowMedia(false)
+ .allowAlarms(true)
+ .build());
+ mController.onPreferenceChange(mockPref, false);
+ mRule.setZenPolicy(new ZenPolicy.Builder()
+ .allowMedia(false)
+ .allowAlarms(false)
+ .build());
+ verify(mBackend).updateZenRule(RULE_ID, mRule);
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/notification/ZenRuleDefaultPolicyPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenRuleDefaultPolicyPreferenceControllerTest.java
new file mode 100644
index 00000000000..e350793b0e3
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/ZenRuleDefaultPolicyPreferenceControllerTest.java
@@ -0,0 +1,90 @@
+/*
+ * 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 static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.NotificationManager;
+import android.content.Context;
+import android.service.notification.ZenPolicy;
+
+import androidx.preference.PreferenceScreen;
+
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+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;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(RobolectricTestRunner.class)
+public class ZenRuleDefaultPolicyPreferenceControllerTest extends
+ ZenRuleCustomPrefContrTestBase {
+
+ @Mock
+ private ZenModeBackend mBackend;
+ @Mock
+ private NotificationManager mNotificationManager;
+ @Mock
+ private ZenCustomRadioButtonPreference mockPref;
+ @Mock
+ private PreferenceScreen mScreen;
+
+ private Context mContext;
+ private ZenRuleDefaultPolicyPreferenceController mController;
+
+ @Override
+ AbstractZenCustomRulePreferenceController getController() {
+ return mController;
+ }
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ ShadowApplication shadowApplication = ShadowApplication.getInstance();
+ shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
+
+ mContext = RuntimeEnvironment.application;
+ mController = new ZenRuleDefaultPolicyPreferenceController(mContext, mock(Lifecycle.class),
+ PREF_KEY);
+ ReflectionHelpers.setField(mController, "mBackend", mBackend);
+ when(mBackend.getAutomaticZenRule(RULE_ID)).thenReturn(mRule);
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mockPref);
+ mController.displayPreference(mScreen);
+ }
+
+ @Test
+ public void updateState_nullZenPolicy() {
+ updateControllerZenPolicy(null);
+ mController.updateState(mockPref);
+ verify(mockPref).setChecked(true);
+ }
+
+ @Test
+ public void updateState_hasZenPolicy() {
+ updateControllerZenPolicy(new ZenPolicy.Builder().build());
+ mController.updateState(mockPref);
+ verify(mockPref).setChecked(false);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/ZenRulePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenRulePreferenceControllerTest.java
new file mode 100644
index 00000000000..5d070e56699
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/ZenRulePreferenceControllerTest.java
@@ -0,0 +1,92 @@
+/*
+ * 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 static junit.framework.Assert.assertEquals;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.app.AutomaticZenRule;
+import android.app.NotificationManager;
+import android.content.Context;
+
+import androidx.preference.PreferenceScreen;
+
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+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;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(RobolectricTestRunner.class)
+public class ZenRulePreferenceControllerTest {
+
+ @Mock
+ private ZenModeBackend mBackend;
+ @Mock
+ private NotificationManager mNotificationManager;
+ @Mock
+ private ZenCustomRadioButtonPreference mockPref;
+ @Mock
+ private PreferenceScreen mScreen;
+
+ private Context mContext;
+ private TestablePreferenceController mController;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ ShadowApplication shadowApplication = ShadowApplication.getInstance();
+ shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
+
+ mContext = RuntimeEnvironment.application;
+ mController = new TestablePreferenceController(mContext,"test", mock(Lifecycle.class));
+ ReflectionHelpers.setField(mController, "mBackend", mBackend);
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mockPref);
+ mController.displayPreference(mScreen);
+ }
+
+ @Test
+ public void onResumeTest() {
+ final String id = "testid";
+ final AutomaticZenRule rule = new AutomaticZenRule("test", null, null,
+ null, null, NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+
+ assertTrue(mController.mRule == null);
+ assertTrue(mController.mId == null);
+
+ mController.onResume(rule, id);
+
+ assertEquals(mController.mId, id);
+ assertEquals(mController.mRule, rule);
+ }
+
+ class TestablePreferenceController extends AbstractZenCustomRulePreferenceController {
+ TestablePreferenceController(Context context, String key,
+ Lifecycle lifecycle) {
+ super(context, key, lifecycle);
+ }
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/ZenRuleRepeatCallersPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenRuleRepeatCallersPreferenceControllerTest.java
new file mode 100644
index 00000000000..45062d4f456
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/ZenRuleRepeatCallersPreferenceControllerTest.java
@@ -0,0 +1,123 @@
+/*
+ * 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 static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.NotificationManager;
+import android.content.Context;
+import android.service.notification.ZenPolicy;
+
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+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;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(RobolectricTestRunner.class)
+public class ZenRuleRepeatCallersPreferenceControllerTest extends ZenRuleCustomPrefContrTestBase {
+
+ private ZenRuleRepeatCallersPreferenceController mController;
+
+ @Mock
+ private ZenModeBackend mBackend;
+ @Mock
+ private NotificationManager mNotificationManager;
+ @Mock
+ private SwitchPreference mockPref;
+ @Mock
+ private NotificationManager.Policy mPolicy;
+ @Mock
+ private PreferenceScreen mPreferenceScreen;
+ private Context mContext;
+
+ @Override
+ AbstractZenCustomRulePreferenceController getController() {
+ return mController;
+ }
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ ShadowApplication shadowApplication = ShadowApplication.getInstance();
+ shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
+
+ mContext = RuntimeEnvironment.application;
+ when(mNotificationManager.getNotificationPolicy()).thenReturn(mPolicy);
+ mController = new ZenRuleRepeatCallersPreferenceController(mContext, PREF_KEY,
+ mock(Lifecycle.class), 15);
+ ReflectionHelpers.setField(mController, "mBackend", mBackend);
+ when(mBackend.getAutomaticZenRule(anyString())).thenReturn(mRule);
+ when(mPreferenceScreen.findPreference(mController.getPreferenceKey())).thenReturn(
+ mockPref);
+ mController.displayPreference(mPreferenceScreen);
+ }
+
+ @Test
+ public void updateState_Priority_anyCallers() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .allowCalls(ZenPolicy.PEOPLE_TYPE_ANYONE)
+ .allowRepeatCallers(false)
+ .build());
+ mController.updateState(mockPref);
+
+ verify(mockPref).setEnabled(false);
+ verify(mockPref).setChecked(true);
+ }
+
+ @Test
+ public void onPreferenceChanged_EnableRepeatCallers() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .allowCalls(ZenPolicy.PEOPLE_TYPE_CONTACTS)
+ .allowRepeatCallers(false)
+ .build());
+ mController.updateState(mockPref);
+ mController.onPreferenceChange(mockPref, true);
+ mRule.setZenPolicy(new ZenPolicy.Builder()
+ .allowCalls(ZenPolicy.PEOPLE_TYPE_CONTACTS)
+ .allowRepeatCallers(true)
+ .build());
+ verify(mBackend).updateZenRule(RULE_ID, mRule);
+ }
+
+ @Test
+ public void onPreferenceChanged_DisableRepeatCallers() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .allowCalls(ZenPolicy.PEOPLE_TYPE_CONTACTS)
+ .allowRepeatCallers(true)
+ .build());
+ mController.updateState(mockPref);
+ mController.onPreferenceChange(mockPref, false);
+ mRule.setZenPolicy(new ZenPolicy.Builder()
+ .allowCalls(ZenPolicy.PEOPLE_TYPE_CONTACTS)
+ .allowRepeatCallers(false)
+ .build());
+ verify(mBackend).updateZenRule(RULE_ID, mRule);
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/notification/ZenRuleStarredContactsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenRuleStarredContactsPreferenceControllerTest.java
new file mode 100644
index 00000000000..6c422eb2412
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/ZenRuleStarredContactsPreferenceControllerTest.java
@@ -0,0 +1,171 @@
+/*
+ * 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 static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.app.NotificationManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.service.notification.ZenPolicy;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+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;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(RobolectricTestRunner.class)
+public class ZenRuleStarredContactsPreferenceControllerTest extends ZenRuleCustomPrefContrTestBase {
+
+ private ZenRuleStarredContactsPreferenceController mCallsController;
+ private ZenRuleStarredContactsPreferenceController mMessagesController;
+ private static int CURR_CONTROLLER = ZenPolicy.PRIORITY_CATEGORY_CALLS;
+
+ @Mock
+ private ZenModeBackend mBackend;
+ @Mock
+ private NotificationManager mNotificationManager;
+ @Mock
+ private Preference mockPref;
+ @Mock
+ private PreferenceScreen mPreferenceScreen;
+ @Mock
+ private Intent testIntent;
+ @Mock
+ private ComponentName mComponentName;
+ private Context mContext;
+
+ @Override
+ AbstractZenCustomRulePreferenceController getController() {
+ if (CURR_CONTROLLER == ZenPolicy.PRIORITY_CATEGORY_MESSAGES) {
+ return mMessagesController;
+ } else {
+ return mCallsController;
+ }
+ }
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ ShadowApplication shadowApplication = ShadowApplication.getInstance();
+ shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
+
+ mContext = RuntimeEnvironment.application;
+ when(testIntent.resolveActivity(any())).thenReturn(mComponentName);
+
+ mCallsController = new ZenRuleStarredContactsPreferenceController(
+ mContext, mock(Lifecycle.class), ZenPolicy.PRIORITY_CATEGORY_CALLS,
+ "zen_mode_starred_contacts_callers");
+ when(mBackend.getAutomaticZenRule(RULE_ID)).thenReturn(mRule);
+ ReflectionHelpers.setField(mCallsController, "mBackend", mBackend);
+ ReflectionHelpers.setField(mCallsController, "mStarredContactsIntent", testIntent);
+ when(mPreferenceScreen.findPreference(mCallsController.getPreferenceKey()))
+ .thenReturn(mockPref);
+ mCallsController.displayPreference(mPreferenceScreen);
+
+ mMessagesController = new ZenRuleStarredContactsPreferenceController(
+ mContext, mock(Lifecycle.class), ZenPolicy.PRIORITY_CATEGORY_MESSAGES,
+ "zen_mode_starred_contacts_messages");
+ ReflectionHelpers.setField(mMessagesController, "mBackend", mBackend);
+ ReflectionHelpers.setField(mMessagesController, "mStarredContactsIntent", testIntent);
+ when(mPreferenceScreen.findPreference(mMessagesController.getPreferenceKey()))
+ .thenReturn(mockPref);
+ mMessagesController.displayPreference(mPreferenceScreen);
+ }
+
+ @Test
+ public void isAvailable_noCallers() {
+ CURR_CONTROLLER = ZenPolicy.PRIORITY_CATEGORY_CALLS;
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .allowCalls(ZenPolicy.PEOPLE_TYPE_NONE)
+ .build());
+ assertThat(mCallsController.isAvailable()).isFalse();
+ }
+
+ @Test
+ public void isAvailable_anyCallers() {
+ CURR_CONTROLLER = ZenPolicy.PRIORITY_CATEGORY_CALLS;
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .allowCalls(ZenPolicy.PEOPLE_TYPE_ANYONE)
+ .build());
+
+ assertThat(mCallsController.isAvailable()).isFalse();
+ }
+
+ @Test
+ public void isAvailable_starredCallers() {
+ CURR_CONTROLLER = ZenPolicy.PRIORITY_CATEGORY_CALLS;
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .allowCalls(ZenPolicy.PEOPLE_TYPE_STARRED)
+ .build());
+
+ assertThat(mCallsController.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void isAvailable_noMessages() {
+ CURR_CONTROLLER = ZenPolicy.PRIORITY_CATEGORY_MESSAGES;
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .allowMessages(ZenPolicy.PEOPLE_TYPE_NONE)
+ .build());
+ assertThat(mCallsController.isAvailable()).isFalse();
+ }
+
+ @Test
+ public void isAvailable_anyMessages() {
+ CURR_CONTROLLER = ZenPolicy.PRIORITY_CATEGORY_MESSAGES;
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .allowMessages(ZenPolicy.PEOPLE_TYPE_ANYONE)
+ .build());
+
+ assertThat(mMessagesController.isAvailable()).isFalse();
+ }
+
+ @Test
+ public void isAvailable_starredMessageContacts() {
+ CURR_CONTROLLER = ZenPolicy.PRIORITY_CATEGORY_MESSAGES;
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .allowMessages(ZenPolicy.PEOPLE_TYPE_STARRED)
+ .build());
+
+ assertThat(mMessagesController.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void nullPreference_displayPreference() {
+ when(mPreferenceScreen.findPreference(mMessagesController.getPreferenceKey()))
+ .thenReturn(null);
+
+ // should not throw a null pointer
+ mMessagesController.displayPreference(mPreferenceScreen);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/ZenRuleVisEffectPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenRuleVisEffectPreferenceControllerTest.java
new file mode 100644
index 00000000000..c99d20724a9
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/ZenRuleVisEffectPreferenceControllerTest.java
@@ -0,0 +1,187 @@
+/*
+ * 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 static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.NotificationManager;
+import android.content.Context;
+import android.content.res.Resources;
+import android.service.notification.ZenPolicy;
+
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.widget.DisabledCheckBoxPreference;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+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;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(RobolectricTestRunner.class)
+public class ZenRuleVisEffectPreferenceControllerTest extends ZenRuleCustomPrefContrTestBase {
+
+ private static final @ZenPolicy.VisualEffect int EFFECT_PEEK = ZenPolicy.VISUAL_EFFECT_PEEK;
+ private static final @ZenPolicy.VisualEffect int PARENT_EFFECT1 = ZenPolicy.VISUAL_EFFECT_BADGE;
+ private static final @ZenPolicy.VisualEffect int PARENT_EFFECT2 =
+ ZenPolicy.VISUAL_EFFECT_NOTIFICATION_LIST;
+ private static final int PREF_METRICS = 1;
+
+ @Mock
+ private ZenModeBackend mBackend;
+ @Mock
+ private DisabledCheckBoxPreference mockPref;
+ @Mock
+ private PreferenceScreen mScreen;
+ @Mock
+ NotificationManager mNotificationManager;
+
+ private Context mContext;
+ private ZenRuleVisEffectPreferenceController mController;
+
+ @Override
+ AbstractZenCustomRulePreferenceController getController() {
+ return mController;
+ }
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ ShadowApplication shadowApplication = ShadowApplication.getInstance();
+ shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
+ when(mNotificationManager.getNotificationPolicy()).thenReturn(
+ mock(NotificationManager.Policy.class));
+
+ mContext = RuntimeEnvironment.application;
+ mController = new ZenRuleVisEffectPreferenceController(mContext, mock(Lifecycle.class),
+ PREF_KEY, EFFECT_PEEK, PREF_METRICS, null);
+ ReflectionHelpers.setField(mController, "mBackend", mBackend);
+ when(mBackend.getAutomaticZenRule(RULE_ID)).thenReturn(mRule);
+
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mockPref);
+ mController.displayPreference(mScreen);
+ }
+
+ @Test
+ public void isAvailable() {
+ // VISUAL_EFFECT_PEEK isn't available until after onResume is called
+ assertFalse(mController.isAvailable());
+ updateControllerZenPolicy(new ZenPolicy()); // calls onResume
+ assertTrue(mController.isAvailable());
+
+ // VISUAL_EFFECT_LIGHTS is only available if the device has an LED:
+ Context mockContext = mock(Context.class);
+ mController = new ZenRuleVisEffectPreferenceController(mockContext, mock(Lifecycle.class),
+ PREF_KEY, ZenPolicy.VISUAL_EFFECT_LIGHTS, PREF_METRICS, null);
+ updateControllerZenPolicy(new ZenPolicy()); // calls onResume
+
+ Resources mockResources = mock(Resources.class);
+ when(mockContext.getResources()).thenReturn(mockResources);
+
+ when(mockResources.getBoolean(com.android.internal.R.bool.config_intrusiveNotificationLed))
+ .thenReturn(false); // no light
+ assertFalse(mController.isAvailable());
+
+ when(mockResources.getBoolean(com.android.internal.R.bool.config_intrusiveNotificationLed))
+ .thenReturn(true); // has light
+ assertTrue(mController.isAvailable());
+ }
+
+ @Test
+ public void updateState_notChecked() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .showPeeking(true)
+ .build());
+ mController.updateState(mockPref);
+
+ verify(mockPref).setChecked(false);
+ verify(mockPref).enableCheckbox(true);
+ }
+
+ @Test
+ public void updateState_checked() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .showPeeking(false)
+ .build());
+ mController.updateState(mockPref);
+
+ verify(mockPref).setChecked(true);
+ verify(mockPref).enableCheckbox(true);
+ }
+
+ @Test
+ public void updateState_checkedFalse_parentChecked() {
+ mController.mParentSuppressedEffects = new int[]{PARENT_EFFECT1, PARENT_EFFECT2};
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .showVisualEffect(EFFECT_PEEK, true)
+ .showVisualEffect(PARENT_EFFECT1, true)
+ .showVisualEffect(PARENT_EFFECT2, false)
+ .build());
+ mController.updateState(mockPref);
+
+ verify(mockPref).setChecked(true);
+ verify(mockPref).enableCheckbox(false);
+ }
+
+ @Test
+ public void updateState_checkedFalse_parentNotChecked() {
+ mController.mParentSuppressedEffects = new int[]{PARENT_EFFECT1, PARENT_EFFECT2};
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .showVisualEffect(EFFECT_PEEK, true)
+ .showVisualEffect(PARENT_EFFECT1, true)
+ .showVisualEffect(PARENT_EFFECT2, true)
+ .build());
+ mController.updateState(mockPref);
+
+ verify(mockPref).setChecked(false);
+ verify(mockPref).enableCheckbox(true);
+ }
+
+ @Test
+ public void onPreferenceChanged_checkedFalse() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .showPeeking(false)
+ .build());
+ mController.onPreferenceChange(mockPref, false);
+ mRule.setZenPolicy(new ZenPolicy.Builder(mRule.getZenPolicy())
+ .showPeeking(true)
+ .build());
+ verify(mBackend).updateZenRule(RULE_ID, mRule);
+ }
+
+ @Test
+ public void onPreferenceChanged_checkedTrue() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .showPeeking(true)
+ .build());
+ mController.onPreferenceChange(mockPref, true);
+ mRule.setZenPolicy(new ZenPolicy.Builder(mRule.getZenPolicy())
+ .showPeeking(false)
+ .build());
+ verify(mBackend).updateZenRule(RULE_ID, mRule);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/ZenRuleVisEffectsAllPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenRuleVisEffectsAllPreferenceControllerTest.java
new file mode 100644
index 00000000000..5ef6194e56f
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/ZenRuleVisEffectsAllPreferenceControllerTest.java
@@ -0,0 +1,104 @@
+/*
+ * 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 static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.NotificationManager;
+import android.content.Context;
+import android.service.notification.ZenPolicy;
+
+import androidx.preference.PreferenceScreen;
+
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+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;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(RobolectricTestRunner.class)
+public class ZenRuleVisEffectsAllPreferenceControllerTest extends
+ ZenRuleCustomPrefContrTestBase {
+
+ @Mock
+ private ZenModeBackend mBackend;
+ @Mock
+ private NotificationManager mNotificationManager;
+ @Mock
+ private ZenCustomRadioButtonPreference mockPref;
+ @Mock
+ private PreferenceScreen mScreen;
+
+ private ZenRuleVisEffectsAllPreferenceController mController;
+ private Context mContext;
+
+ @Override
+ AbstractZenCustomRulePreferenceController getController() {
+ return mController;
+ }
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ ShadowApplication shadowApplication = ShadowApplication.getInstance();
+ shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
+ mContext = RuntimeEnvironment.application;
+ mController = new ZenRuleVisEffectsAllPreferenceController(mContext, mock(Lifecycle.class),
+ PREF_KEY);
+ ReflectionHelpers.setField(mController, "mBackend", mBackend);
+ when(mBackend.getAutomaticZenRule(RULE_ID)).thenReturn(mRule);
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mockPref);
+ mController.displayPreference(mScreen);
+ }
+
+ @Test
+ public void updateState_noVisEffects() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .hideAllVisualEffects()
+ .build());
+ mController.updateState(mockPref);
+ verify(mockPref).setChecked(false);
+ }
+
+ @Test
+ public void updateState_showAllVisualEffects() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .showAllVisualEffects()
+ .build());
+ mController.updateState(mockPref);
+ verify(mockPref).setChecked(true);
+ }
+
+ @Test
+ public void updateState_customEffects() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .showPeeking(true)
+ .showBadges(false)
+ .build());
+ mController.updateState(mockPref);
+
+ verify(mockPref).setChecked(false);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/ZenRuleVisEffectsCustomPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenRuleVisEffectsCustomPreferenceControllerTest.java
new file mode 100644
index 00000000000..79ef8d2da5b
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/ZenRuleVisEffectsCustomPreferenceControllerTest.java
@@ -0,0 +1,104 @@
+/*
+ * 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 static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.NotificationManager;
+import android.content.Context;
+import android.service.notification.ZenPolicy;
+
+import androidx.preference.PreferenceScreen;
+
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+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;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(RobolectricTestRunner.class)
+public class ZenRuleVisEffectsCustomPreferenceControllerTest extends
+ ZenRuleCustomPrefContrTestBase {
+
+ @Mock
+ private ZenModeBackend mBackend;
+ @Mock
+ private NotificationManager mNotificationManager;
+ @Mock
+ private ZenCustomRadioButtonPreference mockPref;
+ @Mock
+ private PreferenceScreen mScreen;
+
+ private ZenRuleVisEffectsCustomPreferenceController mController;
+ private Context mContext;
+
+ @Override
+ AbstractZenCustomRulePreferenceController getController() {
+ return mController;
+ }
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ ShadowApplication shadowApplication = ShadowApplication.getInstance();
+ shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
+ mContext = RuntimeEnvironment.application;
+ mController = new ZenRuleVisEffectsCustomPreferenceController(mContext, mock(Lifecycle.class),
+ PREF_KEY);
+ ReflectionHelpers.setField(mController, "mBackend", mBackend);
+ when(mBackend.getAutomaticZenRule(RULE_ID)).thenReturn(mRule);
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mockPref);
+ mController.displayPreference(mScreen);
+ }
+
+ @Test
+ public void updateState_noVisEffects() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .hideAllVisualEffects()
+ .build());
+ mController.updateState(mockPref);
+ verify(mockPref).setChecked(false);
+ }
+
+ @Test
+ public void updateState_showAllVisualEffects() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .showAllVisualEffects()
+ .build());
+ mController.updateState(mockPref);
+ verify(mockPref).setChecked(false);
+ }
+
+ @Test
+ public void updateState_customEffects() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .showPeeking(true)
+ .showBadges(false)
+ .build());
+ mController.updateState(mockPref);
+
+ verify(mockPref).setChecked(true);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/ZenRuleVisEffectsNonePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenRuleVisEffectsNonePreferenceControllerTest.java
new file mode 100644
index 00000000000..d66433eea62
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/ZenRuleVisEffectsNonePreferenceControllerTest.java
@@ -0,0 +1,104 @@
+/*
+ * 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 static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.NotificationManager;
+import android.content.Context;
+import android.service.notification.ZenPolicy;
+
+import androidx.preference.PreferenceScreen;
+
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+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;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(RobolectricTestRunner.class)
+public class ZenRuleVisEffectsNonePreferenceControllerTest extends
+ ZenRuleCustomPrefContrTestBase {
+
+ @Mock
+ private ZenModeBackend mBackend;
+ @Mock
+ private NotificationManager mNotificationManager;
+ @Mock
+ private ZenCustomRadioButtonPreference mockPref;
+ @Mock
+ private PreferenceScreen mScreen;
+
+ private ZenRuleVisEffectsNonePreferenceController mController;
+ private Context mContext;
+
+ @Override
+ AbstractZenCustomRulePreferenceController getController() {
+ return mController;
+ }
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ ShadowApplication shadowApplication = ShadowApplication.getInstance();
+ shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
+ mContext = RuntimeEnvironment.application;
+ mController = new ZenRuleVisEffectsNonePreferenceController(mContext, mock(Lifecycle.class),
+ PREF_KEY);
+ ReflectionHelpers.setField(mController, "mBackend", mBackend);
+ when(mBackend.getAutomaticZenRule(RULE_ID)).thenReturn(mRule);
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mockPref);
+ mController.displayPreference(mScreen);
+ }
+
+ @Test
+ public void updateState_noVisEffects() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .hideAllVisualEffects()
+ .build());
+ mController.updateState(mockPref);
+ verify(mockPref).setChecked(true);
+ }
+
+ @Test
+ public void updateState_showAllVisualEffects() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .showAllVisualEffects()
+ .build());
+ mController.updateState(mockPref);
+ verify(mockPref).setChecked(false);
+ }
+
+ @Test
+ public void updateState_custom() {
+ updateControllerZenPolicy(new ZenPolicy.Builder()
+ .showPeeking(true)
+ .showBadges(false)
+ .build());
+ mController.updateState(mockPref);
+
+ verify(mockPref).setChecked(false);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/panel/FakePanelContent.java b/tests/robotests/src/com/android/settings/panel/FakePanelContent.java
index 60f0d5db96e..1d799529922 100644
--- a/tests/robotests/src/com/android/settings/panel/FakePanelContent.java
+++ b/tests/robotests/src/com/android/settings/panel/FakePanelContent.java
@@ -29,7 +29,7 @@ import java.util.List;
*/
public class FakePanelContent implements PanelContent {
- public static final String FAKE_KEY = "fake_key";
+ public static final String FAKE_ACTION = "fake_action";
public static final CharSequence TITLE = "title";
diff --git a/tests/robotests/src/com/android/settings/panel/FakeSettingsPanelActivity.java b/tests/robotests/src/com/android/settings/panel/FakeSettingsPanelActivity.java
index afd0becc040..2a62b5423e4 100644
--- a/tests/robotests/src/com/android/settings/panel/FakeSettingsPanelActivity.java
+++ b/tests/robotests/src/com/android/settings/panel/FakeSettingsPanelActivity.java
@@ -27,8 +27,7 @@ public class FakeSettingsPanelActivity extends SettingsPanelActivity {
@Override
public Intent getIntent() {
- final Intent intent = new Intent();
- intent.putExtra(SettingsPanelActivity.EXTRA_PANEL_TYPE, FakePanelContent.FAKE_KEY);
+ final Intent intent = new Intent(FakePanelContent.FAKE_ACTION);
return intent;
}
}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/panel/PanelFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/panel/PanelFeatureProviderImplTest.java
index 754c9379060..99d5d6cea55 100644
--- a/tests/robotests/src/com/android/settings/panel/PanelFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/panel/PanelFeatureProviderImplTest.java
@@ -20,6 +20,7 @@ package com.android.settings.panel;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
+import android.provider.Settings;
import org.junit.Before;
import org.junit.Test;
@@ -43,8 +44,16 @@ public class PanelFeatureProviderImplTest {
@Test
public void getPanel_internetConnectivityKey_returnsCorrectPanel() {
final PanelContent panel = mProvider.getPanel(mContext,
- SettingsPanelActivity.PANEL_TYPE_WIFI);
+ Settings.Panel.ACTION_INTERNET_CONNECTIVITY);
assertThat(panel).isInstanceOf(InternetConnectivityPanel.class);
}
+
+ @Test
+ public void getPanel_volume_returnsCorrectPanel() {
+ final PanelContent panel = mProvider.getPanel(mContext,
+ Settings.Panel.ACTION_VOLUME);
+
+ assertThat(panel).isInstanceOf(VolumePanel.class);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/security/trustagent/TrustAgentsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/security/trustagent/TrustAgentsPreferenceControllerTest.java
index 7eb64b95b48..d7aa42c5737 100644
--- a/tests/robotests/src/com/android/settings/security/trustagent/TrustAgentsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/security/trustagent/TrustAgentsPreferenceControllerTest.java
@@ -28,6 +28,7 @@ import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.service.trust.TrustAgentService;
+import android.text.TextUtils;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
@@ -96,7 +97,7 @@ public class TrustAgentsPreferenceControllerTest {
@Test
public void onStart_noTrustAgent_shouldNotAddPreference() {
final List availableAgents = createFakeAvailableAgents();
- mPackageManager.addResolveInfoForIntent(TEST_INTENT, availableAgents);
+ mPackageManager.setResolveInfosForIntent(TEST_INTENT, availableAgents);
mController.displayPreference(mPreferenceScreen);
mController.onStart();
@@ -109,15 +110,16 @@ public class TrustAgentsPreferenceControllerTest {
onStart_hasAUninstalledTrustAgent_shouldRemoveOnePreferenceAndLeaveTwoPreferences() {
final List availableAgents = createFakeAvailableAgents();
final ResolveInfo uninstalledTrustAgent = availableAgents.get(0);
+
for (ResolveInfo rInfo : availableAgents) {
ShadowTrustAgentManager.grantPermissionToResolveInfo(rInfo);
}
- mPackageManager.addResolveInfoForIntent(TEST_INTENT, availableAgents);
+ mPackageManager.setResolveInfosForIntent(TEST_INTENT, availableAgents);
mController.displayPreference(mPreferenceScreen);
mController.onStart();
availableAgents.remove(uninstalledTrustAgent);
- mPackageManager.addResolveInfoForIntent(TEST_INTENT, availableAgents);
+ mPackageManager.setResolveInfosForIntent(TEST_INTENT, availableAgents);
mController.onStart();
assertThat(mPreferenceScreen.getPreferenceCount()).isEqualTo(2);
@@ -131,13 +133,13 @@ public class TrustAgentsPreferenceControllerTest {
for (ResolveInfo rInfo : availableAgents) {
ShadowTrustAgentManager.grantPermissionToResolveInfo(rInfo);
}
- mPackageManager.addResolveInfoForIntent(TEST_INTENT, availableAgents);
+ mPackageManager.setResolveInfosForIntent(TEST_INTENT, availableAgents);
mController.displayPreference(mPreferenceScreen);
mController.onStart();
availableAgents.add(newTrustAgent);
ShadowTrustAgentManager.grantPermissionToResolveInfo(newTrustAgent);
- mPackageManager.addResolveInfoForIntent(TEST_INTENT, availableAgents);
+ mPackageManager.setResolveInfosForIntent(TEST_INTENT, availableAgents);
mController.onStart();
assertThat(mPreferenceScreen.getPreferenceCount()).isEqualTo(4);
@@ -150,7 +152,7 @@ public class TrustAgentsPreferenceControllerTest {
for (ResolveInfo rInfo : availableAgents) {
ShadowTrustAgentManager.grantPermissionToResolveInfo(rInfo);
}
- mPackageManager.addResolveInfoForIntent(TEST_INTENT, availableAgents);
+ mPackageManager.setResolveInfosForIntent(TEST_INTENT, availableAgents);
mController.displayPreference(mPreferenceScreen);
mController.onStart();
@@ -169,7 +171,7 @@ public class TrustAgentsPreferenceControllerTest {
for (ResolveInfo rInfo : availableAgents) {
ShadowTrustAgentManager.grantPermissionToResolveInfo(rInfo);
}
- mPackageManager.addResolveInfoForIntent(TEST_INTENT, availableAgents);
+ mPackageManager.setResolveInfosForIntent(TEST_INTENT, availableAgents);
ShadowRestrictedLockUtilsInternal.setKeyguardDisabledFeatures(
DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS);
@@ -213,8 +215,14 @@ public class TrustAgentsPreferenceControllerTest {
private final static List sPermissionGrantedList = new ArrayList<>();
@Implementation
- public boolean shouldProvideTrust(ResolveInfo resolveInfo, PackageManager pm) {
- return sPermissionGrantedList.contains(resolveInfo);
+ protected boolean shouldProvideTrust(ResolveInfo resolveInfo, PackageManager pm) {
+ for (ResolveInfo info : sPermissionGrantedList) {
+ if (info.serviceInfo.equals(resolveInfo.serviceInfo)) {
+ return true;
+ }
+ }
+
+ return false;
}
private static void grantPermissionToResolveInfo(ResolveInfo rInfo) {
diff --git a/tests/robotests/src/com/android/settings/shortcut/CreateShortcutPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/shortcut/CreateShortcutPreferenceControllerTest.java
index e132aac2f45..f9cedb33443 100644
--- a/tests/robotests/src/com/android/settings/shortcut/CreateShortcutPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/shortcut/CreateShortcutPreferenceControllerTest.java
@@ -118,13 +118,13 @@ public class CreateShortcutPreferenceControllerTest {
ri2.activityInfo.applicationInfo = new ApplicationInfo();
ri2.activityInfo.applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
- mPackageManager.addResolveInfoForIntent(
+ mPackageManager.setResolveInfosForIntent(
new Intent(CreateShortcutPreferenceController.SHORTCUT_PROBE),
Arrays.asList(ri1, ri2));
final List info = mController.queryShortcuts();
assertThat(info).hasSize(1);
- assertThat(info.get(0)).isEqualTo(ri2);
+ assertThat(info.get(0).activityInfo).isEqualTo(ri2.activityInfo);
}
@Test
@@ -143,13 +143,13 @@ public class CreateShortcutPreferenceControllerTest {
ri2.activityInfo.applicationInfo = new ApplicationInfo();
ri2.activityInfo.applicationInfo.flags = ApplicationInfo.FLAG_SYSTEM;
- mPackageManager.addResolveInfoForIntent(
+ mPackageManager.setResolveInfosForIntent(
new Intent(CreateShortcutPreferenceController.SHORTCUT_PROBE),
Arrays.asList(ri1, ri2));
final List info = mController.queryShortcuts();
assertThat(info).hasSize(2);
- assertThat(info.get(0)).isEqualTo(ri2);
- assertThat(info.get(1)).isEqualTo(ri1);
+ assertThat(info.get(0).activityInfo).isEqualTo(ri2.activityInfo);
+ assertThat(info.get(1).activityInfo).isEqualTo(ri1.activityInfo);
}
}
diff --git a/tests/robotests/src/com/android/settings/shortcut/ShortcutsUpdateTaskTest.java b/tests/robotests/src/com/android/settings/shortcut/ShortcutsUpdateTaskTest.java
index 0bc041424f6..8352e7a9634 100644
--- a/tests/robotests/src/com/android/settings/shortcut/ShortcutsUpdateTaskTest.java
+++ b/tests/robotests/src/com/android/settings/shortcut/ShortcutsUpdateTaskTest.java
@@ -80,12 +80,14 @@ public class ShortcutsUpdateTaskTest {
.setComponent(new ComponentName(
mContext, Settings.ManageApplicationsActivity.class));
final ResolveInfo ri1 = mock(ResolveInfo.class);
+ ri1.nonLocalizedLabel = "label1";
+
final Intent shortcut2 = new Intent(CreateShortcutPreferenceController.SHORTCUT_PROBE)
.setComponent(new ComponentName(
mContext, Settings.SoundSettingsActivity.class));
final ResolveInfo ri2 = mock(ResolveInfo.class);
- when(ri1.loadLabel(any(PackageManager.class))).thenReturn("label1");
- when(ri2.loadLabel(any(PackageManager.class))).thenReturn("label2");
+ ri2.nonLocalizedLabel = "label2";
+
mPackageManager.addResolveInfoForIntent(shortcut1, ri1);
mPackageManager.addResolveInfoForIntent(shortcut2, ri2);
diff --git a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
index b1292677898..7eae3e4ad1a 100644
--- a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
@@ -55,7 +55,7 @@ import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
import com.android.settings.testutils.shadow.ShadowThreadUtils;
import com.android.settings.testutils.shadow.ShadowUserManager;
import com.android.settings.testutils.shadow.ShadowUtils;
-import com.android.settings.wifi.WifiSlice;
+import com.android.settings.wifi.slice.WifiSlice;
import com.android.settingslib.wifi.WifiTracker;
import org.junit.After;
diff --git a/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
index a864bf6e561..41935fe434f 100644
--- a/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
+++ b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
@@ -23,7 +23,6 @@ import android.content.Context;
import com.android.settings.accounts.AccountFeatureProvider;
import com.android.settings.applications.ApplicationFeatureProvider;
-import com.android.settings.biometrics.face.FaceFeatureProvider;
import com.android.settings.bluetooth.BluetoothFeatureProvider;
import com.android.settings.dashboard.DashboardFeatureProvider;
import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
@@ -66,7 +65,6 @@ public class FakeFeatureFactory extends FeatureFactory {
public final AssistGestureFeatureProvider assistGestureFeatureProvider;
public final AccountFeatureProvider mAccountFeatureProvider;
public final ContextualCardFeatureProvider mContextualCardFeatureProvider;
- public final FaceFeatureProvider mFaceFeatureProvider;
public final BluetoothFeatureProvider mBluetoothFeatureProvider;
public PanelFeatureProvider panelFeatureProvider;
@@ -112,7 +110,6 @@ public class FakeFeatureFactory extends FeatureFactory {
mAccountFeatureProvider = mock(AccountFeatureProvider.class);
mContextualCardFeatureProvider = mock(ContextualCardFeatureProvider.class);
panelFeatureProvider = mock(PanelFeatureProvider.class);
- mFaceFeatureProvider = mock(FaceFeatureProvider.class);
mBluetoothFeatureProvider = mock(BluetoothFeatureProvider.class);
}
@@ -202,15 +199,10 @@ public class FakeFeatureFactory extends FeatureFactory {
}
@Override
- public ContextualCardFeatureProvider getContextualCardFeatureProvider() {
+ public ContextualCardFeatureProvider getContextualCardFeatureProvider(Context context) {
return mContextualCardFeatureProvider;
}
- @Override
- public FaceFeatureProvider getFaceFeatureProvider() {
- return mFaceFeatureProvider;
- }
-
@Override
public BluetoothFeatureProvider getBluetoothFeatureProvider(Context context) {
return mBluetoothFeatureProvider;
diff --git a/tests/robotests/src/com/android/settings/webview/WebViewAppPickerTest.java b/tests/robotests/src/com/android/settings/webview/WebViewAppPickerTest.java
index 1435529a784..363e04614ae 100644
--- a/tests/robotests/src/com/android/settings/webview/WebViewAppPickerTest.java
+++ b/tests/robotests/src/com/android/settings/webview/WebViewAppPickerTest.java
@@ -39,6 +39,7 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageItemInfo;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
+import android.graphics.drawable.ColorDrawable;
import android.os.UserManager;
import android.webkit.UserPackage;
@@ -56,6 +57,8 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
+import org.robolectric.Shadows;
+import org.robolectric.shadows.ShadowPackageManager;
import org.robolectric.util.ReflectionHelpers;
import java.util.Arrays;
@@ -341,6 +344,11 @@ public class WebViewAppPickerTest {
when(mPackageManager.getPackageInfo(eq(DEFAULT_PACKAGE_NAME), anyInt())).thenReturn(
packageInfo);
+ // Subvert attempts to load an unbadged icon for the application.
+ PackageManager pm = RuntimeEnvironment.application.getPackageManager();
+ ShadowPackageManager spm = Shadows.shadowOf(pm);
+ spm.setUnbadgedApplicationIcon(DEFAULT_PACKAGE_NAME, new ColorDrawable());
+
RadioButtonPreference mockPreference = mock(RadioButtonPreference.class);
mPicker.bindPreference(mockPreference, DEFAULT_PACKAGE_NAME, webviewAppInfo, null);
mPicker
diff --git a/tests/robotests/src/com/android/settings/wifi/slice/ContextualWifiSliceTest.java b/tests/robotests/src/com/android/settings/wifi/slice/ContextualWifiSliceTest.java
new file mode 100644
index 00000000000..bf5fba83cc0
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/wifi/slice/ContextualWifiSliceTest.java
@@ -0,0 +1,103 @@
+/*
+ * 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.slice;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
+
+import androidx.core.graphics.drawable.IconCompat;
+import androidx.slice.Slice;
+import androidx.slice.SliceItem;
+import androidx.slice.SliceMetadata;
+import androidx.slice.SliceProvider;
+import androidx.slice.core.SliceAction;
+import androidx.slice.widget.SliceLiveData;
+
+import com.android.settings.R;
+import com.android.settings.testutils.SliceTester;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.List;
+
+@RunWith(RobolectricTestRunner.class)
+public class ContextualWifiSliceTest {
+
+ private Context mContext;
+ private ContentResolver mResolver;
+ private WifiManager mWifiManager;
+ private ContextualWifiSlice mWifiSlice;
+
+ @Before
+ public void setUp() {
+ mContext = spy(RuntimeEnvironment.application);
+ mResolver = mock(ContentResolver.class);
+ doReturn(mResolver).when(mContext).getContentResolver();
+ mWifiManager = mContext.getSystemService(WifiManager.class);
+
+ // Set-up specs for SliceMetadata.
+ SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
+ mWifiManager.setWifiEnabled(true);
+
+ mWifiSlice = new ContextualWifiSlice(mContext);
+ }
+
+ @Test
+ public void getWifiSlice_hasActiveConnection_shouldReturnNull() {
+ final WifiConfiguration config = new WifiConfiguration();
+ config.SSID = "123";
+ mWifiManager.connect(config, null /* listener */);
+
+ final Slice wifiSlice = mWifiSlice.getSlice();
+
+ assertThat(wifiSlice).isNull();
+ }
+
+ @Test
+ public void getWifiSlice_previousDisplayed_hasActiveConnection_shouldHaveTitleAndToggle() {
+ mWifiSlice.mPreviouslyDisplayed = true;
+ final WifiConfiguration config = new WifiConfiguration();
+ config.SSID = "123";
+ mWifiManager.connect(config, null /* listener */);
+
+ final Slice wifiSlice = mWifiSlice.getSlice();
+ final SliceMetadata metadata = SliceMetadata.from(mContext, wifiSlice);
+
+ final List toggles = metadata.getToggles();
+ assertThat(toggles).hasSize(1);
+
+ final SliceAction primaryAction = metadata.getPrimaryAction();
+ final IconCompat expectedToggleIcon = IconCompat.createWithResource(mContext,
+ R.drawable.ic_settings_wireless);
+ assertThat(primaryAction.getIcon().toString()).isEqualTo(expectedToggleIcon.toString());
+
+ final List sliceItems = wifiSlice.getItems();
+ SliceTester.assertTitle(sliceItems, mContext.getString(R.string.wifi_settings));
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiSliceTest.java b/tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java
similarity index 96%
rename from tests/robotests/src/com/android/settings/wifi/WifiSliceTest.java
rename to tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java
index 2d4dd045f38..3c78749ddfb 100644
--- a/tests/robotests/src/com/android/settings/wifi/WifiSliceTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/slice/WifiSliceTest.java
@@ -12,16 +12,15 @@
* 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;
+package com.android.settings.wifi.slice;
import static android.app.slice.Slice.HINT_LIST_ITEM;
import static android.app.slice.SliceItem.FORMAT_SLICE;
import static com.android.settings.slices.CustomSliceRegistry.WIFI_SLICE_URI;
-import static com.android.settings.wifi.WifiSlice.DEFAULT_EXPANDED_ROW_COUNT;
+import static com.android.settings.wifi.slice.WifiSlice.DEFAULT_EXPANDED_ROW_COUNT;
import static com.google.common.truth.Truth.assertThat;
@@ -29,7 +28,6 @@ import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
import android.content.ContentResolver;
import android.content.Context;
diff --git a/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinishTest.java b/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinishTest.java
index 3a8887343f0..0a46403e1c2 100644
--- a/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinishTest.java
+++ b/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollFinishTest.java
@@ -36,6 +36,9 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.settings.R;
+import com.google.android.setupcompat.PartnerCustomizationLayout;
+import com.google.android.setupcompat.template.ButtonFooterMixin;
+
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -57,7 +60,9 @@ public class FingerprintEnrollFinishTest {
intending(hasComponent(enrollingComponent))
.respondWith(new ActivityResult(Activity.RESULT_CANCELED, null));
- onView(withId(R.id.add_another_button)).perform(click());
+ PartnerCustomizationLayout layout =
+ mActivityRule.getActivity().findViewById(R.id.setup_wizard_layout);
+ layout.getMixin(ButtonFooterMixin.class).getPrimaryButtonView().performClick();
intended(hasComponent(enrollingComponent));
assertFalse(mActivityRule.getActivity().isFinishing());
@@ -72,7 +77,9 @@ public class FingerprintEnrollFinishTest {
intending(hasComponent(enrollingComponent))
.respondWith(new ActivityResult(Activity.RESULT_OK, null));
- onView(withId(R.id.add_another_button)).perform(click());
+ PartnerCustomizationLayout layout =
+ mActivityRule.getActivity().findViewById(R.id.setup_wizard_layout);
+ layout.getMixin(ButtonFooterMixin.class).getPrimaryButtonView().performClick();
intended(hasComponent(enrollingComponent));
assertTrue(mActivityRule.getActivity().isFinishing());
diff --git a/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroductionTest.java b/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroductionTest.java
index e937b7f85e6..5078cc2501f 100644
--- a/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroductionTest.java
+++ b/tests/unit/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollIntroductionTest.java
@@ -32,6 +32,9 @@ import android.widget.TextView;
import com.android.settings.R;
+import com.google.android.setupcompat.PartnerCustomizationLayout;
+import com.google.android.setupcompat.template.ButtonFooterMixin;
+
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -80,7 +83,8 @@ public class FingerprintEnrollIntroductionTest
final TextView errorTextView = (TextView) mActivity.findViewById(R.id.error_text);
assertNotNull(errorTextView.getText().toString());
- final Button nextButton = (Button) mActivity.findViewById(R.id.fingerprint_next_button);
+ PartnerCustomizationLayout layout = mActivity.findViewById(R.id.setup_wizard_layout);
+ final Button nextButton = layout.getMixin(ButtonFooterMixin.class).getPrimaryButtonView();
assertEquals(View.GONE, nextButton.getVisibility());
}
diff --git a/tests/unit/src/com/android/settings/wifi/WifiSettingsUiTest.java b/tests/unit/src/com/android/settings/wifi/WifiSettingsUiTest.java
index be593a9bee8..d068ce0d97e 100644
--- a/tests/unit/src/com/android/settings/wifi/WifiSettingsUiTest.java
+++ b/tests/unit/src/com/android/settings/wifi/WifiSettingsUiTest.java
@@ -195,17 +195,6 @@ public class WifiSettingsUiTest {
matches(isDisplayed()));
}
- @Test
- public void noSavedNetworks_wifiEnabled_shouldNotShowSavedNetworksButton() {
- setWifiState(WifiManager.WIFI_STATE_ENABLED);
- when(mWifiTracker.getNumSavedNetworks()).thenReturn(0);
-
- launchActivity();
-
- onView(withText(resourceId(STRING, WIFI_SAVED_ACCESS_POINTS_LABEL))).check(
- matches(not(isDisplayed())));
- }
-
@Test
public void noSavedNetworks_wifiDisabled_shouldNotShowSavedNetworksButton() {
setWifiState(WifiManager.WIFI_STATE_DISABLED);
@@ -342,24 +331,4 @@ public class WifiSettingsUiTest {
onView(withId(resourceId(ID, PASSWORD_LAYOUT))).check(matches(isDisplayed()));
onView(withId(resourceId(ID, PASSWORD))).check(matches(isDisplayed()));
}
-
- @Ignore("b/73796195")
- @Test
- public void onConnectedChanged_shouldNotFetchAPs() {
- setWifiState(WifiManager.WIFI_STATE_ENABLED);
- when(mWifiTracker.isConnected()).thenReturn(true);
-
- launchActivity();
-
- verify(mWifiTracker, times(1)).getAccessPoints();
- onView(withText(WIFI_DISPLAY_STATUS_CONNECTED)).check(matches(isDisplayed()));
-
- // Invoke onConnectedChanged
- when(mWifiTracker.isConnected()).thenReturn(false);
- mWifiListener.onConnectedChanged();
-
- // Verify no additional call to getAccessPoints
- getInstrumentation().waitForIdleSync();
- verify(mWifiTracker, times(1)).getAccessPoints();
- }
}
diff --git a/tests/unit/src/com/android/settings/wifi/dpp/WifiQrCodetest.java b/tests/unit/src/com/android/settings/wifi/dpp/WifiQrCodetest.java
new file mode 100644
index 00000000000..775ca489ffe
--- /dev/null
+++ b/tests/unit/src/com/android/settings/wifi/dpp/WifiQrCodetest.java
@@ -0,0 +1,213 @@
+/*
+ * 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.dpp;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class WifiQrCodetest {
+ // Valid Wi-Fi DPP QR code & it's parameters
+ private static final String VALID_WIFI_DPP_QR_CODE = "DPP:I:SN=4774LH2b4044;M:010203040506;K:"
+ + "MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADURzxmttZoIRIPWGoQMV00XHWCAQIhXruVWOz0NjlkIA=;;";
+
+ private static final String PUBLIC_KEY_OF_VALID_WIFI_DPP_QR_CODE =
+ "MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADURzxmttZoIRIPWGoQMV00XHWCAQIhXruVWOz0NjlkIA=";
+
+ private static final String INFORMATION_OF_VALID_WIFI_DPP_QR_CODE =
+ "SN=4774LH2b4044";
+
+ // Valid ZXing reader library's Wi-Fi Network config format & it's parameters
+ private static final String VALID_ZXING_WIFI_QR_CODE =
+ "WIFI:T:WPA;S:mynetwork;P:mypass;H:true;;";
+
+ // Valid ZXing reader library's Wi-Fi Network config format - security type nopass and no password
+ private static final String VALID_ZXING_WIFI_QR_CODE_NOPASS_AND_NO_PASSWORD =
+ "WIFI:T:nopass;S:mynetwork;;";
+
+ // Valid ZXing reader library's Wi-Fi Network config format - no security and no password
+ private static final String VALID_ZXING_WIFI_QR_CODE_NO_SECURITY_AND_NO_PASSWORD =
+ "WIFI:T:;S:mynetwork;P:;H:false;;";
+
+ private static final String SECURITY_OF_VALID_ZXING_WIFI_QR_CODE = "WPA";
+ private static final String SECURITY_OF_VALID_ZXING_WIFI_QR_CODE_NOPASS = "nopass";
+ private static final String SSID_OF_VALID_ZXING_WIFI_QR_CODE = "mynetwork";
+ private static final String PASSWORD_OF_VALID_ZXING_WIFI_QR_CODE = "mypass";
+
+ // Invalid scheme QR code
+ private static final String INVALID_SCHEME_QR_CODE = "BT:T:WPA;S:mynetwork;P:mypass;H:true;;";
+
+ // Invalid Wi-Fi DPP QR code - no public key - case 1
+ private static final String INVALID_WIFI_DPP_QR_CODE_NO_PUBLIC_KEY_1 =
+ "DPP:I:SN=4774LH2b4044;M:010203040506;K:;;";
+
+ // Invalid Wi-Fi DPP QR code - no public key - case 2
+ private static final String INVALID_WIFI_DPP_QR_CODE_NO_PUBLIC_KEY_2 =
+ "DPP:I:SN=4774LH2b4044;M:010203040506;;";
+
+ // Invalid ZXing reader library's Wi-Fi Network config format - no password
+ private static final String INVALID_ZXING_WIFI_QR_CODE_NO_PASSWORD =
+ "WIFI:T:WPA;S:mynetwork;P:;;";
+
+ // Invalid ZXing reader library's Wi-Fi Network config format - no SSID
+ private static final String INVALID_ZXING_WIFI_QR_CODE_NO_SSID =
+ "WIFI:T:WPA;P:mypass;;";
+
+ @Test
+ public void parseValidWifiDppQrCode() {
+ WifiQrCode wifiQrCode = new WifiQrCode(VALID_WIFI_DPP_QR_CODE);
+
+ assertEquals(WifiQrCode.SCHEME_DPP, wifiQrCode.getScheme());
+ assertEquals(PUBLIC_KEY_OF_VALID_WIFI_DPP_QR_CODE, wifiQrCode.getPublicKey());
+ assertEquals(INFORMATION_OF_VALID_WIFI_DPP_QR_CODE, wifiQrCode.getInformation());
+ }
+
+ @Test
+ public void parseValidZxingWifiQrCode() {
+ WifiQrCode wifiQrCode = new WifiQrCode(VALID_ZXING_WIFI_QR_CODE);
+ WifiNetworkConfig config = wifiQrCode.getWifiNetworkConfig();
+
+ assertEquals(WifiQrCode.SCHEME_ZXING_WIFI_NETWORK_CONFIG, wifiQrCode.getScheme());
+ assertNotNull(config);
+ assertEquals(SECURITY_OF_VALID_ZXING_WIFI_QR_CODE, config.getSecurity());
+ assertEquals(SSID_OF_VALID_ZXING_WIFI_QR_CODE, config.getSsid());
+ assertEquals(PASSWORD_OF_VALID_ZXING_WIFI_QR_CODE, config.getPreSharedKey());
+ assertEquals(true, config.getHiddenSsid());
+ }
+
+ @Test
+ public void parseValidZxingWifiQrCode_noPass_and_no_password() {
+ WifiQrCode wifiQrCode = new WifiQrCode(VALID_ZXING_WIFI_QR_CODE_NOPASS_AND_NO_PASSWORD);
+ WifiNetworkConfig config = wifiQrCode.getWifiNetworkConfig();
+
+ assertEquals(WifiQrCode.SCHEME_ZXING_WIFI_NETWORK_CONFIG, wifiQrCode.getScheme());
+ assertNotNull(config);
+ assertEquals(SECURITY_OF_VALID_ZXING_WIFI_QR_CODE_NOPASS, config.getSecurity());
+ assertEquals(SSID_OF_VALID_ZXING_WIFI_QR_CODE, config.getSsid());
+ assertNull(config.getPreSharedKey());
+ assertEquals(false, config.getHiddenSsid());
+ }
+
+ @Test
+ public void parseValidZxingWifiQrCode_no_security_and_no_password() {
+ WifiQrCode wifiQrCode = new WifiQrCode(VALID_ZXING_WIFI_QR_CODE_NO_SECURITY_AND_NO_PASSWORD);
+ WifiNetworkConfig config = wifiQrCode.getWifiNetworkConfig();
+
+ assertEquals(WifiQrCode.SCHEME_ZXING_WIFI_NETWORK_CONFIG, wifiQrCode.getScheme());
+ assertNotNull(config);
+ assertNull(config.getSecurity());
+ assertEquals(SSID_OF_VALID_ZXING_WIFI_QR_CODE, config.getSsid());
+ assertNull(config.getPreSharedKey());
+ assertEquals(false, config.getHiddenSsid());
+ }
+
+ @Test
+ public void testRemoveBackSlash() {
+ assertEquals("\\", WifiQrCode.removeBackSlash("\\\\"));
+ assertEquals("ab", WifiQrCode.removeBackSlash("a\\b"));
+ assertEquals("a", WifiQrCode.removeBackSlash("\\a"));
+ assertEquals("\\b", WifiQrCode.removeBackSlash("\\\\b"));
+ assertEquals("c\\", WifiQrCode.removeBackSlash("c\\\\"));
+ }
+
+ @Test
+ public void parseEmptyQrCode_shouldThrowIllegalArgumentException() {
+ try {
+ new WifiQrCode(null);
+ fail("Null QR code");
+ } catch (IllegalArgumentException e) {
+ // Do nothing
+ }
+
+ try {
+ new WifiQrCode("");
+ fail("Empty string QR code");
+ } catch (IllegalArgumentException e) {
+ // Do nothing
+ }
+
+ try {
+ new WifiQrCode("DPP:;");
+ fail("Empty content WIFI DPP QR code");
+ } catch (IllegalArgumentException e) {
+ // Do nothing
+ }
+
+ try {
+ new WifiQrCode("WIFI:;");
+ fail("Empty content ZXing WIFI QR code");
+ } catch (IllegalArgumentException e) {
+ // Do nothing
+ }
+ }
+
+ @Test
+ public void parseInvalidSchemeQrCode_shouldThrowIllegalArgumentException() {
+ try {
+ new WifiQrCode(INVALID_SCHEME_QR_CODE);
+ fail("Invalid scheme");
+ } catch (IllegalArgumentException e) {
+ // Do nothing
+ }
+ }
+
+ @Test
+ public void parseInvalidWifiDppQrCode_noPublicKey_shouldThrowIllegalArgumentException() {
+ try {
+ new WifiQrCode(INVALID_WIFI_DPP_QR_CODE_NO_PUBLIC_KEY_1);
+ fail("No public key case 1");
+ } catch (IllegalArgumentException e) {
+ // Do nothing
+ }
+
+ try {
+ new WifiQrCode(INVALID_WIFI_DPP_QR_CODE_NO_PUBLIC_KEY_2);
+ fail("No public key case 2");
+ } catch (IllegalArgumentException e) {
+ // Do nothing
+ }
+ }
+
+ @Test
+ public void parseInvalidZxingWifiQrCode_noPassword_shouldThrowIllegalArgumentException() {
+ try {
+ new WifiQrCode(INVALID_ZXING_WIFI_QR_CODE_NO_PASSWORD);
+ fail("No password");
+ } catch (IllegalArgumentException e) {
+ // Do nothing
+ }
+ }
+
+ @Test
+ public void parseInvalidZxingWifiQrCode_noSsid_shouldThrowIllegalArgumentException() {
+ try {
+ new WifiQrCode(INVALID_ZXING_WIFI_QR_CODE_NO_SSID);
+ fail("No SSID");
+ } catch (IllegalArgumentException e) {
+ // Do nothing
+ }
+ }
+}