diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 5a4db20d8aa..fc5b8304f84 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1004,6 +1004,34 @@
android:value="true" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
-
+
+
+
+
+
@@ -2227,15 +2258,10 @@
-
+
-
-
-
-
-
@@ -2686,10 +2712,6 @@
-
-
-
-
@@ -3200,99 +3222,6 @@
android:permission="android.permission.DUMP"
android:enabled="@bool/config_has_help" />
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
diff --git a/res/layout/zen_mode_settings_button.xml b/res/layout/zen_mode_settings_button.xml
index 82989fc7863..4fe522d799f 100644
--- a/res/layout/zen_mode_settings_button.xml
+++ b/res/layout/zen_mode_settings_button.xml
@@ -30,7 +30,7 @@
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
- android:layout_gravity="center"
+ android:layout_gravity="left"
android:text="@string/zen_mode_button_turn_on"
android:paddingEnd="8dp" />
@@ -40,7 +40,7 @@
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
- android:layout_gravity="center"
+ android:layout_gravity="left"
android:text="@string/zen_mode_button_turn_off"
android:paddingEnd="8dp" />
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 7ab9afbb008..cb6f9be5d04 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -266,14 +266,16 @@
- PWD
-
+
+ - @string/wifi_ap_choose_auto
- @string/wifi_ap_choose_2G
- @string/wifi_ap_choose_5G
+ - @string/wifi_ap_choose_auto
- @string/wifi_ap_choose_2G
diff --git a/res/values/config.xml b/res/values/config.xml
index 097350b0b81..ce611649452 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -44,6 +44,10 @@
false
+
+ false
+
com.android.settings.overlay.FeatureFactoryImpl
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index d4071ed359a..16ac1281ae0 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -106,13 +106,9 @@
24dp
-
- 16dp
- 16dp
-
72dp
- 24dp
+ 16dp
Disabled by admin
+
+ Show lockdown option
+
+ Display power button option that turns off extended access and fingerprint unlocking.
None
@@ -1116,14 +1120,18 @@
-
- Set screen lock
+
+ Set screen lock for security
-
- Protect your device
+
+ Prevent others from using your tablet
+
+ Prevent others from using your device
+
+ Prevent others from using your phone
-
- Use fingerprint
+
+ Unlock with fingerprint
Unlock with your fingerprint
@@ -1941,6 +1949,8 @@
Show password
Select AP Band
+
+ Auto
2.4 GHz Band
@@ -2247,7 +2257,7 @@
Turn on Wi-Fi Calling
- Use Wi-Fi instead of mobile network
+ Extend coverage by calling over Wi-Fi
Calling preference
@@ -5588,10 +5598,12 @@
Add account
Work profile isn\u2019t available yet
-
- Work mode
-
- Allow work profile to function, including apps, background sync, and related features
+
+ Work profile
+
+ Managed by your organization
+
+ Apps and notifications are off
Remove work profile
@@ -6437,6 +6449,7 @@
+
Account for content
@@ -6845,6 +6858,9 @@
Do Not Disturb
+
+ Turn on Do Not Disturb
+
Behavior
@@ -6872,11 +6888,11 @@
Automatic rule
-
- Set Do Not Disturb rules
+
+ Silence phone at certain times
- Limit sounds & vibrations at certain times
+ Set Do Not Disturb rules
Use rule
@@ -6902,6 +6918,9 @@
Add
+
+ Turn on
+
Turn on now
@@ -6920,6 +6939,12 @@
Do Not Disturb was automatically turned on by an app (%s)
+
+ Priority only
+
+
+ %1$s. %2$s
+
Work profile sounds
@@ -6965,6 +6990,9 @@
Notifications
+
+ Recently sent
+
Advanced
@@ -8415,7 +8443,7 @@
Set Night Light schedule
- Tint screen amber to help you fall asleep
+ Automatically tint screen every night
Night Light is on
@@ -8696,7 +8724,10 @@
Ranking object doesn\'t contain this key.
- Emulate a display with a cutout
+ Simulate a display with a cutout
+
+
+ None
Special app access
@@ -8834,9 +8865,6 @@
Open camera quickly
-
- Press power button twice to open camera
-
Flip camera
@@ -8846,13 +8874,6 @@
Take selfies faster
-
- Double-twist phone for selfie mode
-
- Double-twist tablet for selfie mode
-
- Double-twist device for selfie mode
-
Double-tap to check phone
@@ -8863,9 +8884,6 @@
To check time, notification icons, and other info, double-tap your screen.
-
- Check notifications when screen is off
-
Lift to check phone
@@ -8880,9 +8898,6 @@
To check time, notification icons, and other info, pick up your device.
-
- Check notifications when screen is off
-
Swipe fingerprint for notifications
@@ -8898,9 +8913,6 @@
See notifications quickly
-
- Swipe down on the fingerprint sensor
-
@@ -9223,4 +9235,15 @@
[DO NOT TRANSLATE] -->
+
+ My Phone
+
+ My Tablet
+
+ My Device
+
+ Account
+
+ Device name
+
diff --git a/res/xml/configure_notification_settings.xml b/res/xml/configure_notification_settings.xml
index 21904e671a9..520ebaa5fa8 100644
--- a/res/xml/configure_notification_settings.xml
+++ b/res/xml/configure_notification_settings.xml
@@ -19,8 +19,28 @@
android:key="configure_notification_settings">
+ android:key="recent_notifications_category"
+ android:title="@string/recent_notifications"
+ android:order="-200">
+
+
+
+
+
+
+
+
+
+
+
+
+
-
diff --git a/res/xml/managed_profile_settings.xml b/res/xml/managed_profile_settings.xml
index 58fcd8802a6..c283e13ca52 100644
--- a/res/xml/managed_profile_settings.xml
+++ b/res/xml/managed_profile_settings.xml
@@ -20,14 +20,13 @@
+ android:title="@string/work_mode_label"
+ android:summary="@string/summary_placeholder"/>
+ settings:useAdditionalSummary="true"/>
\ No newline at end of file
diff --git a/res/xml/my_device_info.xml b/res/xml/my_device_info.xml
new file mode 100644
index 00000000000..673b2a5722a
--- /dev/null
+++ b/res/xml/my_device_info.xml
@@ -0,0 +1,167 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/xml/security_lockscreen_settings.xml b/res/xml/security_lockscreen_settings.xml
index 7a45bec59b0..6faedd72972 100644
--- a/res/xml/security_lockscreen_settings.xml
+++ b/res/xml/security_lockscreen_settings.xml
@@ -33,6 +33,11 @@
android:title="@string/owner_info_settings_title"
android:summary="@string/owner_info_settings_summary" />
+
+
diff --git a/src/com/android/settings/ApnPreference.java b/src/com/android/settings/ApnPreference.java
index 4e89efc781c..9a6eeaf46da 100755
--- a/src/com/android/settings/ApnPreference.java
+++ b/src/com/android/settings/ApnPreference.java
@@ -16,6 +16,7 @@
package com.android.settings;
+import static android.provider.Telephony.Carriers.CONTENT_URI;
import static android.provider.Telephony.Carriers.FILTERED_URI;
import android.content.ContentUris;
@@ -36,6 +37,7 @@ import android.widget.RelativeLayout;
public class ApnPreference extends Preference implements
CompoundButton.OnCheckedChangeListener, OnClickListener {
final static String TAG = "ApnPreference";
+ private boolean mDpcEnforced = false;
private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
@@ -119,7 +121,8 @@ public class ApnPreference extends Preference implements
Context context = getContext();
if (context != null) {
int pos = Integer.parseInt(getKey());
- Uri url = ContentUris.withAppendedId(FILTERED_URI, pos);
+ Uri url = ContentUris.withAppendedId(
+ mDpcEnforced ? FILTERED_URI : CONTENT_URI, pos);
Intent editIntent = new Intent(Intent.ACTION_EDIT, url);
editIntent.putExtra(ApnSettings.SUB_ID, mSubId);
context.startActivity(editIntent);
@@ -138,4 +141,8 @@ public class ApnPreference extends Preference implements
public void setSubId(int subId) {
mSubId = subId;
}
+
+ public void setDpcEnforced(boolean enforced) {
+ mDpcEnforced = enforced;
+ }
}
diff --git a/src/com/android/settings/ApnSettings.java b/src/com/android/settings/ApnSettings.java
index 3628121808e..2c22a790e8d 100755
--- a/src/com/android/settings/ApnSettings.java
+++ b/src/com/android/settings/ApnSettings.java
@@ -16,6 +16,7 @@
package com.android.settings;
+import static android.provider.Telephony.Carriers.CONTENT_URI;
import static android.provider.Telephony.Carriers.ENFORCE_MANAGED_URI;
import static android.provider.Telephony.Carriers.FILTERED_URI;
@@ -291,6 +292,7 @@ public class ApnSettings extends RestrictedSettingsFragment implements
mSelectedKey = getSelectedApnKey();
cursor.moveToFirst();
+ boolean enforced = isDpcApnEnforced();
while (!cursor.isAfterLast()) {
String name = cursor.getString(NAME_INDEX);
String apn = cursor.getString(APN_INDEX);
@@ -307,6 +309,7 @@ public class ApnSettings extends RestrictedSettingsFragment implements
pref.setPersistent(false);
pref.setOnPreferenceChangeListener(this);
pref.setSubId(subId);
+ pref.setDpcEnforced(enforced);
boolean selectable = ((type == null) || !type.equals("mms"));
pref.setSelectable(selectable);
@@ -398,7 +401,7 @@ public class ApnSettings extends RestrictedSettingsFragment implements
@Override
public boolean onPreferenceTreeClick(Preference preference) {
int pos = Integer.parseInt(preference.getKey());
- Uri url = ContentUris.withAppendedId(FILTERED_URI, pos);
+ Uri url = ContentUris.withAppendedId(isDpcApnEnforced() ? FILTERED_URI : CONTENT_URI, pos);
startActivity(new Intent(Intent.ACTION_EDIT, url));
return true;
}
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index d13a62dcbb3..dcf7ed508c7 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -16,7 +16,6 @@
package com.android.settings;
-import static com.android.settings.core.FeatureFlags.BATTERY_SETTINGS_V2;
import static com.android.settings.core.FeatureFlags.CONNECTED_DEVICE_V2;
import android.os.Bundle;
@@ -55,6 +54,7 @@ public class Settings extends SettingsActivity {
public static class NightDisplaySettingsActivity extends SettingsActivity { /* empty */ }
public static class NightDisplaySuggestionActivity extends NightDisplaySettingsActivity { /* empty */ }
public static class DeviceInfoSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class MeCardActivity extends SettingsActivity { /* empty */ }
public static class ApplicationSettingsActivity extends SettingsActivity { /* empty */ }
public static class ManageApplicationsActivity extends SettingsActivity { /* empty */ }
public static class ManageAssistActivity extends SettingsActivity { /* empty */ }
@@ -133,16 +133,8 @@ public class Settings extends SettingsActivity {
public static class AppWriteSettingsActivity extends SettingsActivity { /* empty */ }
public static class AdvancedAppsActivity extends SettingsActivity { /* empty */ }
- public static class ManageExternalSourcesActivity extends SettingsActivity {
- /* empty */ }
+ public static class ManageExternalSourcesActivity extends SettingsActivity {/* empty */ }
public static class ManageAppExternalSourcesActivity extends SettingsActivity { /* empty */ }
- public static class DoubleTapPowerSuggestionActivity extends SettingsActivity { /* empty */ }
- public static class DoubleTwistSuggestionActivity extends SettingsActivity { /* empty */ }
- public static class AmbientDisplaySuggestionActivity extends SettingsActivity { /* empty */ }
- public static class AmbientDisplayPickupSuggestionActivity extends SettingsActivity {
- /* empty */ }
- public static class SwipeToNotificationSuggestionActivity extends SettingsActivity {
- /* empty */ }
public static class WallpaperSettingsActivity extends SettingsActivity { /* empty */ }
public static class ManagedProfileSettingsActivity extends SettingsActivity { /* empty */ }
public static class DeletionHelperActivity extends SettingsActivity { /* empty */ }
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index d3580d18b86..3ac268a7927 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -877,6 +877,19 @@ public class SettingsActivity extends SettingsDrawerActivity
WifiDisplaySettings.isAvailable(this), isAdmin)
|| somethingChanged;
+ // Enable/disable the Me Card page.
+ final boolean isMeCardEnabled = featureFactory
+ .getAccountFeatureProvider()
+ .isMeCardEnabled(this);
+ somethingChanged = setTileEnabled(new ComponentName(packageName,
+ Settings.MeCardActivity.class.getName()),
+ isMeCardEnabled, isAdmin)
+ || somethingChanged;
+ somethingChanged = setTileEnabled(new ComponentName(packageName,
+ Settings.DeviceInfoSettingsActivity.class.getName()),
+ !isMeCardEnabled, isAdmin)
+ || somethingChanged;
+
if (UserHandle.MU_ENABLED && !isAdmin) {
// When on restricted users, disable all extra categories (but only the settings ones).
diff --git a/src/com/android/settings/accounts/AccountFeatureProvider.java b/src/com/android/settings/accounts/AccountFeatureProvider.java
new file mode 100644
index 00000000000..bbfc48ac17c
--- /dev/null
+++ b/src/com/android/settings/accounts/AccountFeatureProvider.java
@@ -0,0 +1,34 @@
+/*
+ * 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.accounts;
+
+import android.accounts.Account;
+import android.content.Context;
+import android.util.FeatureFlagUtils;
+
+import com.android.settings.core.FeatureFlags;
+
+public interface AccountFeatureProvider {
+ String getAccountType();
+ Account[] getAccounts(Context context);
+ /**
+ * Checks whether or not to display the new About Phone page.
+ */
+ default boolean isMeCardEnabled(Context context) {
+ return FeatureFlagUtils.isEnabled(context, FeatureFlags.ABOUT_PHONE_V2);
+ }
+}
diff --git a/src/com/android/settings/accounts/AccountFeatureProviderImpl.java b/src/com/android/settings/accounts/AccountFeatureProviderImpl.java
new file mode 100644
index 00000000000..90b581ba80e
--- /dev/null
+++ b/src/com/android/settings/accounts/AccountFeatureProviderImpl.java
@@ -0,0 +1,16 @@
+package com.android.settings.accounts;
+
+import android.accounts.Account;
+import android.content.Context;
+
+public class AccountFeatureProviderImpl implements AccountFeatureProvider {
+ @Override
+ public String getAccountType() {
+ return null;
+ }
+
+ @Override
+ public Account[] getAccounts(Context context) {
+ return new Account[0];
+ }
+}
diff --git a/src/com/android/settings/accounts/ManagedProfileSettings.java b/src/com/android/settings/accounts/ManagedProfileSettings.java
index 3ea7cf730d5..09330428d39 100644
--- a/src/com/android/settings/accounts/ManagedProfileSettings.java
+++ b/src/com/android/settings/accounts/ManagedProfileSettings.java
@@ -104,8 +104,7 @@ public class ManagedProfileSettings extends SettingsPreferenceFragment
private void loadDataAndPopulateUi() {
if (mWorkModePreference != null) {
- mWorkModePreference.setChecked(
- !mUserManager.isQuietModeEnabled(mManagedUser));
+ updateWorkModePreference();
}
if (mContactPrefrence != null) {
@@ -124,6 +123,14 @@ public class ManagedProfileSettings extends SettingsPreferenceFragment
return MetricsProto.MetricsEvent.ACCOUNTS_WORK_PROFILE_SETTINGS;
}
+ private void updateWorkModePreference() {
+ boolean isWorkModeOn = !mUserManager.isQuietModeEnabled(mManagedUser);
+ mWorkModePreference.setChecked(isWorkModeOn);
+ mWorkModePreference.setSummary(isWorkModeOn
+ ? R.string.work_mode_on_summary
+ : R.string.work_mode_off_summary);
+ }
+
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
@@ -159,8 +166,7 @@ public class ManagedProfileSettings extends SettingsPreferenceFragment
|| action.equals(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE)) {
if (intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
UserHandle.USER_NULL) == mManagedUser.getIdentifier()) {
- mWorkModePreference.setChecked(
- !mUserManager.isQuietModeEnabled(mManagedUser));
+ updateWorkModePreference();
}
return;
}
diff --git a/src/com/android/settings/core/FeatureFlags.java b/src/com/android/settings/core/FeatureFlags.java
index 4b5ce782a24..4b8ccd10e4e 100644
--- a/src/com/android/settings/core/FeatureFlags.java
+++ b/src/com/android/settings/core/FeatureFlags.java
@@ -27,4 +27,5 @@ public class FeatureFlags {
public static final String SECURITY_SETTINGS_V2 = "settings_security_settings_v2";
public static final String ZONE_PICKER_V2 = "settings_zone_picker_v2";
public static final String SUGGESTION_UI_V2 = "settings_suggestion_ui_v2";
+ public static final String ABOUT_PHONE_V2 = "settings_about_phone_v2";
}
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index 026cc2bd777..2cb1cbfa42b 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -298,5 +298,6 @@ public class SettingsGateway {
Settings.DateTimeSettingsActivity.class.getName(),
Settings.DeviceInfoSettingsActivity.class.getName(),
Settings.EnterprisePrivacySettingsActivity.class.getName(),
+ Settings.MeCardActivity.class.getName(),
};
}
diff --git a/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java b/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java
index fe19b958c2d..05c1effe8b6 100644
--- a/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java
+++ b/src/com/android/settings/dashboard/suggestions/SuggestionFeatureProviderImpl.java
@@ -30,20 +30,10 @@ import android.util.Pair;
import com.android.internal.logging.nano.MetricsProto;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settings.Settings.AmbientDisplayPickupSuggestionActivity;
-import com.android.settings.Settings.AmbientDisplaySuggestionActivity;
-import com.android.settings.Settings.DoubleTapPowerSuggestionActivity;
-import com.android.settings.Settings.DoubleTwistSuggestionActivity;
import com.android.settings.Settings.NightDisplaySuggestionActivity;
-import com.android.settings.Settings.SwipeToNotificationSuggestionActivity;
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
import com.android.settings.fingerprint.FingerprintEnrollSuggestionActivity;
import com.android.settings.fingerprint.FingerprintSuggestionActivity;
-import com.android.settings.gestures.DoubleTapPowerPreferenceController;
-import com.android.settings.gestures.DoubleTapScreenPreferenceController;
-import com.android.settings.gestures.DoubleTwistPreferenceController;
-import com.android.settings.gestures.PickupGesturePreferenceController;
-import com.android.settings.gestures.SwipeToNotificationPreferenceController;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.password.ScreenLockSuggestionActivity;
import com.android.settings.support.NewDeviceIntroSuggestionActivity;
@@ -98,21 +88,6 @@ public class SuggestionFeatureProviderImpl implements SuggestionFeatureProvider
return hasUsedNightDisplay(context);
} else if (className.equals(NewDeviceIntroSuggestionActivity.class.getName())) {
return NewDeviceIntroSuggestionActivity.isSuggestionComplete(context);
- } else if (className.equals(DoubleTapPowerSuggestionActivity.class.getName())) {
- return DoubleTapPowerPreferenceController
- .isSuggestionComplete(context, getSharedPrefs(context));
- } else if (className.equals(DoubleTwistSuggestionActivity.class.getName())) {
- return DoubleTwistPreferenceController
- .isSuggestionComplete(context, getSharedPrefs(context));
- } else if (className.equals(AmbientDisplaySuggestionActivity.class.getName())) {
- return DoubleTapScreenPreferenceController
- .isSuggestionComplete(context, getSharedPrefs(context));
- } else if (className.equals(AmbientDisplayPickupSuggestionActivity.class.getName())) {
- return PickupGesturePreferenceController
- .isSuggestionComplete(context, getSharedPrefs(context));
- } else if (className.equals(SwipeToNotificationSuggestionActivity.class.getName())) {
- return SwipeToNotificationPreferenceController
- .isSuggestionComplete(context, getSharedPrefs(context));
}
return false;
}
diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
index 0420ecfa1cc..ce4b7bf9d75 100644
--- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
+++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
@@ -398,6 +398,7 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra
controllers.add(new CameraLaserSensorPreferenceController(context));
controllers.add(new WifiDisplayCertificationPreferenceController(context));
controllers.add(new WifiVerboseLoggingPreferenceController(context));
+ controllers.add(new WifiConnectedMacRandomizationPreferenceController(context));
controllers.add(new MobileDataAlwaysOnPreferenceController(context));
controllers.add(new TetheringHardwareAccelPreferenceController(context));
controllers.add(new SelectUsbConfigPreferenceController(context, lifecycle));
diff --git a/src/com/android/settings/development/EmulateDisplayCutoutPreferenceController.java b/src/com/android/settings/development/EmulateDisplayCutoutPreferenceController.java
index 1035a1b9847..d6c74f911eb 100644
--- a/src/com/android/settings/development/EmulateDisplayCutoutPreferenceController.java
+++ b/src/com/android/settings/development/EmulateDisplayCutoutPreferenceController.java
@@ -16,41 +16,52 @@
package com.android.settings.development;
+import static android.os.UserHandle.USER_SYSTEM;
+
import android.content.Context;
import android.content.om.IOverlayManager;
import android.content.om.OverlayInfo;
+import android.content.pm.PackageManager;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.UserHandle;
import android.support.annotation.VisibleForTesting;
+import android.support.v7.preference.ListPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
-import android.support.v7.preference.TwoStatePreference;
+import android.text.TextUtils;
+import com.android.internal.util.ArrayUtils;
+import com.android.settings.R;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.development.DeveloperOptionsPreferenceController;
+import java.util.List;
+
public class EmulateDisplayCutoutPreferenceController extends
DeveloperOptionsPreferenceController implements Preference.OnPreferenceChangeListener,
PreferenceControllerMixin {
- private static final String EMULATION_OVERLAY = "com.android.internal.display.cutout.emulation";
+ public static final String EMULATION_OVERLAY_PREFIX =
+ "com.android.internal.display.cutout.emulation.";
private static final String KEY = "display_cutout_emulation";
private final IOverlayManager mOverlayManager;
private final boolean mAvailable;
- private TwoStatePreference mPreference;
+ private ListPreference mPreference;
+ private PackageManager mPackageManager;
@VisibleForTesting
- EmulateDisplayCutoutPreferenceController(Context context, IOverlayManager overlayManager) {
+ EmulateDisplayCutoutPreferenceController(Context context, PackageManager packageManager,
+ IOverlayManager overlayManager) {
super(context);
mOverlayManager = overlayManager;
- mAvailable = overlayManager != null && getEmulationOverlayInfo() != null;
+ mPackageManager = packageManager;
+ mAvailable = overlayManager != null && getOverlayInfos().length > 0;
}
public EmulateDisplayCutoutPreferenceController(Context context) {
- this(context, IOverlayManager.Stub.asInterface(
+ this(context, context.getPackageManager(), IOverlayManager.Stub.asInterface(
ServiceManager.getService(Context.OVERLAY_SERVICE)));
}
@@ -67,45 +78,95 @@ public class EmulateDisplayCutoutPreferenceController extends
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
- setPreference((TwoStatePreference) screen.findPreference(getPreferenceKey()));
+ setPreference((ListPreference) screen.findPreference(getPreferenceKey()));
}
@VisibleForTesting
- void setPreference(TwoStatePreference preference) {
+ void setPreference(ListPreference preference) {
mPreference = preference;
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
- return writeEnabled((boolean) newValue);
+ return setEmulationOverlay((String) newValue);
}
- private boolean writeEnabled(boolean newValue) {
- OverlayInfo current = getEmulationOverlayInfo();
- if (current == null || current.isEnabled() == newValue) {
- return false;
+ private boolean setEmulationOverlay(String packageName) {
+ OverlayInfo[] overlays = getOverlayInfos();
+ CharSequence currentPackageName = null;
+ for (OverlayInfo o : overlays) {
+ if (o.isEnabled()) {
+ currentPackageName = o.packageName;
+ }
}
- try {
- return mOverlayManager.setEnabled(EMULATION_OVERLAY, newValue, UserHandle.USER_SYSTEM);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
+
+ if (TextUtils.isEmpty(packageName) && TextUtils.isEmpty(currentPackageName)
+ || TextUtils.equals(packageName, currentPackageName)) {
+ // Already set.
+ return true;
}
+
+ for (OverlayInfo o : overlays) {
+ boolean isEnabled = o.isEnabled();
+ boolean shouldBeEnabled = TextUtils.equals(o.packageName, packageName);
+ if (isEnabled != shouldBeEnabled) {
+ try {
+ mOverlayManager.setEnabled(o.packageName, shouldBeEnabled, USER_SYSTEM);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+ updateState(mPreference);
+ return true;
}
@Override
public void updateState(Preference preference) {
- OverlayInfo overlayInfo = getEmulationOverlayInfo();
- mPreference.setChecked(overlayInfo != null && overlayInfo.isEnabled());
+ OverlayInfo[] overlays = getOverlayInfos();
+
+ CharSequence[] pkgs = new CharSequence[overlays.length + 1];
+ CharSequence[] labels = new CharSequence[pkgs.length];
+
+ int current = 0;
+ pkgs[0] = "";
+ labels[0] = mContext.getString(R.string.display_cutout_emulation_none);
+
+ for (int i = 0; i < overlays.length; i++) {
+ OverlayInfo o = overlays[i];
+ pkgs[i+1] = o.packageName;
+ if (o.isEnabled()) {
+ current = i+1;
+ }
+ }
+ for (int i = 1; i < pkgs.length; i++) {
+ try {
+ labels[i] = mPackageManager.getApplicationInfo(pkgs[i].toString(), 0)
+ .loadLabel(mPackageManager);
+ } catch (PackageManager.NameNotFoundException e) {
+ labels[i] = pkgs[i];
+ }
+ }
+
+ mPreference.setEntries(labels);
+ mPreference.setEntryValues(pkgs);
+ mPreference.setValueIndex(current);
+ mPreference.setSummary(labels[current]);
}
- private OverlayInfo getEmulationOverlayInfo() {
- OverlayInfo overlayInfo = null;
+ private OverlayInfo[] getOverlayInfos() {
try {
- overlayInfo = mOverlayManager.getOverlayInfo(EMULATION_OVERLAY, UserHandle.USER_SYSTEM);
+ @SuppressWarnings("unchecked") List overlayInfos =
+ mOverlayManager.getOverlayInfosForTarget("android", USER_SYSTEM);
+ for (int i = overlayInfos.size() - 1; i >= 0; i--) {
+ if (!overlayInfos.get(i).packageName.startsWith(EMULATION_OVERLAY_PREFIX)) {
+ overlayInfos.remove(i);
+ }
+ }
+ return overlayInfos.toArray(new OverlayInfo[overlayInfos.size()]);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
- return overlayInfo;
}
@Override
@@ -115,8 +176,8 @@ public class EmulateDisplayCutoutPreferenceController extends
@Override
protected void onDeveloperOptionsSwitchDisabled() {
- writeEnabled(false);
- mPreference.setChecked(false);
+ setEmulationOverlay("");
+ updateState(mPreference);
mPreference.setEnabled(false);
}
}
diff --git a/src/com/android/settings/development/WifiConnectedMacRandomizationPreferenceController.java b/src/com/android/settings/development/WifiConnectedMacRandomizationPreferenceController.java
new file mode 100644
index 00000000000..eae2355c7a2
--- /dev/null
+++ b/src/com/android/settings/development/WifiConnectedMacRandomizationPreferenceController.java
@@ -0,0 +1,93 @@
+/*
+ * 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.development;
+
+import android.content.Context;
+import android.provider.Settings;
+import android.support.annotation.VisibleForTesting;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.development.DeveloperOptionsPreferenceController;
+
+public class WifiConnectedMacRandomizationPreferenceController extends
+ DeveloperOptionsPreferenceController implements Preference.OnPreferenceChangeListener,
+ PreferenceControllerMixin {
+
+ private static final String WIFI_CONNECTED_MAC_RANDOMIZATION_KEY =
+ "wifi_connected_mac_randomization";
+
+ @VisibleForTesting
+ static final int SETTING_VALUE_ON = 1;
+ @VisibleForTesting
+ static final int SETTING_VALUE_OFF = 0;
+
+ private SwitchPreference mPreference;
+
+ public WifiConnectedMacRandomizationPreferenceController(Context context) {
+ super(context);
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return mContext.getResources().getBoolean(
+ R.bool.config_wifi_support_connected_mac_randomization);
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return WIFI_CONNECTED_MAC_RANDOMIZATION_KEY;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPreference = (SwitchPreference) screen.findPreference(getPreferenceKey());
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ final boolean isEnabled = (Boolean) newValue;
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED,
+ isEnabled ? SETTING_VALUE_ON : SETTING_VALUE_OFF);
+ return true;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ final int enableMode = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED, SETTING_VALUE_OFF);
+ mPreference.setChecked(enableMode != SETTING_VALUE_OFF);
+ }
+
+ @Override
+ protected void onDeveloperOptionsSwitchEnabled() {
+ mPreference.setEnabled(true);
+ }
+
+ @Override
+ protected void onDeveloperOptionsSwitchDisabled() {
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED, SETTING_VALUE_OFF);
+ mPreference.setChecked(false);
+ mPreference.setEnabled(false);
+ }
+}
diff --git a/src/com/android/settings/deviceinfo/BrandedAccountPreferenceController.java b/src/com/android/settings/deviceinfo/BrandedAccountPreferenceController.java
new file mode 100644
index 00000000000..5565e3de840
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/BrandedAccountPreferenceController.java
@@ -0,0 +1,78 @@
+/*
+ * 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.deviceinfo;
+
+import android.accounts.Account;
+import android.content.Context;
+import android.os.Bundle;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.R;
+import com.android.settings.Utils;
+import com.android.settings.accounts.AccountDetailDashboardFragment;
+import com.android.settings.accounts.AccountFeatureProvider;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.overlay.FeatureFactory;
+
+public class BrandedAccountPreferenceController extends BasePreferenceController {
+ private static final String KEY_PREFERENCE_TITLE = "account";
+ private final Account[] mAccounts;
+
+ public BrandedAccountPreferenceController(Context context) {
+ super(context, KEY_PREFERENCE_TITLE);
+ final AccountFeatureProvider accountFeatureProvider = FeatureFactory.getFactory(
+ mContext).getAccountFeatureProvider();
+ mAccounts = accountFeatureProvider.getAccounts(mContext);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ if (mAccounts != null && mAccounts.length > 0) {
+ return AVAILABLE;
+ }
+ return DISABLED_FOR_USER;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ final AccountFeatureProvider accountFeatureProvider = FeatureFactory.getFactory(
+ mContext).getAccountFeatureProvider();
+ final Preference accountPreference = screen.findPreference(KEY_PREFERENCE_TITLE);
+ if (accountPreference != null && (mAccounts == null || mAccounts.length == 0)) {
+ screen.removePreference(accountPreference);
+ return;
+ }
+
+ accountPreference.setSummary(mAccounts[0].name);
+ accountPreference.setOnPreferenceClickListener(preference -> {
+ final Bundle args = new Bundle();
+ args.putParcelable(AccountDetailDashboardFragment.KEY_ACCOUNT,
+ mAccounts[0]);
+ args.putParcelable(AccountDetailDashboardFragment.KEY_USER_HANDLE,
+ android.os.Process.myUserHandle());
+ args.putString(AccountDetailDashboardFragment.KEY_ACCOUNT_TYPE,
+ accountFeatureProvider.getAccountType());
+ Utils.startWithFragment(mContext, AccountDetailDashboardFragment.class.getName(),
+ args, null, 0,
+ R.string.account_sync_title, null, MetricsEvent.ACCOUNT);
+ return true;
+ });
+ }
+}
diff --git a/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java b/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java
new file mode 100644
index 00000000000..a3018072c30
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java
@@ -0,0 +1,180 @@
+/*
+ * 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.deviceinfo.aboutphone;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.os.Bundle;
+import android.os.UserManager;
+import android.provider.SearchIndexableResource;
+import android.telephony.TelephonyManager;
+import android.view.View;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.R;
+import com.android.settings.SettingsActivity;
+import com.android.settings.Utils;
+import com.android.settings.applications.LayoutPreference;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.deviceinfo.BluetoothAddressPreferenceController;
+import com.android.settings.deviceinfo.BrandedAccountPreferenceController;
+import com.android.settings.deviceinfo.BuildNumberPreferenceController;
+import com.android.settings.deviceinfo.DeviceModelPreferenceController;
+import com.android.settings.deviceinfo.FccEquipmentIdPreferenceController;
+import com.android.settings.deviceinfo.FeedbackPreferenceController;
+import com.android.settings.deviceinfo.ImsStatusPreferenceController;
+import com.android.settings.deviceinfo.IpAddressPreferenceController;
+import com.android.settings.deviceinfo.ManualPreferenceController;
+import com.android.settings.deviceinfo.PhoneNumberPreferenceController;
+import com.android.settings.deviceinfo.RegulatoryInfoPreferenceController;
+import com.android.settings.deviceinfo.SafetyInfoPreferenceController;
+import com.android.settings.deviceinfo.WifiMacAddressPreferenceController;
+import com.android.settings.deviceinfo.firmwareversion.FirmwareVersionPreferenceController;
+import com.android.settings.deviceinfo.imei.ImeiInfoPreferenceController;
+import com.android.settings.deviceinfo.simstatus.SimStatusPreferenceController;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Indexable;
+import com.android.settings.widget.EntityHeaderController;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class MyDeviceInfoFragment extends DashboardFragment {
+ private static final String LOG_TAG = "MeCardFragment";
+
+ private static final String KEY_MY_DEVICE_INFO_HEADER = "my_device_info_header";
+ private static final String KEY_LEGAL_CONTAINER = "legal_container";
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsEvent.DEVICEINFO;
+ }
+
+ @Override
+ public int getHelpResource() {
+ return R.string.help_uri_about;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ initHeader();
+ }
+
+ @Override
+ protected String getLogTag() {
+ return LOG_TAG;
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.my_device_info;
+ }
+
+ @Override
+ protected List getPreferenceControllers(Context context) {
+ return buildPreferenceControllers(context, getActivity(), this /* fragment */,
+ getLifecycle());
+ }
+
+ private static List buildPreferenceControllers(Context context,
+ Activity activity, Fragment fragment, Lifecycle lifecycle) {
+ final List controllers = new ArrayList<>();
+ controllers.add(new PhoneNumberPreferenceController(context));
+ controllers.add(new BrandedAccountPreferenceController(context));
+ controllers.add(new SimStatusPreferenceController(context, fragment));
+ controllers.add(new DeviceModelPreferenceController(context, fragment));
+ controllers.add(new ImeiInfoPreferenceController(context, fragment));
+ controllers.add(new FirmwareVersionPreferenceController(context, fragment));
+ controllers.add(new ImsStatusPreferenceController(context, lifecycle));
+ controllers.add(new IpAddressPreferenceController(context, lifecycle));
+ controllers.add(new WifiMacAddressPreferenceController(context, lifecycle));
+ controllers.add(new BluetoothAddressPreferenceController(context, lifecycle));
+ controllers.add(new RegulatoryInfoPreferenceController(context));
+ controllers.add(new SafetyInfoPreferenceController(context));
+ controllers.add(new ManualPreferenceController(context));
+ controllers.add(new FeedbackPreferenceController(fragment, context));
+ controllers.add(new FccEquipmentIdPreferenceController(context));
+ controllers.add(
+ new BuildNumberPreferenceController(context, activity, fragment, lifecycle));
+ // TODO: Add preference controller for getting the device name.
+ return controllers;
+ }
+
+ private void initHeader() {
+ // TODO: Migrate into its own controller.
+ final LayoutPreference headerPreference =
+ (LayoutPreference) getPreferenceScreen().findPreference(KEY_MY_DEVICE_INFO_HEADER);
+ final View appSnippet = headerPreference.findViewById(R.id.entity_header);
+ final Activity context = getActivity();
+ final Bundle bundle = getArguments();
+ EntityHeaderController controller = EntityHeaderController
+ .newInstance(context, this, appSnippet)
+ .setRecyclerView(getListView(), getLifecycle())
+ .setButtonActions(EntityHeaderController.ActionType.ACTION_NONE,
+ EntityHeaderController.ActionType.ACTION_NONE);
+
+ // TODO: There may be an avatar setting action we can use here.
+ final int iconId = bundle.getInt("icon_id", 0);
+ if (iconId == 0) {
+ UserManager userManager = (UserManager) getActivity().getSystemService(
+ Context.USER_SERVICE);
+ UserInfo info = Utils.getExistingUser(userManager, android.os.Process.myUserHandle());
+ controller.setLabel(info.name);
+ controller.setIcon(
+ com.android.settingslib.Utils.getUserIcon(getActivity(), userManager, info));
+ }
+
+ controller.done(context, true /* rebindActions */);
+ }
+
+ /**
+ * For Search.
+ */
+ public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider() {
+
+ @Override
+ public List getXmlResourcesToIndex(
+ Context context, boolean enabled) {
+ final SearchIndexableResource sir = new SearchIndexableResource(context);
+ sir.xmlResId = R.xml.my_device_info;
+ return Arrays.asList(sir);
+ }
+
+ @Override
+ public List getPreferenceControllers(
+ Context context) {
+ return buildPreferenceControllers(context, null /*activity */,
+ null /* fragment */, null /* lifecycle */);
+ }
+
+ @Override
+ public List getNonIndexableKeys(Context context) {
+ List keys = super.getNonIndexableKeys(context);
+ // The legal container is duplicated, so we ignore it here.
+ keys.add(KEY_LEGAL_CONTAINER);
+ return keys;
+ }
+ };
+}
diff --git a/src/com/android/settings/fuelgauge/RestrictedAppDetails.java b/src/com/android/settings/fuelgauge/RestrictedAppDetails.java
index bdaaa3a66a9..e09a8a38c84 100644
--- a/src/com/android/settings/fuelgauge/RestrictedAppDetails.java
+++ b/src/com/android/settings/fuelgauge/RestrictedAppDetails.java
@@ -20,11 +20,9 @@ import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
-import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.UserHandle;
import android.support.v14.preference.PreferenceFragment;
-import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.CheckBoxPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceGroup;
@@ -36,9 +34,7 @@ import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.Utils;
import com.android.settings.dashboard.DashboardFragment;
-import com.android.settings.fuelgauge.anomaly.Anomaly;
-import com.android.settings.fuelgauge.anomaly.AnomalyDialogFragment;
-import com.android.settings.fuelgauge.anomaly.AnomalyPreference;
+import com.android.settings.widget.AppCheckBoxPreference;
import com.android.settingslib.core.AbstractPreferenceController;
import java.util.List;
@@ -120,7 +116,7 @@ public class RestrictedAppDetails extends DashboardFragment {
final Context context = getPrefContext();
for (int i = 0, size = mPackageOpsList.size(); i < size; i++) {
- final CheckBoxPreference checkBoxPreference = new CheckBoxPreference(context);
+ final CheckBoxPreference checkBoxPreference = new AppCheckBoxPreference(context);
final AppOpsManager.PackageOps packageOps = mPackageOpsList.get(i);
try {
final ApplicationInfo applicationInfo = mPackageManager.getApplicationInfo(
@@ -128,6 +124,10 @@ public class RestrictedAppDetails extends DashboardFragment {
checkBoxPreference.setChecked(true);
checkBoxPreference.setTitle(mPackageManager.getApplicationLabel(applicationInfo));
checkBoxPreference.setKey(packageOps.getPackageName());
+ checkBoxPreference.setIcon(
+ Utils.getBadgedIcon(mIconDrawableFactory, mPackageManager,
+ packageOps.getPackageName(),
+ UserHandle.getUserId(packageOps.getUid())));
checkBoxPreference.setOnPreferenceChangeListener((pref, value) -> {
// change the toggle
final int mode = (Boolean) value ? AppOpsManager.MODE_IGNORED
diff --git a/src/com/android/settings/location/LocationEnabler.java b/src/com/android/settings/location/LocationEnabler.java
index 4dcdac0c456..28ee2138abb 100644
--- a/src/com/android/settings/location/LocationEnabler.java
+++ b/src/com/android/settings/location/LocationEnabler.java
@@ -34,8 +34,10 @@ import com.android.settingslib.core.lifecycle.events.OnPause;
import com.android.settingslib.core.lifecycle.events.OnResume;
import static com.android.settingslib.Utils.updateLocationMode;
+import static com.android.settingslib.Utils.updateLocationEnabled;
import static com.android.settingslib.RestrictedLockUtils.checkIfRestrictionEnforced;
+
/**
* A class that listens to location settings change and modifies location settings
* settings.
@@ -106,6 +108,25 @@ public class LocationEnabler implements LifecycleObserver, OnResume, OnPause {
}
}
+ void setLocationEnabled(boolean enabled) {
+ final int currentMode = Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
+
+ if (isRestricted()) {
+ // Location toggling disabled by user restriction. Read the current location mode to
+ // update the location master switch.
+ if (Log.isLoggable(TAG, Log.INFO)) {
+ Log.i(TAG, "Restricted user, not setting location mode");
+ }
+ if (mListener != null) {
+ mListener.onLocationModeChanged(currentMode, true);
+ }
+ return;
+ }
+ updateLocationEnabled(mContext, enabled, UserHandle.myUserId());
+ refreshLocationMode();
+ }
+
void setLocationMode(int mode) {
final int currentMode = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
diff --git a/src/com/android/settings/location/LocationSettings.java b/src/com/android/settings/location/LocationSettings.java
index d0fca16629d..85c049db1d5 100644
--- a/src/com/android/settings/location/LocationSettings.java
+++ b/src/com/android/settings/location/LocationSettings.java
@@ -47,15 +47,8 @@ import java.util.List;
*
* - Platform location controls
*
- * - In switch bar: location master switch. Used to toggle
- * {@link android.provider.Settings.Secure#LOCATION_MODE} between
- * {@link android.provider.Settings.Secure#LOCATION_MODE_OFF} and another location mode.
+ *
- In switch bar: location master switch. Used to toggle location on and off.
*
- * - Mode preference: only available if the master switch is on, selects between
- * {@link android.provider.Settings.Secure#LOCATION_MODE} of
- * {@link android.provider.Settings.Secure#LOCATION_MODE_HIGH_ACCURACY},
- * {@link android.provider.Settings.Secure#LOCATION_MODE_BATTERY_SAVING}, or
- * {@link android.provider.Settings.Secure#LOCATION_MODE_SENSORS_ONLY}.
*
* - Recent location requests: automatically populated by {@link RecentLocationApps}
* - Location services: multi-app settings provided from outside the Android framework. Each
diff --git a/src/com/android/settings/location/LocationSwitchBarController.java b/src/com/android/settings/location/LocationSwitchBarController.java
index 6522dc75be2..ca1932f9cc6 100644
--- a/src/com/android/settings/location/LocationSwitchBarController.java
+++ b/src/com/android/settings/location/LocationSwitchBarController.java
@@ -96,9 +96,6 @@ public class LocationSwitchBarController implements SwitchBar.OnSwitchChangeList
*/
@Override
public void onSwitchChanged(Switch switchView, boolean isChecked) {
- mLocationEnabler.setLocationMode(isChecked
- ? android.provider.Settings.Secure.LOCATION_MODE_PREVIOUS
- : android.provider.Settings.Secure.LOCATION_MODE_OFF);
+ mLocationEnabler.setLocationEnabled(isChecked);
}
-
}
diff --git a/src/com/android/settings/notification/AppNotificationSettings.java b/src/com/android/settings/notification/AppNotificationSettings.java
index ef0f40bb571..333e0600118 100644
--- a/src/com/android/settings/notification/AppNotificationSettings.java
+++ b/src/com/android/settings/notification/AppNotificationSettings.java
@@ -176,15 +176,6 @@ public class AppNotificationSettings extends NotificationSettingsBase {
} else {
groupCategory.setTitle(group.getName());
groupCategory.setKey(group.getId());
- Bundle groupArgs = new Bundle();
- groupArgs.putInt(AppInfoBase.ARG_PACKAGE_UID, mUid);
- groupArgs.putString(AppInfoBase.ARG_PACKAGE_NAME, mPkg);
- groupArgs.putString(Settings.EXTRA_CHANNEL_GROUP_ID, group.getId());
- Intent channelIntent = Utils.onBuildStartFragmentIntent(getActivity(),
- ChannelGroupNotificationSettings.class.getName(),
- groupArgs, null, R.string.notification_group_title,
- null, false, getMetricsCategory());
- groupCategory.setIntent(channelIntent);
populateGroupToggle(groupCategory, group);
}
diff --git a/src/com/android/settings/notification/ConfigureNotificationSettings.java b/src/com/android/settings/notification/ConfigureNotificationSettings.java
index 253346683cc..7cfa1248245 100644
--- a/src/com/android/settings/notification/ConfigureNotificationSettings.java
+++ b/src/com/android/settings/notification/ConfigureNotificationSettings.java
@@ -17,6 +17,8 @@
package com.android.settings.notification;
import android.app.Activity;
+import android.app.Application;
+import android.app.Fragment;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
@@ -77,11 +79,18 @@ public class ConfigureNotificationSettings extends DashboardFragment {
@Override
protected List getPreferenceControllers(Context context) {
- return buildPreferenceControllers(context, getLifecycle());
+ final Activity activity = getActivity();
+ final Application app;
+ if (activity != null) {
+ app = activity.getApplication();
+ } else {
+ app = null;
+ }
+ return buildPreferenceControllers(context, getLifecycle(), app, this);
}
private static List buildPreferenceControllers(Context context,
- Lifecycle lifecycle) {
+ Lifecycle lifecycle, Application app, Fragment host) {
final List controllers = new ArrayList<>();
final BadgingNotificationPreferenceController badgeController =
new BadgingNotificationPreferenceController(context);
@@ -96,6 +105,8 @@ public class ConfigureNotificationSettings extends DashboardFragment {
lifecycle.addObserver(pulseController);
lifecycle.addObserver(lockScreenNotificationController);
}
+ controllers.add(new RecentNotifyingAppsPreferenceController(
+ context, new NotificationBackend(), app, host));
controllers.add(new SwipeToNotificationPreferenceController(context, lifecycle,
KEY_SWIPE_DOWN));
controllers.add(badgeController);
@@ -167,7 +178,7 @@ public class ConfigureNotificationSettings extends DashboardFragment {
@Override
public List getPreferenceControllers(
Context context) {
- return buildPreferenceControllers(context, null);
+ return buildPreferenceControllers(context, null, null, null);
}
@Override
diff --git a/src/com/android/settings/notification/EnableZenModeDialog.java b/src/com/android/settings/notification/EnableZenModeDialog.java
new file mode 100644
index 00000000000..f683a2116cb
--- /dev/null
+++ b/src/com/android/settings/notification/EnableZenModeDialog.java
@@ -0,0 +1,467 @@
+package com.android.settings.notification;
+
+/*
+ * 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.
+ */
+
+import static android.util.Log.wtf;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.app.AlarmManager;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.service.notification.Condition;
+import android.service.notification.ZenModeConfig;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.CompoundButton;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.RadioButton;
+import android.widget.RadioGroup;
+import android.widget.ScrollView;
+import android.widget.TextView;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.R;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.Objects;
+
+public class EnableZenModeDialog extends InstrumentedDialogFragment {
+
+ private static final String TAG = "EnableZenModeDialog";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ private static final int[] MINUTE_BUCKETS = ZenModeConfig.MINUTE_BUCKETS;
+ private static final int MIN_BUCKET_MINUTES = MINUTE_BUCKETS[0];
+ private static final int MAX_BUCKET_MINUTES = MINUTE_BUCKETS[MINUTE_BUCKETS.length - 1];
+ private static final int DEFAULT_BUCKET_INDEX = Arrays.binarySearch(MINUTE_BUCKETS, 60);
+
+ @VisibleForTesting
+ public static final int FOREVER_CONDITION_INDEX = 0;
+ @VisibleForTesting
+ public static final int COUNTDOWN_CONDITION_INDEX = 1;
+ @VisibleForTesting
+ public static final int COUNTDOWN_ALARM_CONDITION_INDEX = 2;
+ @VisibleForTesting
+ protected Activity mActivity;
+
+ private static final int SECONDS_MS = 1000;
+ private static final int MINUTES_MS = 60 * SECONDS_MS;
+
+ @VisibleForTesting
+ protected Uri mForeverId;
+ private int mBucketIndex = -1;
+
+ private AlarmManager mAlarmManager;
+ private int mUserId;
+ private boolean mAttached;
+
+ @VisibleForTesting
+ protected Context mContext;
+
+ private RadioGroup mZenRadioGroup;
+ @VisibleForTesting
+ protected LinearLayout mZenRadioGroupContent;
+ private int MAX_MANUAL_DND_OPTIONS = 3;
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ NotificationManager noMan = (NotificationManager) getContext().
+ getSystemService(Context.NOTIFICATION_SERVICE);
+ mContext = getContext();
+ mForeverId = Condition.newId(mContext).appendPath("forever").build();
+ mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
+ mUserId = mContext.getUserId();
+ mAttached = false;
+
+ final AlertDialog.Builder builder = new AlertDialog.Builder(getContext())
+ .setTitle(R.string.zen_mode_settings_turn_on_dialog_title)
+ .setNegativeButton(R.string.cancel, null)
+ .setPositiveButton(R.string.zen_mode_enable_dialog_turn_on,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ int checkedId = mZenRadioGroup.getCheckedRadioButtonId();
+ ConditionTag tag = getConditionTagAt(checkedId);
+
+ if (isForever(tag.condition)) {
+ MetricsLogger.action(getContext(),
+ MetricsProto.MetricsEvent.
+ NOTIFICATION_ZEN_MODE_TOGGLE_ON_FOREVER);
+ } else if (isAlarm(tag.condition)) {
+ MetricsLogger.action(getContext(),
+ MetricsProto.MetricsEvent.
+ NOTIFICATION_ZEN_MODE_TOGGLE_ON_ALARM);
+ } else if (isCountdown(tag.condition)) {
+ MetricsLogger.action(getContext(),
+ MetricsProto.MetricsEvent.
+ NOTIFICATION_ZEN_MODE_TOGGLE_ON_COUNTDOWN);
+ } else {
+ wtf(TAG, "Invalid manual condition: " + tag.condition);
+ }
+ // always triggers priority-only dnd with chosen condition
+ noMan.setZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+ getRealConditionId(tag.condition), TAG);
+ }
+ });
+
+ View contentView = getContentView();
+ bindConditions(forever());
+ builder.setView(contentView);
+ return builder.create();
+ }
+
+ private void hideAllConditions() {
+ final int N = mZenRadioGroupContent.getChildCount();
+ for (int i = 0; i < N; i++) {
+ mZenRadioGroupContent.getChildAt(i).setVisibility(View.GONE);
+ }
+ }
+
+ protected View getContentView() {
+ if (mActivity == null) {
+ mActivity = getActivity();
+ }
+ final LayoutInflater inflater = mActivity.getLayoutInflater();
+ View contentView = inflater.inflate(R.layout.zen_mode_turn_on_dialog_container, null);
+ ScrollView container = (ScrollView) contentView.findViewById(R.id.container);
+
+ mZenRadioGroup = container.findViewById(R.id.zen_radio_buttons);
+ mZenRadioGroupContent = container.findViewById(R.id.zen_radio_buttons_content);
+
+ for (int i = 0; i < MAX_MANUAL_DND_OPTIONS; i++) {
+ final View radioButton = inflater.inflate(R.layout.zen_mode_radio_button,
+ mZenRadioGroup, false);
+ mZenRadioGroup.addView(radioButton);
+ radioButton.setId(i);
+
+ final View radioButtonContent = inflater.inflate(R.layout.zen_mode_condition,
+ mZenRadioGroupContent, false);
+ radioButtonContent.setId(i + MAX_MANUAL_DND_OPTIONS);
+ mZenRadioGroupContent.addView(radioButtonContent);
+ }
+ hideAllConditions();
+ return contentView;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsProto.MetricsEvent.NOTIFICATION_ZEN_MODE_ENABLE_DIALOG;
+ }
+
+ @VisibleForTesting
+ protected void bind(final Condition condition, final View row, final int rowId) {
+ if (condition == null) throw new IllegalArgumentException("condition must not be null");
+ final boolean enabled = condition.state == Condition.STATE_TRUE;
+ final ConditionTag tag = row.getTag() != null ? (ConditionTag) row.getTag() :
+ new ConditionTag();
+ row.setTag(tag);
+ final boolean first = tag.rb == null;
+ if (tag.rb == null) {
+ tag.rb = (RadioButton) mZenRadioGroup.getChildAt(rowId);
+ }
+ tag.condition = condition;
+ final Uri conditionId = getConditionId(tag.condition);
+ if (DEBUG) Log.d(TAG, "bind i=" + mZenRadioGroupContent.indexOfChild(row) + " first="
+ + first + " condition=" + conditionId);
+ tag.rb.setEnabled(enabled);
+ tag.rb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ if (isChecked) {
+ tag.rb.setChecked(true);
+ if (DEBUG) Log.d(TAG, "onCheckedChanged " + conditionId);
+ MetricsLogger.action(mContext,
+ MetricsProto.MetricsEvent.QS_DND_CONDITION_SELECT);
+ announceConditionSelection(tag);
+ }
+ }
+ });
+
+ updateUi(tag, row, condition, enabled, rowId, conditionId);
+ row.setVisibility(View.VISIBLE);
+ }
+
+ @VisibleForTesting
+ protected ConditionTag getConditionTagAt(int index) {
+ return (ConditionTag) mZenRadioGroupContent.getChildAt(index).getTag();
+ }
+
+ @VisibleForTesting
+ protected void bindConditions(Condition c) {
+ // forever
+ bind(forever(), mZenRadioGroupContent.getChildAt(FOREVER_CONDITION_INDEX),
+ FOREVER_CONDITION_INDEX);
+ if (c == null) {
+ bindGenericCountdown();
+ bindNextAlarm(getTimeUntilNextAlarmCondition());
+ } else if (isForever(c)) {
+ getConditionTagAt(FOREVER_CONDITION_INDEX).rb.setChecked(true);
+ bindGenericCountdown();
+ bindNextAlarm(getTimeUntilNextAlarmCondition());
+ } else {
+ if (isAlarm(c)) {
+ bindGenericCountdown();
+ bindNextAlarm(c);
+ getConditionTagAt(COUNTDOWN_ALARM_CONDITION_INDEX).rb.setChecked(true);
+ } else if (isCountdown(c)) {
+ bindNextAlarm(getTimeUntilNextAlarmCondition());
+ bind(c, mZenRadioGroupContent.getChildAt(COUNTDOWN_CONDITION_INDEX),
+ COUNTDOWN_CONDITION_INDEX);
+ getConditionTagAt(COUNTDOWN_CONDITION_INDEX).rb.setChecked(true);
+ } else {
+ wtf(TAG, "Invalid manual condition: " + c);
+ }
+ }
+ }
+
+ public static Uri getConditionId(Condition condition) {
+ return condition != null ? condition.id : null;
+ }
+
+ public Condition forever() {
+ Uri foreverId = Condition.newId(mContext).appendPath("forever").build();
+ return new Condition(foreverId, foreverSummary(mContext), "", "", 0 /*icon*/,
+ Condition.STATE_TRUE, 0 /*flags*/);
+ }
+
+ public long getNextAlarm() {
+ final AlarmManager.AlarmClockInfo info = mAlarmManager.getNextAlarmClock(mUserId);
+ return info != null ? info.getTriggerTime() : 0;
+ }
+
+ @VisibleForTesting
+ protected boolean isAlarm(Condition c) {
+ return c != null && ZenModeConfig.isValidCountdownToAlarmConditionId(c.id);
+ }
+
+ @VisibleForTesting
+ protected boolean isCountdown(Condition c) {
+ return c != null && ZenModeConfig.isValidCountdownConditionId(c.id);
+ }
+
+ private boolean isForever(Condition c) {
+ return c != null && mForeverId.equals(c.id);
+ }
+
+ private Uri getRealConditionId(Condition condition) {
+ return isForever(condition) ? null : getConditionId(condition);
+ }
+
+ private String foreverSummary(Context context) {
+ return context.getString(com.android.internal.R.string.zen_mode_forever);
+ }
+
+ private static void setToMidnight(Calendar calendar) {
+ calendar.set(Calendar.HOUR_OF_DAY, 0);
+ calendar.set(Calendar.MINUTE, 0);
+ calendar.set(Calendar.SECOND, 0);
+ calendar.set(Calendar.MILLISECOND, 0);
+ }
+
+ // Returns a time condition if the next alarm is within the next week.
+ @VisibleForTesting
+ protected Condition getTimeUntilNextAlarmCondition() {
+ GregorianCalendar weekRange = new GregorianCalendar();
+ setToMidnight(weekRange);
+ weekRange.add(Calendar.DATE, 6);
+ final long nextAlarmMs = getNextAlarm();
+ if (nextAlarmMs > 0) {
+ GregorianCalendar nextAlarm = new GregorianCalendar();
+ nextAlarm.setTimeInMillis(nextAlarmMs);
+ setToMidnight(nextAlarm);
+
+ if (weekRange.compareTo(nextAlarm) >= 0) {
+ return ZenModeConfig.toNextAlarmCondition(mContext, nextAlarmMs,
+ ActivityManager.getCurrentUser());
+ }
+ }
+ return null;
+ }
+
+ @VisibleForTesting
+ protected void bindGenericCountdown() {
+ mBucketIndex = DEFAULT_BUCKET_INDEX;
+ Condition countdown = ZenModeConfig.toTimeCondition(mContext,
+ MINUTE_BUCKETS[mBucketIndex], ActivityManager.getCurrentUser());
+ if (!mAttached || getConditionTagAt(COUNTDOWN_CONDITION_INDEX).condition == null) {
+ bind(countdown, mZenRadioGroupContent.getChildAt(COUNTDOWN_CONDITION_INDEX),
+ COUNTDOWN_CONDITION_INDEX);
+ }
+ }
+
+ private void updateUi(ConditionTag tag, View row, Condition condition,
+ boolean enabled, int rowId, Uri conditionId) {
+ if (tag.lines == null) {
+ tag.lines = row.findViewById(android.R.id.content);
+ }
+ if (tag.line1 == null) {
+ tag.line1 = (TextView) row.findViewById(android.R.id.text1);
+ }
+
+ if (tag.line2 == null) {
+ tag.line2 = (TextView) row.findViewById(android.R.id.text2);
+ }
+
+ final String line1 = !TextUtils.isEmpty(condition.line1) ? condition.line1
+ : condition.summary;
+ final String line2 = condition.line2;
+ tag.line1.setText(line1);
+ if (TextUtils.isEmpty(line2)) {
+ tag.line2.setVisibility(View.GONE);
+ } else {
+ tag.line2.setVisibility(View.VISIBLE);
+ tag.line2.setText(line2);
+ }
+ tag.lines.setEnabled(enabled);
+ tag.lines.setAlpha(enabled ? 1 : .4f);
+
+ tag.lines.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ tag.rb.setChecked(true);
+ }
+ });
+
+ // minus button
+ final ImageView button1 = (ImageView) row.findViewById(android.R.id.button1);
+ button1.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ onClickTimeButton(row, tag, false /*down*/, rowId);
+ }
+ });
+
+ // plus button
+ final ImageView button2 = (ImageView) row.findViewById(android.R.id.button2);
+ button2.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ onClickTimeButton(row, tag, true /*up*/, rowId);
+ }
+ });
+
+ final long time = ZenModeConfig.tryParseCountdownConditionId(conditionId);
+ if (rowId == COUNTDOWN_CONDITION_INDEX && time > 0) {
+ button1.setVisibility(View.VISIBLE);
+ button2.setVisibility(View.VISIBLE);
+ if (mBucketIndex > -1) {
+ button1.setEnabled(mBucketIndex > 0);
+ button2.setEnabled(mBucketIndex < MINUTE_BUCKETS.length - 1);
+ } else {
+ final long span = time - System.currentTimeMillis();
+ button1.setEnabled(span > MIN_BUCKET_MINUTES * MINUTES_MS);
+ final Condition maxCondition = ZenModeConfig.toTimeCondition(mContext,
+ MAX_BUCKET_MINUTES, ActivityManager.getCurrentUser());
+ button2.setEnabled(!Objects.equals(condition.summary, maxCondition.summary));
+ }
+
+ button1.setAlpha(button1.isEnabled() ? 1f : .5f);
+ button2.setAlpha(button2.isEnabled() ? 1f : .5f);
+ } else {
+ button1.setVisibility(View.GONE);
+ button2.setVisibility(View.GONE);
+ }
+ }
+
+ @VisibleForTesting
+ protected void bindNextAlarm(Condition c) {
+ View alarmContent = mZenRadioGroupContent.getChildAt(COUNTDOWN_ALARM_CONDITION_INDEX);
+ ConditionTag tag = (ConditionTag) alarmContent.getTag();
+
+ if (c != null && (!mAttached || tag == null || tag.condition == null)) {
+ bind(c, alarmContent, COUNTDOWN_ALARM_CONDITION_INDEX);
+ }
+
+ // hide the alarm radio button if there isn't a "next alarm condition"
+ tag = (ConditionTag) alarmContent.getTag();
+ boolean showAlarm = tag != null && tag.condition != null;
+ mZenRadioGroup.getChildAt(COUNTDOWN_ALARM_CONDITION_INDEX).setVisibility(
+ showAlarm ? View.VISIBLE : View.GONE);
+ alarmContent.setVisibility(showAlarm ? View.VISIBLE : View.GONE);
+ }
+
+ private void onClickTimeButton(View row, ConditionTag tag, boolean up, int rowId) {
+ MetricsLogger.action(mContext, MetricsProto.MetricsEvent.QS_DND_TIME, up);
+ Condition newCondition = null;
+ final int N = MINUTE_BUCKETS.length;
+ if (mBucketIndex == -1) {
+ // not on a known index, search for the next or prev bucket by time
+ final Uri conditionId = getConditionId(tag.condition);
+ final long time = ZenModeConfig.tryParseCountdownConditionId(conditionId);
+ final long now = System.currentTimeMillis();
+ for (int i = 0; i < N; i++) {
+ int j = up ? i : N - 1 - i;
+ final int bucketMinutes = MINUTE_BUCKETS[j];
+ final long bucketTime = now + bucketMinutes * MINUTES_MS;
+ if (up && bucketTime > time || !up && bucketTime < time) {
+ mBucketIndex = j;
+ newCondition = ZenModeConfig.toTimeCondition(mContext,
+ bucketTime, bucketMinutes, ActivityManager.getCurrentUser(),
+ false /*shortVersion*/);
+ break;
+ }
+ }
+ if (newCondition == null) {
+ mBucketIndex = DEFAULT_BUCKET_INDEX;
+ newCondition = ZenModeConfig.toTimeCondition(mContext,
+ MINUTE_BUCKETS[mBucketIndex], ActivityManager.getCurrentUser());
+ }
+ } else {
+ // on a known index, simply increment or decrement
+ mBucketIndex = Math.max(0, Math.min(N - 1, mBucketIndex + (up ? 1 : -1)));
+ newCondition = ZenModeConfig.toTimeCondition(mContext,
+ MINUTE_BUCKETS[mBucketIndex], ActivityManager.getCurrentUser());
+ }
+ bind(newCondition, row, rowId);
+ tag.rb.setChecked(true);
+ announceConditionSelection(tag);
+ }
+
+ private void announceConditionSelection(ConditionTag tag) {
+ // condition will always be priority-only
+ String modeText = mContext.getString(R.string.zen_interruption_level_priority);
+ if (tag.line1 != null) {
+ mZenRadioGroupContent.announceForAccessibility(mContext.getString(
+ R.string.zen_mode_and_condition, modeText, tag.line1.getText()));
+ }
+ }
+
+ // used as the view tag on condition rows
+ @VisibleForTesting
+ protected static class ConditionTag {
+ public RadioButton rb;
+ public View lines;
+ public TextView line1;
+ public TextView line2;
+ public Condition condition;
+ }
+}
diff --git a/src/com/android/settings/notification/NotificationBackend.java b/src/com/android/settings/notification/NotificationBackend.java
index 4de528e0a03..e047efa154b 100644
--- a/src/com/android/settings/notification/NotificationBackend.java
+++ b/src/com/android/settings/notification/NotificationBackend.java
@@ -27,12 +27,16 @@ import android.content.pm.ParceledListSlice;
import android.graphics.drawable.Drawable;
import android.os.ServiceManager;
import android.os.UserHandle;
+import android.service.notification.NotifyingApp;
import android.util.IconDrawableFactory;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settingslib.Utils;
+import java.util.ArrayList;
+import java.util.List;
+
public class NotificationBackend {
private static final String TAG = "NotificationBackend";
@@ -185,7 +189,6 @@ public class NotificationBackend {
}
}
-
public int getDeletedChannelCount(String pkg, int uid) {
try {
return sINM.getDeletedChannelCount(pkg, uid);
@@ -204,6 +207,15 @@ public class NotificationBackend {
}
}
+ public List getRecentApps() {
+ try {
+ return sINM.getRecentNotifyingAppsForUser(UserHandle.myUserId()).getList();
+ } catch (Exception e) {
+ Log.w(TAG, "Error calling NoMan", e);
+ return new ArrayList<>();
+ }
+ }
+
static class Row {
public String section;
}
diff --git a/src/com/android/settings/notification/NotificationSettingsBase.java b/src/com/android/settings/notification/NotificationSettingsBase.java
index 2a7e7d55848..8b0ed463a80 100644
--- a/src/com/android/settings/notification/NotificationSettingsBase.java
+++ b/src/com/android/settings/notification/NotificationSettingsBase.java
@@ -168,14 +168,7 @@ abstract public class NotificationSettingsBase extends DashboardFragment {
mChannel = (args != null && args.containsKey(Settings.EXTRA_CHANNEL_ID)) ?
mBackend.getChannel(mPkg, mUid, args.getString(Settings.EXTRA_CHANNEL_ID)) : null;
- NotificationChannelGroup group =
- (args != null && args.containsKey(Settings.EXTRA_CHANNEL_GROUP_ID))
- ? mBackend.getGroupWithChannels(mPkg, mUid,
- args.getString(Settings.EXTRA_CHANNEL_GROUP_ID))
- : null;
- if (group != null) {
- mChannelGroup = new NotificationChannelGroupWrapper(group);
- }
+ NotificationChannelGroup group = null;
mSuspendedAppsAdmin = RestrictedLockUtils.checkIfApplicationIsSuspended(
mContext, mPkg, mUserId);
diff --git a/src/com/android/settings/notification/RecentNotifyingAppsPreferenceController.java b/src/com/android/settings/notification/RecentNotifyingAppsPreferenceController.java
new file mode 100644
index 00000000000..ef34a9b65e6
--- /dev/null
+++ b/src/com/android/settings/notification/RecentNotifyingAppsPreferenceController.java
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification;
+
+import android.app.Application;
+import android.app.Fragment;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.UserHandle;
+import android.service.notification.NotifyingApp;
+import android.support.annotation.VisibleForTesting;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceCategory;
+import android.support.v7.preference.PreferenceScreen;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.IconDrawableFactory;
+import android.util.Log;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.R;
+import com.android.settings.Utils;
+import com.android.settings.applications.AppInfoBase;
+import com.android.settings.applications.InstalledAppCounter;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.widget.AppPreference;
+import com.android.settingslib.applications.AppUtils;
+import com.android.settingslib.applications.ApplicationsState;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.wrapper.PackageManagerWrapper;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * This controller displays a list of recently used apps and a "See all" button. If there is
+ * no recently used app, "See all" will be displayed as "Notifications".
+ */
+public class RecentNotifyingAppsPreferenceController extends AbstractPreferenceController
+ implements PreferenceControllerMixin {
+
+ private static final String TAG = "RecentNotisCtrl";
+ private static final String KEY_PREF_CATEGORY = "recent_notifications_category";
+ @VisibleForTesting
+ static final String KEY_DIVIDER = "all_notifications_divider";
+ @VisibleForTesting
+ static final String KEY_SEE_ALL = "all_notifications";
+ private static final int SHOW_RECENT_APP_COUNT = 5;
+ private static final Set SKIP_SYSTEM_PACKAGES = new ArraySet<>();
+
+ private final Fragment mHost;
+ private final PackageManager mPm;
+ private final NotificationBackend mNotificationBackend;
+ private final int mUserId;
+ private final IconDrawableFactory mIconDrawableFactory;
+
+ private List mApps;
+ private final ApplicationsState mApplicationsState;
+
+ private PreferenceCategory mCategory;
+ private Preference mSeeAllPref;
+ private Preference mDivider;
+ private boolean mHasRecentApps;
+
+ static {
+ SKIP_SYSTEM_PACKAGES.addAll(Arrays.asList(
+ "android",
+ "com.android.phone",
+ "com.android.settings",
+ "com.android.systemui",
+ "com.android.providers.calendar",
+ "com.android.providers.media"
+ ));
+ }
+
+ public RecentNotifyingAppsPreferenceController(Context context, NotificationBackend backend,
+ Application app, Fragment host) {
+ this(context, backend, app == null ? null : ApplicationsState.getInstance(app), host);
+ }
+
+ @VisibleForTesting(otherwise = VisibleForTesting.NONE)
+ RecentNotifyingAppsPreferenceController(Context context, NotificationBackend backend,
+ ApplicationsState appState, Fragment host) {
+ super(context);
+ mIconDrawableFactory = IconDrawableFactory.newInstance(context);
+ mUserId = UserHandle.myUserId();
+ mPm = context.getPackageManager();
+ mHost = host;
+ mApplicationsState = appState;
+ mNotificationBackend = backend;
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return true;
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY_PREF_CATEGORY;
+ }
+
+ @Override
+ public void updateNonIndexableKeys(List keys) {
+ PreferenceControllerMixin.super.updateNonIndexableKeys(keys);
+ // Don't index category name into search. It's not actionable.
+ keys.add(KEY_PREF_CATEGORY);
+ keys.add(KEY_DIVIDER);
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ mCategory = (PreferenceCategory) screen.findPreference(getPreferenceKey());
+ mSeeAllPref = screen.findPreference(KEY_SEE_ALL);
+ mDivider = screen.findPreference(KEY_DIVIDER);
+ super.displayPreference(screen);
+ refreshUi(mCategory.getContext());
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ refreshUi(mCategory.getContext());
+ // Show total number of installed apps as See all's summary.
+ new InstalledAppCounter(mContext, InstalledAppCounter.IGNORE_INSTALL_REASON,
+ new PackageManagerWrapper(mContext.getPackageManager())) {
+ @Override
+ protected void onCountComplete(int num) {
+ if (mHasRecentApps) {
+ mSeeAllPref.setTitle(mContext.getString(R.string.see_all_apps_title, num));
+ } else {
+ mSeeAllPref.setSummary(mContext.getString(R.string.apps_summary, num));
+ }
+ }
+ }.execute();
+
+ }
+
+ @VisibleForTesting
+ void refreshUi(Context prefContext) {
+ reloadData();
+ final List recentApps = getDisplayableRecentAppList();
+ if (recentApps != null && !recentApps.isEmpty()) {
+ mHasRecentApps = true;
+ displayRecentApps(prefContext, recentApps);
+ } else {
+ mHasRecentApps = false;
+ displayOnlyAllAppsLink();
+ }
+ }
+
+ @VisibleForTesting
+ void reloadData() {
+ mApps = mNotificationBackend.getRecentApps();
+ }
+
+ private void displayOnlyAllAppsLink() {
+ mCategory.setTitle(null);
+ mDivider.setVisible(false);
+ mSeeAllPref.setTitle(R.string.notifications_title);
+ mSeeAllPref.setIcon(null);
+ int prefCount = mCategory.getPreferenceCount();
+ for (int i = prefCount - 1; i >= 0; i--) {
+ final Preference pref = mCategory.getPreference(i);
+ if (!TextUtils.equals(pref.getKey(), KEY_SEE_ALL)) {
+ mCategory.removePreference(pref);
+ }
+ }
+ }
+
+ private void displayRecentApps(Context prefContext, List recentApps) {
+ mCategory.setTitle(R.string.recent_notifications);
+ mDivider.setVisible(true);
+ mSeeAllPref.setSummary(null);
+ mSeeAllPref.setIcon(R.drawable.ic_chevron_right_24dp);
+
+ // Rebind prefs/avoid adding new prefs if possible. Adding/removing prefs causes jank.
+ // Build a cached preference pool
+ final Map appPreferences = new ArrayMap<>();
+ int prefCount = mCategory.getPreferenceCount();
+ for (int i = 0; i < prefCount; i++) {
+ final Preference pref = mCategory.getPreference(i);
+ final String key = pref.getKey();
+ if (!TextUtils.equals(key, KEY_SEE_ALL)) {
+ appPreferences.put(key, pref);
+ }
+ }
+ final int recentAppsCount = recentApps.size();
+ for (int i = 0; i < recentAppsCount; i++) {
+ final NotifyingApp app = recentApps.get(i);
+ // Bind recent apps to existing prefs if possible, or create a new pref.
+ final String pkgName = app.getPackage();
+ final ApplicationsState.AppEntry appEntry =
+ mApplicationsState.getEntry(app.getPackage(), mUserId);
+ if (appEntry == null) {
+ continue;
+ }
+
+ boolean rebindPref = true;
+ Preference pref = appPreferences.remove(pkgName);
+ if (pref == null) {
+ pref = new AppPreference(prefContext);
+ rebindPref = false;
+ }
+ pref.setKey(pkgName);
+ pref.setTitle(appEntry.label);
+ pref.setIcon(mIconDrawableFactory.getBadgedIcon(appEntry.info));
+ pref.setSummary(Utils.formatRelativeTime(mContext,
+ System.currentTimeMillis() - app.getLastNotified(), false));
+ pref.setOrder(i);
+ pref.setOnPreferenceClickListener(preference -> {
+ AppInfoBase.startAppInfoFragment(AppNotificationSettings.class,
+ R.string.notifications_title, pkgName, appEntry.info.uid, mHost,
+ 1001 /*RequestCode */,
+ MetricsProto.MetricsEvent.MANAGE_APPLICATIONS_NOTIFICATIONS);
+ return true;
+ });
+ if (!rebindPref) {
+ mCategory.addPreference(pref);
+ }
+ }
+ // Remove unused prefs from pref cache pool
+ for (Preference unusedPrefs : appPreferences.values()) {
+ mCategory.removePreference(unusedPrefs);
+ }
+ }
+
+ private List getDisplayableRecentAppList() {
+ Collections.sort(mApps);
+ List displayableApps = new ArrayList<>(SHOW_RECENT_APP_COUNT);
+ int count = 0;
+ for (NotifyingApp app : mApps) {
+ final ApplicationsState.AppEntry appEntry = mApplicationsState.getEntry(
+ app.getPackage(), mUserId);
+ if (appEntry == null) {
+ continue;
+ }
+ if (!shouldIncludePkgInRecents(app.getPackage())) {
+ continue;
+ }
+ displayableApps.add(app);
+ count++;
+ if (count >= SHOW_RECENT_APP_COUNT) {
+ break;
+ }
+ }
+ return displayableApps;
+ }
+
+
+ /**
+ * Whether or not the app should be included in recent list.
+ */
+ private boolean shouldIncludePkgInRecents(String pkgName) {
+ if (SKIP_SYSTEM_PACKAGES.contains(pkgName)) {
+ Log.d(TAG, "System package, skipping " + pkgName);
+ return false;
+ }
+ final Intent launchIntent = new Intent().addCategory(Intent.CATEGORY_LAUNCHER)
+ .setPackage(pkgName);
+
+ if (mPm.resolveActivity(launchIntent, 0) == null) {
+ // Not visible on launcher -> likely not a user visible app, skip if non-instant.
+ final ApplicationsState.AppEntry appEntry =
+ mApplicationsState.getEntry(pkgName, mUserId);
+ if (!AppUtils.isInstant(appEntry.info)) {
+ Log.d(TAG, "Not a user visible or instant app, skipping " + pkgName);
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/src/com/android/settings/notification/ZenModeButtonPreferenceController.java b/src/com/android/settings/notification/ZenModeButtonPreferenceController.java
index f5169f04500..da540f4100e 100644
--- a/src/com/android/settings/notification/ZenModeButtonPreferenceController.java
+++ b/src/com/android/settings/notification/ZenModeButtonPreferenceController.java
@@ -16,6 +16,7 @@
package com.android.settings.notification;
+import android.app.FragmentManager;
import android.content.Context;
import android.provider.Settings;
import android.support.v7.preference.Preference;
@@ -31,12 +32,16 @@ import com.android.settingslib.core.lifecycle.Lifecycle;
public class ZenModeButtonPreferenceController extends AbstractZenModePreferenceController
implements PreferenceControllerMixin {
+ private static final String TAG = "EnableZenModeButton";
protected static final String KEY = "zen_mode_settings_button_container";
private Button mZenButtonOn;
private Button mZenButtonOff;
+ private FragmentManager mFragment;
- public ZenModeButtonPreferenceController(Context context, Lifecycle lifecycle) {
+ public ZenModeButtonPreferenceController(Context context, Lifecycle lifecycle, FragmentManager
+ fragment) {
super(context, KEY, lifecycle);
+ mFragment = fragment;
}
@Override
@@ -56,11 +61,8 @@ public class ZenModeButtonPreferenceController extends AbstractZenModePreference
if (null == mZenButtonOn) {
mZenButtonOn = (Button) ((LayoutPreference) preference)
.findViewById(R.id.zen_mode_settings_turn_on_button);
- mZenButtonOn.setOnClickListener(v -> {
- mMetricsFeatureProvider.action(mContext,
- MetricsProto.MetricsEvent.ACTION_ZEN_TOGGLE_DND_BUTTON, true);
- mBackend.setZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS);
- });
+ mZenButtonOn.setOnClickListener(v ->
+ new EnableZenModeDialog().show(mFragment, TAG));
}
if (null == mZenButtonOff) {
diff --git a/src/com/android/settings/notification/ZenModeSettings.java b/src/com/android/settings/notification/ZenModeSettings.java
index 1ee20d30633..a6145c442d1 100644
--- a/src/com/android/settings/notification/ZenModeSettings.java
+++ b/src/com/android/settings/notification/ZenModeSettings.java
@@ -17,6 +17,7 @@
package com.android.settings.notification;
import android.app.AutomaticZenRule;
+import android.app.FragmentManager;
import android.app.NotificationManager;
import android.app.NotificationManager.Policy;
import android.content.Context;
@@ -50,7 +51,7 @@ public class ZenModeSettings extends ZenModeSettingsBase {
@Override
protected List getPreferenceControllers(Context context) {
- return buildPreferenceControllers(context, getLifecycle());
+ return buildPreferenceControllers(context, getLifecycle(), getFragmentManager());
}
@Override
@@ -59,11 +60,11 @@ public class ZenModeSettings extends ZenModeSettingsBase {
}
private static List buildPreferenceControllers(Context context,
- Lifecycle lifecycle) {
+ Lifecycle lifecycle, FragmentManager fragmentManager) {
List controllers = new ArrayList<>();
controllers.add(new ZenModeBehaviorPreferenceController(context, lifecycle));
controllers.add(new ZenModeAutomationPreferenceController(context));
- controllers.add(new ZenModeButtonPreferenceController(context, lifecycle));
+ controllers.add(new ZenModeButtonPreferenceController(context, lifecycle, fragmentManager));
controllers.add(new ZenModeSettingsFooterPreferenceController(context, lifecycle));
return controllers;
}
@@ -211,7 +212,7 @@ public class ZenModeSettings extends ZenModeSettingsBase {
@Override
public List getPreferenceControllers(Context
context) {
- return buildPreferenceControllers(context, null);
+ return buildPreferenceControllers(context, null, null);
}
};
}
diff --git a/src/com/android/settings/overlay/FeatureFactory.java b/src/com/android/settings/overlay/FeatureFactory.java
index dc9df8399f9..71fbaa4ecdd 100644
--- a/src/com/android/settings/overlay/FeatureFactory.java
+++ b/src/com/android/settings/overlay/FeatureFactory.java
@@ -21,6 +21,7 @@ import android.text.TextUtils;
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.bluetooth.BluetoothFeatureProvider;
import com.android.settings.connecteddevice.SmsMirroringFeatureProvider;
@@ -109,6 +110,8 @@ public abstract class FeatureFactory {
public abstract SlicesFeatureProvider getSlicesFeatureProvider();
+ public abstract AccountFeatureProvider getAccountFeatureProvider();
+
public static final class FactoryNotFoundException extends RuntimeException {
public FactoryNotFoundException(Throwable throwable) {
super("Unable to create factory. Did you misconfigure Proguard?", throwable);
diff --git a/src/com/android/settings/overlay/FeatureFactoryImpl.java b/src/com/android/settings/overlay/FeatureFactoryImpl.java
index 275ebb66865..45dc238c42d 100644
--- a/src/com/android/settings/overlay/FeatureFactoryImpl.java
+++ b/src/com/android/settings/overlay/FeatureFactoryImpl.java
@@ -23,6 +23,8 @@ import android.net.ConnectivityManager;
import android.os.UserManager;
import android.support.annotation.Keep;
+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.bluetooth.BluetoothFeatureProvider;
@@ -78,6 +80,7 @@ public class FeatureFactoryImpl extends FeatureFactory {
private DataPlanFeatureProvider mDataPlanFeatureProvider;
private SmsMirroringFeatureProvider mSmsMirroringFeatureProvider;
private SlicesFeatureProvider mSlicesFeatureProvider;
+ private AccountFeatureProvider mAccountFeatureProvider;
@Override
public SupportFeatureProvider getSupportFeatureProvider(Context context) {
@@ -219,4 +222,12 @@ public class FeatureFactoryImpl extends FeatureFactory {
}
return mSlicesFeatureProvider;
}
+
+ @Override
+ public AccountFeatureProvider getAccountFeatureProvider() {
+ if (mAccountFeatureProvider == null) {
+ mAccountFeatureProvider = new AccountFeatureProviderImpl();
+ }
+ return mAccountFeatureProvider;
+ }
}
diff --git a/src/com/android/settings/search/SearchIndexableResourcesImpl.java b/src/com/android/settings/search/SearchIndexableResourcesImpl.java
index 2c20703c49f..034cbd0e06b 100644
--- a/src/com/android/settings/search/SearchIndexableResourcesImpl.java
+++ b/src/com/android/settings/search/SearchIndexableResourcesImpl.java
@@ -21,6 +21,7 @@ import android.support.annotation.VisibleForTesting;
import com.android.settings.DateTimeSettings;
import com.android.settings.DisplaySettings;
import com.android.settings.LegalSettings;
+import com.android.settings.deviceinfo.aboutphone.MyDeviceInfoFragment;
import com.android.settings.accessibility.AccessibilitySettings;
import com.android.settings.accessibility.AccessibilityShortcutPreferenceFragment;
import com.android.settings.accessibility.MagnificationPreferenceFragment;
@@ -173,6 +174,7 @@ public class SearchIndexableResourcesImpl implements SearchIndexableResources {
addIndex(ZenModeAutomationSettings.class);
addIndex(NightDisplaySettings.class);
addIndex(SmartBatterySettings.class);
+ addIndex(MyDeviceInfoFragment.class);
}
@Override
diff --git a/src/com/android/settings/security/LockdownButtonPreferenceController.java b/src/com/android/settings/security/LockdownButtonPreferenceController.java
new file mode 100644
index 00000000000..89605020b39
--- /dev/null
+++ b/src/com/android/settings/security/LockdownButtonPreferenceController.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.security;
+
+import android.content.Context;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.TwoStatePreference;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.core.TogglePreferenceController;
+
+public class LockdownButtonPreferenceController extends TogglePreferenceController {
+
+ private static final String KEY_LOCKDOWN_ENALBED = "security_setting_lockdown_enabled";
+
+ private final LockPatternUtils mLockPatternUtils;
+
+ public LockdownButtonPreferenceController(Context context) {
+ super(context, KEY_LOCKDOWN_ENALBED);
+ mLockPatternUtils = new LockPatternUtils(context);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ if (mLockPatternUtils.isSecure(UserHandle.myUserId())) {
+ return BasePreferenceController.AVAILABLE;
+ } else {
+ return BasePreferenceController.DISABLED_FOR_USER;
+ }
+ }
+
+ @Override
+ public boolean isChecked() {
+ return Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.LOCKDOWN_IN_POWER_MENU, 0) != 0;
+ }
+
+ @Override
+ public boolean setChecked(boolean isChecked) {
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.LOCKDOWN_IN_POWER_MENU, isChecked ? 1 : 0);
+ return true;
+ }
+}
diff --git a/src/com/android/settings/security/LockscreenDashboardFragment.java b/src/com/android/settings/security/LockscreenDashboardFragment.java
index df4ca30d995..7054181e431 100644
--- a/src/com/android/settings/security/LockscreenDashboardFragment.java
+++ b/src/com/android/settings/security/LockscreenDashboardFragment.java
@@ -93,6 +93,8 @@ public class LockscreenDashboardFragment extends DashboardFragment
mOwnerInfoPreferenceController =
new OwnerInfoPreferenceController(context, this, lifecycle);
controllers.add(mOwnerInfoPreferenceController);
+ controllers.add(new LockdownButtonPreferenceController(context));
+
return controllers;
}
@@ -122,6 +124,7 @@ public class LockscreenDashboardFragment extends DashboardFragment
KEY_ADD_USER_FROM_LOCK_SCREEN));
controllers.add(new OwnerInfoPreferenceController(
context, null /* fragment */, null /* lifecycle */));
+ controllers.add(new LockdownButtonPreferenceController(context));
return controllers;
}
diff --git a/src/com/android/settings/widget/AppCheckBoxPreference.java b/src/com/android/settings/widget/AppCheckBoxPreference.java
new file mode 100644
index 00000000000..9cb1d78163d
--- /dev/null
+++ b/src/com/android/settings/widget/AppCheckBoxPreference.java
@@ -0,0 +1,38 @@
+/*
+ * 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.widget;
+
+import android.content.Context;
+import android.support.v7.preference.CheckBoxPreference;
+import android.util.AttributeSet;
+
+import com.android.settings.R;
+
+/**
+ * {@link CheckBoxPreference} that used only to display app
+ */
+public class AppCheckBoxPreference extends CheckBoxPreference {
+ public AppCheckBoxPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setLayoutResource(R.layout.preference_app);
+ }
+
+ public AppCheckBoxPreference(Context context) {
+ super(context);
+ setLayoutResource(R.layout.preference_app);
+ }
+}
diff --git a/src/com/android/settings/widget/SettingsAppWidgetProvider.java b/src/com/android/settings/widget/SettingsAppWidgetProvider.java
index 7dacaf5f2aa..5ccfc1b585f 100644
--- a/src/com/android/settings/widget/SettingsAppWidgetProvider.java
+++ b/src/com/android/settings/widget/SettingsAppWidgetProvider.java
@@ -16,6 +16,7 @@
package com.android.settings.widget;
+import android.app.ActivityManager;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
@@ -33,10 +34,12 @@ import android.os.AsyncTask;
import android.os.Handler;
import android.os.IPowerManager;
import android.os.PowerManager;
+import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserManager;
import android.provider.Settings;
+import android.provider.Settings.Secure;
import android.util.Log;
import android.widget.RemoteViews;
@@ -561,27 +564,14 @@ public class SettingsAppWidgetProvider extends AppWidgetProvider {
final UserManager um =
(UserManager) context.getSystemService(Context.USER_SERVICE);
if (!um.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION)) {
- int currentMode = Settings.Secure.getInt(resolver,
- Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
- int mode = Settings.Secure.LOCATION_MODE_HIGH_ACCURACY;
- switch (currentMode) {
- case Settings.Secure.LOCATION_MODE_HIGH_ACCURACY:
- mode = Settings.Secure.LOCATION_MODE_BATTERY_SAVING;
- break;
- case Settings.Secure.LOCATION_MODE_BATTERY_SAVING:
- mode = Settings.Secure.LOCATION_MODE_HIGH_ACCURACY;
- break;
- case Settings.Secure.LOCATION_MODE_SENSORS_ONLY:
- mode = Settings.Secure.LOCATION_MODE_OFF;
- break;
- case Settings.Secure.LOCATION_MODE_OFF:
- mode = Settings.Secure.LOCATION_MODE_PREVIOUS;
- break;
- }
- Settings.Secure.putInt(resolver, Settings.Secure.LOCATION_MODE, mode);
- return mode != Settings.Secure.LOCATION_MODE_OFF;
+ LocationManager lm =
+ (LocationManager) context.getSystemService(
+ Context.LOCATION_SERVICE);
+ boolean currentLocationEnabled = lm.isLocationEnabled();
+ lm.setLocationEnabledForUser(
+ !currentLocationEnabled, Process.myUserHandle());
+ return lm.isLocationEnabled();
}
-
return getActualState(context) == STATE_ENABLED;
}
diff --git a/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceController.java b/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceController.java
index 1e299abc2e3..4c47a0d02a3 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceController.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceController.java
@@ -18,6 +18,7 @@ package com.android.settings.wifi.tether;
import static android.net.wifi.WifiConfiguration.AP_BAND_2GHZ;
import static android.net.wifi.WifiConfiguration.AP_BAND_5GHZ;
+import static android.net.wifi.WifiConfiguration.AP_BAND_ANY;
import android.content.Context;
import android.net.wifi.WifiConfiguration;
@@ -32,7 +33,8 @@ public class WifiTetherApBandPreferenceController extends WifiTetherBasePreferen
private static final String TAG = "WifiTetherApBandPref";
private static final String PREF_KEY = "wifi_tether_network_ap_band";
private static final String[] BAND_VALUES =
- {String.valueOf(AP_BAND_2GHZ), String.valueOf(AP_BAND_5GHZ)};
+ {String.valueOf(AP_BAND_ANY), String.valueOf(AP_BAND_2GHZ),
+ String.valueOf(AP_BAND_5GHZ)};
private final String[] mBandEntries;
private int mBandIndex;
@@ -65,7 +67,7 @@ public class WifiTetherApBandPreferenceController extends WifiTetherBasePreferen
} else {
preference.setEntries(mBandEntries);
preference.setEntryValues(BAND_VALUES);
- preference.setSummary(mBandEntries[mBandIndex]);
+ preference.setSummary(mBandEntries[mBandIndex + 1]);
preference.setValue(String.valueOf(mBandIndex));
}
}
@@ -78,7 +80,8 @@ public class WifiTetherApBandPreferenceController extends WifiTetherBasePreferen
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
mBandIndex = Integer.parseInt((String) newValue);
- preference.setSummary(mBandEntries[mBandIndex]);
+ Log.d(TAG, "Band preference changed, updating band index to " + mBandIndex);
+ preference.setSummary(mBandEntries[mBandIndex + 1]);
mListener.onTetherConfigUpdated();
return true;
}
diff --git a/tests/robotests/res/values-mcc999/config.xml b/tests/robotests/res/values-mcc999/config.xml
index a3205f33f29..f437f966b32 100644
--- a/tests/robotests/res/values-mcc999/config.xml
+++ b/tests/robotests/res/values-mcc999/config.xml
@@ -54,4 +54,5 @@
false
false
false
+ false
diff --git a/tests/robotests/res/values/config.xml b/tests/robotests/res/values/config.xml
index 4004106cc9d..359df6cc0a5 100644
--- a/tests/robotests/res/values/config.xml
+++ b/tests/robotests/res/values/config.xml
@@ -21,4 +21,5 @@
true
true
true
+ true
\ No newline at end of file
diff --git a/tests/robotests/src/android/content/om/IOverlayManager.java b/tests/robotests/src/android/content/om/IOverlayManager.java
index cc1d0efa791..8a895e7afc4 100644
--- a/tests/robotests/src/android/content/om/IOverlayManager.java
+++ b/tests/robotests/src/android/content/om/IOverlayManager.java
@@ -16,10 +16,15 @@ package android.content.om;
import android.os.IBinder;
+import java.util.ArrayList;
+import java.util.LinkedList;
+
public interface IOverlayManager {
public OverlayInfo getOverlayInfo(String packageName, int userId);
+ public java.util.List getOverlayInfosForTarget(java.lang.String targetPackageName, int userId);
+
public boolean setEnabled(java.lang.String packageName, boolean enable, int userId);
public static class Stub {
diff --git a/tests/robotests/src/android/content/om/OverlayInfo.java b/tests/robotests/src/android/content/om/OverlayInfo.java
index 98ce0910f09..fb7fef1d141 100644
--- a/tests/robotests/src/android/content/om/OverlayInfo.java
+++ b/tests/robotests/src/android/content/om/OverlayInfo.java
@@ -14,8 +14,17 @@
package android.content.om;
+import android.annotation.NonNull;
+
public class OverlayInfo {
+ public final String packageName;
+
+ public OverlayInfo(@NonNull String packageName, @NonNull String targetPackageName,
+ @NonNull String baseCodePath, int state, int userId) {
+ this.packageName = packageName;
+ }
+
public boolean isEnabled() {
return false;
}
diff --git a/tests/robotests/src/android/service/notification/NotifyingApp.java b/tests/robotests/src/android/service/notification/NotifyingApp.java
new file mode 100644
index 00000000000..f36069b20c2
--- /dev/null
+++ b/tests/robotests/src/android/service/notification/NotifyingApp.java
@@ -0,0 +1,112 @@
+/*
+ * 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 android.service.notification;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * Stub implementation of framework's NotifyingApp for Robolectric tests. Otherwise Robolectric
+ * throws ClassNotFoundError.
+ *
+ * TODO: Remove this class when Robolectric supports P
+ */
+public final class NotifyingApp implements Comparable {
+
+ private int mUid;
+ private String mPkg;
+ private long mLastNotified;
+
+ public NotifyingApp() {}
+
+ public int getUid() {
+ return mUid;
+ }
+
+ /**
+ * Sets the uid of the package that sent the notification. Returns self.
+ */
+ public NotifyingApp setUid(int mUid) {
+ this.mUid = mUid;
+ return this;
+ }
+
+ public String getPackage() {
+ return mPkg;
+ }
+
+ /**
+ * Sets the package that sent the notification. Returns self.
+ */
+ public NotifyingApp setPackage(@NonNull String mPkg) {
+ this.mPkg = mPkg;
+ return this;
+ }
+
+ public long getLastNotified() {
+ return mLastNotified;
+ }
+
+ /**
+ * Sets the time the notification was originally sent. Returns self.
+ */
+ public NotifyingApp setLastNotified(long mLastNotified) {
+ this.mLastNotified = mLastNotified;
+ return this;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ NotifyingApp that = (NotifyingApp) o;
+ return getUid() == that.getUid()
+ && getLastNotified() == that.getLastNotified()
+ && Objects.equals(mPkg, that.mPkg);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(getUid(), mPkg, getLastNotified());
+ }
+
+ /**
+ * Sorts notifying apps from newest last notified date to oldest.
+ */
+ @Override
+ public int compareTo(NotifyingApp o) {
+ if (getLastNotified() == o.getLastNotified()) {
+ if (getUid() == o.getUid()) {
+ return getPackage().compareTo(o.getPackage());
+ }
+ return Integer.compare(getUid(), o.getUid());
+ }
+
+ return -Long.compare(getLastNotified(), o.getLastNotified());
+ }
+
+ @Override
+ public String toString() {
+ return "NotifyingApp{"
+ + "mUid=" + mUid
+ + ", mPkg='" + mPkg + '\''
+ + ", mLastNotified=" + mLastNotified
+ + '}';
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/development/EmulateDisplayCutoutPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/EmulateDisplayCutoutPreferenceControllerTest.java
index c9841f698ec..a6af6d6cb39 100644
--- a/tests/robotests/src/com/android/settings/development/EmulateDisplayCutoutPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/EmulateDisplayCutoutPreferenceControllerTest.java
@@ -16,6 +16,9 @@
package com.android.settings.development;
+import static com.android.settings.development.EmulateDisplayCutoutPreferenceController
+ .EMULATION_OVERLAY_PREFIX;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
@@ -29,7 +32,8 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.om.IOverlayManager;
import android.content.om.OverlayInfo;
-import android.support.v7.preference.TwoStatePreference;
+import android.content.pm.PackageManager;
+import android.support.v7.preference.ListPreference;
import com.android.settings.TestConfig;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
@@ -41,78 +45,95 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.annotation.Config;
+import java.util.Arrays;
+
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class EmulateDisplayCutoutPreferenceControllerTest {
+ static final OverlayInfo ONE_DISABLED =
+ new FakeOverlay(EMULATION_OVERLAY_PREFIX + ".one", false);
+ static final OverlayInfo ONE_ENABLED =
+ new FakeOverlay(EMULATION_OVERLAY_PREFIX + ".one", true);
+ static final OverlayInfo TWO_DISABLED =
+ new FakeOverlay(EMULATION_OVERLAY_PREFIX + ".two", false);
+ static final OverlayInfo TWO_ENABLED =
+ new FakeOverlay(EMULATION_OVERLAY_PREFIX + ".two", true);
+
@Mock Context mContext;
@Mock IOverlayManager mOverlayManager;
- @Mock TwoStatePreference mPreference;
+ @Mock PackageManager mPackageManager;
+ @Mock ListPreference mPreference;
EmulateDisplayCutoutPreferenceController mController;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
- when(mOverlayManager.getOverlayInfo(any(), anyInt())).thenReturn(DISABLED);
- mController = new EmulateDisplayCutoutPreferenceController(mContext, mOverlayManager);
+ mockCurrentOverlays();
+ when(mPackageManager.getApplicationInfo(any(), anyInt())).thenThrow(
+ PackageManager.NameNotFoundException.class);
+ mController = createController();
mController.setPreference(mPreference);
}
+ Object mockCurrentOverlays(OverlayInfo... overlays) {
+ return when(mOverlayManager.getOverlayInfosForTarget(eq("android"), anyInt()))
+ .thenReturn(Arrays.asList(overlays));
+ }
+
@Test
public void isAvailable_true() throws Exception {
- when(mOverlayManager.getOverlayInfo(any(), anyInt())).thenReturn(DISABLED);
+ mockCurrentOverlays(ONE_DISABLED, TWO_DISABLED);
- assertThat(new EmulateDisplayCutoutPreferenceController(mContext, mOverlayManager)
- .isAvailable()).isTrue();
+ assertThat(createController().isAvailable()).isTrue();
}
@Test
public void isAvailable_false() throws Exception {
- when(mOverlayManager.getOverlayInfo(any(), anyInt())).thenReturn(null);
+ mockCurrentOverlays();
- assertThat(new EmulateDisplayCutoutPreferenceController(mContext, mOverlayManager)
- .isAvailable()).isFalse();
+ assertThat(createController().isAvailable()).isFalse();
}
@Test
public void onPreferenceChange_enable() throws Exception {
- when(mOverlayManager.getOverlayInfo(any(), anyInt())).thenReturn(DISABLED);
+ mockCurrentOverlays(ONE_DISABLED, TWO_DISABLED);
- mController.onPreferenceChange(null, true);
+ mController.onPreferenceChange(null, TWO_DISABLED.packageName);
- verify(mOverlayManager).setEnabled(any(), eq(true), anyInt());
+ verify(mOverlayManager).setEnabled(eq(TWO_DISABLED.packageName), eq(true), anyInt());
}
@Test
public void onPreferenceChange_disable() throws Exception {
- when(mOverlayManager.getOverlayInfo(any(), anyInt())).thenReturn(ENABLED);
+ mockCurrentOverlays(ONE_DISABLED, TWO_ENABLED);
- mController.onPreferenceChange(null, false);
+ mController.onPreferenceChange(null, "");
- verify(mOverlayManager).setEnabled(any(), eq(false), anyInt());
+ verify(mOverlayManager).setEnabled(eq(TWO_ENABLED.packageName), eq(false), anyInt());
}
@Test
public void updateState_enabled() throws Exception {
- when(mOverlayManager.getOverlayInfo(any(), anyInt())).thenReturn(ENABLED);
+ mockCurrentOverlays(ONE_DISABLED, TWO_ENABLED);
mController.updateState(null);
- verify(mPreference).setChecked(true);
+ verify(mPreference).setValueIndex(2);
}
@Test
public void updateState_disabled() throws Exception {
- when(mOverlayManager.getOverlayInfo(any(), anyInt())).thenReturn(DISABLED);
+ mockCurrentOverlays(ONE_DISABLED, TWO_DISABLED);
mController.updateState(null);
- verify(mPreference).setChecked(false);
+ verify(mPreference).setValueIndex(0);
}
@Test
public void onDeveloperOptionsSwitchEnabled() throws Exception {
- when(mOverlayManager.getOverlayInfo(any(), anyInt())).thenReturn(DISABLED);
+ mockCurrentOverlays();
mController.onDeveloperOptionsSwitchEnabled();
@@ -122,27 +143,30 @@ public class EmulateDisplayCutoutPreferenceControllerTest {
@Test
public void onDeveloperOptionsSwitchDisabled() throws Exception {
- when(mOverlayManager.getOverlayInfo(any(), anyInt())).thenReturn(ENABLED);
+ mockCurrentOverlays(ONE_ENABLED, TWO_DISABLED);
mController.onDeveloperOptionsSwitchDisabled();
verify(mPreference).setEnabled(false);
- verify(mPreference).setChecked(false);
- verify(mOverlayManager).setEnabled(any(), eq(false), anyInt());
+ verify(mOverlayManager).setEnabled(eq(ONE_ENABLED.packageName), eq(false), anyInt());
}
- static final OverlayInfo ENABLED = new OverlayInfo() {
+ private EmulateDisplayCutoutPreferenceController createController() {
+ return new EmulateDisplayCutoutPreferenceController(mContext, mPackageManager,
+ mOverlayManager);
+ }
+
+ private static class FakeOverlay extends OverlayInfo {
+ private final boolean mEnabled;
+
+ public FakeOverlay(String pkg, boolean enabled) {
+ super(pkg, "android", "/", 0, 0);
+ mEnabled = enabled;
+ }
+
@Override
public boolean isEnabled() {
- return true;
+ return mEnabled;
}
- };
-
- static final OverlayInfo DISABLED = new OverlayInfo() {
- @Override
- public boolean isEnabled() {
- return false;
- }
- };
-
+ }
}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/development/WifiConnectedMacRandomizationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/WifiConnectedMacRandomizationPreferenceControllerTest.java
new file mode 100644
index 00000000000..9a80c5c5efd
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/WifiConnectedMacRandomizationPreferenceControllerTest.java
@@ -0,0 +1,133 @@
+/*
+ * 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.development;
+
+import static com.android.settings.development.WifiConnectedMacRandomizationPreferenceController
+ .SETTING_VALUE_OFF;
+import static com.android.settings.development.WifiConnectedMacRandomizationPreferenceController
+ .SETTING_VALUE_ON;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.provider.Settings;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class WifiConnectedMacRandomizationPreferenceControllerTest {
+
+ @Mock
+ private PreferenceScreen mPreferenceScreen;
+
+ private Context mContext;
+ private SwitchPreference mPreference;
+ private WifiConnectedMacRandomizationPreferenceController mController;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mController = new WifiConnectedMacRandomizationPreferenceController(mContext);
+ mPreference = new SwitchPreference(mContext);
+ when(mPreferenceScreen.findPreference(mController.getPreferenceKey())).thenReturn(
+ mPreference);
+ mController.displayPreference(mPreferenceScreen);
+ }
+
+ @Test
+ public void isAvailable_trueSupportFlag_shouldReturnTrue() {
+ assertThat(mController.isAvailable()).isTrue();
+ }
+
+ @Test
+ @Config(qualifiers = "mcc999")
+ public void isAvailable_falseSupportFlag_shouldReturnFalse() {
+ assertThat(mController.isAvailable()).isFalse();
+ }
+
+ @Test
+ public void onPreferenceChange_settingEnabled_shouldEnableConnectedMacRandomization() {
+ mController.onPreferenceChange(mPreference, true /* new value */);
+
+ final int mode = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED, -1 /* default */);
+
+ assertThat(mode).isEqualTo(SETTING_VALUE_ON);
+ }
+
+ @Test
+ public void onPreferenceChange_settingDisabled_shouldDisableConnectedMacRandomization() {
+ mController.onPreferenceChange(mPreference, false /* new value */);
+
+ final int mode = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED, -1 /* default */);
+
+ assertThat(mode).isEqualTo(SETTING_VALUE_OFF);
+ }
+
+ @Test
+ public void updateState_settingEnabled_shouldEnablePreference() {
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED, SETTING_VALUE_ON);
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.isChecked()).isTrue();
+ }
+
+ @Test
+ public void updateState_settingDisabled_shouldDisablePreference() {
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED, SETTING_VALUE_OFF);
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.isChecked()).isFalse();
+ }
+
+ @Test
+ public void onDeveloperOptionsSwitchEnabled_shouldEnablePreference() {
+ mController.onDeveloperOptionsSwitchEnabled();
+
+ assertThat(mPreference.isEnabled()).isTrue();
+ }
+
+ @Test
+ public void onDeveloperOptionsSwitchDisabled_shouldDisablePreference() {
+ mController.onDeveloperOptionsSwitchDisabled();
+
+ final int mode = Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.WIFI_CONNECTED_MAC_RANDOMIZATION_ENABLED, -1 /* default */);
+
+ assertThat(mode).isEqualTo(SETTING_VALUE_OFF);
+ assertThat(mPreference.isChecked()).isFalse();
+ assertThat(mPreference.isEnabled()).isFalse();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/BrandedAccountPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/BrandedAccountPreferenceControllerTest.java
new file mode 100644
index 00000000000..521800b57fa
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/deviceinfo/BrandedAccountPreferenceControllerTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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.deviceinfo;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+
+import android.accounts.Account;
+import android.content.Context;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class BrandedAccountPreferenceControllerTest {
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private Context mContext;
+ private BrandedAccountPreferenceController mController;
+ private FakeFeatureFactory fakeFeatureFactory;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ fakeFeatureFactory = FakeFeatureFactory.setupForTest();
+ mController = new BrandedAccountPreferenceController(mContext);
+ }
+
+ @Test
+ public void isAvailable_defaultOff() {
+ assertThat(mController.isAvailable()).isFalse();
+ }
+
+ @Test
+ public void isAvailable_onWhenAccountIsAvailable() {
+ when(fakeFeatureFactory.mAccountFeatureProvider.getAccounts(any(Context.class))).thenReturn(
+ new Account[]
+ {new Account("fake@account.foo", "fake.reallyfake")});
+ mController = new BrandedAccountPreferenceController(mContext);
+ assertThat(mController.isAvailable()).isTrue();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/MyDeviceInfoFragmentTest.java b/tests/robotests/src/com/android/settings/deviceinfo/MyDeviceInfoFragmentTest.java
new file mode 100644
index 00000000000..36f0662c2a8
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/deviceinfo/MyDeviceInfoFragmentTest.java
@@ -0,0 +1,100 @@
+/*
+ * 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.deviceinfo;
+
+import static com.android.settings.SettingsActivity.EXTRA_FRAGMENT_ARG_KEY;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doNothing;
+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.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.support.v7.preference.PreferenceScreen;
+import android.telephony.TelephonyManager;
+
+import com.android.settings.deviceinfo.aboutphone.MyDeviceInfoFragment;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.SettingsShadowResources;
+import com.android.settings.testutils.shadow.SettingsShadowSystemProperties;
+import com.android.settings.testutils.shadow.ShadowConnectivityManager;
+import com.android.settings.testutils.shadow.ShadowUserManager;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowApplication;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(
+ manifest = TestConfig.MANIFEST_PATH,
+ sdk = TestConfig.SDK_VERSION,
+ shadows = {ShadowConnectivityManager.class, ShadowUserManager.class}
+)
+public class MyDeviceInfoFragmentTest {
+ @Mock
+ private Activity mActivity;
+ @Mock
+ private PreferenceScreen mScreen;
+ @Mock
+ private TelephonyManager mTelephonyManager;
+
+ private Context mContext;
+ private MyDeviceInfoFragment mSettings;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ FakeFeatureFactory.setupForTest();
+ mContext = RuntimeEnvironment.application;
+ mSettings = spy(new MyDeviceInfoFragment());
+
+ when(mSettings.getActivity()).thenReturn(mActivity);
+ when(mSettings.getContext()).thenReturn(mContext);
+ when(mActivity.getTheme()).thenReturn(mContext.getTheme());
+ when(mActivity.getResources()).thenReturn(mContext.getResources());
+ doNothing().when(mSettings).onCreatePreferences(any(), any());
+
+ doReturn(mScreen).when(mSettings).getPreferenceScreen();
+ when(mSettings.getPreferenceScreen()).thenReturn(mScreen);
+ ShadowApplication.getInstance().setSystemService(Context.TELEPHONY_SERVICE,
+ mTelephonyManager);
+ }
+
+ @Test
+ @Config(shadows = {SettingsShadowResources.SettingsShadowTheme.class,
+ SettingsShadowSystemProperties.class})
+ public void onCreate_fromSearch_shouldNotOverrideInitialExpandedCount() {
+ final Bundle args = new Bundle();
+ args.putString(EXTRA_FRAGMENT_ARG_KEY, "search_key");
+ mSettings.setArguments(args);
+
+ mSettings.onCreate(null /* icicle */);
+
+ verify(mScreen).setInitialExpandedChildrenCount(Integer.MAX_VALUE);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/RestrictedAppDetailsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/RestrictedAppDetailsTest.java
index a9de06176b4..521ead4d337 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/RestrictedAppDetailsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/RestrictedAppDetailsTest.java
@@ -28,6 +28,7 @@ import android.content.pm.PackageManager;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceCategory;
import android.support.v7.preference.PreferenceManager;
+import android.util.IconDrawableFactory;
import com.android.settings.TestConfig;
@@ -53,6 +54,8 @@ public class RestrictedAppDetailsTest {
private PackageManager mPackageManager;
@Mock
private ApplicationInfo mApplicationInfo;
+ @Mock
+ private IconDrawableFactory mIconDrawableFactory;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private PreferenceManager mPreferenceManager;
private RestrictedAppDetails mFragment;
@@ -68,6 +71,7 @@ public class RestrictedAppDetailsTest {
doReturn(mPreferenceManager).when(mFragment).getPreferenceManager();
doReturn(mContext).when(mPreferenceManager).getContext();
mFragment.mPackageManager = mPackageManager;
+ mFragment.mIconDrawableFactory = mIconDrawableFactory;
mFragment.mPackageOpsList = new ArrayList<>();
mFragment.mPackageOpsList.add(
new AppOpsManager.PackageOps(PACKAGE_NAME, UID, null /* entries */));
diff --git a/tests/robotests/src/com/android/settings/location/LocationEnablerTest.java b/tests/robotests/src/com/android/settings/location/LocationEnablerTest.java
index f456f4109e5..8cc92cdf43f 100644
--- a/tests/robotests/src/com/android/settings/location/LocationEnablerTest.java
+++ b/tests/robotests/src/com/android/settings/location/LocationEnablerTest.java
@@ -43,6 +43,7 @@ import com.android.settings.TestConfig;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.ShadowSecureSettings;
import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.wrapper.LocationManagerWrapper;
import java.util.ArrayList;
import java.util.List;
import org.junit.Before;
@@ -53,11 +54,15 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH,
sdk = TestConfig.SDK_VERSION,
- shadows = {ShadowSecureSettings.class})
+ shadows = {
+ ShadowSecureSettings.class,
+ LocationEnablerTest.ShadowLocationManagerWrapper.class})
public class LocationEnablerTest {
@Mock
@@ -124,7 +129,7 @@ public class LocationEnablerTest {
}
@Test
- public void isEnabled_locationONotRestricted_shouldReturnTrue() {
+ public void isEnabled_locationNotRestricted_shouldReturnTrue() {
when(mUserManager.hasUserRestriction(anyString())).thenReturn(false);
assertThat(mEnabler.isEnabled(Settings.Secure.LOCATION_MODE_BATTERY_SAVING)).isTrue();
@@ -178,14 +183,35 @@ public class LocationEnablerTest {
when(mUserManager.hasUserRestriction(anyString())).thenReturn(false);
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_BATTERY_SAVING);
-
mEnabler.setLocationMode(Settings.Secure.LOCATION_MODE_HIGH_ACCURACY);
verify(mContext).sendBroadcastAsUser(
argThat(actionMatches(LocationManager.MODE_CHANGING_ACTION)),
eq(UserHandle.of(ActivityManager.getCurrentUser())),
eq(WRITE_SECURE_SETTINGS));
+ }
+ @Test
+ public void setLocationEnabled_notRestricted_shouldRefreshLocation() {
+ when(mUserManager.hasUserRestriction(anyString())).thenReturn(false);
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
+ mEnabler.setLocationEnabled(true);
+
+ verify(mEnabler).refreshLocationMode();
+ }
+
+ @Test
+ public void setLocationEnabled_notRestricted_shouldBroadcastUpdate() {
+ when(mUserManager.hasUserRestriction(anyString())).thenReturn(false);
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
+ mEnabler.setLocationEnabled(true);
+
+ verify(mContext).sendBroadcastAsUser(
+ argThat(actionMatches(LocationManager.MODE_CHANGING_ACTION)),
+ eq(UserHandle.of(ActivityManager.getCurrentUser())),
+ eq(WRITE_SECURE_SETTINGS));
}
@Test
@@ -241,5 +267,12 @@ public class LocationEnablerTest {
return intent -> TextUtils.equals(expected, intent.getAction());
}
+ @Implements(value = LocationManagerWrapper.class)
+ public static class ShadowLocationManagerWrapper {
+ @Implementation
+ public void setLocationEnabledForUser(boolean enabled, UserHandle userHandle) {
+ // Do nothing
+ }
+ }
}
diff --git a/tests/robotests/src/com/android/settings/location/LocationSwitchBarControllerTest.java b/tests/robotests/src/com/android/settings/location/LocationSwitchBarControllerTest.java
index 6d824acca8a..4410d6f2c47 100644
--- a/tests/robotests/src/com/android/settings/location/LocationSwitchBarControllerTest.java
+++ b/tests/robotests/src/com/android/settings/location/LocationSwitchBarControllerTest.java
@@ -88,18 +88,17 @@ public class LocationSwitchBarControllerTest {
}
@Test
- public void onSwitchChanged_switchChecked_shouldSetPreviousLocationMode() {
+ public void onSwitchChanged_switchChecked_shouldSetLocationEnabled() {
mController.onSwitchChanged(mSwitch, true);
- verify(mEnabler).setLocationMode(
- android.provider.Settings.Secure.LOCATION_MODE_PREVIOUS);
+ verify(mEnabler).setLocationEnabled(true);
}
@Test
- public void onSwitchChanged_switchUnchecked_shouldSetLocationModeOff() {
+ public void onSwitchChanged_switchUnchecked_shouldSetLocationDisabled() {
mController.onSwitchChanged(mSwitch, false);
- verify(mEnabler).setLocationMode(android.provider.Settings.Secure.LOCATION_MODE_OFF);
+ verify(mEnabler).setLocationEnabled(false);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/notification/EnableZenModeDialogTest.java b/tests/robotests/src/com/android/settings/notification/EnableZenModeDialogTest.java
new file mode 100644
index 00000000000..8b5ef79dcbc
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/EnableZenModeDialogTest.java
@@ -0,0 +1,152 @@
+/*
+ * 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.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.content.Context;
+import android.net.Uri;
+import android.service.notification.Condition;
+import android.view.LayoutInflater;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class EnableZenModeDialogTest {
+ private EnableZenModeDialog mController;
+
+ @Mock
+ private Context mContext;
+ @Mock
+ private Activity mActivity;
+ @Mock
+ private Fragment mFragment;
+
+ private Context mShadowContext;
+ private LayoutInflater mLayoutInflater;
+ private Condition mCountdownCondition;
+ private Condition mAlarmCondition;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mShadowContext = RuntimeEnvironment.application;
+ when(mActivity.getApplicationContext()).thenReturn(mShadowContext);
+ when(mContext.getApplicationContext()).thenReturn(mContext);
+ when(mFragment.getContext()).thenReturn(mShadowContext);
+ mLayoutInflater = LayoutInflater.from(mShadowContext);
+ when(mActivity.getLayoutInflater()).thenReturn(mLayoutInflater);
+
+ mController = spy(new EnableZenModeDialog());
+ mController.mContext = mContext;
+ mController.mActivity = mActivity;
+ mController.mForeverId = Condition.newId(mContext).appendPath("forever").build();
+ when(mContext.getString(com.android.internal.R.string.zen_mode_forever))
+ .thenReturn("testSummary");
+ mController.getContentView();
+
+ // these methods use static calls to ZenModeConfig which would normally fail in robotests,
+ // so instead do nothing:
+ doNothing().when(mController).bindGenericCountdown();
+ doReturn(null).when(mController).getTimeUntilNextAlarmCondition();
+ doNothing().when(mController).bindNextAlarm(any());
+
+ // as a result of doing nothing above, must bind manually:
+ Uri alarm = Condition.newId(mContext).appendPath("alarm").build();
+ mAlarmCondition = new Condition(alarm, "alarm", "", "", 0, 0, 0);
+ Uri countdown = Condition.newId(mContext).appendPath("countdown").build();
+ mCountdownCondition = new Condition(countdown, "countdown", "", "", 0, 0, 0);
+ mController.bind(mCountdownCondition,
+ mController.mZenRadioGroupContent.getChildAt(
+ EnableZenModeDialog.COUNTDOWN_CONDITION_INDEX),
+ EnableZenModeDialog.COUNTDOWN_CONDITION_INDEX);
+ mController.bind(mAlarmCondition,
+ mController.mZenRadioGroupContent.getChildAt(
+ EnableZenModeDialog.COUNTDOWN_ALARM_CONDITION_INDEX),
+ EnableZenModeDialog.COUNTDOWN_ALARM_CONDITION_INDEX);
+ }
+
+ @Test
+ public void testForeverChecked() {
+ mController.bindConditions(mController.forever());
+
+ assertTrue(mController.getConditionTagAt(EnableZenModeDialog.FOREVER_CONDITION_INDEX).rb
+ .isChecked());
+ assertFalse(mController.getConditionTagAt(EnableZenModeDialog.COUNTDOWN_CONDITION_INDEX).rb
+ .isChecked());
+ assertFalse(mController.getConditionTagAt(
+ EnableZenModeDialog.COUNTDOWN_ALARM_CONDITION_INDEX).rb.isChecked());
+ }
+
+ @Test
+ public void testNoneChecked() {
+ mController.bindConditions(null);
+ assertFalse(mController.getConditionTagAt(EnableZenModeDialog.FOREVER_CONDITION_INDEX).rb
+ .isChecked());
+ assertFalse(mController.getConditionTagAt(EnableZenModeDialog.COUNTDOWN_CONDITION_INDEX).rb
+ .isChecked());
+ assertFalse(mController.getConditionTagAt(
+ EnableZenModeDialog.COUNTDOWN_ALARM_CONDITION_INDEX).rb.isChecked());
+ }
+
+ @Test
+ public void testAlarmChecked() {
+ doReturn(false).when(mController).isCountdown(mAlarmCondition);
+ doReturn(true).when(mController).isAlarm(mAlarmCondition);
+
+ mController.bindConditions(mAlarmCondition);
+ assertFalse(mController.getConditionTagAt(EnableZenModeDialog.FOREVER_CONDITION_INDEX).rb
+ .isChecked());
+ assertFalse(mController.getConditionTagAt(EnableZenModeDialog.COUNTDOWN_CONDITION_INDEX).rb
+ .isChecked());
+ assertTrue(mController.getConditionTagAt(
+ EnableZenModeDialog.COUNTDOWN_ALARM_CONDITION_INDEX).rb.isChecked());
+ }
+
+ @Test
+ public void testCountdownChecked() {
+ doReturn(false).when(mController).isAlarm(mCountdownCondition);
+ doReturn(true).when(mController).isCountdown(mCountdownCondition);
+
+ mController.bindConditions(mCountdownCondition);
+ assertFalse(mController.getConditionTagAt(EnableZenModeDialog.FOREVER_CONDITION_INDEX).rb
+ .isChecked());
+ assertTrue(mController.getConditionTagAt(EnableZenModeDialog.COUNTDOWN_CONDITION_INDEX).rb
+ .isChecked());
+ assertFalse(mController.getConditionTagAt(
+ EnableZenModeDialog.COUNTDOWN_ALARM_CONDITION_INDEX).rb.isChecked());
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/notification/RecentNotifyingAppsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/RecentNotifyingAppsPreferenceControllerTest.java
new file mode 100644
index 00000000000..a25bb002502
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/RecentNotifyingAppsPreferenceControllerTest.java
@@ -0,0 +1,301 @@
+/*
+ * 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.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.argThat;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Application;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.service.notification.NotifyingApp;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceCategory;
+import android.support.v7.preference.PreferenceScreen;
+import android.text.TextUtils;
+
+import com.android.settings.R;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.applications.AppUtils;
+import com.android.settingslib.applications.ApplicationsState;
+import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.ArgumentMatcher;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class RecentNotifyingAppsPreferenceControllerTest {
+
+ @Mock
+ private PreferenceScreen mScreen;
+ @Mock
+ private PreferenceCategory mCategory;
+ @Mock
+ private Preference mSeeAllPref;
+ @Mock
+ private PreferenceCategory mDivider;
+ @Mock
+ private UserManager mUserManager;
+ @Mock
+ private ApplicationsState mAppState;
+ @Mock
+ private PackageManager mPackageManager;
+ @Mock
+ private ApplicationsState.AppEntry mAppEntry;
+ @Mock
+ private ApplicationInfo mApplicationInfo;
+ @Mock
+ private NotificationBackend mBackend;
+
+ private Context mContext;
+ private RecentNotifyingAppsPreferenceController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+ doReturn(mUserManager).when(mContext).getSystemService(Context.USER_SERVICE);
+ doReturn(mPackageManager).when(mContext).getPackageManager();
+
+ mController = new RecentNotifyingAppsPreferenceController(
+ mContext, mBackend, mAppState, null);
+ when(mScreen.findPreference(anyString())).thenReturn(mCategory);
+
+ when(mScreen.findPreference(RecentNotifyingAppsPreferenceController.KEY_SEE_ALL))
+ .thenReturn(mSeeAllPref);
+ when(mScreen.findPreference(RecentNotifyingAppsPreferenceController.KEY_DIVIDER))
+ .thenReturn(mDivider);
+ when(mCategory.getContext()).thenReturn(mContext);
+ }
+
+ @Test
+ public void isAlwaysAvailable() {
+ assertThat(mController.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void doNotIndexCategory() {
+ final List nonIndexable = new ArrayList<>();
+
+ mController.updateNonIndexableKeys(nonIndexable);
+
+ assertThat(nonIndexable).containsAllOf(mController.getPreferenceKey(),
+ RecentNotifyingAppsPreferenceController.KEY_DIVIDER);
+ }
+
+ @Test
+ public void onDisplayAndUpdateState_shouldRefreshUi() {
+ mController = spy(new RecentNotifyingAppsPreferenceController(
+ mContext, null, (ApplicationsState) null, null));
+
+ doNothing().when(mController).refreshUi(mContext);
+
+ mController.displayPreference(mScreen);
+ mController.updateState(mCategory);
+
+ verify(mController, times(2)).refreshUi(mContext);
+ }
+
+ @Test
+ @Config(qualifiers = "mcc999")
+ public void display_shouldNotShowRecents_showAppInfoPreference() {
+ mController.displayPreference(mScreen);
+
+ verify(mCategory, never()).addPreference(any(Preference.class));
+ verify(mCategory).setTitle(null);
+ verify(mSeeAllPref).setTitle(R.string.notifications_title);
+ verify(mSeeAllPref).setIcon(null);
+ verify(mDivider).setVisible(false);
+ }
+
+ @Test
+ public void display_showRecents() {
+ final List apps = new ArrayList<>();
+ final NotifyingApp app1 = new NotifyingApp()
+ .setPackage("pkg.class")
+ .setLastNotified(System.currentTimeMillis());
+ final NotifyingApp app2 = new NotifyingApp()
+ .setLastNotified(System.currentTimeMillis())
+ .setPackage("com.android.settings");
+ final NotifyingApp app3 = new NotifyingApp()
+ .setLastNotified(System.currentTimeMillis() - 1000)
+ .setPackage("pkg.class2");
+
+ apps.add(app1);
+ apps.add(app2);
+ apps.add(app3);
+
+ // app1, app2 are valid apps. app3 is invalid.
+ when(mAppState.getEntry(app1.getPackage(), UserHandle.myUserId()))
+ .thenReturn(mAppEntry);
+ when(mAppState.getEntry(app2.getPackage(), UserHandle.myUserId()))
+ .thenReturn(mAppEntry);
+ when(mAppState.getEntry(app3.getPackage(), UserHandle.myUserId()))
+ .thenReturn(null);
+ when(mPackageManager.resolveActivity(any(Intent.class), anyInt())).thenReturn(
+ new ResolveInfo());
+ when(mBackend.getRecentApps()).thenReturn(apps);
+ mAppEntry.info = mApplicationInfo;
+
+ mController.displayPreference(mScreen);
+
+ verify(mCategory).setTitle(R.string.recent_notifications);
+ // Only add app1. app2 is skipped because of the package name, app3 skipped because
+ // it's invalid app.
+ verify(mCategory, times(1)).addPreference(any(Preference.class));
+
+ verify(mSeeAllPref).setSummary(null);
+ verify(mSeeAllPref).setIcon(R.drawable.ic_chevron_right_24dp);
+ verify(mDivider).setVisible(true);
+ }
+
+ @Test
+ public void display_showRecentsWithInstantApp() {
+ // Regular app.
+ final List apps = new ArrayList<>();
+ final NotifyingApp app1 = new NotifyingApp().
+ setLastNotified(System.currentTimeMillis())
+ .setPackage("com.foo.bar");
+ apps.add(app1);
+
+ // Instant app.
+ final NotifyingApp app2 = new NotifyingApp()
+ .setLastNotified(System.currentTimeMillis() + 200)
+ .setPackage("com.foo.barinstant");
+ apps.add(app2);
+
+ ApplicationsState.AppEntry app1Entry = mock(ApplicationsState.AppEntry.class);
+ ApplicationsState.AppEntry app2Entry = mock(ApplicationsState.AppEntry.class);
+ app1Entry.info = mApplicationInfo;
+ app2Entry.info = mApplicationInfo;
+
+ when(mAppState.getEntry(app1.getPackage(), UserHandle.myUserId())).thenReturn(app1Entry);
+ when(mAppState.getEntry(app2.getPackage(), UserHandle.myUserId())).thenReturn(app2Entry);
+
+ // Only the regular app app1 should have its intent resolve.
+ when(mPackageManager.resolveActivity(argThat(intentMatcher(app1.getPackage())),
+ anyInt())).thenReturn(new ResolveInfo());
+
+ when(mBackend.getRecentApps()).thenReturn(apps);
+
+ // Make sure app2 is considered an instant app.
+ ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
+ (InstantAppDataProvider) (ApplicationInfo info) -> {
+ if (info == app2Entry.info) {
+ return true;
+ } else {
+ return false;
+ }
+ });
+
+ mController.displayPreference(mScreen);
+
+ ArgumentCaptor prefCaptor = ArgumentCaptor.forClass(Preference.class);
+ verify(mCategory, times(2)).addPreference(prefCaptor.capture());
+ List prefs = prefCaptor.getAllValues();
+ assertThat(prefs.get(1).getKey()).isEqualTo(app1.getPackage());
+ assertThat(prefs.get(0).getKey()).isEqualTo(app2.getPackage());
+ }
+
+ @Test
+ public void display_hasRecentButNoneDisplayable_showAppInfo() {
+ final List apps = new ArrayList<>();
+ final NotifyingApp app1 = new NotifyingApp()
+ .setPackage("com.android.phone")
+ .setLastNotified(System.currentTimeMillis());
+ final NotifyingApp app2 = new NotifyingApp()
+ .setPackage("com.android.settings")
+ .setLastNotified(System.currentTimeMillis());
+ apps.add(app1);
+ apps.add(app2);
+
+ // app1, app2 are not displayable
+ when(mAppState.getEntry(app1.getPackage(), UserHandle.myUserId()))
+ .thenReturn(mock(ApplicationsState.AppEntry.class));
+ when(mAppState.getEntry(app2.getPackage(), UserHandle.myUserId()))
+ .thenReturn(mock(ApplicationsState.AppEntry.class));
+ when(mPackageManager.resolveActivity(any(Intent.class), anyInt())).thenReturn(
+ new ResolveInfo());
+ when(mBackend.getRecentApps()).thenReturn(apps);
+
+ mController.displayPreference(mScreen);
+
+ verify(mCategory, never()).addPreference(any(Preference.class));
+ verify(mCategory).setTitle(null);
+ verify(mSeeAllPref).setTitle(R.string.notifications_title);
+ verify(mSeeAllPref).setIcon(null);
+ }
+
+ @Test
+ public void display_showRecents_formatSummary() {
+ final List apps = new ArrayList<>();
+ final NotifyingApp app1 = new NotifyingApp()
+ .setLastNotified(System.currentTimeMillis())
+ .setPackage("pkg.class");
+ apps.add(app1);
+
+ when(mAppState.getEntry(app1.getPackage(), UserHandle.myUserId()))
+ .thenReturn(mAppEntry);
+ when(mPackageManager.resolveActivity(any(Intent.class), anyInt())).thenReturn(
+ new ResolveInfo());
+ when(mBackend.getRecentApps()).thenReturn(apps);
+ mAppEntry.info = mApplicationInfo;
+
+ mController.displayPreference(mScreen);
+
+ verify(mCategory).addPreference(argThat(summaryMatches("0 min. ago")));
+ }
+
+ private static ArgumentMatcher summaryMatches(String expected) {
+ return preference -> TextUtils.equals(expected, preference.getSummary());
+ }
+
+ // Used for matching an intent with a specific package name.
+ private static ArgumentMatcher intentMatcher(String packageName) {
+ return intent -> packageName.equals(intent.getPackage());
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeButtonPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeButtonPreferenceControllerTest.java
index 862b8d06afe..ed42890b3e3 100644
--- a/tests/robotests/src/com/android/settings/notification/ZenModeButtonPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ZenModeButtonPreferenceControllerTest.java
@@ -26,6 +26,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.FragmentManager;
import android.app.NotificationManager;
import android.content.ContentResolver;
import android.content.Context;
@@ -79,7 +80,8 @@ public class ZenModeButtonPreferenceControllerTest {
mContext = shadowApplication.getApplicationContext();
mContentResolver = RuntimeEnvironment.application.getContentResolver();
- mController = new ZenModeButtonPreferenceController(mContext, mock(Lifecycle.class));
+ mController = new ZenModeButtonPreferenceController(mContext, mock(Lifecycle.class),
+ mock(FragmentManager.class));
when(mNotificationManager.getNotificationPolicy()).thenReturn(mPolicy);
ReflectionHelpers.setField(mController, "mBackend", mBackend);
ReflectionHelpers.setField(mController, "mZenButtonOn", mZenButtonOn);
diff --git a/tests/robotests/src/com/android/settings/security/LockdownButtonPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/security/LockdownButtonPreferenceControllerTest.java
new file mode 100644
index 00000000000..7738f863e62
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/security/LockdownButtonPreferenceControllerTest.java
@@ -0,0 +1,98 @@
+/*
+ * 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.security;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.provider.Settings;
+import android.support.v14.preference.SwitchPreference;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class LockdownButtonPreferenceControllerTest {
+ @Mock
+ private LockPatternUtils mLockPatternUtils;
+ private SwitchPreference mPreference;
+
+ private Context mContext;
+ private LockdownButtonPreferenceController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mPreference = new SwitchPreference(mContext);
+
+ mController = spy(new LockdownButtonPreferenceController(mContext));
+ ReflectionHelpers.setField(mController, "mLockPatternUtils", mLockPatternUtils);
+ }
+
+ @Test
+ public void isAvailable_lockSet_shouldReturnTrue() throws Exception {
+ when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true);
+ assertThat(mController.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void isAvailable_lockUnset_shouldReturnFalse() throws Exception {
+ when(mLockPatternUtils.isSecure(anyInt())).thenReturn(false);
+ assertThat(mController.isAvailable()).isFalse();
+ }
+
+ @Test
+ public void onPreferenceChange_settingIsUpdated() throws Exception {
+ boolean state = Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.LOCKDOWN_IN_POWER_MENU, 0) != 0;
+ assertThat(mController.onPreferenceChange(mPreference, !state)).isTrue();
+ boolean newState = Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.LOCKDOWN_IN_POWER_MENU, 0) != 0;
+ assertThat(newState).isEqualTo(!state);
+ }
+
+ @Test
+ public void onSettingChange_preferenceIsUpdated() throws Exception {
+ boolean state = Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.LOCKDOWN_IN_POWER_MENU, 0) != 0;
+ mController.updateState(mPreference);
+ assertThat(mPreference.isChecked()).isEqualTo(state);
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.LOCKDOWN_IN_POWER_MENU, state ? 0 : 1);
+
+ mController.updateState(mPreference);
+ assertThat(mPreference.isChecked()).isEqualTo(!state);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
index 752ca1e21dc..ad51f79cab2 100644
--- a/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
+++ b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
@@ -21,6 +21,7 @@ import static org.mockito.Mockito.when;
import android.content.Context;
+import com.android.settings.accounts.AccountFeatureProvider;
import com.android.settings.applications.ApplicationFeatureProvider;
import com.android.settings.bluetooth.BluetoothFeatureProvider;
import com.android.settings.connecteddevice.SmsMirroringFeatureProvider;
@@ -65,6 +66,7 @@ public class FakeFeatureFactory extends FeatureFactory {
public final SmsMirroringFeatureProvider smsMirroringFeatureProvider;
public final SlicesFeatureProvider slicesFeatureProvider;
public SearchFeatureProvider searchFeatureProvider;
+ public final AccountFeatureProvider mAccountFeatureProvider;
/**
* Call this in {@code @Before} method of the test class to use fake factory.
@@ -104,6 +106,7 @@ public class FakeFeatureFactory extends FeatureFactory {
dataPlanFeatureProvider = mock(DataPlanFeatureProvider.class);
smsMirroringFeatureProvider = mock(SmsMirroringFeatureProvider.class);
slicesFeatureProvider = mock(SlicesFeatureProvider.class);
+ mAccountFeatureProvider = mock(AccountFeatureProvider.class);
}
@Override
@@ -190,4 +193,9 @@ public class FakeFeatureFactory extends FeatureFactory {
public SlicesFeatureProvider getSlicesFeatureProvider() {
return slicesFeatureProvider;
}
+
+ @Override
+ public AccountFeatureProvider getAccountFeatureProvider() {
+ return mAccountFeatureProvider;
+ }
}
diff --git a/tests/robotests/src/com/android/settings/widget/AppCheckBoxPreferenceTest.java b/tests/robotests/src/com/android/settings/widget/AppCheckBoxPreferenceTest.java
new file mode 100644
index 00000000000..d540a62ec7e
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/widget/AppCheckBoxPreferenceTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.widget;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+
+import com.android.settings.R;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class AppCheckBoxPreferenceTest {
+
+ private Context mContext;
+ private AppCheckBoxPreference mPreference;
+ private AppCheckBoxPreference mAttrPreference;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ mPreference = new AppCheckBoxPreference(mContext);
+ mAttrPreference = new AppCheckBoxPreference(mContext, null /* attrs */);
+ }
+
+ @Test
+ public void testGetLayoutResource() {
+ assertThat(mPreference.getLayoutResource()).isEqualTo(R.layout.preference_app);
+ assertThat(mAttrPreference.getLayoutResource()).isEqualTo(R.layout.preference_app);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceControllerTest.java
index 6832ca8e6d8..2a633d9a6c1 100644
--- a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceControllerTest.java
@@ -80,7 +80,7 @@ public class WifiTetherApBandPreferenceControllerTest {
mController.displayPreference(mScreen);
- assertThat(mListPreference.getEntries().length).isEqualTo(2);
+ assertThat(mListPreference.getEntries().length).isEqualTo(3);
}
@Test
@@ -113,13 +113,18 @@ public class WifiTetherApBandPreferenceControllerTest {
when(mWifiManager.is5GHzBandSupported()).thenReturn(true);
mController.displayPreference(mScreen);
+
+ // -1 is WifiConfiguration.AP_BAND_ANY, for 'Auto' option.
+ mController.onPreferenceChange(mListPreference, "-1");
+ assertThat(mController.getBandIndex()).isEqualTo(-1);
+
mController.onPreferenceChange(mListPreference, "1");
assertThat(mController.getBandIndex()).isEqualTo(1);
mController.onPreferenceChange(mListPreference, "0");
assertThat(mController.getBandIndex()).isEqualTo(0);
- verify(mListener, times(2)).onTetherConfigUpdated();
+ verify(mListener, times(3)).onTetherConfigUpdated();
}
@Test
diff --git a/tests/unit/src/com/android/settings/notification/ChannelGroupNotificationSettingsTest.java b/tests/unit/src/com/android/settings/notification/ChannelGroupNotificationSettingsTest.java
deleted file mode 100644
index ce2c408fa50..00000000000
--- a/tests/unit/src/com/android/settings/notification/ChannelGroupNotificationSettingsTest.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.notification;
-
-import static android.app.NotificationManager.IMPORTANCE_HIGH;
-import static android.app.NotificationManager.IMPORTANCE_MIN;
-import static android.support.test.espresso.Espresso.onView;
-import static android.support.test.espresso.assertion.ViewAssertions.matches;
-import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static android.support.test.espresso.matcher.ViewMatchers.withId;
-import static android.support.test.espresso.matcher.ViewMatchers.withText;
-
-import static org.hamcrest.Matchers.allOf;
-import static org.junit.Assert.fail;
-
-import android.app.INotificationManager;
-import android.app.Instrumentation;
-import android.app.NotificationChannel;
-import android.app.NotificationChannelGroup;
-import android.app.NotificationManager;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Process;
-import android.os.ServiceManager;
-import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class ChannelGroupNotificationSettingsTest {
-
- private Context mTargetContext;
- private Instrumentation mInstrumentation;
- private NotificationManager mNm;
-
- @Before
- public void setUp() {
- mInstrumentation = InstrumentationRegistry.getInstrumentation();
- mTargetContext = mInstrumentation.getTargetContext();
- mNm = (NotificationManager) mTargetContext.getSystemService(Context.NOTIFICATION_SERVICE);
- }
-
- @Test
- public void launchNotificationSetting_displaysChannels() {
- NotificationChannelGroup group =
- new NotificationChannelGroup(this.getClass().getName(), this.getClass().getName());
- group.setDescription("description");
- NotificationChannel channel = new NotificationChannel(this.getClass().getName(),
- "channel" + this.getClass().getName(), IMPORTANCE_MIN);
- channel.setGroup(this.getClass().getName());
- NotificationChannel channel2 = new NotificationChannel("2"+this.getClass().getName(),
- "2channel" + this.getClass().getName(), IMPORTANCE_MIN);
- channel2.setGroup(this.getClass().getName());
-
- mNm.createNotificationChannelGroup(group);
- mNm.createNotificationChannel(channel);
- mNm.createNotificationChannel(channel2);
-
- final Intent intent = new Intent(Settings.ACTION_CHANNEL_GROUP_NOTIFICATION_SETTINGS)
- .putExtra(Settings.EXTRA_APP_PACKAGE, mTargetContext.getPackageName())
- .putExtra(Settings.EXTRA_CHANNEL_GROUP_ID, group.getId());
-
- mInstrumentation.startActivitySync(intent);
-
- onView(allOf(withText(group.getName().toString()))).check(matches(isDisplayed()));
- onView(allOf(withText(channel.getName().toString()))).check(
- matches(isDisplayed()));
- onView(allOf(withText(group.getDescription().toString()))).check(
- matches(isDisplayed()));
- onView(allOf(withText(channel2.getName().toString()))).check(
- matches(isDisplayed()));
- try {
- onView(allOf(withText("Android is blocking this group of notifications from"
- + " appearing on this device"))).check(matches(isDisplayed()));
- fail("Blocking footer erroneously appearing");
- } catch (Exception e) {
- // expected
- }
- }
-
- @Test
- public void launchNotificationSettings_blockedGroup() throws Exception {
- NotificationChannelGroup blocked =
- new NotificationChannelGroup("blocked", "blocked");
- NotificationChannel channel =
- new NotificationChannel("channel", "channel", IMPORTANCE_HIGH);
- channel.setGroup(blocked.getId());
- mNm.createNotificationChannelGroup(blocked);
- mNm.createNotificationChannel(channel);
-
- INotificationManager sINM = INotificationManager.Stub.asInterface(
- ServiceManager.getService(Context.NOTIFICATION_SERVICE));
- blocked.setBlocked(true);
- sINM.updateNotificationChannelGroupForPackage(
- mTargetContext.getPackageName(), Process.myUid(), blocked);
-
- final Intent intent = new Intent(Settings.ACTION_CHANNEL_GROUP_NOTIFICATION_SETTINGS)
- .putExtra(Settings.EXTRA_APP_PACKAGE, mTargetContext.getPackageName())
- .putExtra(Settings.EXTRA_CHANNEL_GROUP_ID, blocked.getId());
- mInstrumentation.startActivitySync(intent);
-
- onView(allOf(withText("Off"), isDisplayed())).check(matches(isDisplayed()));
- onView(allOf(withText("Android is blocking this group of notifications from"
- + " appearing on this device"))).check(matches(isDisplayed()));
-
- try {
- onView(allOf(withText(channel.getName().toString()))).check(matches(isDisplayed()));
- fail("settings appearing for blocked group");
- } catch (Exception e) {
- // expected
- }
- }
-}