Snap for 4751292 from 167612df0e to qt-release

Change-Id: I01a896a207bbe3cb20ad0c2811e172df5f96660f
This commit is contained in:
android-build-team Robot
2018-04-28 09:35:16 +00:00
38 changed files with 2300 additions and 247 deletions

View File

@@ -738,23 +738,6 @@
android:value="true" />
</activity>
<activity
android:name="Settings$ZenModeBlockedEffectsSettingsActivity"
android:label="@string/zen_mode_what_to_block_title"
android:icon="@drawable/ic_settings_notifications"
android:exported="true"
android:taskAffinity="com.android.settings"
android:parentActivityName="Settings">
<intent-filter android:priority="1">
<action android:name="android.settings.ZEN_MODE_BLOCKED_EFFECTS_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.notification.ZenModeBlockedEffectsSettings" />
<meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
android:value="true" />
</activity>
<activity
android:name=".notification.ZenOnboardingActivity"
android:label="@string/zen_onboarding_dnd_visual_disturbances_header"
@@ -2341,7 +2324,7 @@
android:label="@string/header_add_an_account"
android:configChanges="orientation|keyboardHidden|screenSize">
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.accounts.ChooseAccountActivity" />
android:value="com.android.settings.accounts.ChooseAccountFragment" />
</activity>
<activity android:name=".CryptKeeper"

View File

@@ -17,7 +17,8 @@
android:viewportWidth="24"
android:viewportHeight="24"
android:width="24dp"
android:height="24dp">
android:height="24dp"
android:tint="?android:attr/colorControlNormal">
<path android:fillColor="#FF000000"
android:pathData="M3 6h18V4H3C1.9 4 1 4.9 1 6v12c0 1.10.9 2 2 2h4v-2H3V6z M13 12H9
v1.78C8.39 14.33 8 15.11 8 16c0 0.89 0.39 1.67 1 2.22 V20h4v-1.78c0.61-0.55 1-1.34

View File

@@ -16,10 +16,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM10,
16.5v-9l6,4.5 -6,4.5z"/>
</vector>
android:viewportWidth="48.0"
android:viewportHeight="48.0">
<path android:fillColor="#FFFFFF" android:pathData="M24,24m-19,0a19,19 0,1 1,38 0a19,19 0,1 1,-38 0"/>
<path android:fillColor="#1A73E8" android:pathData="M20,33l12,-9l-12,-9z"/>
<path android:fillColor="#1A73E8" android:pathData="M24,4C12.96,4 4,12.96 4,24s8.96,20 20,20s20,-8.96 20,-20S35.04,4 24,4zM24,40c-8.82,0 -16,-7.18 -16,-16S15.18,8 24,8s16,7.18 16,16S32.82,40 24,40z"/>
</vector>

View File

@@ -0,0 +1,90 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:gravity="center_vertical"
android:background="@android:color/transparent"
android:clipToPadding="false">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="?android:attr/selectableItemBackground"
android:gravity="start|center_vertical"
android:clipToPadding="false">
<LinearLayout
android:id="@+id/checkbox_frame"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:minWidth="56dp"
android:layout_marginEnd="16dp"
android:orientation="vertical">
<RadioButton
android:id="@android:id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@null"
android:focusable="false"
android:clickable="false" />
</LinearLayout>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingTop="16dp"
android:paddingBottom="16dp">
<TextView
android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceListItem"
android:ellipsize="marquee" />
<TextView
android:id="@android:id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@android:id/title"
android:layout_alignStart="@android:id/title"
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
android:textColor="?android:attr/textColorSecondary"
android:maxLines="10" />
</RelativeLayout>
</LinearLayout>
<include layout="@layout/preference_two_target_divider" />
<LinearLayout
android:id="@android:id/widget_frame"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:minWidth="64dp"
android:orientation="vertical" />
</LinearLayout>

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<!-- Layout used by CheckBoxPreference for the checkbox style. This is inflated
inside android.R.layout.preference. -->
<RadioButton xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@null"
android:focusable="false"
android:clickable="false" />

View File

@@ -4486,8 +4486,8 @@
<string name="user_installed_services_category_title">Downloaded services</string>
<!-- Title for the accessibility preference category of settings considered to be experimental, meaning they might be changed or removed in the future. [CHAR LIMIT=50] -->
<string name="experimental_category_title">Experimental</string>
<!-- Title for feature flags dashboard DO NOT TRANSLATE -->
<string name="feature_flags_dashboard_title" translatable="false">Feature flags</string>
<!-- Title for feature flags dashboard where developers can turn on experimental features [CHAR LIMIT=50] -->
<string name="feature_flags_dashboard_title">Feature flags</string>
<!-- Title for the Talkback Accessibility Service. Displayed on the Accessibility Settings screen in Setup Wizard. [CHAR_LIMIT=25] -->
<string name="talkback_title">Talkback</string>
<!-- Summary for the Talkback Accessibility Service. Lets the user know that Talkback is a screenreader and that it is usually most helpful to blind and low vision users and whether the service is on. [CHAR_LIMIT=none] -->
@@ -7215,8 +7215,39 @@
<!-- Do not disturb: Subtitle for the Visual signals option to toggle on/off visual signals/alerts when the screen is on/when screen is off. [CHAR LIMIT=30] -->
<string name="zen_mode_visual_signals_settings_subtitle">Allow visual signals</string>
<!-- Do not disturb: restrict notifications title [CHAR LIMIT=60] -->
<string name="zen_mode_restrict_notifications_screen_title">Restrict notifications</string>
<!-- Do not disturb: restrict notifications title [CHAR LIMIT=60] -->
<string name="zen_mode_restrict_notifications_title">Notifications</string>
<!-- Do not disturb: restrict notifications category title [CHAR LIMIT=100] -->
<string name="zen_mode_restrict_notifications_category">When Do Not Disturb is turned on</string>
<!-- Do not disturb: Mute notifications option [CHAR LIMIT=60] -->
<string name="zen_mode_restrict_notifications_mute">Mute notifications</string>
<!-- Do not disturb:Mute notifications summary [CHAR LIMIT=NONE] -->
<string name="zen_mode_restrict_notifications_mute_summary">Show notifications but mute sounds &amp; vibrations</string>
<!-- Do not disturb:Mute notifications footer [CHAR LIMIT=NONE] -->
<string name="zen_mode_restrict_notifications_mute_footer">When new notifications arrive your phone won\u2019t make a sound or vibration</string>
<!-- Do not disturb: Hide notifications option [CHAR LIMIT=60] -->
<string name="zen_mode_restrict_notifications_hide">Hide &amp; mute notifications</string>
<!-- Do not disturb: Hide notifications summary [CHAR LIMIT=NONE] -->
<string name="zen_mode_restrict_notifications_hide_summary">Notifications will not appear at all</string>
<!-- Do not disturb: Hide notifications footer [CHAR LIMIT=NONE] -->
<string name="zen_mode_restrict_notifications_hide_footer">You won\u2019t see new or existing notifications when Do Not Disturb is on. However, notifications needed for basic phone activity and status will still appear.</string>
<!-- Do not disturb: Custom settings option [CHAR LIMIT=60] -->
<string name="zen_mode_restrict_notifications_custom">Custom</string>
<!-- Do not disturb: restrict notifications page, menu option [CHAR LIMIT=60] -->
<string name="zen_mode_restrict_notifications_enable_custom">Enable custom setting</string>
<!-- Do not disturb: restrict notifications page, menu option [CHAR LIMIT=60] -->
<string name="zen_mode_restrict_notifications_disable_custom">Remove custom setting</string>
<!-- Do not disturb: restrict notifications page, menu option [CHAR LIMIT=60] -->
<string name="zen_mode_restrict_notifications_summary_muted">Will appear</string>
<!-- Do not disturb: restrict notifications page, menu option [CHAR LIMIT=60] -->
<string name="zen_mode_restrict_notifications_summary_custom">Partially hidden</string>
<!-- Do not disturb: restrict notifications page, menu option [CHAR LIMIT=60] -->
<string name="zen_mode_restrict_notifications_summary_hidden">Hidden</string>
<!-- Do not disturb: what to block title [CHAR LIMIT = 60] -->
<string name="zen_mode_what_to_block_title">Block visual disturbances</string>
<string name="zen_mode_what_to_block_title">Custom restrictions</string>
<!-- Do not disturb: what to block > effects title [CHAR LIMIT = 60] -->
<string name="zen_mode_block_effects_screen_on">When the screen is on</string>
<!-- Do not disturb: what to block > effects title [CHAR LIMIT = 60] -->

View File

@@ -14,6 +14,9 @@
limitations under the License.
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
</PreferenceScreen>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="add_account_screen"
android:title="@string/header_add_an_account"
settings:controller="com.android.settings.accounts.ChooseAccountPreferenceController" />

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
android:key="zen_mode_restrict_settings_page"
android:title="@string/zen_mode_restrict_notifications_screen_title">
<PreferenceCategory
android:key="restrict_category"
android:title="@string/zen_mode_restrict_notifications_category">
<com.android.settings.notification.ZenCustomRadioButtonPreference
android:key="zen_mute_notifications"
android:title="@string/zen_mode_restrict_notifications_mute"
android:summary="@string/zen_mode_restrict_notifications_mute_summary"/>
<com.android.settings.notification.ZenCustomRadioButtonPreference
android:key="zen_hide_notifications"
android:title="@string/zen_mode_restrict_notifications_hide"
android:summary="@string/zen_mode_restrict_notifications_hide_summary"/>
<com.android.settings.notification.ZenCustomRadioButtonPreference
android:key="zen_custom"
android:title="@string/zen_mode_restrict_notifications_custom" />
</PreferenceCategory>
<com.android.settingslib.widget.FooterPreference />
</PreferenceScreen>

View File

@@ -31,8 +31,8 @@
<!-- What to block (effects) -->
<Preference
android:key="zen_mode_block_effects_settings"
android:title="@string/zen_mode_what_to_block_title"
android:fragment="com.android.settings.notification.ZenModeBlockedEffectsSettings" />
android:title="@string/zen_mode_restrict_notifications_title"
android:fragment="com.android.settings.notification.ZenModeRestrictNotificationsSettings" />
<!-- Behavior settings (exceptions) -->
<Preference

View File

@@ -0,0 +1,107 @@
/*
* 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.content.Context;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.SearchIndexableResource;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.search.SearchIndexable;
import java.util.ArrayList;
import java.util.List;
/**
* Activity asking a user to select an account to be set up.
*/
@SearchIndexable
public class ChooseAccountFragment extends DashboardFragment {
private static final String TAG = "ChooseAccountFragment";
@Override
public int getMetricsCategory() {
return MetricsEvent.ACCOUNTS_CHOOSE_ACCOUNT_ACTIVITY;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
final String[] authorities = getIntent().getStringArrayExtra(
AccountPreferenceBase.AUTHORITIES_FILTER_KEY);
final String[] accountTypesFilter = getIntent().getStringArrayExtra(
AccountPreferenceBase.ACCOUNT_TYPES_FILTER_KEY);
final UserManager userManager = UserManager.get(getContext());
final UserHandle userHandle = Utils.getSecureTargetUser(getActivity().getActivityToken(),
userManager, null /* arguments */, getIntent().getExtras());
use(ChooseAccountPreferenceController.class).initialize(authorities, accountTypesFilter,
userHandle, getActivity());
use(EnterpriseDisclosurePreferenceController.class).setFooterPreferenceMixin(
mFooterPreferenceMixin);
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.add_account_settings;
}
@Override
protected String getLogTag() {
return TAG;
}
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
return buildControllers(context);
}
private static List<AbstractPreferenceController> buildControllers(Context context) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
controllers.add(new EnterpriseDisclosurePreferenceController(context));
return controllers;
}
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
boolean enabled) {
final ArrayList<SearchIndexableResource> result = new ArrayList<>();
final SearchIndexableResource sir = new SearchIndexableResource(context);
sir.xmlResId = R.xml.add_account_settings;
result.add(sir);
return result;
}
@Override
public List<AbstractPreferenceController> createPreferenceControllers(
Context context) {
return buildControllers(context);
}
};
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2010 The Android Open Source Project
* 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.
@@ -30,24 +30,11 @@ import android.content.SyncAdapterType;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
import androidx.preference.Preference;
import androidx.preference.PreferenceGroup;
import android.util.Log;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.CharSequences;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import com.android.settingslib.widget.FooterPreference;
import com.android.settingslib.widget.FooterPreferenceMixin;
import com.google.android.collect.Maps;
@@ -55,89 +42,87 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
/**
* Activity asking a user to select an account to be set up.
*
* An extra {@link UserHandle} can be specified in the intent as {@link EXTRA_USER}, if the user for
* which the action needs to be performed is different to the one the Settings App will run in.
*/
public class ChooseAccountActivity extends SettingsPreferenceFragment {
public class ChooseAccountPreferenceController extends BasePreferenceController {
private static final String TAG = "ChooseAccountActivity";
private static final String TAG = "ChooseAccountPrefCtrler";
private EnterprisePrivacyFeatureProvider mFeatureProvider;
private FooterPreference mEnterpriseDisclosurePreference = null;
private final List<ProviderEntry> mProviderList;
private final Map<String, AuthenticatorDescription> mTypeToAuthDescription;
private String[] mAuthorities;
private PreferenceGroup mAddAccountGroup;
private final ArrayList<ProviderEntry> mProviderList = new ArrayList<ProviderEntry>();
public HashSet<String> mAccountTypesFilter;
private Set<String> mAccountTypesFilter;
private AuthenticatorDescription[] mAuthDescs;
private HashMap<String, ArrayList<String>> mAccountTypeToAuthorities = null;
private Map<String, AuthenticatorDescription> mTypeToAuthDescription
= new HashMap<String, AuthenticatorDescription>();
private Map<String, List<String>> mAccountTypeToAuthorities;
// The UserHandle of the user we are choosing an account for
private UserHandle mUserHandle;
private UserManager mUm;
private Activity mActivity;
private PreferenceScreen mScreen;
private static class ProviderEntry implements Comparable<ProviderEntry> {
private final CharSequence name;
private final String type;
ProviderEntry(CharSequence providerName, String accountType) {
name = providerName;
type = accountType;
}
public ChooseAccountPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
public int compareTo(ProviderEntry another) {
if (name == null) {
return -1;
}
if (another.name == null) {
return +1;
}
return CharSequences.compareToIgnoreCase(name, another.name);
}
mProviderList = new ArrayList<>();
mTypeToAuthDescription = new HashMap<>();
}
@Override
public int getMetricsCategory() {
return MetricsEvent.ACCOUNTS_CHOOSE_ACCOUNT_ACTIVITY;
}
public void initialize(String[] authorities, String[] accountTypesFilter, UserHandle userHandle,
Activity activity) {
mActivity = activity;
mAuthorities = authorities;
mUserHandle = userHandle;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
final Activity activity = getActivity();
mFeatureProvider = FeatureFactory.getFactory(activity)
.getEnterprisePrivacyFeatureProvider(activity);
addPreferencesFromResource(R.xml.add_account_settings);
mAuthorities = getIntent().getStringArrayExtra(
AccountPreferenceBase.AUTHORITIES_FILTER_KEY);
String[] accountTypesFilter = getIntent().getStringArrayExtra(
AccountPreferenceBase.ACCOUNT_TYPES_FILTER_KEY);
if (accountTypesFilter != null) {
mAccountTypesFilter = new HashSet<String>();
mAccountTypesFilter = new HashSet<>();
for (String accountType : accountTypesFilter) {
mAccountTypesFilter.add(accountType);
}
}
mAddAccountGroup = getPreferenceScreen();
mUm = UserManager.get(getContext());
mUserHandle = Utils.getSecureTargetUser(getActivity().getActivityToken(), mUm,
null /* arguments */, getIntent().getExtras());
}
@Override
public int getAvailabilityStatus() {
return AVAILABLE;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mScreen = screen;
updateAuthDescriptions();
}
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
if (!(preference instanceof ProviderPreference)) {
return false;
}
ProviderPreference pref = (ProviderPreference) preference;
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Attempting to add account of type " + pref.getAccountType());
}
finishWithAccountType(pref.getAccountType());
return true;
}
/**
* Updates provider icons. Subclasses should call this in onCreate()
* and update any UI that depends on AuthenticatorDescriptions in onAuthDescriptionsUpdated().
*/
private void updateAuthDescriptions() {
mAuthDescs = AccountManager.get(getContext()).getAuthenticatorTypesAsUser(
mAuthDescs = AccountManager.get(mContext).getAuthenticatorTypesAsUser(
mUserHandle.getIdentifier());
for (int i = 0; i < mAuthDescs.length; i++) {
mTypeToAuthDescription.put(mAuthDescs[i].type, mAuthDescs[i]);
@@ -148,12 +133,12 @@ public class ChooseAccountActivity extends SettingsPreferenceFragment {
private void onAuthDescriptionsUpdated() {
// Create list of providers to show on preference screen
for (int i = 0; i < mAuthDescs.length; i++) {
String accountType = mAuthDescs[i].type;
CharSequence providerName = getLabelForType(accountType);
final String accountType = mAuthDescs[i].type;
final CharSequence providerName = getLabelForType(accountType);
// Skip preferences for authorities not specified. If no authorities specified,
// then include them all.
ArrayList<String> accountAuths = getAuthoritiesForAccountType(accountType);
final List<String> accountAuths = getAuthoritiesForAccountType(accountType);
boolean addAccountPref = true;
if (mAuthorities != null && mAuthorities.length > 0 && accountAuths != null) {
addAccountPref = false;
@@ -169,38 +154,39 @@ public class ChooseAccountActivity extends SettingsPreferenceFragment {
addAccountPref = false;
}
if (addAccountPref) {
mProviderList.add(new ProviderEntry(providerName, accountType));
mProviderList.add(
new ProviderEntry(providerName, accountType));
} else {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Skipped pref " + providerName + ": has no authority we need");
}
}
}
final Context context = getPreferenceScreen().getContext();
final Context context = mScreen.getContext();
if (mProviderList.size() == 1) {
// There's only one provider that matches. If it is disabled by admin show the
// support dialog otherwise run it.
EnforcedAdmin admin = RestrictedLockUtils.checkIfAccountManagementDisabled(
context, mProviderList.get(0).type, mUserHandle.getIdentifier());
final RestrictedLockUtils.EnforcedAdmin admin =
RestrictedLockUtils.checkIfAccountManagementDisabled(
context, mProviderList.get(0).getType(), mUserHandle.getIdentifier());
if (admin != null) {
setResult(RESULT_CANCELED, RestrictedLockUtils.getShowAdminSupportDetailsIntent(
context, admin));
finish();
mActivity.setResult(RESULT_CANCELED,
RestrictedLockUtils.getShowAdminSupportDetailsIntent(
context, admin));
mActivity.finish();
} else {
finishWithAccountType(mProviderList.get(0).type);
finishWithAccountType(mProviderList.get(0).getType());
}
} else if (mProviderList.size() > 0) {
Collections.sort(mProviderList);
mAddAccountGroup.removeAll();
for (ProviderEntry pref : mProviderList) {
Drawable drawable = getDrawableForType(pref.type);
ProviderPreference p = new ProviderPreference(getPreferenceScreen().getContext(),
pref.type, drawable, pref.name);
final Drawable drawable = getDrawableForType(pref.getType());
final ProviderPreference p = new ProviderPreference(context,
pref.getType(), drawable, pref.getName());
p.setKey(pref.getType().toString());
p.checkAccountManagementAndSetDisabled(mUserHandle.getIdentifier());
mAddAccountGroup.addPreference(p);
mScreen.addPreference(p);
}
addEnterpriseDisclosure();
} else {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
final StringBuilder auths = new StringBuilder();
@@ -210,38 +196,25 @@ public class ChooseAccountActivity extends SettingsPreferenceFragment {
}
Log.v(TAG, "No providers found for authorities: " + auths);
}
setResult(RESULT_CANCELED);
finish();
mActivity.setResult(RESULT_CANCELED);
mActivity.finish();
}
}
private void addEnterpriseDisclosure() {
final CharSequence disclosure = mFeatureProvider.getDeviceOwnerDisclosure();
if (disclosure == null) {
return;
}
if (mEnterpriseDisclosurePreference == null) {
mEnterpriseDisclosurePreference = mFooterPreferenceMixin.createFooterPreference();
mEnterpriseDisclosurePreference.setSelectable(false);
}
mEnterpriseDisclosurePreference.setTitle(disclosure);
mAddAccountGroup.addPreference(mEnterpriseDisclosurePreference);
}
public ArrayList<String> getAuthoritiesForAccountType(String type) {
private List<String> getAuthoritiesForAccountType(String type) {
if (mAccountTypeToAuthorities == null) {
mAccountTypeToAuthorities = Maps.newHashMap();
SyncAdapterType[] syncAdapters = ContentResolver.getSyncAdapterTypesAsUser(
final SyncAdapterType[] syncAdapters = ContentResolver.getSyncAdapterTypesAsUser(
mUserHandle.getIdentifier());
for (int i = 0, n = syncAdapters.length; i < n; i++) {
final SyncAdapterType sa = syncAdapters[i];
ArrayList<String> authorities = mAccountTypeToAuthorities.get(sa.accountType);
List<String> authorities = mAccountTypeToAuthorities.get(sa.accountType);
if (authorities == null) {
authorities = new ArrayList<String>();
authorities = new ArrayList<>();
mAccountTypeToAuthorities.put(sa.accountType, authorities);
}
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.d(TAG, "added authority " + sa.authority + " to accountType "
Log.v(TAG, "added authority " + sa.authority + " to accountType "
+ sa.accountType);
}
authorities.add(sa.authority);
@@ -252,18 +225,20 @@ public class ChooseAccountActivity extends SettingsPreferenceFragment {
/**
* Gets an icon associated with a particular account type. If none found, return null.
*
* @param accountType the type of account
* @return a drawable for the icon or a default icon returned by
* {@link PackageManager#getDefaultActivityIcon} if one cannot be found.
*/
protected Drawable getDrawableForType(final String accountType) {
@VisibleForTesting
Drawable getDrawableForType(final String accountType) {
Drawable icon = null;
if (mTypeToAuthDescription.containsKey(accountType)) {
try {
AuthenticatorDescription desc = mTypeToAuthDescription.get(accountType);
Context authContext = getActivity()
final AuthenticatorDescription desc = mTypeToAuthDescription.get(accountType);
final Context authContext = mActivity
.createPackageContextAsUser(desc.packageName, 0, mUserHandle);
icon = getPackageManager().getUserBadgedIcon(
icon = mContext.getPackageManager().getUserBadgedIcon(
authContext.getDrawable(desc.iconId), mUserHandle);
} catch (PackageManager.NameNotFoundException e) {
Log.w(TAG, "No icon name for account type " + accountType);
@@ -274,21 +249,23 @@ public class ChooseAccountActivity extends SettingsPreferenceFragment {
if (icon != null) {
return icon;
} else {
return getPackageManager().getDefaultActivityIcon();
return mContext.getPackageManager().getDefaultActivityIcon();
}
}
/**
* Gets the label associated with a particular account type. If none found, return null.
*
* @param accountType the type of account
* @return a CharSequence for the label or null if one cannot be found.
*/
protected CharSequence getLabelForType(final String accountType) {
@VisibleForTesting
CharSequence getLabelForType(final String accountType) {
CharSequence label = null;
if (mTypeToAuthDescription.containsKey(accountType)) {
try {
AuthenticatorDescription desc = mTypeToAuthDescription.get(accountType);
Context authContext = getActivity()
final AuthenticatorDescription desc = mTypeToAuthDescription.get(accountType);
final Context authContext = mActivity
.createPackageContextAsUser(desc.packageName, 0, mUserHandle);
label = authContext.getResources().getText(desc.labelId);
} catch (PackageManager.NameNotFoundException e) {
@@ -300,23 +277,11 @@ public class ChooseAccountActivity extends SettingsPreferenceFragment {
return label;
}
@Override
public boolean onPreferenceTreeClick(Preference preference) {
if (preference instanceof ProviderPreference) {
ProviderPreference pref = (ProviderPreference) preference;
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Attempting to add account of type " + pref.getAccountType());
}
finishWithAccountType(pref.getAccountType());
}
return true;
}
private void finishWithAccountType(String accountType) {
Intent intent = new Intent();
intent.putExtra(AddAccountSettings.EXTRA_SELECTED_ACCOUNT, accountType);
intent.putExtra(EXTRA_USER, mUserHandle);
setResult(RESULT_OK, intent);
finish();
mActivity.setResult(RESULT_OK, intent);
mActivity.finish();
}
}

View File

@@ -0,0 +1,79 @@
/*
* 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.content.Context;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.enterprise.EnterprisePrivacyFeatureProvider;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.widget.FooterPreference;
import com.android.settingslib.widget.FooterPreferenceMixin;
import androidx.annotation.VisibleForTesting;
import androidx.preference.PreferenceScreen;
public class EnterpriseDisclosurePreferenceController extends BasePreferenceController {
private final EnterprisePrivacyFeatureProvider mFeatureProvider;
private FooterPreferenceMixin mFooterPreferenceMixin;
private PreferenceScreen mScreen;
public EnterpriseDisclosurePreferenceController(Context context) {
// Preference key doesn't matter as we are creating the preference in code.
super(context, "add_account_enterprise_disclosure_footer");
mFeatureProvider = FeatureFactory.getFactory(mContext)
.getEnterprisePrivacyFeatureProvider(mContext);
}
public void setFooterPreferenceMixin(FooterPreferenceMixin footerPreferenceMixin) {
mFooterPreferenceMixin = footerPreferenceMixin;
}
@Override
public int getAvailabilityStatus() {
if (getDisclosure() == null) {
return DISABLED_UNSUPPORTED;
}
return AVAILABLE;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mScreen = screen;
addEnterpriseDisclosure();
}
@VisibleForTesting
CharSequence getDisclosure() {
return mFeatureProvider.getDeviceOwnerDisclosure();
}
private void addEnterpriseDisclosure() {
final CharSequence disclosure = getDisclosure();
if (disclosure == null) {
return;
}
final FooterPreference enterpriseDisclosurePreference =
mFooterPreferenceMixin.createFooterPreference();
enterpriseDisclosurePreference.setSelectable(false);
enterpriseDisclosurePreference.setTitle(disclosure);
mScreen.addPreference(enterpriseDisclosurePreference);
}
}

View File

@@ -0,0 +1,47 @@
/*
* 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 com.android.internal.util.CharSequences;
public class ProviderEntry implements Comparable<ProviderEntry> {
private final CharSequence name;
private final String type;
ProviderEntry(CharSequence providerName, String accountType) {
name = providerName;
type = accountType;
}
public int compareTo(ProviderEntry another) {
if (name == null) {
return -1;
}
if (another.name == null) {
return +1;
}
return CharSequences.compareToIgnoreCase(name, another.name);
}
public CharSequence getName() {
return name;
}
public String getType() {
return type;
}
}

View File

@@ -56,6 +56,7 @@ public final class BluetoothDevicePreference extends GearPreference implements
private AlertDialog mDisconnectDialog;
private String contentDescription = null;
private boolean mHideSecondTarget = false;
/* Talk-back descriptions for various BT icons */
Resources mResources;
@@ -86,7 +87,8 @@ public final class BluetoothDevicePreference extends GearPreference implements
protected boolean shouldHideSecondTarget() {
return mCachedDevice == null
|| mCachedDevice.getBondState() != BluetoothDevice.BOND_BONDED
|| mUserManager.hasUserRestriction(DISALLOW_CONFIG_BLUETOOTH);
|| mUserManager.hasUserRestriction(DISALLOW_CONFIG_BLUETOOTH)
|| mHideSecondTarget;
}
@Override
@@ -112,6 +114,10 @@ public final class BluetoothDevicePreference extends GearPreference implements
return mCachedDevice;
}
public void hideSecondTarget(boolean hideSecondTarget) {
mHideSecondTarget = hideSecondTarget;
}
public void onDeviceAttributesChanged() {
/*
* The preference framework takes care of making sure the value has

View File

@@ -56,29 +56,14 @@ public abstract class BluetoothDeviceUpdater implements BluetoothCallback,
protected final DevicePreferenceCallback mDevicePreferenceCallback;
protected final Map<BluetoothDevice, Preference> mPreferenceMap;
protected Context mPrefContext;
protected DashboardFragment mFragment;
private final boolean mShowDeviceWithoutNames;
private DashboardFragment mFragment;
private Preference.OnPreferenceClickListener mDevicePreferenceClickListener = null;
@VisibleForTesting
final GearPreference.OnGearClickListener mDeviceProfilesListener = pref -> {
final CachedBluetoothDevice device =
((BluetoothDevicePreference) pref).getBluetoothDevice();
if (device == null) {
return;
}
final Bundle args = new Bundle();
args.putString(BluetoothDeviceDetailsFragment.KEY_DEVICE_ADDRESS,
device.getDevice().getAddress());
new SubSettingLauncher(mFragment.getContext())
.setDestination(BluetoothDeviceDetailsFragment.class.getName())
.setArguments(args)
.setTitle(R.string.device_details_title)
.setSourceMetricsCategory(mFragment.getMetricsCategory())
.launch();
launchDeviceDetails(pref);
};
private class PreferenceClickListener implements
@@ -201,7 +186,7 @@ public abstract class BluetoothDeviceUpdater implements BluetoothCallback,
public abstract boolean isFilterMatched(CachedBluetoothDevice cachedBluetoothDevice);
/**
* Update whether to show {@cde cachedBluetoothDevice} in the list.
* Update whether to show {@link CachedBluetoothDevice} in the list.
*/
protected void update(CachedBluetoothDevice cachedBluetoothDevice) {
if (isFilterMatched(cachedBluetoothDevice)) {
@@ -239,6 +224,28 @@ public abstract class BluetoothDeviceUpdater implements BluetoothCallback,
}
}
/**
* Get {@link CachedBluetoothDevice} from {@link Preference} and it is used to init
* {@link SubSettingLauncher} to launch {@link BluetoothDeviceDetailsFragment}
*/
protected void launchDeviceDetails(Preference preference) {
final CachedBluetoothDevice device =
((BluetoothDevicePreference) preference).getBluetoothDevice();
if (device == null) {
return;
}
final Bundle args = new Bundle();
args.putString(BluetoothDeviceDetailsFragment.KEY_DEVICE_ADDRESS,
device.getDevice().getAddress());
new SubSettingLauncher(mFragment.getContext())
.setDestination(BluetoothDeviceDetailsFragment.class.getName())
.setArguments(args)
.setTitle(R.string.device_details_title)
.setSourceMetricsCategory(mFragment.getMetricsCategory())
.launch();
}
/**
* @return {@code true} if {@code cachedBluetoothDevice} is connected
* and the bond state is bonded.

View File

@@ -16,12 +16,19 @@
package com.android.settings.bluetooth;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.media.AudioManager;
import androidx.annotation.VisibleForTesting;
import android.os.Bundle;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import com.android.settings.R;
import com.android.settings.connecteddevice.DevicePreferenceCallback;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
@@ -116,4 +123,20 @@ public class ConnectedBluetoothDeviceUpdater extends BluetoothDeviceUpdater {
}
return isFilterMatched;
}
@Override
protected void addPreference(CachedBluetoothDevice cachedDevice) {
super.addPreference(cachedDevice);
final BluetoothDevice device = cachedDevice.getDevice();
if (mPreferenceMap.containsKey(device)) {
final BluetoothDevicePreference btPreference =
(BluetoothDevicePreference) mPreferenceMap.get(device);
btPreference.setOnGearClickListener(null);
btPreference.hideSecondTarget(true);
btPreference.setOnPreferenceClickListener((Preference p) -> {
launchDeviceDetails(p);
return true;
});
}
}
}

View File

@@ -31,7 +31,7 @@ import com.android.settings.accessibility.CaptionPropertiesFragment;
import com.android.settings.accessibility.ToggleDaltonizerPreferenceFragment;
import com.android.settings.accounts.AccountDashboardFragment;
import com.android.settings.accounts.AccountSyncSettings;
import com.android.settings.accounts.ChooseAccountActivity;
import com.android.settings.accounts.ChooseAccountFragment;
import com.android.settings.accounts.ManagedProfileSettings;
import com.android.settings.applications.AppAndNotificationDashboardFragment;
import com.android.settings.applications.DefaultAppSettings;
@@ -236,7 +236,7 @@ public class SettingsGateway {
PictureInPictureSettings.class.getName(),
PictureInPictureDetails.class.getName(),
ManagedProfileSettings.class.getName(),
ChooseAccountActivity.class.getName(),
ChooseAccountFragment.class.getName(),
IccLockSettings.class.getName(),
TestingSettings.class.getName(),
WifiAPITest.class.getName(),

View File

@@ -54,6 +54,7 @@ abstract public class AbstractZenModePreferenceController extends
protected static ZenModeConfigWrapper mZenModeConfigWrapper;
protected MetricsFeatureProvider mMetricsFeatureProvider;
protected final ZenModeBackend mBackend;
protected PreferenceScreen mScreen;
public AbstractZenModePreferenceController(Context context, String key,
Lifecycle lifecycle) {
@@ -71,16 +72,26 @@ abstract public class AbstractZenModePreferenceController extends
mBackend = ZenModeBackend.getInstance(context);
}
@Override
public String getPreferenceKey() {
return KEY;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mSettingObserver = new SettingObserver(screen.findPreference(KEY));
mScreen = screen;
Preference pref = screen.findPreference(KEY);
if (pref != null) {
mSettingObserver = new SettingObserver(pref);
}
}
@Override
public void onResume() {
if (mSettingObserver != null) {
mSettingObserver.register(mContext.getContentResolver());
mSettingObserver.onChange(false, null);
}
}
@@ -91,14 +102,6 @@ abstract public class AbstractZenModePreferenceController extends
}
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
mBackend.updatePolicy();
mBackend.updateZenMode();
}
protected NotificationManager.Policy getPolicy() {
return mNotificationManager.getNotificationPolicy();
}
@@ -144,8 +147,13 @@ abstract public class AbstractZenModePreferenceController extends
@Override
public void onChange(boolean selfChange, Uri uri) {
super.onChange(selfChange, uri);
if (ZEN_MODE_URI.equals(uri) || ZEN_MODE_CONFIG_ETAG_URI.equals(uri)
if (uri == null || ZEN_MODE_URI.equals(uri) || ZEN_MODE_CONFIG_ETAG_URI.equals(uri)
|| ZEN_MODE_DURATION_URI.equals(uri)) {
mBackend.updatePolicy();
mBackend.updateZenMode();
if (mScreen != null) {
displayPreference(mScreen);
}
updateState(mPreference);
}
}

View File

@@ -0,0 +1,140 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.notification;
import android.content.Context;
import androidx.preference.PreferenceViewHolder;
import android.util.AttributeSet;
import android.view.View;
import android.widget.RadioButton;
import com.android.settings.R;
import com.android.settingslib.TwoTargetPreference;
/**
* A radio button preference with a divider and a settings icon that links to another screen.
*/
public class ZenCustomRadioButtonPreference extends TwoTargetPreference
implements View.OnClickListener {
private RadioButton mButton;
private boolean mChecked;
private OnGearClickListener mOnGearClickListener;
private OnRadioButtonClickListener mOnRadioButtonClickListener;
public ZenCustomRadioButtonPreference(Context context, AttributeSet attrs,
int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
setLayoutResource(R.layout.preference_two_target_radio);
}
public ZenCustomRadioButtonPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setLayoutResource(R.layout.preference_two_target_radio);
}
public ZenCustomRadioButtonPreference(Context context, AttributeSet attrs) {
super(context, attrs);
setLayoutResource(R.layout.preference_two_target_radio);
}
public ZenCustomRadioButtonPreference(Context context) {
super(context);
setLayoutResource(R.layout.preference_two_target_radio);
}
@Override
protected int getSecondTargetResId() {
return R.layout.preference_widget_gear;
}
public void setOnGearClickListener(OnGearClickListener l) {
mOnGearClickListener = l;
notifyChanged();
}
public void setOnRadioButtonClickListener(OnRadioButtonClickListener l) {
mOnRadioButtonClickListener = l;
notifyChanged();
}
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
View buttonFrame = holder.findViewById(R.id.checkbox_frame);
if (buttonFrame != null) {
buttonFrame.setOnClickListener(this);
}
mButton = (RadioButton) holder.findViewById(android.R.id.checkbox);
if (mButton != null) {
mButton.setChecked(mChecked);
}
final View gear = holder.findViewById(android.R.id.widget_frame);
if (mOnGearClickListener != null) {
gear.setVisibility(View.VISIBLE);
gear.setOnClickListener(this);
} else {
gear.setVisibility(View.GONE);
gear.setOnClickListener(null);
}
}
public boolean isChecked() {
return mButton != null && mChecked;
}
public void setChecked(boolean checked) {
mChecked = checked;
if (mButton != null) {
mButton.setChecked(checked);
}
}
public RadioButton getRadioButton() {
return mButton;
}
@Override
public void onClick() {
if (mOnRadioButtonClickListener != null) {
mOnRadioButtonClickListener.onRadioButtonClick(this);
}
}
@Override
public void onClick(View v) {
if (v.getId() == android.R.id.widget_frame) {
if (mOnGearClickListener != null) {
mOnGearClickListener.onGearClick(this);
}
} else if (v.getId() == R.id.checkbox_frame) {
if (mOnRadioButtonClickListener != null) {
mOnRadioButtonClickListener.onRadioButtonClick(this);
}
}
}
public interface OnGearClickListener {
void onGearClick(ZenCustomRadioButtonPreference p);
}
public interface OnRadioButtonClickListener {
void onRadioButtonClick(ZenCustomRadioButtonPreference p);
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.notification;
import android.app.NotificationManager.Policy;
import android.content.Context;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settingslib.core.lifecycle.Lifecycle;
public class ZenFooterPreferenceController extends AbstractZenModePreferenceController {
public ZenFooterPreferenceController(Context context, Lifecycle lifecycle,
String key) {
super(context, key, lifecycle);
}
@Override
public boolean isAvailable() {
return mBackend.mPolicy.suppressedVisualEffects == 0
|| Policy.areAllVisualEffectsSuppressed(mBackend.mPolicy.suppressedVisualEffects);
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
if (mBackend.mPolicy.suppressedVisualEffects == 0) {
preference.setTitle(R.string.zen_mode_restrict_notifications_mute_footer);
} else if (Policy.areAllVisualEffectsSuppressed(mBackend.mPolicy.suppressedVisualEffects)) {
preference.setTitle(R.string.zen_mode_restrict_notifications_hide_footer);
} else {
preference.setTitle(null);
}
}
protected void hide(PreferenceScreen screen) {
setVisible(screen, getPreferenceKey(), false /* visible */);
}
}

View File

@@ -0,0 +1,151 @@
/*
* 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.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_ZEN_SHOW_CUSTOM;
import android.content.Context;
import android.os.Bundle;
import android.provider.SearchIndexableResource;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.search.SearchIndexable;
import com.android.settingslib.widget.FooterPreference;
import java.util.ArrayList;
import java.util.List;
@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
public class ZenModeRestrictNotificationsSettings extends ZenModeSettingsBase implements Indexable {
protected static final int APP_MENU_SHOW_CUSTOM = 1;
protected boolean mShowMenuSelected;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
menu.add(0, APP_MENU_SHOW_CUSTOM, 0, R.string.zen_mode_restrict_notifications_enable_custom)
.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
}
@Override
public boolean onOptionsItemSelected(MenuItem menuItem) {
if (menuItem.getItemId() == APP_MENU_SHOW_CUSTOM) {
final FeatureFactory featureFactory = FeatureFactory.getFactory(mContext);
MetricsFeatureProvider metrics = featureFactory.getMetricsFeatureProvider();
mShowMenuSelected = !mShowMenuSelected;
ZenModeVisEffectsCustomPreferenceController custom =
use(ZenModeVisEffectsCustomPreferenceController.class);
custom.setShownByMenu(mShowMenuSelected);
if (mShowMenuSelected) {
custom.select();
metrics.action(mContext, ACTION_ZEN_SHOW_CUSTOM, true);
} else {
metrics.action(mContext, ACTION_ZEN_SHOW_CUSTOM, false);
}
return true;
}
return false;
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
if (mShowMenuSelected && !use(ZenModeVisEffectsCustomPreferenceController.class)
.areCustomOptionsSelected()) {
menu.findItem(APP_MENU_SHOW_CUSTOM)
.setTitle(R.string.zen_mode_restrict_notifications_disable_custom);
} else {
menu.findItem(APP_MENU_SHOW_CUSTOM)
.setTitle(R.string.zen_mode_restrict_notifications_enable_custom);
}
}
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
return buildPreferenceControllers(context, getLifecycle());
}
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
Lifecycle lifecycle) {
List<AbstractPreferenceController> controllers = new ArrayList<>();
controllers.add(new ZenModeVisEffectsNonePreferenceController(
context, lifecycle, "zen_mute_notifications"));
controllers.add(new ZenModeVisEffectsAllPreferenceController(
context, lifecycle, "zen_hide_notifications"));
controllers.add(new ZenModeVisEffectsCustomPreferenceController(
context, lifecycle, "zen_custom"));
controllers.add(new ZenFooterPreferenceController(context, lifecycle,
FooterPreference.KEY_FOOTER));
return controllers;
}
@Override
protected int getPreferenceScreenResId() {
return R.xml.zen_mode_restrict_notifications_settings;
}
@Override
public int getMetricsCategory() {
return MetricsEvent.SETTINGS_ZEN_NOTIFICATIONS;
}
/**
* For Search.
*/
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
boolean enabled) {
final ArrayList<SearchIndexableResource> result = new ArrayList<>();
final SearchIndexableResource sir = new SearchIndexableResource(context);
sir.xmlResId = R.xml.zen_mode_restrict_notifications_settings;
result.add(sir);
return result;
}
@Override
public List<String> getNonIndexableKeys(Context context) {
final List<String> keys = super.getNonIndexableKeys(context);
return keys;
}
@Override
public List<AbstractPreferenceController> createPreferenceControllers(Context context) {
return buildPreferenceControllers(context, null);
}
};
}

View File

@@ -160,24 +160,15 @@ public class ZenModeSettings extends ZenModeSettingsBase {
}
String getBlockedEffectsSummary(Policy policy) {
List<String> blockedStrings = new ArrayList<>();
if (Policy.areAnyScreenOffEffectsSuppressed(policy.suppressedVisualEffects)) {
blockedStrings.add(mContext.getResources().getString(
R.string.zen_mode_block_effect_summary_screen_off));
}
if (Policy.areAnyScreenOnEffectsSuppressed(policy.suppressedVisualEffects)) {
blockedStrings.add(mContext.getResources().getString(
R.string.zen_mode_block_effect_summary_screen_on));
}
if (blockedStrings.size() == 0) {
if (policy.suppressedVisualEffects == 0) {
return mContext.getResources().getString(
R.string.zen_mode_block_effect_summary_none);
} else if (blockedStrings.size() == 1) {
return blockedStrings.get(0);
R.string.zen_mode_restrict_notifications_summary_muted);
} else if (Policy.areAllVisualEffectsSuppressed(policy.suppressedVisualEffects)) {
return mContext.getResources().getString(
R.string.zen_mode_restrict_notifications_summary_hidden);
} else {
return mContext.getResources().getString(R.string.join_two_unrelated_items,
blockedStrings.get(0), blockedStrings.get(1));
return mContext.getResources().getString(
R.string.zen_mode_restrict_notifications_summary_custom);
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.notification;
import android.app.NotificationManager.Policy;
import android.content.Context;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settingslib.core.lifecycle.Lifecycle;
public class ZenModeVisEffectsAllPreferenceController
extends AbstractZenModePreferenceController
implements ZenCustomRadioButtonPreference.OnRadioButtonClickListener {
protected static final int EFFECTS = Policy.SUPPRESSED_EFFECT_SCREEN_OFF
| Policy.SUPPRESSED_EFFECT_SCREEN_ON
| Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT
| Policy.SUPPRESSED_EFFECT_LIGHTS
| Policy.SUPPRESSED_EFFECT_PEEK
| Policy.SUPPRESSED_EFFECT_STATUS_BAR
| Policy.SUPPRESSED_EFFECT_BADGE
| Policy.SUPPRESSED_EFFECT_AMBIENT
| Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
public ZenModeVisEffectsAllPreferenceController(Context context, Lifecycle lifecycle,
String key) {
super(context, key, lifecycle);
}
@Override
public boolean isAvailable() {
return true;
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
boolean everythingBlocked = Policy.areAllVisualEffectsSuppressed(
mBackend.mPolicy.suppressedVisualEffects);
ZenCustomRadioButtonPreference pref = (ZenCustomRadioButtonPreference) preference;
pref.setOnRadioButtonClickListener(this);
pref.setChecked(everythingBlocked);
}
protected void deselect(PreferenceScreen screen) {
ZenCustomRadioButtonPreference preference =
(ZenCustomRadioButtonPreference) screen.findPreference(getPreferenceKey());
if (preference != null) {
preference.setChecked(false);
}
}
@Override
public void onRadioButtonClick(ZenCustomRadioButtonPreference p) {
mMetricsFeatureProvider.action(mContext,
MetricsProto.MetricsEvent.ACTION_ZEN_SOUND_AND_VIS_EFFECTS, true);
mBackend.saveVisualEffectsPolicy(EFFECTS, true);
}
}

View File

@@ -0,0 +1,92 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.notification;
import android.app.NotificationManager.Policy;
import android.content.Context;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.core.SubSettingLauncher;
import com.android.settingslib.core.lifecycle.Lifecycle;
public class ZenModeVisEffectsCustomPreferenceController
extends AbstractZenModePreferenceController {
protected boolean mShowMenuSelected;
protected static final int INTERRUPTIVE_EFFECTS = Policy.SUPPRESSED_EFFECT_AMBIENT
| Policy.SUPPRESSED_EFFECT_PEEK
| Policy.SUPPRESSED_EFFECT_LIGHTS
| Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
public ZenModeVisEffectsCustomPreferenceController(Context context, Lifecycle lifecycle,
String key) {
super(context, key, lifecycle);
}
@Override
public boolean isAvailable() {
if (mShowMenuSelected) {
return true;
}
return areCustomOptionsSelected();
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
ZenCustomRadioButtonPreference pref = (ZenCustomRadioButtonPreference) preference;
pref.setChecked(areCustomOptionsSelected());
pref.setOnGearClickListener(p -> {
new SubSettingLauncher(mContext)
.setDestination(ZenModeBlockedEffectsSettings.class.getName())
.setTitle(R.string.zen_mode_what_to_block_title)
.setSourceMetricsCategory(MetricsProto.MetricsEvent.SETTINGS_ZEN_NOTIFICATIONS)
.launch();
});
pref.setOnRadioButtonClickListener(p -> {
select();
});
}
protected void setShownByMenu(boolean shown) {
mShowMenuSelected = shown;
}
protected boolean areCustomOptionsSelected() {
boolean allEffectsSuppressed =
Policy.areAllVisualEffectsSuppressed(mBackend.mPolicy.suppressedVisualEffects);
boolean noEffectsSuppressed = mBackend.mPolicy.suppressedVisualEffects == 0;
return !(allEffectsSuppressed || noEffectsSuppressed);
}
protected void select() {
mMetricsFeatureProvider.action(mContext,
MetricsProto.MetricsEvent.ACTION_ZEN_CUSTOM, true);
mBackend.savePolicy(mBackend.mPolicy.priorityCategories,
mBackend.mPolicy.priorityCallSenders,
mBackend.mPolicy.priorityMessageSenders,
INTERRUPTIVE_EFFECTS);
}
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.notification;
import android.app.NotificationManager.Policy;
import android.content.Context;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settingslib.core.lifecycle.Lifecycle;
public class ZenModeVisEffectsNonePreferenceController
extends AbstractZenModePreferenceController
implements ZenCustomRadioButtonPreference.OnRadioButtonClickListener {
protected static final int EFFECTS = Policy.SUPPRESSED_EFFECT_SCREEN_OFF
| Policy.SUPPRESSED_EFFECT_SCREEN_ON
| Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT
| Policy.SUPPRESSED_EFFECT_LIGHTS
| Policy.SUPPRESSED_EFFECT_PEEK
| Policy.SUPPRESSED_EFFECT_STATUS_BAR
| Policy.SUPPRESSED_EFFECT_BADGE
| Policy.SUPPRESSED_EFFECT_AMBIENT
| Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
public ZenModeVisEffectsNonePreferenceController(Context context, Lifecycle lifecycle,
String key) {
super(context, key, lifecycle);
}
@Override
public boolean isAvailable() {
return true;
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
boolean nothingBlocked = mBackend.mPolicy.suppressedVisualEffects == 0;
ZenCustomRadioButtonPreference pref = (ZenCustomRadioButtonPreference) preference;
pref.setOnRadioButtonClickListener(this);
pref.setChecked(nothingBlocked);
}
@Override
public void onRadioButtonClick(ZenCustomRadioButtonPreference preference) {
mMetricsFeatureProvider.action(mContext,
MetricsProto.MetricsEvent.ACTION_ZEN_SOUND_ONLY, true);
mBackend.saveVisualEffectsPolicy(EFFECTS, false);
}
protected void deselect(PreferenceScreen screen) {
ZenCustomRadioButtonPreference preference =
(ZenCustomRadioButtonPreference) screen.findPreference(getPreferenceKey());
if (preference != null) {
preference.setChecked(false);
}
}
}

View File

@@ -17,7 +17,6 @@ com.android.settings.applications.ManageDomainUrls
com.android.settings.applications.appinfo.WriteSettingsDetails
com.android.settings.applications.ProcessStatsSummary
com.android.settings.users.RestrictedProfileSettings
com.android.settings.accounts.ChooseAccountActivity
com.android.settings.accessibility.ToggleAutoclickPreferenceFragment
com.android.settings.applications.AppLaunchSettings
com.android.settings.applications.ProcessStatsUi

View File

@@ -0,0 +1,205 @@
/*
* 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 static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import android.accounts.AuthenticatorDescription;
import android.app.Activity;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.SyncAdapterType;
import android.graphics.drawable.ColorDrawable;
import android.os.UserHandle;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.ShadowAccountManager;
import com.android.settings.testutils.shadow.ShadowContentResolver;
import com.android.settings.testutils.shadow.ShadowRestrictedLockUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import androidx.preference.Preference;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(shadows = {ShadowAccountManager.class, ShadowContentResolver.class,
ShadowRestrictedLockUtils.class})
public class ChooseAccountPreferenceControllerTest {
private Context mContext;
private ChooseAccountPreferenceController mController;
private Activity mActivity;
private PreferenceManager mPreferenceManager;
private PreferenceScreen mPreferenceScreen;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mController = spy(new ChooseAccountPreferenceController(mContext, "controller_key"));
mActivity = Robolectric.setupActivity(Activity.class);
mPreferenceManager = new PreferenceManager(mContext);
mPreferenceScreen = mPreferenceManager.createPreferenceScreen(mContext);
}
@After
public void tearDown() {
ShadowContentResolver.reset();
ShadowAccountManager.resetAuthenticator();
ShadowRestrictedLockUtils.clearDisabledTypes();
}
@Test
public void getAvailabilityStatus_byDefault_shouldBeShown() {
assertThat(mController.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.AVAILABLE);
}
@Test
public void handlePreferenceTreeClick_notProviderPreference_shouldReturnFalse() {
final Preference preference = new Preference(mContext);
assertThat(mController.handlePreferenceTreeClick(preference)).isFalse();
}
@Test
public void handlePreferenceTreeClick_isProviderPreference_shouldFinishFragment() {
final ProviderPreference providerPreference = new ProviderPreference(mContext,
"account_type", null /* icon */, "provider_name");
mController.initialize(null, null, null, mActivity);
mController.handlePreferenceTreeClick(providerPreference);
assertThat(mActivity.isFinishing()).isTrue();
}
@Test
public void updateAuthDescriptions_oneProvider_shouldNotAddPreference() {
final AuthenticatorDescription authDesc = new AuthenticatorDescription("com.acct1",
"com.android.settings",
R.string.header_add_an_account, 0, 0, 0, false);
ShadowAccountManager.addAuthenticator(authDesc);
final SyncAdapterType[] syncAdapters = {new SyncAdapterType("authority" /* authority */,
"com.acct1" /* accountType */, false /* userVisible */,
true /* supportsUploading */)};
ShadowContentResolver.setSyncAdapterTypes(syncAdapters);
ShadowRestrictedLockUtils.setHasSystemFeature(true);
ShadowRestrictedLockUtils.setDevicePolicyManager(mock(DevicePolicyManager.class));
ShadowRestrictedLockUtils.setDisabledTypes(new String[] {"test_type"});
doReturn("label").when(mController).getLabelForType(anyString());
mController.initialize(null, null, new UserHandle(3), mActivity);
mController.displayPreference(mPreferenceScreen);
assertThat(mActivity.isFinishing()).isTrue();
assertThat(mPreferenceScreen.getPreferenceCount()).isEqualTo(0);
}
@Test
public void updateAuthDescriptions_oneAdminDisabledProvider_shouldNotAddPreference() {
final AuthenticatorDescription authDesc = new AuthenticatorDescription("com.acct1",
"com.android.settings",
R.string.header_add_an_account, 0, 0, 0, false);
ShadowAccountManager.addAuthenticator(authDesc);
final SyncAdapterType[] syncAdapters = {new SyncAdapterType("authority" /* authority */,
"com.acct1" /* accountType */, false /* userVisible */,
true /* supportsUploading */)};
ShadowContentResolver.setSyncAdapterTypes(syncAdapters);
ShadowRestrictedLockUtils.setHasSystemFeature(true);
ShadowRestrictedLockUtils.setDevicePolicyManager(mock(DevicePolicyManager.class));
ShadowRestrictedLockUtils.setDisabledTypes(new String[] {"com.acct1"});
doReturn("label").when(mController).getLabelForType(anyString());
mController.initialize(null, null, new UserHandle(3), mActivity);
mController.displayPreference(mPreferenceScreen);
assertThat(mActivity.isFinishing()).isTrue();
assertThat(mPreferenceScreen.getPreferenceCount()).isEqualTo(0);
}
@Test
public void updateAuthDescriptions_noProvider_shouldNotAddPreference() {
final AuthenticatorDescription authDesc = new AuthenticatorDescription("com.acct1",
"com.android.settings",
R.string.header_add_an_account, 0, 0, 0, false);
ShadowAccountManager.addAuthenticator(authDesc);
final SyncAdapterType[] syncAdapters = {new SyncAdapterType("authority" /* authority */,
"com.acct1" /* accountType */, false /* userVisible */,
true /* supportsUploading */)};
ShadowContentResolver.setSyncAdapterTypes(syncAdapters);
doReturn("label").when(mController).getLabelForType(anyString());
mController.initialize(new String[] {"test_authoritiy1"}, null, new UserHandle(3),
mActivity);
mController.displayPreference(mPreferenceScreen);
assertThat(mActivity.isFinishing()).isTrue();
assertThat(mPreferenceScreen.getPreferenceCount()).isEqualTo(0);
}
@Test
public void
updateAuthDescriptions_twoProvider_shouldAddTwoPreference() {
final AuthenticatorDescription authDesc = new AuthenticatorDescription("com.acct1",
"com.android.settings",
R.string.header_add_an_account, 0, 0, 0, false);
final AuthenticatorDescription authDesc2 = new AuthenticatorDescription("com.acct2",
"com.android.settings",
R.string.header_add_an_account, 0, 0, 0, false);
ShadowAccountManager.addAuthenticator(authDesc);
ShadowAccountManager.addAuthenticator(authDesc2);
final SyncAdapterType[] syncAdapters = {new SyncAdapterType("authority" /* authority */,
"com.acct1" /* accountType */, false /* userVisible */,
true /* supportsUploading */), new SyncAdapterType("authority2" /* authority */,
"com.acct2" /* accountType */, false /* userVisible */,
true /* supportsUploading */)};
ShadowContentResolver.setSyncAdapterTypes(syncAdapters);
doReturn("label").when(mController).getLabelForType(anyString());
doReturn("label2").when(mController).getLabelForType(anyString());
doReturn(new ColorDrawable()).when(mController).getDrawableForType(anyString());
doReturn(new ColorDrawable()).when(mController).getDrawableForType(anyString());
mController.initialize(null, null, new UserHandle(3), mActivity);
mController.displayPreference(mPreferenceScreen);
assertThat(mPreferenceScreen.getPreferenceCount()).isEqualTo(2);
}
}

View File

@@ -0,0 +1,99 @@
/*
* 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 static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import android.content.Context;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.widget.FooterPreferenceMixin;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
@RunWith(SettingsRobolectricTestRunner.class)
public class EnterpriseDisclosurePreferenceControllerTest {
private static final String TEST_DISCLOSURE = "This is a test disclosure.";
private ChooseAccountFragment mFragment;
private Context mContext;
private EnterpriseDisclosurePreferenceController mController;
private FooterPreferenceMixin mFooterPreferenceMixin;
private PreferenceManager mPreferenceManager;
private PreferenceScreen mPreferenceScreen;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mController = spy(new EnterpriseDisclosurePreferenceController(mContext));
mFragment = spy(new ChooseAccountFragment());
mFooterPreferenceMixin = new FooterPreferenceMixin(mFragment, mFragment.getLifecycle());
mPreferenceManager = new PreferenceManager(mContext);
mPreferenceScreen = mPreferenceManager.createPreferenceScreen(mContext);
}
@Test
public void getAvailabilityStatus_hasDisclosure_shouldBeAvailable() {
doReturn(TEST_DISCLOSURE).when(mController).getDisclosure();
assertThat(mController.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.AVAILABLE);
}
@Test
public void getAvailabilityStatus_noDisclosure_shouldBeDisabled() {
doReturn(null).when(mController).getDisclosure();
assertThat(mController.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.DISABLED_UNSUPPORTED);
}
@Test
public void displayPreference_hasDisclosure_shouldSetTitle() {
doReturn(TEST_DISCLOSURE).when(mController).getDisclosure();
doReturn(mPreferenceScreen).when(mFragment).getPreferenceScreen();
doReturn(mPreferenceManager).when(mFragment).getPreferenceManager();
mController.setFooterPreferenceMixin(mFooterPreferenceMixin);
mController.displayPreference(mPreferenceScreen);
assertThat(mPreferenceScreen.getPreferenceCount()).isEqualTo(1);
assertThat(mPreferenceScreen.getPreference(0).getTitle()).isEqualTo(TEST_DISCLOSURE);
}
@Test
public void displayPreference_noDisclosure_shouldBeInvisible() {
doReturn(null).when(mController).getDisclosure();
mController.displayPreference(mPreferenceScreen);
assertThat(mPreferenceScreen.getPreferenceCount()).isEqualTo(0);
}
}

View File

@@ -15,6 +15,7 @@
*/
package com.android.settings.bluetooth;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
@@ -207,4 +208,15 @@ public class ConnectedBluetoothDeviceUpdaterTest {
verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice);
}
@Test
public void addPreference_addPreference_shouldHideSecondTarget() {
BluetoothDevicePreference btPreference =
new BluetoothDevicePreference(mContext, mCachedBluetoothDevice, true);
mBluetoothDeviceUpdater.mPreferenceMap.put(mBluetoothDevice, btPreference);
mBluetoothDeviceUpdater.addPreference(mCachedBluetoothDevice);
assertThat(btPreference.shouldHideSecondTarget()).isTrue();
}
}

View File

@@ -43,7 +43,6 @@ import android.text.TextUtils;
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 org.junit.Before;
import org.junit.Test;
@@ -62,7 +61,7 @@ import java.util.List;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(shadows = {
ShadowSecureSettings.class,
LocationEnablerTest.ShadowLocationManagerWrapper.class})
LocationEnablerTest.ShadowLocationManager.class})
public class LocationEnablerTest {
@Mock
@@ -272,8 +271,8 @@ public class LocationEnablerTest {
return intent -> TextUtils.equals(expected, intent.getAction());
}
@Implements(value = LocationManagerWrapper.class)
public static class ShadowLocationManagerWrapper {
@Implements(value = LocationManager.class)
public static class ShadowLocationManager {
@Implementation
public void setLocationEnabledForUser(boolean enabled, UserHandle userHandle) {

View File

@@ -0,0 +1,113 @@
/*
* 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.Mockito.mock;
import static org.mockito.Mockito.verify;
import android.content.Context;
import androidx.preference.Preference.OnPreferenceChangeListener;
import androidx.preference.PreferenceViewHolder;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.Switch;
import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.widget.MasterSwitchPreference;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RuntimeEnvironment;
@RunWith(SettingsRobolectricTestRunner.class)
public class ZenCustomRadioButtonPreferenceTest {
private Context mContext;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
}
@Test
public void createNewPreference_shouldSetLayout() {
final ZenCustomRadioButtonPreference preference
= new ZenCustomRadioButtonPreference(mContext);
assertThat(preference.getLayoutResource()).isEqualTo(R.layout.preference_two_target_radio);
assertThat(preference.getWidgetLayoutResource())
.isEqualTo(R.layout.preference_widget_gear);
}
@Test
public void setChecked_shouldUpdateButtonCheckedState() {
final ZenCustomRadioButtonPreference preference =
new ZenCustomRadioButtonPreference(mContext);
final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(
LayoutInflater.from(mContext).inflate(
R.layout.preference_two_target_radio, null));
final RadioButton toggle = (RadioButton) holder.findViewById(android.R.id.checkbox);
preference.onBindViewHolder(holder);
preference.setChecked(true);
assertThat(toggle.isChecked()).isTrue();
preference.setChecked(false);
assertThat(toggle.isChecked()).isFalse();
}
@Test
public void clickRadioButton_shouldNotifyRadioButtonClicked() {
final ZenCustomRadioButtonPreference preference
= new ZenCustomRadioButtonPreference(mContext);
final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(
LayoutInflater.from(mContext).inflate(R.layout.preference_two_target_radio, null));
final View toggle = holder.findViewById(R.id.checkbox_frame);
ZenCustomRadioButtonPreference.OnRadioButtonClickListener l = mock(
ZenCustomRadioButtonPreference.OnRadioButtonClickListener.class);
preference.setOnRadioButtonClickListener(l);
preference.onBindViewHolder(holder);
toggle.performClick();
verify(l).onRadioButtonClick(preference);
}
@Test
public void clickWidgetView_shouldNotifyWidgetClicked() {
final ZenCustomRadioButtonPreference preference =
new ZenCustomRadioButtonPreference(mContext);
final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(
LayoutInflater.from(mContext).inflate(R.layout.preference_two_target_radio, null));
final View widgetView = holder.findViewById(android.R.id.widget_frame);
ZenCustomRadioButtonPreference.OnGearClickListener l = mock(
ZenCustomRadioButtonPreference.OnGearClickListener.class);
preference.setOnGearClickListener(l);
preference.onBindViewHolder(holder);
widgetView.performClick();
verify(l).onGearClick(preference);
}
}

View File

@@ -0,0 +1,138 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.notification;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.NotificationManager;
import android.content.Context;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.widget.FooterPreference;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.shadows.ShadowApplication;
import org.robolectric.util.ReflectionHelpers;
@RunWith(SettingsRobolectricTestRunner.class)
public class ZenFooterPreferenceControllerTest {
private ZenFooterPreferenceController mController;
@Mock
private ZenModeBackend mBackend;
@Mock
private FooterPreference mockPref;
private Context mContext;
@Mock
private PreferenceScreen mScreen;
@Mock NotificationManager mNotificationManager;
private static final String PREF_KEY = "main_pref";
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
ShadowApplication shadowApplication = ShadowApplication.getInstance();
mContext = shadowApplication.getApplicationContext();
shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
when(mNotificationManager.getNotificationPolicy()).thenReturn(
mock(NotificationManager.Policy.class));
mController = new ZenFooterPreferenceController(
mContext, mock(Lifecycle.class), PREF_KEY);
ReflectionHelpers.setField(mController, "mBackend", mBackend);
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mockPref);
}
@Test
public void isAvailable_noVisEffects() {
mBackend.mPolicy = new NotificationManager.Policy(0, 0, 0, 0);
assertThat(mController.isAvailable()).isTrue();
}
@Test
public void isAvailable_someVisEffects() {
mBackend.mPolicy = new NotificationManager.Policy(0, 0, 0, 2);
assertThat(mController.isAvailable()).isFalse();
}
@Test
public void isAvailable_allVisEffects() {
int allSuppressed = SUPPRESSED_EFFECT_SCREEN_OFF
| SUPPRESSED_EFFECT_SCREEN_ON
| SUPPRESSED_EFFECT_FULL_SCREEN_INTENT
| SUPPRESSED_EFFECT_AMBIENT
| SUPPRESSED_EFFECT_STATUS_BAR
| SUPPRESSED_EFFECT_BADGE
| SUPPRESSED_EFFECT_LIGHTS
| SUPPRESSED_EFFECT_PEEK
| SUPPRESSED_EFFECT_NOTIFICATION_LIST;
mBackend.mPolicy = new NotificationManager.Policy(0, 0, 0, allSuppressed);
assertThat(mController.isAvailable()).isTrue();
}
@Test
public void updateSummary_noVisEffects() {
mBackend.mPolicy = new NotificationManager.Policy(0, 0, 0, 0);
mController.updateState(mockPref);
verify(mockPref).setTitle(R.string.zen_mode_restrict_notifications_mute_footer);
}
@Test
public void getSummary_someVisEffects() {
mBackend.mPolicy = new NotificationManager.Policy(0, 0, 0, 2);
mController.updateState(mockPref);
verify(mockPref).setTitle(null);
}
@Test
public void getSummary_allVisEffects() {
int allSuppressed = SUPPRESSED_EFFECT_SCREEN_OFF
| SUPPRESSED_EFFECT_SCREEN_ON
| SUPPRESSED_EFFECT_FULL_SCREEN_INTENT
| SUPPRESSED_EFFECT_AMBIENT
| SUPPRESSED_EFFECT_STATUS_BAR
| SUPPRESSED_EFFECT_BADGE
| SUPPRESSED_EFFECT_LIGHTS
| SUPPRESSED_EFFECT_PEEK
| SUPPRESSED_EFFECT_NOTIFICATION_LIST;
mBackend.mPolicy = new NotificationManager.Policy(0, 0, 0, allSuppressed);
mController.updateState(mockPref);
verify(mockPref).setTitle(R.string.zen_mode_restrict_notifications_hide_footer);
}
}

View File

@@ -74,29 +74,23 @@ public class ZenModeSettingsTest {
@Test
public void testBlockedEffectsSummary_none() {
NotificationManager.Policy policy = new NotificationManager.Policy(0, 0, 0, 0);
assertEquals("Never", mBuilder.getBlockedEffectsSummary(policy));
assertEquals(mContext.getString(R.string.zen_mode_restrict_notifications_summary_muted),
mBuilder.getBlockedEffectsSummary(policy));
}
@Test
public void testBlockedEffectsSummary_screen_on() {
public void testBlockedEffectsSummary_some() {
NotificationManager.Policy policy = new NotificationManager.Policy(
0, 0, 0, NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK);
assertEquals("When screen is on", mBuilder.getBlockedEffectsSummary(policy));
assertEquals(mContext.getString(R.string.zen_mode_restrict_notifications_summary_custom),
mBuilder.getBlockedEffectsSummary(policy));
}
@Test
public void testBlockedEffectsSummary_screen_off() {
public void testBlockedEffectsSummary_all() {
NotificationManager.Policy policy = new NotificationManager.Policy(
0, 0, 0, NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT);
assertEquals("When screen is off", mBuilder.getBlockedEffectsSummary(policy));
}
@Test
public void testBlockedEffectsSummary_both() {
NotificationManager.Policy policy = new NotificationManager.Policy(0, 0, 0,
NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST
| NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS);
assertEquals("When screen is off, When screen is on",
0, 0, 0, 511);
assertEquals(mContext.getString(R.string.zen_mode_restrict_notifications_summary_hidden),
mBuilder.getBlockedEffectsSummary(policy));
}

View File

@@ -0,0 +1,141 @@
/*
* 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 android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent
.ACTION_ZEN_SOUND_AND_VIS_EFFECTS;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.NotificationManager;
import android.content.Context;
import androidx.preference.PreferenceScreen;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.widget.DisabledCheckBoxPreference;
import com.android.settings.widget.RadioButtonPreference;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.shadows.ShadowApplication;
import org.robolectric.util.ReflectionHelpers;
@RunWith(SettingsRobolectricTestRunner.class)
public class ZenModeVisEffectsAllPreferenceControllerTest {
private ZenModeVisEffectsAllPreferenceController mController;
@Mock
private ZenModeBackend mBackend;
@Mock
private ZenCustomRadioButtonPreference mockPref;
private Context mContext;
private FakeFeatureFactory mFeatureFactory;
@Mock
private PreferenceScreen mScreen;
@Mock NotificationManager mNotificationManager;
private static final String PREF_KEY = "main_pref";
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
ShadowApplication shadowApplication = ShadowApplication.getInstance();
mContext = shadowApplication.getApplicationContext();
mFeatureFactory = FakeFeatureFactory.setupForTest();
shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
when(mNotificationManager.getNotificationPolicy()).thenReturn(
mock(NotificationManager.Policy.class));
mController = new ZenModeVisEffectsAllPreferenceController(
mContext, mock(Lifecycle.class), PREF_KEY);
ReflectionHelpers.setField(mController, "mBackend", mBackend);
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mockPref);
mController.displayPreference(mScreen);
}
@Test
public void isAvailable() {
assertTrue(mController.isAvailable());
}
@Test
public void updateState_notChecked() {
mBackend.mPolicy = new NotificationManager.Policy(0, 0, 0, 1);
mController.updateState(mockPref);
verify(mockPref).setChecked(false);
}
@Test
public void updateState_checked() {
int allSuppressed = SUPPRESSED_EFFECT_SCREEN_OFF
| SUPPRESSED_EFFECT_SCREEN_ON
| SUPPRESSED_EFFECT_FULL_SCREEN_INTENT
| SUPPRESSED_EFFECT_AMBIENT
| SUPPRESSED_EFFECT_STATUS_BAR
| SUPPRESSED_EFFECT_BADGE
| SUPPRESSED_EFFECT_LIGHTS
| SUPPRESSED_EFFECT_PEEK
| SUPPRESSED_EFFECT_NOTIFICATION_LIST;
mBackend.mPolicy = new NotificationManager.Policy(0, 0, 0, allSuppressed);
mController.updateState(mockPref);
verify(mockPref).setChecked(true);
}
@Test
public void onPreferenceChanged_checkedTrue() {
int allSuppressed = SUPPRESSED_EFFECT_SCREEN_OFF
| SUPPRESSED_EFFECT_SCREEN_ON
| SUPPRESSED_EFFECT_FULL_SCREEN_INTENT
| SUPPRESSED_EFFECT_AMBIENT
| SUPPRESSED_EFFECT_STATUS_BAR
| SUPPRESSED_EFFECT_BADGE
| SUPPRESSED_EFFECT_LIGHTS
| SUPPRESSED_EFFECT_PEEK
| SUPPRESSED_EFFECT_NOTIFICATION_LIST;
mBackend.mPolicy = new NotificationManager.Policy(0, 0, 0, 1);
mController.onRadioButtonClick(mockPref);
verify(mBackend).saveVisualEffectsPolicy(allSuppressed, true);
verify(mFeatureFactory.metricsFeatureProvider).action(eq(mContext),
eq(ACTION_ZEN_SOUND_AND_VIS_EFFECTS),
eq(true));
}
}

View File

@@ -0,0 +1,167 @@
/*
* 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 android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_ZEN_CUSTOM;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent
.ACTION_ZEN_SOUND_AND_VIS_EFFECTS;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.NotificationManager;
import android.content.Context;
import androidx.preference.PreferenceScreen;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.shadows.ShadowApplication;
import org.robolectric.util.ReflectionHelpers;
@RunWith(SettingsRobolectricTestRunner.class)
public class ZenModeVisEffectsCustomPreferenceControllerTest {
private ZenModeVisEffectsCustomPreferenceController mController;
@Mock
private ZenModeBackend mBackend;
@Mock
private ZenCustomRadioButtonPreference mockPref;
private Context mContext;
private FakeFeatureFactory mFeatureFactory;
@Mock
private PreferenceScreen mScreen;
@Mock NotificationManager mNotificationManager;
private static final String PREF_KEY = "main_pref";
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
ShadowApplication shadowApplication = ShadowApplication.getInstance();
mContext = shadowApplication.getApplicationContext();
mFeatureFactory = FakeFeatureFactory.setupForTest();
shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
when(mNotificationManager.getNotificationPolicy()).thenReturn(
mock(NotificationManager.Policy.class));
mController = new ZenModeVisEffectsCustomPreferenceController(
mContext, mock(Lifecycle.class), PREF_KEY);
ReflectionHelpers.setField(mController, "mBackend", mBackend);
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mockPref);
}
@Test
public void isAvailable_menuOff_noVisEffects() {
mBackend.mPolicy = new NotificationManager.Policy(0, 0, 0, 0);
mController.mShowMenuSelected = false;
assertThat(mController.isAvailable()).isFalse();
}
@Test
public void isAvailable_menuOn_noVisEffects() {
mBackend.mPolicy = new NotificationManager.Policy(0, 0, 0, 0);
mController.mShowMenuSelected = true;
assertThat(mController.isAvailable()).isTrue();
}
@Test
public void isAvailable_menuOn_visEffects() {
mBackend.mPolicy = new NotificationManager.Policy(0, 0, 0, 1);
mController.mShowMenuSelected = false;
assertThat(mController.isAvailable()).isTrue();
}
@Test
public void updateState_notChecked_noVisEffects() {
mBackend.mPolicy = new NotificationManager.Policy(0, 0, 0, 0);
mController.updateState(mockPref);
verify(mockPref).setChecked(false);
}
@Test
public void updateState_notChecked_allVisEffects() {
int allSuppressed = SUPPRESSED_EFFECT_SCREEN_OFF
| SUPPRESSED_EFFECT_SCREEN_ON
| SUPPRESSED_EFFECT_FULL_SCREEN_INTENT
| SUPPRESSED_EFFECT_AMBIENT
| SUPPRESSED_EFFECT_STATUS_BAR
| SUPPRESSED_EFFECT_BADGE
| SUPPRESSED_EFFECT_LIGHTS
| SUPPRESSED_EFFECT_PEEK
| SUPPRESSED_EFFECT_NOTIFICATION_LIST;
mBackend.mPolicy = new NotificationManager.Policy(0, 0, 0, allSuppressed);
mController.updateState(mockPref);
verify(mockPref).setChecked(false);
}
@Test
public void updateState_checked() {
mBackend.mPolicy = new NotificationManager.Policy(0, 0, 0, 2);
mController.updateState(mockPref);
verify(mockPref).setChecked(true);
}
@Test
public void updateState_listeners() {
mBackend.mPolicy = new NotificationManager.Policy(0, 0, 0, 2);
mController.updateState(mockPref);
verify(mockPref).setOnGearClickListener(any());
verify(mockPref).setOnRadioButtonClickListener(any());
}
@Test
public void select() {
int interruptiveSuppressed = SUPPRESSED_EFFECT_FULL_SCREEN_INTENT
| SUPPRESSED_EFFECT_AMBIENT
| SUPPRESSED_EFFECT_LIGHTS
| SUPPRESSED_EFFECT_PEEK;
mBackend.mPolicy = new NotificationManager.Policy(0, 0, 0, 1);
mController.select();
verify(mBackend).savePolicy(anyInt(), anyInt(), anyInt(), eq(interruptiveSuppressed));
verify(mFeatureFactory.metricsFeatureProvider).action(eq(mContext),
eq(ACTION_ZEN_CUSTOM),
eq(true));
}
}

View File

@@ -0,0 +1,132 @@
/*
* 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 android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_ZEN_SOUND_ONLY;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.NotificationManager;
import android.content.Context;
import androidx.preference.PreferenceScreen;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.widget.DisabledCheckBoxPreference;
import com.android.settings.widget.RadioButtonPreference;
import com.android.settingslib.core.lifecycle.Lifecycle;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.shadows.ShadowApplication;
import org.robolectric.util.ReflectionHelpers;
@RunWith(SettingsRobolectricTestRunner.class)
public class ZenModeVisEffectsNonePreferenceControllerTest {
private ZenModeVisEffectsNonePreferenceController mController;
@Mock
private ZenModeBackend mBackend;
@Mock
private ZenCustomRadioButtonPreference mockPref;
private Context mContext;
private FakeFeatureFactory mFeatureFactory;
@Mock
private PreferenceScreen mScreen;
@Mock NotificationManager mNotificationManager;
private static final String PREF_KEY = "main_pref";
private static final int PREF_METRICS = 1;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
ShadowApplication shadowApplication = ShadowApplication.getInstance();
mContext = shadowApplication.getApplicationContext();
mFeatureFactory = FakeFeatureFactory.setupForTest();
shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
when(mNotificationManager.getNotificationPolicy()).thenReturn(
mock(NotificationManager.Policy.class));
mController = new ZenModeVisEffectsNonePreferenceController(
mContext, mock(Lifecycle.class), PREF_KEY);
ReflectionHelpers.setField(mController, "mBackend", mBackend);
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mockPref);
mController.displayPreference(mScreen);
}
@Test
public void isAvailable() {
assertTrue(mController.isAvailable());
}
@Test
public void updateState_notChecked() {
mBackend.mPolicy = new NotificationManager.Policy(0, 0, 0, 1);
mController.updateState(mockPref);
verify(mockPref).setChecked(false);
}
@Test
public void updateState_checked() {
mBackend.mPolicy = new NotificationManager.Policy(0, 0, 0, 0);
mController.updateState(mockPref);
verify(mockPref).setChecked(true);
}
@Test
public void onRadioButtonClick() {
int allSuppressed = SUPPRESSED_EFFECT_SCREEN_OFF
| SUPPRESSED_EFFECT_SCREEN_ON
| SUPPRESSED_EFFECT_FULL_SCREEN_INTENT
| SUPPRESSED_EFFECT_AMBIENT
| SUPPRESSED_EFFECT_STATUS_BAR
| SUPPRESSED_EFFECT_BADGE
| SUPPRESSED_EFFECT_LIGHTS
| SUPPRESSED_EFFECT_PEEK
| SUPPRESSED_EFFECT_NOTIFICATION_LIST;
mBackend.mPolicy = new NotificationManager.Policy(0, 0, 0, 1);
mController.onRadioButtonClick(mockPref);
verify(mBackend).saveVisualEffectsPolicy(allSuppressed, false);
verify(mFeatureFactory.metricsFeatureProvider).action(nullable(Context.class),
eq(ACTION_ZEN_SOUND_ONLY),
eq(true));
}
}

View File

@@ -22,10 +22,24 @@ import android.accounts.AuthenticatorDescription;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import java.util.HashMap;
import java.util.Map;
@Implements(AccountManager.class)
public class ShadowAccountManager {
public class ShadowAccountManager{
private static final Map<String, AuthenticatorDescription> sAuthenticators = new HashMap<>();
@Implementation
public AuthenticatorDescription[] getAuthenticatorTypesAsUser(int userId) {
return null;
return sAuthenticators.values().toArray(new AuthenticatorDescription[sAuthenticators.size()]);
}
public static void addAuthenticator(AuthenticatorDescription authenticator) {
sAuthenticators.put(authenticator.type, authenticator);
}
public static void resetAuthenticator() {
sAuthenticators.clear();
}
}

View File

@@ -16,6 +16,7 @@
package com.android.settings.testutils.shadow;
import android.annotation.UserIdInt;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import com.android.internal.util.ArrayUtils;
@@ -28,26 +29,31 @@ import org.robolectric.annotation.Resetter;
@Implements(RestrictedLockUtils.class)
public class ShadowRestrictedLockUtils {
private static boolean isRestricted;
private static String[] restrictedPkgs;
private static boolean adminSupportDetailsIntentLaunched;
private static int keyguardDisabledFeatures;
private static boolean sIsRestricted;
private static boolean sAdminSupportDetailsIntentLaunched;
private static boolean sHasSystemFeature;
private static String[] sRestrictedPkgs;
private static DevicePolicyManager sDevicePolicyManager;
private static String[] sDisabledTypes;
private static int sKeyguardDisabledFeatures;
@Resetter
public static void reset() {
isRestricted = false;
restrictedPkgs = null;
adminSupportDetailsIntentLaunched = false;
keyguardDisabledFeatures = 0;
sIsRestricted = false;
sRestrictedPkgs = null;
sAdminSupportDetailsIntentLaunched = false;
sKeyguardDisabledFeatures = 0;
sDisabledTypes = new String[0];
}
@Implementation
public static EnforcedAdmin checkIfMeteredDataRestricted(Context context,
String packageName, int userId) {
if (isRestricted) {
if (sIsRestricted) {
return new EnforcedAdmin();
}
if (ArrayUtils.contains(restrictedPkgs, packageName)) {
if (ArrayUtils.contains(sRestrictedPkgs, packageName)) {
return new EnforcedAdmin();
}
return null;
@@ -55,32 +61,67 @@ public class ShadowRestrictedLockUtils {
@Implementation
public static void sendShowAdminSupportDetailsIntent(Context context, EnforcedAdmin admin) {
adminSupportDetailsIntentLaunched = true;
sAdminSupportDetailsIntentLaunched = true;
}
@Implementation
public static EnforcedAdmin checkIfAccountManagementDisabled(Context context,
String accountType, int userId) {
if (accountType == null) {
return null;
}
if (!sHasSystemFeature || sDevicePolicyManager == null) {
return null;
}
boolean isAccountTypeDisabled = false;
if (ArrayUtils.contains(sDisabledTypes, accountType)) {
isAccountTypeDisabled = true;
}
if (!isAccountTypeDisabled) {
return null;
}
return new EnforcedAdmin();
}
@Implementation
public static EnforcedAdmin checkIfKeyguardFeaturesDisabled(Context context,
int features, final @UserIdInt int userId) {
return (keyguardDisabledFeatures & features) == 0 ? null : new EnforcedAdmin();
return (sKeyguardDisabledFeatures & features) == 0 ? null : new EnforcedAdmin();
}
public static boolean hasAdminSupportDetailsIntentLaunched() {
return adminSupportDetailsIntentLaunched;
return sAdminSupportDetailsIntentLaunched;
}
public static void clearAdminSupportDetailsIntentLaunch() {
adminSupportDetailsIntentLaunched = false;
sAdminSupportDetailsIntentLaunched = false;
}
public static void setRestricted(boolean restricted) {
isRestricted = restricted;
sIsRestricted = restricted;
}
public static void setRestrictedPkgs(String... pkgs) {
restrictedPkgs = pkgs;
sRestrictedPkgs = pkgs;
}
public static void setHasSystemFeature(boolean hasSystemFeature) {
sHasSystemFeature = hasSystemFeature;
}
public static void setDevicePolicyManager(DevicePolicyManager dpm) {
sDevicePolicyManager = dpm;
}
public static void setDisabledTypes(String[] disabledTypes) {
sDisabledTypes = disabledTypes;
}
public static void clearDisabledTypes() {
sDisabledTypes = new String[0];
}
public static void setKeyguardDisabledFeatures(int features) {
keyguardDisabledFeatures = features;
sKeyguardDisabledFeatures = features;
}
}