nonVisibleKeys) {
- final IBackupManager backupManager = IBackupManager.Stub.asInterface(
- ServiceManager.getService(Context.BACKUP_SERVICE));
- boolean isServiceActive = false;
- try {
- isServiceActive = backupManager.isBackupServiceActive(UserHandle.myUserId());
- } catch (RemoteException e) {
- Log.w(TAG, "Failed querying backup manager service activity status. " +
- "Assuming it is inactive.");
- }
- boolean vendorSpecific = context.getPackageManager().
- resolveContentProvider(GSETTINGS_PROVIDER, 0) == null;
- if (vendorSpecific || isServiceActive) {
- nonVisibleKeys.add(BACKUP_INACTIVE);
- }
- if (vendorSpecific || !isServiceActive) {
- nonVisibleKeys.add(BACKUP_DATA);
- nonVisibleKeys.add(AUTO_RESTORE);
- nonVisibleKeys.add(CONFIGURE_ACCOUNT);
- }
- }
-}
diff --git a/src/com/android/settings/ResetNetworkConfirm.java b/src/com/android/settings/ResetNetworkConfirm.java
index fdec66206ea..4bdd8e1dba8 100644
--- a/src/com/android/settings/ResetNetworkConfirm.java
+++ b/src/com/android/settings/ResetNetworkConfirm.java
@@ -32,9 +32,11 @@ import android.os.Bundle;
import android.os.RecoverySystem;
import android.os.UserHandle;
import android.os.UserManager;
+import android.provider.Telephony;
import android.support.annotation.VisibleForTesting;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -151,9 +153,20 @@ public class ResetNetworkConfirm extends InstrumentedFragment {
ImsManager.factoryReset(context);
restoreDefaultApn(context);
esimFactoryReset(context, context.getPackageName());
+ // There has been issues when Sms raw table somehow stores orphan
+ // fragments. They lead to garbled message when new fragments come
+ // in and combied with those stale ones. In case this happens again,
+ // user can reset all network settings which will clean up this table.
+ cleanUpSmsRawTable(context);
}
};
+ private void cleanUpSmsRawTable(Context context) {
+ ContentResolver resolver = context.getContentResolver();
+ Uri uri = Uri.withAppendedPath(Telephony.Sms.CONTENT_URI, "raw/permanentDelete");
+ resolver.delete(uri, null, null);
+ }
+
@VisibleForTesting
void esimFactoryReset(Context context, String packageName) {
if (mEraseEsim) {
diff --git a/src/com/android/settings/RestrictedSettingsFragment.java b/src/com/android/settings/RestrictedSettingsFragment.java
index b17ca84650f..3b69effc24a 100644
--- a/src/com/android/settings/RestrictedSettingsFragment.java
+++ b/src/com/android/settings/RestrictedSettingsFragment.java
@@ -27,6 +27,7 @@ import android.os.Bundle;
import android.os.PersistableBundle;
import android.os.UserHandle;
import android.os.UserManager;
+import android.support.annotation.VisibleForTesting;
import android.view.View;
import android.widget.TextView;
@@ -56,7 +57,7 @@ public abstract class RestrictedSettingsFragment extends SettingsPreferenceFragm
protected static final String RESTRICT_IF_OVERRIDABLE = "restrict_if_overridable";
// No RestrictedSettingsFragment screens should use this number in startActivityForResult.
- private static final int REQUEST_PIN_CHALLENGE = 12309;
+ @VisibleForTesting static final int REQUEST_PIN_CHALLENGE = 12309;
private static final String KEY_CHALLENGE_SUCCEEDED = "chsc";
private static final String KEY_CHALLENGE_REQUESTED = "chrq";
@@ -86,7 +87,8 @@ public abstract class RestrictedSettingsFragment extends SettingsPreferenceFragm
}
};
- private AlertDialog mActionDisabledDialog;
+ @VisibleForTesting
+ AlertDialog mActionDisabledDialog;
/**
* @param restrictionKey The restriction key to check before pin protecting
@@ -153,6 +155,10 @@ public abstract class RestrictedSettingsFragment extends SettingsPreferenceFragm
if (resultCode == Activity.RESULT_OK) {
mChallengeSucceeded = true;
mChallengeRequested = false;
+ if (mActionDisabledDialog != null && mActionDisabledDialog.isShowing()) {
+ mActionDisabledDialog.setOnDismissListener(null);
+ mActionDisabledDialog.dismiss();
+ }
} else {
mChallengeSucceeded = false;
}
diff --git a/src/com/android/settings/accessibility/AccessibilitySettings.java b/src/com/android/settings/accessibility/AccessibilitySettings.java
index af95101916e..0268ca48817 100644
--- a/src/com/android/settings/accessibility/AccessibilitySettings.java
+++ b/src/com/android/settings/accessibility/AccessibilitySettings.java
@@ -344,6 +344,21 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
return super.onPreferenceTreeClick(preference);
}
+ public static CharSequence getServiceSummary(Context context, AccessibilityServiceInfo info,
+ boolean serviceEnabled) {
+ final String serviceState = serviceEnabled
+ ? context.getString(R.string.accessibility_summary_state_enabled)
+ : context.getString(R.string.accessibility_summary_state_disabled);
+ final CharSequence serviceSummary = info.loadSummary(context.getPackageManager());
+ final String stateSummaryCombo = context.getString(
+ R.string.preference_summary_default_combination,
+ serviceState, serviceSummary);
+
+ return (TextUtils.isEmpty(serviceSummary))
+ ? serviceState
+ : stateSummaryCombo;
+ }
+
private void handleToggleTextContrastPreferenceClick() {
Settings.Secure.putInt(getContentResolver(),
Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED,
@@ -545,15 +560,9 @@ public class AccessibilitySettings extends SettingsPreferenceFragment implements
preference.setSummary(R.string.accessibility_summary_state_stopped);
description = getString(R.string.accessibility_description_state_stopped);
} else {
- final String serviceState = serviceEnabled ?
- getString(R.string.accessibility_summary_state_enabled) :
- getString(R.string.accessibility_summary_state_disabled);
- final CharSequence serviceSummary = info.loadSummary(getPackageManager());
- final String stateSummaryCombo = getString(
- R.string.preference_summary_default_combination,
- serviceState, serviceSummary);
- preference.setSummary((TextUtils.isEmpty(serviceSummary)) ? serviceState
- : stateSummaryCombo);
+ final CharSequence serviceSummary = getServiceSummary(getContext(), info,
+ serviceEnabled);
+ preference.setSummary(serviceSummary);
}
// Disable all accessibility services that are not permitted.
diff --git a/src/com/android/settings/accessibility/AccessibilitySlicePreferenceController.java b/src/com/android/settings/accessibility/AccessibilitySlicePreferenceController.java
new file mode 100644
index 00000000000..6b9a480ff81
--- /dev/null
+++ b/src/com/android/settings/accessibility/AccessibilitySlicePreferenceController.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.accessibility;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.provider.Settings;
+import android.view.accessibility.AccessibilityManager;
+
+import com.android.settings.accessibility.AccessibilitySettings;
+import com.android.settings.core.TogglePreferenceController;
+import com.android.settingslib.accessibility.AccessibilityUtils;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * PreferenceController for accessibility services to be used by Slices.
+ * Wraps the common logic which enables accessibility services and checks their availability.
+ *
+ * Should not be used in a {@link com.android.settings.dashboard.DashboardFragment}.
+ */
+public class AccessibilitySlicePreferenceController extends TogglePreferenceController {
+
+ private final ComponentName mComponentName;
+
+ private final int ON = 1;
+ private final int OFF = 0;
+
+ public AccessibilitySlicePreferenceController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
+ mComponentName = ComponentName.unflattenFromString(getPreferenceKey());
+
+ if (mComponentName == null) {
+ throw new IllegalArgumentException(
+ "Illegal Component Name from: " + preferenceKey);
+ }
+ }
+
+ @Override
+ public CharSequence getSummary() {
+ final AccessibilityServiceInfo serviceInfo = getAccessibilityServiceInfo();
+ return serviceInfo == null
+ ? "" : AccessibilitySettings.getServiceSummary(mContext, serviceInfo, isChecked());
+ }
+
+ @Override
+ public boolean isChecked() {
+ final ContentResolver contentResolver = mContext.getContentResolver();
+ final boolean accessibilityEnabled = Settings.Secure.getInt(contentResolver,
+ Settings.Secure.ACCESSIBILITY_ENABLED, OFF) == ON;
+
+ if (!accessibilityEnabled) {
+ return false;
+ }
+
+ final Set componentNames =
+ AccessibilityUtils.getEnabledServicesFromSettings(mContext);
+
+ return componentNames.contains(mComponentName);
+ }
+
+ @Override
+ public boolean setChecked(boolean isChecked) {
+ if (getAccessibilityServiceInfo() == null) {
+ return false;
+ }
+ AccessibilityUtils.setAccessibilityServiceState(mContext, mComponentName, isChecked);
+ return isChecked == isChecked(); // Verify that it was probably changed.
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ // Return unsupported when the service is disabled or not installed.
+ return getAccessibilityServiceInfo() == null ? DISABLED_UNSUPPORTED : AVAILABLE;
+ }
+
+ private AccessibilityServiceInfo getAccessibilityServiceInfo() {
+ final AccessibilityManager accessibilityManager = mContext.getSystemService(
+ AccessibilityManager.class);
+ final List serviceList =
+ accessibilityManager.getInstalledAccessibilityServiceList();
+
+ for (AccessibilityServiceInfo serviceInfo : serviceList) {
+ if (mComponentName.equals(serviceInfo.getComponentName())) {
+ return serviceInfo;
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/src/com/android/settings/accounts/AccountPreferenceController.java b/src/com/android/settings/accounts/AccountPreferenceController.java
index b17219885a3..d9410b261d5 100644
--- a/src/com/android/settings/accounts/AccountPreferenceController.java
+++ b/src/com/android/settings/accounts/AccountPreferenceController.java
@@ -40,6 +40,7 @@ import android.support.v7.preference.Preference;
import android.support.v7.preference.Preference.OnPreferenceClickListener;
import android.support.v7.preference.PreferenceGroup;
import android.support.v7.preference.PreferenceScreen;
+import android.text.BidiFormatter;
import android.util.ArrayMap;
import android.util.Log;
import android.util.SparseArray;
@@ -313,7 +314,7 @@ public class AccountPreferenceController extends AbstractPreferenceController
preferenceGroup.setOrder(mAccountProfileOrder++);
if (isSingleProfile()) {
preferenceGroup.setTitle(context.getString(R.string.account_for_section_header,
- userInfo.name));
+ BidiFormatter.getInstance().unicodeWrap(userInfo.name)));
preferenceGroup.setContentDescription(
mContext.getString(R.string.account_settings));
} else if (userInfo.isManagedProfile()) {
diff --git a/src/com/android/settings/backup/AutoRestorePreferenceController.java b/src/com/android/settings/backup/AutoRestorePreferenceController.java
new file mode 100644
index 00000000000..7bcf350e3df
--- /dev/null
+++ b/src/com/android/settings/backup/AutoRestorePreferenceController.java
@@ -0,0 +1,89 @@
+/*
+ * 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.backup;
+
+import android.app.backup.IBackupManager;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.provider.Settings;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.Preference;
+import android.util.Log;
+
+import com.android.settings.core.TogglePreferenceController;
+
+public class AutoRestorePreferenceController extends TogglePreferenceController {
+ private static final String TAG = "AutoRestorePrefCtrler";
+
+ private PrivacySettingsConfigData mPSCD;
+ private Preference mPreference;
+
+ public AutoRestorePreferenceController(Context context, String key) {
+ super(context, key);
+ }
+
+ public void setPrivacySettingsConfigData(final PrivacySettingsConfigData pData) {
+ mPSCD = pData;
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ if (!PrivacySettingsUtils.isAdminUser(mContext)) {
+ return DISABLED_FOR_USER;
+ }
+ if (PrivacySettingsUtils.isInvisibleKey(mContext, PrivacySettingsUtils.AUTO_RESTORE)) {
+ return DISABLED_UNSUPPORTED;
+ }
+ return AVAILABLE;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ mPreference = preference;
+ preference.setEnabled(mPSCD.isBackupEnabled());
+ }
+
+ @Override
+ public boolean isChecked() {
+ final ContentResolver res = mContext.getContentResolver();
+
+ return Settings.Secure.getInt(res,
+ Settings.Secure.BACKUP_AUTO_RESTORE, 1) == 1;
+ }
+
+ @Override
+ public boolean setChecked(boolean isChecked) {
+ final boolean nextValue = isChecked;
+ boolean result = false;
+
+ final IBackupManager backupManager = IBackupManager.Stub.asInterface(
+ ServiceManager.getService(Context.BACKUP_SERVICE));
+
+ try {
+ backupManager.setAutoRestore(nextValue);
+ result = true;
+ } catch (RemoteException e) {
+ ((SwitchPreference) mPreference).setChecked(!nextValue);
+ Log.e(TAG, "Error can't set setAutoRestore", e);
+ }
+
+ return result;
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/backup/BackupDataPreferenceController.java b/src/com/android/settings/backup/BackupDataPreferenceController.java
new file mode 100644
index 00000000000..0a0f581c1f5
--- /dev/null
+++ b/src/com/android/settings/backup/BackupDataPreferenceController.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.settings.backup;
+
+import android.content.Context;
+import android.support.v7.preference.Preference;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.R;
+
+public class BackupDataPreferenceController extends BasePreferenceController {
+ private PrivacySettingsConfigData mPSCD;
+
+ public BackupDataPreferenceController(Context context, String key) {
+ super(context, key);
+ }
+
+ public void setPrivacySettingsConfigData(final PrivacySettingsConfigData pData) {
+ mPSCD = pData;
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ if (!PrivacySettingsUtils.isAdminUser(mContext)) {
+ return DISABLED_FOR_USER;
+ }
+ if (PrivacySettingsUtils.isInvisibleKey(mContext, PrivacySettingsUtils.BACKUP_DATA)) {
+ return DISABLED_UNSUPPORTED;
+ }
+ return AVAILABLE;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ if (mPSCD.isBackupGray()) {
+ preference.setEnabled(false);
+ }
+ }
+
+ @Override
+ public CharSequence getSummary() {
+ if (!mPSCD.isBackupGray()) {
+ return mPSCD.isBackupEnabled()
+ ? mContext.getText(R.string.accessibility_feature_state_on)
+ : mContext.getText(R.string.accessibility_feature_state_off);
+ }
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/backup/BackupInactivePreferenceController.java b/src/com/android/settings/backup/BackupInactivePreferenceController.java
new file mode 100644
index 00000000000..d44801e97e2
--- /dev/null
+++ b/src/com/android/settings/backup/BackupInactivePreferenceController.java
@@ -0,0 +1,39 @@
+/*
+ * 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.backup;
+
+import android.content.Context;
+
+import com.android.settings.core.BasePreferenceController;
+
+public class BackupInactivePreferenceController extends BasePreferenceController {
+
+ public BackupInactivePreferenceController(Context context, String key) {
+ super(context, key);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ if (!PrivacySettingsUtils.isAdminUser(mContext)) {
+ return DISABLED_FOR_USER;
+ }
+ if (PrivacySettingsUtils.isInvisibleKey(mContext, PrivacySettingsUtils.BACKUP_INACTIVE)) {
+ return DISABLED_UNSUPPORTED;
+ }
+ return AVAILABLE;
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/backup/ConfigureAccountPreferenceController.java b/src/com/android/settings/backup/ConfigureAccountPreferenceController.java
new file mode 100644
index 00000000000..f1bcee9150f
--- /dev/null
+++ b/src/com/android/settings/backup/ConfigureAccountPreferenceController.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.settings.backup;
+
+import android.content.Context;
+import android.content.Intent;
+import android.support.v7.preference.Preference;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.R;
+
+public class ConfigureAccountPreferenceController extends BasePreferenceController {
+ private PrivacySettingsConfigData mPSCD;
+
+ public ConfigureAccountPreferenceController(Context context, String key) {
+ super(context, key);
+ }
+
+ public void setPrivacySettingsConfigData(final PrivacySettingsConfigData pData) {
+ mPSCD = pData;
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ if (!PrivacySettingsUtils.isAdminUser(mContext)) {
+ return DISABLED_FOR_USER;
+ }
+ if (PrivacySettingsUtils.isInvisibleKey(mContext, PrivacySettingsUtils.CONFIGURE_ACCOUNT)) {
+ return DISABLED_UNSUPPORTED;
+ }
+ return AVAILABLE;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ final Intent configIntent = mPSCD.getConfigIntent();
+ final boolean configureEnabled = (configIntent != null) && mPSCD.isBackupEnabled();
+ preference.setEnabled(configureEnabled);
+ preference.setIntent(configIntent);
+ }
+
+ @Override
+ public CharSequence getSummary() {
+ final String configSummary = mPSCD.getConfigSummary();
+ return configSummary != null
+ ? configSummary
+ : mContext.getText(R.string.backup_configure_account_default_summary);
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/backup/DataManagementPreferenceController.java b/src/com/android/settings/backup/DataManagementPreferenceController.java
new file mode 100644
index 00000000000..de987abbde8
--- /dev/null
+++ b/src/com/android/settings/backup/DataManagementPreferenceController.java
@@ -0,0 +1,58 @@
+/*
+ * 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.backup;
+
+import android.content.Context;
+import android.support.v7.preference.Preference;
+
+import com.android.settings.core.BasePreferenceController;
+
+public class DataManagementPreferenceController extends BasePreferenceController {
+ private PrivacySettingsConfigData mPSCD;
+ private boolean mManageEnabled;
+
+ public DataManagementPreferenceController(Context context, String key) {
+ super(context, key);
+ }
+
+ public void setPrivacySettingsConfigData(final PrivacySettingsConfigData pData) {
+ mPSCD = pData;
+ mManageEnabled = (mPSCD.getManageIntent() != null) && mPSCD.isBackupEnabled();
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ if (!PrivacySettingsUtils.isAdminUser(mContext)) {
+ return DISABLED_FOR_USER;
+ }
+ if (!mManageEnabled) {
+ return DISABLED_UNSUPPORTED;
+ }
+ return AVAILABLE;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ if (mManageEnabled) {
+ preference.setIntent(mPSCD.getManageIntent());
+ final String manageLabel = mPSCD.getManageLabel();
+ if (manageLabel != null) {
+ preference.setTitle(manageLabel);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/backup/PrivacySettings.java b/src/com/android/settings/backup/PrivacySettings.java
new file mode 100644
index 00000000000..9b342e74774
--- /dev/null
+++ b/src/com/android/settings/backup/PrivacySettings.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2009 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.backup;
+
+import android.content.Context;
+import android.provider.SearchIndexableResource;
+
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.R;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settingslib.search.SearchIndexable;
+
+import java.util.Arrays;
+import java.util.List;
+
+@SearchIndexable
+public class PrivacySettings extends DashboardFragment {
+ private static final String TAG = "PrivacySettings";
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsEvent.PRIVACY;
+ }
+
+ @Override
+ protected String getLogTag() {
+ return TAG;
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.privacy_settings;
+ }
+
+ @Override
+ public int getHelpResource() {
+ return R.string.help_url_backup_reset;
+ }
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ updatePrivacySettingsConfigData(context);
+ }
+
+ @Override
+ protected void updatePreferenceStates() {
+ updatePrivacySettingsConfigData(getContext());
+ super.updatePreferenceStates();
+ }
+
+ private void updatePrivacySettingsConfigData(final Context context) {
+ final PrivacySettingsConfigData pData = new PrivacySettingsConfigData();
+ if (PrivacySettingsUtils.isAdminUser(context)) {
+ PrivacySettingsUtils.updatePrivacyBuffer(context, pData);
+ }
+
+ use(BackupDataPreferenceController.class).setPrivacySettingsConfigData(pData);
+ use(ConfigureAccountPreferenceController.class).setPrivacySettingsConfigData(pData);
+ use(DataManagementPreferenceController.class).setPrivacySettingsConfigData(pData);
+ use(AutoRestorePreferenceController.class).setPrivacySettingsConfigData(pData);
+ }
+
+ public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider() {
+ @Override
+ public List getXmlResourcesToIndex(Context context,
+ boolean enabled) {
+ final SearchIndexableResource sir = new SearchIndexableResource(context);
+ sir.xmlResId = R.xml.privacy_settings;
+ return Arrays.asList(sir);
+ }
+
+ @Override
+ protected boolean isPageSearchEnabled(Context context) {
+ final BackupSettingsHelper backupHelper = new BackupSettingsHelper(context);
+ return !backupHelper.isBackupProvidedByManufacturer() &&
+ !backupHelper.isIntentProvidedByTransport();
+ }
+ };
+}
diff --git a/src/com/android/settings/backup/PrivacySettingsConfigData.java b/src/com/android/settings/backup/PrivacySettingsConfigData.java
new file mode 100644
index 00000000000..9b72a829a26
--- /dev/null
+++ b/src/com/android/settings/backup/PrivacySettingsConfigData.java
@@ -0,0 +1,85 @@
+/*
+ * 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.backup;
+
+import android.content.Intent;
+
+public class PrivacySettingsConfigData {
+ private boolean mBackupEnabled;
+ private boolean mBackupGray;
+ private Intent mConfigIntent;
+ private String mConfigSummary;
+ private Intent mManageIntent;
+ private String mManageLabel;
+
+ public PrivacySettingsConfigData() {
+ mBackupEnabled = false;
+ mBackupGray = false;
+ mConfigIntent = null;
+ mConfigSummary = null;
+ mManageIntent = null;
+ mManageLabel = null;
+ }
+
+ public boolean isBackupEnabled() {
+ return mBackupEnabled;
+ }
+
+ public void setBackupEnabled(final boolean backupEnabled) {
+ mBackupEnabled = backupEnabled;
+ }
+
+ public boolean isBackupGray() {
+ return mBackupGray;
+ }
+
+ public void setBackupGray(final boolean backupGray) {
+ mBackupGray = backupGray;
+ }
+
+ public Intent getConfigIntent() {
+ return mConfigIntent;
+ }
+
+ public void setConfigIntent(final Intent configIntent) {
+ mConfigIntent = configIntent;
+ }
+
+ public String getConfigSummary() {
+ return mConfigSummary;
+ }
+
+ public void setConfigSummary(final String configSummary) {
+ mConfigSummary = configSummary;
+ }
+
+ public Intent getManageIntent() {
+ return mManageIntent;
+ }
+
+ public void setManageIntent(final Intent manageIntent) {
+ mManageIntent = manageIntent;
+ }
+
+ public String getManageLabel() {
+ return mManageLabel;
+ }
+
+ public void setManageLabel(final String manageLabel) {
+ mManageLabel = manageLabel;
+ }
+}
diff --git a/src/com/android/settings/backup/PrivacySettingsUtils.java b/src/com/android/settings/backup/PrivacySettingsUtils.java
new file mode 100644
index 00000000000..f8f21ddeef1
--- /dev/null
+++ b/src/com/android/settings/backup/PrivacySettingsUtils.java
@@ -0,0 +1,122 @@
+/*
+ * 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.backup;
+
+import android.app.backup.IBackupManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.Log;
+
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+public class PrivacySettingsUtils {
+ private static final String TAG = "PrivacySettingsUtils";
+ private static final String GSETTINGS_PROVIDER = "com.google.settings";
+
+ static final String BACKUP_DATA = "backup_data";
+ static final String AUTO_RESTORE = "auto_restore";
+ static final String CONFIGURE_ACCOUNT = "configure_account";
+ static final String BACKUP_INACTIVE = "backup_inactive";
+
+ // Don't allow any access if this is not an admin user.
+ // TODO: backup/restore currently only works with owner user b/22760572
+ static boolean isAdminUser(final Context context) {
+ return UserManager.get(context).isAdminUser();
+ }
+
+ /**
+ * Send a {@param key} to check its preference will display in PrivacySettings or not.
+ */
+ static boolean isInvisibleKey(final Context context, final String key) {
+ final Set keysToRemove = getInvisibleKey(context);
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG,
+ "keysToRemove size=" + keysToRemove.size() + " keysToRemove=" + keysToRemove);
+ }
+ if (keysToRemove.contains(key)) {
+ return true;
+ }
+ return false;
+ }
+
+ private static Set getInvisibleKey(final Context context) {
+ final IBackupManager backupManager = IBackupManager.Stub.asInterface(
+ ServiceManager.getService(Context.BACKUP_SERVICE));
+ boolean isServiceActive = false;
+ try {
+ isServiceActive = backupManager.isBackupServiceActive(UserHandle.myUserId());
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed querying backup manager service activity status. " +
+ "Assuming it is inactive.");
+ }
+ boolean vendorSpecific = context.getPackageManager().
+ resolveContentProvider(GSETTINGS_PROVIDER, 0) == null;
+ final Set inVisibleKeys = new TreeSet<>();
+ if (vendorSpecific || isServiceActive) {
+ inVisibleKeys.add(BACKUP_INACTIVE);
+ }
+ if (vendorSpecific || !isServiceActive) {
+ inVisibleKeys.add(BACKUP_DATA);
+ inVisibleKeys.add(AUTO_RESTORE);
+ inVisibleKeys.add(CONFIGURE_ACCOUNT);
+ }
+ return inVisibleKeys;
+ }
+
+ public static void updatePrivacyBuffer(final Context context, PrivacySettingsConfigData data) {
+ final IBackupManager backupManager = IBackupManager.Stub.asInterface(
+ ServiceManager.getService(Context.BACKUP_SERVICE));
+
+ try {
+ data.setBackupEnabled(backupManager.isBackupEnabled());
+ String transport = backupManager.getCurrentTransport();
+ data.setConfigIntent(validatedActivityIntent(context,
+ backupManager.getConfigurationIntent(transport), "config"));
+ data.setConfigSummary(backupManager.getDestinationString(transport));
+ data.setManageIntent(validatedActivityIntent(context,
+ backupManager.getDataManagementIntent(transport), "management"));
+ data.setManageLabel(backupManager.getDataManagementLabel(transport));
+ data.setBackupGray(false);
+ } catch (RemoteException e) {
+ // leave it 'false' and disable the UI; there's no backup manager
+ // mBackup.setEnabled(false);
+ data.setBackupGray(true);
+ }
+ }
+
+ private static Intent validatedActivityIntent(final Context context, Intent intent,
+ String logLabel) {
+ if (intent != null) {
+ PackageManager pm = context.getPackageManager();
+ List resolved = pm.queryIntentActivities(intent, 0);
+ if (resolved == null || resolved.isEmpty()) {
+ intent = null;
+ Log.e(TAG, "Backup " + logLabel + " intent " + intent
+ + " fails to resolve; ignoring");
+ }
+ }
+ return intent;
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java b/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java
index 8679b5566c7..ba7cf54e940 100644
--- a/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsHeaderController.java
@@ -73,6 +73,16 @@ public class BluetoothDetailsHeaderController extends BluetoothDetailsController
mHeaderController.setIcon(pair.first);
mHeaderController.setIconContentDescription(pair.second);
mHeaderController.setSummary(summaryText);
+ mHeaderController.setEditListener(v -> showEditDeviceNameDialog());
+ mHeaderController.setButtonActions(
+ EntityHeaderController.ActionType.ACTION_EDIT_PREFERENCE,
+ EntityHeaderController.ActionType.ACTION_NONE);
+ }
+
+ @VisibleForTesting
+ void showEditDeviceNameDialog() {
+ RemoteDeviceNameDialogFragment.newInstance(mCachedDevice).show(
+ mFragment.getFragmentManager(), RemoteDeviceNameDialogFragment.TAG);
}
@Override
diff --git a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
index 1e8288922e2..aa3b42948bb 100644
--- a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
+++ b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
@@ -22,9 +22,6 @@ import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.VisibleForTesting;
-import android.view.Menu;
-import android.view.MenuInflater;
-import android.view.MenuItem;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
@@ -41,9 +38,6 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment
public static final String KEY_DEVICE_ADDRESS = "device_address";
private static final String TAG = "BTDeviceDetailsFrg";
- @VisibleForTesting
- static int EDIT_DEVICE_NAME_ITEM_ID = Menu.FIRST;
-
/**
* An interface to let tests override the normal mechanism for looking up the
* CachedBluetoothDevice and LocalBluetoothManager, and substitute their own mocks instead.
@@ -60,9 +54,12 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment
@VisibleForTesting
static TestDataFactory sTestDataFactory;
- private String mDeviceAddress;
- private LocalBluetoothManager mManager;
- private CachedBluetoothDevice mCachedDevice;
+ @VisibleForTesting
+ String mDeviceAddress;
+ @VisibleForTesting
+ LocalBluetoothManager mManager;
+ @VisibleForTesting
+ CachedBluetoothDevice mCachedDevice;
public BluetoothDeviceDetailsFragment() {
super(DISALLOW_CONFIG_BLUETOOTH);
@@ -117,24 +114,6 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment
return R.xml.bluetooth_device_details_fragment;
}
- @Override
- public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
- MenuItem item = menu.add(0, EDIT_DEVICE_NAME_ITEM_ID, 0, R.string.bluetooth_rename_button);
- item.setIcon(R.drawable.ic_mode_edit);
- item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
- super.onCreateOptionsMenu(menu, inflater);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem menuItem) {
- if (menuItem.getItemId() == EDIT_DEVICE_NAME_ITEM_ID) {
- RemoteDeviceNameDialogFragment.newInstance(mCachedDevice).show(
- getFragmentManager(), RemoteDeviceNameDialogFragment.TAG);
- return true;
- }
- return super.onOptionsItemSelected(menuItem);
- }
-
@Override
protected List createPreferenceControllers(Context context) {
ArrayList controllers = new ArrayList<>();
diff --git a/src/com/android/settings/core/PreferenceControllerListHelper.java b/src/com/android/settings/core/PreferenceControllerListHelper.java
index 738a6952e8c..5879ba443b3 100644
--- a/src/com/android/settings/core/PreferenceControllerListHelper.java
+++ b/src/com/android/settings/core/PreferenceControllerListHelper.java
@@ -54,7 +54,8 @@ public class PreferenceControllerListHelper {
List preferenceMetadata;
try {
preferenceMetadata = PreferenceXmlParserUtils.extractMetadata(context, xmlResId,
- MetadataFlag.FLAG_NEED_KEY | MetadataFlag.FLAG_NEED_PREF_CONTROLLER);
+ MetadataFlag.FLAG_NEED_KEY | MetadataFlag.FLAG_NEED_PREF_CONTROLLER
+ | MetadataFlag.FLAG_INCLUDE_PREF_SCREEN);
} catch (IOException | XmlPullParserException e) {
Log.e(TAG, "Failed to parse preference xml for getting controllers", e);
return controllers;
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index aa9d7b54879..be9b722a5ac 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -21,7 +21,6 @@ import com.android.settings.DeviceAdminSettings;
import com.android.settings.DisplaySettings;
import com.android.settings.IccLockSettings;
import com.android.settings.MasterClear;
-import com.android.settings.PrivacySettings;
import com.android.settings.Settings;
import com.android.settings.TestingSettings;
import com.android.settings.TetherSettings;
@@ -51,6 +50,7 @@ import com.android.settings.applications.appinfo.WriteSettingsDetails;
import com.android.settings.applications.appops.BackgroundCheckSummary;
import com.android.settings.applications.assist.ManageAssist;
import com.android.settings.applications.manageapplications.ManageApplications;
+import com.android.settings.backup.PrivacySettings;
import com.android.settings.backup.ToggleBackupSettingFragment;
import com.android.settings.bluetooth.BluetoothDeviceDetailsFragment;
import com.android.settings.connecteddevice.AdvancedConnectedDeviceDashboardFragment;
diff --git a/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java b/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
index 3ed76d8dd52..82a5b9bd2d0 100644
--- a/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
+++ b/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
@@ -259,8 +259,10 @@ public class DashboardFeatureProviderImpl implements DashboardFeatureProvider {
return;
}
tile.icon = Icon.createWithResource(iconInfo.first, iconInfo.second);
- ThreadUtils.postOnMainThread(() ->
- preference.setIcon(tile.icon.loadDrawable(preference.getContext()))
+ ThreadUtils.postOnMainThread(() -> {
+ preference.setIcon(tile.icon.loadDrawable(preference.getContext()));
+ tile.icon = null;
+ }
);
});
}
diff --git a/src/com/android/settings/datausage/BillingCycleSettings.java b/src/com/android/settings/datausage/BillingCycleSettings.java
index b82e3becef4..c0bf16a4a43 100644
--- a/src/com/android/settings/datausage/BillingCycleSettings.java
+++ b/src/com/android/settings/datausage/BillingCycleSettings.java
@@ -402,7 +402,6 @@ public class BillingCycleSettings extends DataUsageBase implements
*/
public static class ConfirmLimitFragment extends InstrumentedDialogFragment implements
DialogInterface.OnClickListener {
- private static final String EXTRA_MESSAGE = "message";
@VisibleForTesting static final String EXTRA_LIMIT_BYTES = "limitBytes";
public static final float FLOAT = 1.2f;
@@ -414,16 +413,13 @@ public class BillingCycleSettings extends DataUsageBase implements
if (policy == null) return;
final Resources res = parent.getResources();
- final CharSequence message;
final long minLimitBytes = (long) (policy.warningBytes * FLOAT);
final long limitBytes;
// TODO: customize default limits based on network template
- message = res.getString(R.string.data_usage_limit_dialog_mobile);
limitBytes = Math.max(5 * GIB_IN_BYTES, minLimitBytes);
final Bundle args = new Bundle();
- args.putCharSequence(EXTRA_MESSAGE, message);
args.putLong(EXTRA_LIMIT_BYTES, limitBytes);
final ConfirmLimitFragment dialog = new ConfirmLimitFragment();
@@ -441,11 +437,9 @@ public class BillingCycleSettings extends DataUsageBase implements
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Context context = getActivity();
- final CharSequence message = getArguments().getCharSequence(EXTRA_MESSAGE);
-
return new AlertDialog.Builder(context)
.setTitle(R.string.data_usage_limit_dialog_title)
- .setMessage(message)
+ .setMessage(R.string.data_usage_limit_dialog_mobile)
.setPositiveButton(android.R.string.ok, this)
.setNegativeButton(android.R.string.cancel, null)
.create();
diff --git a/src/com/android/settings/datausage/DataUsagePreference.java b/src/com/android/settings/datausage/DataUsagePreference.java
index 766a2a985b1..9d0b1047a90 100644
--- a/src/com/android/settings/datausage/DataUsagePreference.java
+++ b/src/com/android/settings/datausage/DataUsagePreference.java
@@ -56,7 +56,7 @@ public class DataUsagePreference extends Preference implements TemplatePreferenc
DataUsageController.DataUsageInfo usageInfo = controller.getDataUsageInfo(mTemplate);
if (FeatureFlagUtils.isEnabled(getContext(), FeatureFlags.DATA_USAGE_SETTINGS_V2)) {
if (mTemplate.isMatchRuleMobile()) {
- setTitle(getContext().getString(R.string.app_cellular_data_usage));
+ setTitle(R.string.app_cellular_data_usage);
} else {
setTitle(mTitleRes);
setSummary(getContext().getString(R.string.data_usage_template,
@@ -83,7 +83,7 @@ public class DataUsagePreference extends Preference implements TemplatePreferenc
.setSourceMetricsCategory(MetricsProto.MetricsEvent.VIEW_UNKNOWN);
if (FeatureFlagUtils.isEnabled(getContext(), FeatureFlags.DATA_USAGE_SETTINGS_V2)) {
if (mTemplate.isMatchRuleMobile()) {
- launcher.setTitle(getContext().getString(R.string.app_cellular_data_usage));
+ launcher.setTitle(R.string.app_cellular_data_usage);
} else {
launcher.setTitle(mTitleRes);
}
diff --git a/src/com/android/settings/datausage/DataUsageSummaryPreference.java b/src/com/android/settings/datausage/DataUsageSummaryPreference.java
index 86297eb95cb..79be5ab8b3a 100644
--- a/src/com/android/settings/datausage/DataUsageSummaryPreference.java
+++ b/src/com/android/settings/datausage/DataUsageSummaryPreference.java
@@ -187,7 +187,7 @@ public class DataUsageSummaryPreference extends Preference {
updateCarrierInfo(carrierInfo);
if (mLaunchIntent != null) {
launchButton.setOnClickListener((view) -> {
- getContext().sendBroadcast(mLaunchIntent);
+ getContext().startActivity(mLaunchIntent);
});
launchButton.setVisibility(View.VISIBLE);
} else {
diff --git a/src/com/android/settings/deviceinfo/PrivateVolumeForget.java b/src/com/android/settings/deviceinfo/PrivateVolumeForget.java
index b6d50cef75a..af485db0a3b 100644
--- a/src/com/android/settings/deviceinfo/PrivateVolumeForget.java
+++ b/src/com/android/settings/deviceinfo/PrivateVolumeForget.java
@@ -18,13 +18,13 @@ package com.android.settings.deviceinfo;
import android.app.AlertDialog;
import android.app.Dialog;
-import android.app.DialogFragment;
import android.app.Fragment;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.storage.StorageManager;
import android.os.storage.VolumeRecord;
+import android.support.annotation.VisibleForTesting;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
@@ -35,11 +35,13 @@ import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
-import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.core.InstrumentedFragment;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+import com.android.settings.search.actionbar.SearchMenuController;
-public class PrivateVolumeForget extends SettingsPreferenceFragment {
- private static final String TAG_FORGET_CONFIRM = "forget_confirm";
+public class PrivateVolumeForget extends InstrumentedFragment {
+ @VisibleForTesting
+ static final String TAG_FORGET_CONFIRM = "forget_confirm";
private VolumeRecord mRecord;
@@ -48,6 +50,13 @@ public class PrivateVolumeForget extends SettingsPreferenceFragment {
return MetricsEvent.DEVICEINFO_STORAGE;
}
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ setHasOptionsMenu(true);
+ SearchMenuController.init(this /* host */);
+ }
+
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
@@ -116,12 +125,12 @@ public class PrivateVolumeForget extends SettingsPreferenceFragment {
builder.setPositiveButton(R.string.storage_menu_forget,
new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- storage.forgetVolume(fsUuid);
- getActivity().finish();
- }
- });
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ storage.forgetVolume(fsUuid);
+ getActivity().finish();
+ }
+ });
builder.setNegativeButton(R.string.cancel, null);
return builder.create();
diff --git a/src/com/android/settings/deviceinfo/PrivateVolumeFormat.java b/src/com/android/settings/deviceinfo/PrivateVolumeFormat.java
index 4a63e64a446..0bac2964c02 100644
--- a/src/com/android/settings/deviceinfo/PrivateVolumeFormat.java
+++ b/src/com/android/settings/deviceinfo/PrivateVolumeFormat.java
@@ -17,7 +17,6 @@
package com.android.settings.deviceinfo;
import static android.os.storage.DiskInfo.EXTRA_DISK_ID;
-
import static com.android.settings.deviceinfo.StorageWizardBase.EXTRA_FORMAT_FORGET_UUID;
import static com.android.settings.deviceinfo.StorageWizardBase.EXTRA_FORMAT_PRIVATE;
@@ -36,9 +35,9 @@ import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
-import com.android.settings.core.InstrumentedPreferenceFragment;
+import com.android.settings.core.InstrumentedFragment;
-public class PrivateVolumeFormat extends InstrumentedPreferenceFragment {
+public class PrivateVolumeFormat extends InstrumentedFragment {
private VolumeInfo mVolume;
private DiskInfo mDisk;
diff --git a/src/com/android/settings/deviceinfo/PrivateVolumeUnmount.java b/src/com/android/settings/deviceinfo/PrivateVolumeUnmount.java
index 0aa5b920f54..e74abc92950 100644
--- a/src/com/android/settings/deviceinfo/PrivateVolumeUnmount.java
+++ b/src/com/android/settings/deviceinfo/PrivateVolumeUnmount.java
@@ -30,10 +30,11 @@ import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
-import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.core.InstrumentedFragment;
import com.android.settings.deviceinfo.StorageSettings.UnmountTask;
+import com.android.settings.search.actionbar.SearchMenuController;
-public class PrivateVolumeUnmount extends SettingsPreferenceFragment {
+public class PrivateVolumeUnmount extends InstrumentedFragment {
private VolumeInfo mVolume;
private DiskInfo mDisk;
@@ -42,6 +43,13 @@ public class PrivateVolumeUnmount extends SettingsPreferenceFragment {
return MetricsEvent.DEVICEINFO_STORAGE;
}
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ setHasOptionsMenu(true);
+ SearchMenuController.init(this /* host */);
+ }
+
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
diff --git a/src/com/android/settings/deviceinfo/StorageWizardBase.java b/src/com/android/settings/deviceinfo/StorageWizardBase.java
index 4787ac50856..40fc249f697 100644
--- a/src/com/android/settings/deviceinfo/StorageWizardBase.java
+++ b/src/com/android/settings/deviceinfo/StorageWizardBase.java
@@ -22,6 +22,7 @@ import static android.os.storage.VolumeInfo.EXTRA_VOLUME_ID;
import static com.android.settings.deviceinfo.StorageSettings.TAG;
import android.annotation.LayoutRes;
+import android.annotation.NonNull;
import android.app.Activity;
import android.content.Intent;
import android.graphics.drawable.Drawable;
@@ -145,7 +146,7 @@ public abstract class StorageWizardBase extends Activity {
((TextView) aux.requireViewById(R.id.storage_wizard_migrate_v2_checklist_media))
.setText(TextUtils.expandTemplate(
getText(R.string.storage_wizard_migrate_v2_checklist_media),
- mDisk.getShortDescription()));
+ getDiskShortDescription()));
}
protected void setBackButtonText(int resId, CharSequence... args) {
@@ -228,6 +229,26 @@ public abstract class StorageWizardBase extends Activity {
}
}
+ protected @NonNull CharSequence getDiskDescription() {
+ if (mDisk != null) {
+ return mDisk.getDescription();
+ } else if (mVolume != null) {
+ return mVolume.getDescription();
+ } else {
+ return getText(R.string.unknown);
+ }
+ }
+
+ protected @NonNull CharSequence getDiskShortDescription() {
+ if (mDisk != null) {
+ return mDisk.getShortDescription();
+ } else if (mVolume != null) {
+ return mVolume.getDescription();
+ } else {
+ return getText(R.string.unknown);
+ }
+ }
+
private final StorageEventListener mStorageListener = new StorageEventListener() {
@Override
public void onDiskDestroyed(DiskInfo disk) {
diff --git a/src/com/android/settings/deviceinfo/StorageWizardFormatProgress.java b/src/com/android/settings/deviceinfo/StorageWizardFormatProgress.java
index 8e3f8eff166..07119078a81 100644
--- a/src/com/android/settings/deviceinfo/StorageWizardFormatProgress.java
+++ b/src/com/android/settings/deviceinfo/StorageWizardFormatProgress.java
@@ -57,8 +57,8 @@ public class StorageWizardFormatProgress extends StorageWizardBase {
mFormatPrivate = getIntent().getBooleanExtra(EXTRA_FORMAT_PRIVATE, false);
- setHeaderText(R.string.storage_wizard_format_progress_title, mDisk.getShortDescription());
- setBodyText(R.string.storage_wizard_format_progress_body, mDisk.getDescription());
+ setHeaderText(R.string.storage_wizard_format_progress_title, getDiskShortDescription());
+ setBodyText(R.string.storage_wizard_format_progress_body, getDiskDescription());
mTask = (PartitionTask) getLastNonConfigurationInstance();
if (mTask == null) {
diff --git a/src/com/android/settings/deviceinfo/StorageWizardFormatSlow.java b/src/com/android/settings/deviceinfo/StorageWizardFormatSlow.java
index 9c80ff610c8..37df21709e2 100644
--- a/src/com/android/settings/deviceinfo/StorageWizardFormatSlow.java
+++ b/src/com/android/settings/deviceinfo/StorageWizardFormatSlow.java
@@ -39,10 +39,10 @@ public class StorageWizardFormatSlow extends StorageWizardBase {
mFormatPrivate = getIntent().getBooleanExtra(EXTRA_FORMAT_PRIVATE, false);
- setHeaderText(R.string.storage_wizard_slow_v2_title, mDisk.getShortDescription());
- setBodyText(R.string.storage_wizard_slow_v2_body, mDisk.getDescription(),
- mDisk.getShortDescription(), mDisk.getShortDescription(),
- mDisk.getShortDescription());
+ setHeaderText(R.string.storage_wizard_slow_v2_title, getDiskShortDescription());
+ setBodyText(R.string.storage_wizard_slow_v2_body, getDiskDescription(),
+ getDiskShortDescription(), getDiskShortDescription(),
+ getDiskShortDescription());
setBackButtonText(R.string.storage_wizard_slow_v2_start_over);
setNextButtonText(R.string.storage_wizard_slow_v2_continue);
diff --git a/src/com/android/settings/deviceinfo/StorageWizardInit.java b/src/com/android/settings/deviceinfo/StorageWizardInit.java
index 2233cf9f0bd..0fc850b1390 100644
--- a/src/com/android/settings/deviceinfo/StorageWizardInit.java
+++ b/src/com/android/settings/deviceinfo/StorageWizardInit.java
@@ -45,7 +45,7 @@ public class StorageWizardInit extends StorageWizardBase {
mIsPermittedToAdopt = UserManager.get(this).isAdminUser()
&& !ActivityManager.isUserAMonkey();
- setHeaderText(R.string.storage_wizard_init_v2_title, mDisk.getShortDescription());
+ setHeaderText(R.string.storage_wizard_init_v2_title, getDiskShortDescription());
mExternal = requireViewById(R.id.storage_wizard_init_external);
mInternal = requireViewById(R.id.storage_wizard_init_internal);
diff --git a/src/com/android/settings/deviceinfo/StorageWizardMigrateConfirm.java b/src/com/android/settings/deviceinfo/StorageWizardMigrateConfirm.java
index 755f09317c4..969a50ab634 100644
--- a/src/com/android/settings/deviceinfo/StorageWizardMigrateConfirm.java
+++ b/src/com/android/settings/deviceinfo/StorageWizardMigrateConfirm.java
@@ -59,7 +59,7 @@ public class StorageWizardMigrateConfirm extends StorageWizardBase {
}
setIcon(R.drawable.ic_swap_horiz);
- setHeaderText(R.string.storage_wizard_migrate_v2_title, mDisk.getShortDescription());
+ setHeaderText(R.string.storage_wizard_migrate_v2_title, getDiskShortDescription());
setBodyText(R.string.memory_calculating_size);
setAuxChecklist();
@@ -67,7 +67,7 @@ public class StorageWizardMigrateConfirm extends StorageWizardBase {
@Override
public void onPostExecute(String size, String time) {
setBodyText(R.string.storage_wizard_migrate_v2_body,
- mDisk.getDescription(), size, time);
+ getDiskDescription(), size, time);
}
};
diff --git a/src/com/android/settings/deviceinfo/StorageWizardReady.java b/src/com/android/settings/deviceinfo/StorageWizardReady.java
index c5c4ca22314..fdb8d8a4938 100644
--- a/src/com/android/settings/deviceinfo/StorageWizardReady.java
+++ b/src/com/android/settings/deviceinfo/StorageWizardReady.java
@@ -33,20 +33,20 @@ public class StorageWizardReady extends StorageWizardBase {
}
setContentView(R.layout.storage_wizard_generic);
- setHeaderText(R.string.storage_wizard_ready_title, mDisk.getShortDescription());
+ setHeaderText(R.string.storage_wizard_ready_title, getDiskShortDescription());
final VolumeInfo privateVol = findFirstVolume(VolumeInfo.TYPE_PRIVATE);
if (privateVol != null) {
if (getIntent().getBooleanExtra(EXTRA_MIGRATE_SKIP, false)) {
setBodyText(R.string.storage_wizard_ready_v2_internal_body,
- mDisk.getDescription());
+ getDiskDescription());
} else {
setBodyText(R.string.storage_wizard_ready_v2_internal_moved_body,
- mDisk.getDescription(), mDisk.getShortDescription());
+ getDiskDescription(), getDiskShortDescription());
}
} else {
setBodyText(R.string.storage_wizard_ready_v2_external_body,
- mDisk.getDescription());
+ getDiskDescription());
}
setNextButtonText(R.string.done);
diff --git a/src/com/android/settings/deviceinfo/legal/CopyrightPreferenceController.java b/src/com/android/settings/deviceinfo/legal/CopyrightPreferenceController.java
new file mode 100644
index 00000000000..68e51f40df7
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/legal/CopyrightPreferenceController.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.settings.deviceinfo.legal;
+
+import android.content.Context;
+import android.content.Intent;
+
+public class CopyrightPreferenceController extends LegalPreferenceController {
+
+ private static final Intent INTENT = new Intent("android.settings.COPYRIGHT");
+
+ public CopyrightPreferenceController(Context context, String key) {
+ super(context, key);
+ }
+
+ @Override
+ protected Intent getIntent() {
+ return INTENT;
+ }
+}
diff --git a/src/com/android/settings/deviceinfo/legal/LegalPreferenceController.java b/src/com/android/settings/deviceinfo/legal/LegalPreferenceController.java
new file mode 100644
index 00000000000..f64eb4b59fe
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/legal/LegalPreferenceController.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.settings.deviceinfo.legal;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.core.BasePreferenceController;
+
+import java.util.List;
+
+
+public abstract class LegalPreferenceController extends BasePreferenceController {
+ private final PackageManager mPackageManager;
+ private Preference mPreference;
+
+ public LegalPreferenceController(Context context, String key) {
+ super(context, key);
+ mPackageManager = mContext.getPackageManager();
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ if (findMatchingSpecificActivity() != null) {
+ return AVAILABLE;
+ } else {
+ return DISABLED_UNSUPPORTED;
+ }
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ mPreference = screen.findPreference(getPreferenceKey());
+ super.displayPreference(screen);
+
+ if (getAvailabilityStatus() == AVAILABLE) {
+ replacePreferenceIntent();
+ }
+ }
+
+ protected abstract Intent getIntent();
+
+ private ResolveInfo findMatchingSpecificActivity() {
+ final Intent intent = getIntent();
+ if (intent == null) {
+ return null;
+ }
+
+ // Find the activity that is in the system image
+ final List list = mPackageManager.queryIntentActivities(intent, 0);
+ if (list == null) {
+ return null;
+ }
+
+ for (ResolveInfo resolveInfo : list) {
+ if ((resolveInfo.activityInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM)
+ != 0) {
+ return resolveInfo;
+ }
+ }
+
+ // Did not find a matching activity
+ return null;
+ }
+
+ private void replacePreferenceIntent() {
+ final ResolveInfo resolveInfo = findMatchingSpecificActivity();
+ if (resolveInfo == null) {
+ return;
+ }
+
+ // Replace the intent with this specific activity
+ mPreference.setIntent(new Intent().setClassName(
+ resolveInfo.activityInfo.packageName,
+ resolveInfo.activityInfo.name));
+
+ mPreference.setTitle(resolveInfo.loadLabel(mPackageManager));
+ }
+}
diff --git a/src/com/android/settings/deviceinfo/legal/LicensePreferenceController.java b/src/com/android/settings/deviceinfo/legal/LicensePreferenceController.java
new file mode 100644
index 00000000000..67af15b4fc6
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/legal/LicensePreferenceController.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.settings.deviceinfo.legal;
+
+import android.content.Context;
+import android.content.Intent;
+
+public class LicensePreferenceController extends LegalPreferenceController {
+
+ private static final Intent INTENT = new Intent("android.settings.LICENSE");
+
+ public LicensePreferenceController(Context context, String key) {
+ super(context, key);
+ }
+
+ @Override
+ protected Intent getIntent() {
+ return INTENT;
+ }
+}
diff --git a/src/com/android/settings/deviceinfo/legal/TermsPreferenceController.java b/src/com/android/settings/deviceinfo/legal/TermsPreferenceController.java
new file mode 100644
index 00000000000..bccc44579b9
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/legal/TermsPreferenceController.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.settings.deviceinfo.legal;
+
+import android.content.Context;
+import android.content.Intent;
+
+public class TermsPreferenceController extends LegalPreferenceController {
+
+ private static final Intent INTENT = new Intent("android.settings.TERMS");
+
+ public TermsPreferenceController(Context context, String key) {
+ super(context, key);
+ }
+
+ @Override
+ protected Intent getIntent() {
+ return INTENT;
+ }
+}
diff --git a/src/com/android/settings/deviceinfo/legal/WallpaperAttributionsPreferenceController.java b/src/com/android/settings/deviceinfo/legal/WallpaperAttributionsPreferenceController.java
new file mode 100644
index 00000000000..418b149df97
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/legal/WallpaperAttributionsPreferenceController.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.deviceinfo.legal;
+
+import android.content.Context;
+
+import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
+
+public class WallpaperAttributionsPreferenceController extends BasePreferenceController {
+
+ public WallpaperAttributionsPreferenceController(Context context, String key) {
+ super(context, key);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return mContext.getResources().getBoolean(R.bool.config_show_wallpaper_attribution)
+ ? AVAILABLE
+ : DISABLED_UNSUPPORTED;
+ }
+}
diff --git a/src/com/android/settings/deviceinfo/legal/WebViewLicensePreferenceController.java b/src/com/android/settings/deviceinfo/legal/WebViewLicensePreferenceController.java
new file mode 100644
index 00000000000..9d8b3f95027
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/legal/WebViewLicensePreferenceController.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.settings.deviceinfo.legal;
+
+import android.content.Context;
+import android.content.Intent;
+
+public class WebViewLicensePreferenceController extends LegalPreferenceController {
+
+ private static final Intent INTENT = new Intent("android.settings.WEBVIEW_LICENSE");
+
+ public WebViewLicensePreferenceController(Context context, String key) {
+ super(context, key);
+ }
+
+ @Override
+ protected Intent getIntent() {
+ return INTENT;
+ }
+}
diff --git a/src/com/android/settings/fuelgauge/BatteryUtils.java b/src/com/android/settings/fuelgauge/BatteryUtils.java
index c8a5d47cfa8..639c1fbba3e 100644
--- a/src/com/android/settings/fuelgauge/BatteryUtils.java
+++ b/src/com/android/settings/fuelgauge/BatteryUtils.java
@@ -416,6 +416,11 @@ public class BatteryUtils {
mAppOpsManager.setMode(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, uid, packageName, mode);
}
+ public boolean isForceAppStandbyEnabled(int uid, String packageName) {
+ return mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, uid,
+ packageName) == AppOpsManager.MODE_IGNORED;
+ }
+
public void initBatteryStatsHelper(BatteryStatsHelper statsHelper, Bundle bundle,
UserManager userManager) {
statsHelper.create(bundle);
diff --git a/src/com/android/settings/fuelgauge/PowerUsageSummary.java b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
index 09147ca5edd..e314dde6574 100644
--- a/src/com/android/settings/fuelgauge/PowerUsageSummary.java
+++ b/src/com/android/settings/fuelgauge/PowerUsageSummary.java
@@ -109,7 +109,8 @@ public class PowerUsageSummary extends PowerUsageBase implements OnLongClickList
BatteryHeaderPreferenceController mBatteryHeaderPreferenceController;
@VisibleForTesting
boolean mNeedUpdateBatteryTip;
- private BatteryTipPreferenceController mBatteryTipPreferenceController;
+ @VisibleForTesting
+ BatteryTipPreferenceController mBatteryTipPreferenceController;
private int mStatsType = BatteryStats.STATS_SINCE_CHARGED;
@VisibleForTesting
@@ -215,8 +216,8 @@ public class PowerUsageSummary extends PowerUsageBase implements OnLongClickList
mAnomalySparseArray = new SparseArray<>();
restartBatteryInfoLoader();
- mNeedUpdateBatteryTip = icicle == null;
mBatteryTipPreferenceController.restoreInstanceState(icicle);
+ updateBatteryTipFlag(icicle);
}
@Override
@@ -384,6 +385,11 @@ public class PowerUsageSummary extends PowerUsageBase implements OnLongClickList
}
}
+ @VisibleForTesting
+ void updateBatteryTipFlag(Bundle icicle) {
+ mNeedUpdateBatteryTip = icicle == null || mBatteryTipPreferenceController.needUpdate();
+ }
+
@Override
public boolean onLongClick(View view) {
showBothEstimates();
diff --git a/src/com/android/settings/fuelgauge/RestrictedAppDetails.java b/src/com/android/settings/fuelgauge/RestrictedAppDetails.java
index e75112c68a5..96fafb3a0da 100644
--- a/src/com/android/settings/fuelgauge/RestrictedAppDetails.java
+++ b/src/com/android/settings/fuelgauge/RestrictedAppDetails.java
@@ -133,7 +133,8 @@ public class RestrictedAppDetails extends DashboardFragment {
try {
final ApplicationInfo applicationInfo = mPackageManager.getApplicationInfoAsUser(
appInfo.packageName, 0 /* flags */, UserHandle.getUserId(appInfo.uid));
- checkBoxPreference.setChecked(true);
+ checkBoxPreference.setChecked(
+ mBatteryUtils.isForceAppStandbyEnabled(appInfo.uid, appInfo.packageName));
checkBoxPreference.setTitle(mPackageManager.getApplicationLabel(applicationInfo));
checkBoxPreference.setIcon(
Utils.getBadgedIcon(mIconDrawableFactory, mPackageManager,
diff --git a/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java b/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java
index 249bf9b3f57..784c54cfc1f 100644
--- a/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/batterytip/BatteryTipPreferenceController.java
@@ -52,6 +52,7 @@ public class BatteryTipPreferenceController extends BasePreferenceController {
private Map mBatteryTipMap;
private SettingsActivity mSettingsActivity;
private MetricsFeatureProvider mMetricsFeatureProvider;
+ private boolean mNeedUpdate;
@VisibleForTesting
PreferenceGroup mPreferenceGroup;
@VisibleForTesting
@@ -71,6 +72,7 @@ public class BatteryTipPreferenceController extends BasePreferenceController {
mFragment = fragment;
mSettingsActivity = settingsActivity;
mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
+ mNeedUpdate = true;
}
@Override
@@ -111,6 +113,7 @@ public class BatteryTipPreferenceController extends BasePreferenceController {
mBatteryTipMap.put(preference.getKey(), batteryTip);
mPreferenceGroup.addPreference(preference);
batteryTip.log(mContext, mMetricsFeatureProvider);
+ mNeedUpdate = batteryTip.needUpdate();
break;
}
}
@@ -153,6 +156,10 @@ public class BatteryTipPreferenceController extends BasePreferenceController {
outState.putParcelableList(KEY_BATTERY_TIPS, mBatteryTips);
}
+ public boolean needUpdate() {
+ return mNeedUpdate;
+ }
+
/**
* Listener to give the control back to target fragment
*/
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTip.java
index 3c3a5c06992..f02dd7296b2 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTip.java
@@ -86,17 +86,23 @@ public abstract class BatteryTip implements Comparable, Parcelable {
protected int mType;
protected int mState;
protected boolean mShowDialog;
+ /**
+ * Whether we need to update battery tip when configuration change
+ */
+ protected boolean mNeedUpdate;
BatteryTip(Parcel in) {
mType = in.readInt();
mState = in.readInt();
mShowDialog = in.readBoolean();
+ mNeedUpdate = in.readBoolean();
}
BatteryTip(int type, int state, boolean showDialog) {
mType = type;
mState = state;
mShowDialog = showDialog;
+ mNeedUpdate = true;
}
@Override
@@ -109,6 +115,7 @@ public abstract class BatteryTip implements Comparable, Parcelable {
dest.writeInt(mType);
dest.writeInt(mState);
dest.writeBoolean(mShowDialog);
+ dest.writeBoolean(mNeedUpdate);
}
public abstract CharSequence getTitle(Context context);
@@ -144,6 +151,10 @@ public abstract class BatteryTip implements Comparable, Parcelable {
return mShowDialog;
}
+ public boolean needUpdate() {
+ return mNeedUpdate;
+ }
+
public String getKey() {
return KEY_PREFIX + mType;
}
diff --git a/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTip.java b/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTip.java
index 8b161661b55..9aa8363f415 100644
--- a/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTip.java
+++ b/src/com/android/settings/fuelgauge/batterytip/tips/RestrictAppTip.java
@@ -42,12 +42,14 @@ public class RestrictAppTip extends BatteryTip {
public RestrictAppTip(@StateType int state, List restrictApps) {
super(TipType.APP_RESTRICTION, state, state == StateType.NEW /* showDialog */);
mRestrictAppList = restrictApps;
+ mNeedUpdate = false;
}
public RestrictAppTip(@StateType int state, AppInfo appInfo) {
super(TipType.APP_RESTRICTION, state, state == StateType.NEW /* showDialog */);
mRestrictAppList = new ArrayList<>();
mRestrictAppList.add(appInfo);
+ mNeedUpdate = false;
}
@VisibleForTesting
diff --git a/src/com/android/settings/inputmethod/KeyboardLayoutPickerController.java b/src/com/android/settings/inputmethod/KeyboardLayoutPickerController.java
new file mode 100644
index 00000000000..d3f7f17ccb0
--- /dev/null
+++ b/src/com/android/settings/inputmethod/KeyboardLayoutPickerController.java
@@ -0,0 +1,162 @@
+/*
+ * 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.inputmethod;
+
+
+import android.app.Fragment;
+import android.content.Context;
+import android.hardware.input.InputDeviceIdentifier;
+import android.hardware.input.InputManager;
+import android.hardware.input.KeyboardLayout;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.view.InputDevice;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.core.lifecycle.events.OnStop;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+
+public class KeyboardLayoutPickerController extends BasePreferenceController implements
+ InputManager.InputDeviceListener, LifecycleObserver, OnStart, OnStop {
+
+ private final InputManager mIm;
+ private final Map mPreferenceMap;
+
+ private Fragment mParent;
+ private int mInputDeviceId;
+ private InputDeviceIdentifier mInputDeviceIdentifier;
+ private KeyboardLayout[] mKeyboardLayouts;
+ private PreferenceScreen mScreen;
+
+
+ public KeyboardLayoutPickerController(Context context, String key) {
+ super(context, key);
+ mIm = (InputManager) context.getSystemService(Context.INPUT_SERVICE);
+ mInputDeviceId = -1;
+ mPreferenceMap = new HashMap<>();
+ }
+
+ public void initialize(Fragment parent, InputDeviceIdentifier inputDeviceIdentifier) {
+ mParent = parent;
+ mInputDeviceIdentifier = inputDeviceIdentifier;
+ mKeyboardLayouts = mIm.getKeyboardLayoutsForInputDevice(mInputDeviceIdentifier);
+ Arrays.sort(mKeyboardLayouts);
+ }
+
+ @Override
+ public void onStart() {
+ mIm.registerInputDeviceListener(this, null);
+
+ final InputDevice inputDevice =
+ mIm.getInputDeviceByDescriptor(mInputDeviceIdentifier.getDescriptor());
+ if (inputDevice == null) {
+ mParent.getActivity().finish();
+ return;
+ }
+ mInputDeviceId = inputDevice.getId();
+
+ updateCheckedState();
+ }
+
+ @Override
+ public void onStop() {
+ mIm.unregisterInputDeviceListener(this);
+ mInputDeviceId = -1;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mScreen = screen;
+ createPreferenceHierarchy();
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return AVAILABLE;
+ }
+
+ @Override
+ public boolean handlePreferenceTreeClick(Preference preference) {
+ if (!(preference instanceof SwitchPreference)) {
+ return false;
+ }
+
+ final SwitchPreference switchPref = (SwitchPreference) preference;
+ final KeyboardLayout layout = mPreferenceMap.get(switchPref);
+ if (layout != null) {
+ final boolean checked = switchPref.isChecked();
+ if (checked) {
+ mIm.addKeyboardLayoutForInputDevice(mInputDeviceIdentifier,
+ layout.getDescriptor());
+ } else {
+ mIm.removeKeyboardLayoutForInputDevice(mInputDeviceIdentifier,
+ layout.getDescriptor());
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public void onInputDeviceAdded(int deviceId) {
+
+ }
+
+ @Override
+ public void onInputDeviceRemoved(int deviceId) {
+ if (mInputDeviceId >= 0 && deviceId == mInputDeviceId) {
+ mParent.getActivity().finish();
+ }
+ }
+
+ @Override
+ public void onInputDeviceChanged(int deviceId) {
+ if (mInputDeviceId >= 0 && deviceId == mInputDeviceId) {
+ updateCheckedState();
+ }
+ }
+
+ private void updateCheckedState() {
+ final String[] enabledKeyboardLayouts = mIm.getEnabledKeyboardLayoutsForInputDevice(
+ mInputDeviceIdentifier);
+ Arrays.sort(enabledKeyboardLayouts);
+
+ for (Map.Entry entry : mPreferenceMap.entrySet()) {
+ entry.getKey().setChecked(Arrays.binarySearch(enabledKeyboardLayouts,
+ entry.getValue().getDescriptor()) >= 0);
+ }
+ }
+
+ private void createPreferenceHierarchy() {
+ for (KeyboardLayout layout : mKeyboardLayouts) {
+ final SwitchPreference pref = new SwitchPreference(mScreen.getContext());
+ pref.setTitle(layout.getLabel());
+ pref.setSummary(layout.getCollection());
+ pref.setKey(layout.getDescriptor());
+ mScreen.addPreference(pref);
+ mPreferenceMap.put(pref, layout);
+ }
+ }
+}
+
diff --git a/src/com/android/settings/inputmethod/KeyboardLayoutPickerFragment.java b/src/com/android/settings/inputmethod/KeyboardLayoutPickerFragment.java
index 4c9715ca467..2c3f89ba632 100644
--- a/src/com/android/settings/inputmethod/KeyboardLayoutPickerFragment.java
+++ b/src/com/android/settings/inputmethod/KeyboardLayoutPickerFragment.java
@@ -18,29 +18,15 @@ package com.android.settings.inputmethod;
import android.content.Context;
import android.hardware.input.InputDeviceIdentifier;
-import android.hardware.input.InputManager;
-import android.hardware.input.InputManager.InputDeviceListener;
-import android.hardware.input.KeyboardLayout;
-import android.os.Bundle;
-import android.support.v7.preference.CheckBoxPreference;
-import android.support.v7.preference.Preference;
-import android.support.v7.preference.PreferenceScreen;
-import android.view.InputDevice;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.R;
+import com.android.settings.dashboard.DashboardFragment;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-public class KeyboardLayoutPickerFragment extends SettingsPreferenceFragment
- implements InputDeviceListener {
- private InputDeviceIdentifier mInputDeviceIdentifier;
- private int mInputDeviceId = -1;
- private InputManager mIm;
- private KeyboardLayout[] mKeyboardLayouts;
- private HashMap mPreferenceMap = new HashMap<>();
+public class KeyboardLayoutPickerFragment extends DashboardFragment {
+
+ private static final String TAG = "KeyboardLayoutPicker";
/**
* Intent extra: The input device descriptor of the keyboard whose keyboard
@@ -54,105 +40,25 @@ public class KeyboardLayoutPickerFragment extends SettingsPreferenceFragment
}
@Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
+ public void onAttach(Context context) {
+ super.onAttach(context);
- mInputDeviceIdentifier = getActivity().getIntent().getParcelableExtra(
- EXTRA_INPUT_DEVICE_IDENTIFIER);
- if (mInputDeviceIdentifier == null) {
+ final InputDeviceIdentifier inputDeviceIdentifier = getActivity().getIntent().
+ getParcelableExtra(EXTRA_INPUT_DEVICE_IDENTIFIER);
+ if (inputDeviceIdentifier == null) {
getActivity().finish();
}
- mIm = (InputManager) getSystemService(Context.INPUT_SERVICE);
- mKeyboardLayouts = mIm.getKeyboardLayoutsForInputDevice(mInputDeviceIdentifier);
- Arrays.sort(mKeyboardLayouts);
- setPreferenceScreen(createPreferenceHierarchy());
+ use(KeyboardLayoutPickerController.class).initialize(this /*parent*/,
+ inputDeviceIdentifier);
}
@Override
- public void onResume() {
- super.onResume();
-
- mIm.registerInputDeviceListener(this, null);
-
- InputDevice inputDevice =
- mIm.getInputDeviceByDescriptor(mInputDeviceIdentifier.getDescriptor());
- if (inputDevice == null) {
- getActivity().finish();
- return;
- }
- mInputDeviceId = inputDevice.getId();
-
- updateCheckedState();
+ protected String getLogTag() {
+ return TAG;
}
- @Override
- public void onPause() {
- mIm.unregisterInputDeviceListener(this);
- mInputDeviceId = -1;
-
- super.onPause();
- }
-
- @Override
- public boolean onPreferenceTreeClick(Preference preference) {
- if (preference instanceof CheckBoxPreference) {
- CheckBoxPreference checkboxPref = (CheckBoxPreference)preference;
- KeyboardLayout layout = mPreferenceMap.get(checkboxPref);
- if (layout != null) {
- boolean checked = checkboxPref.isChecked();
- if (checked) {
- mIm.addKeyboardLayoutForInputDevice(mInputDeviceIdentifier,
- layout.getDescriptor());
- } else {
- mIm.removeKeyboardLayoutForInputDevice(mInputDeviceIdentifier,
- layout.getDescriptor());
- }
- return true;
- }
- }
- return super.onPreferenceTreeClick(preference);
- }
-
- @Override
- public void onInputDeviceAdded(int deviceId) {
- }
-
- @Override
- public void onInputDeviceChanged(int deviceId) {
- if (mInputDeviceId >= 0 && deviceId == mInputDeviceId) {
- updateCheckedState();
- }
- }
-
- @Override
- public void onInputDeviceRemoved(int deviceId) {
- if (mInputDeviceId >= 0 && deviceId == mInputDeviceId) {
- getActivity().finish();
- }
- }
-
- private PreferenceScreen createPreferenceHierarchy() {
- PreferenceScreen root = getPreferenceManager().createPreferenceScreen(getActivity());
-
- for (KeyboardLayout layout : mKeyboardLayouts) {
- CheckBoxPreference pref = new CheckBoxPreference(getPrefContext());
- pref.setTitle(layout.getLabel());
- pref.setSummary(layout.getCollection());
- root.addPreference(pref);
- mPreferenceMap.put(pref, layout);
- }
- return root;
- }
-
- private void updateCheckedState() {
- String[] enabledKeyboardLayouts = mIm.getEnabledKeyboardLayoutsForInputDevice(
- mInputDeviceIdentifier);
- Arrays.sort(enabledKeyboardLayouts);
-
- for (Map.Entry entry : mPreferenceMap.entrySet()) {
- entry.getKey().setChecked(Arrays.binarySearch(enabledKeyboardLayouts,
- entry.getValue().getDescriptor()) >= 0);
- }
+ protected int getPreferenceScreenResId() {
+ return R.xml.keyboard_layout_picker_fragment;
}
}
diff --git a/src/com/android/settings/inputmethod/UserDictionaryAddWordContents.java b/src/com/android/settings/inputmethod/UserDictionaryAddWordContents.java
index 620bc652815..716226db4c7 100644
--- a/src/com/android/settings/inputmethod/UserDictionaryAddWordContents.java
+++ b/src/com/android/settings/inputmethod/UserDictionaryAddWordContents.java
@@ -60,8 +60,8 @@ public class UserDictionaryAddWordContents {
private String mSavedShortcut;
/* package */ UserDictionaryAddWordContents(final View view, final Bundle args) {
- mWordEditText = (EditText)view.findViewById(R.id.user_dictionary_add_word_text);
- mShortcutEditText = (EditText)view.findViewById(R.id.user_dictionary_add_shortcut);
+ mWordEditText = (EditText) view.findViewById(R.id.user_dictionary_add_word_text);
+ mShortcutEditText = (EditText) view.findViewById(R.id.user_dictionary_add_shortcut);
final String word = args.getString(EXTRA_WORD);
if (null != word) {
mWordEditText.setText(word);
@@ -81,8 +81,8 @@ public class UserDictionaryAddWordContents {
/* package */ UserDictionaryAddWordContents(final View view,
final UserDictionaryAddWordContents oldInstanceToBeEdited) {
- mWordEditText = (EditText)view.findViewById(R.id.user_dictionary_add_word_text);
- mShortcutEditText = (EditText)view.findViewById(R.id.user_dictionary_add_shortcut);
+ mWordEditText = (EditText) view.findViewById(R.id.user_dictionary_add_word_text);
+ mShortcutEditText = (EditText) view.findViewById(R.id.user_dictionary_add_shortcut);
mMode = MODE_EDIT;
mOldWord = oldInstanceToBeEdited.mSavedWord;
mOldShortcut = oldInstanceToBeEdited.mSavedShortcut;
@@ -167,23 +167,24 @@ public class UserDictionaryAddWordContents {
return UserDictionaryAddWordActivity.CODE_WORD_ADDED;
}
- private static final String[] HAS_WORD_PROJECTION = { UserDictionary.Words.WORD };
+ private static final String[] HAS_WORD_PROJECTION = {UserDictionary.Words.WORD};
private static final String HAS_WORD_SELECTION_ONE_LOCALE = UserDictionary.Words.WORD
+ "=? AND " + UserDictionary.Words.LOCALE + "=?";
private static final String HAS_WORD_SELECTION_ALL_LOCALES = UserDictionary.Words.WORD
+ "=? AND " + UserDictionary.Words.LOCALE + " is null";
+
private boolean hasWord(final String word, final Context context) {
final Cursor cursor;
// mLocale == "" indicates this is an entry for all languages. Here, mLocale can't
// be null at all (it's ensured by the updateLocale method).
if ("".equals(mLocale)) {
cursor = context.getContentResolver().query(UserDictionary.Words.CONTENT_URI,
- HAS_WORD_PROJECTION, HAS_WORD_SELECTION_ALL_LOCALES,
- new String[] { word }, null /* sort order */);
+ HAS_WORD_PROJECTION, HAS_WORD_SELECTION_ALL_LOCALES,
+ new String[] {word}, null /* sort order */);
} else {
cursor = context.getContentResolver().query(UserDictionary.Words.CONTENT_URI,
- HAS_WORD_PROJECTION, HAS_WORD_SELECTION_ONE_LOCALE,
- new String[] { word, mLocale }, null /* sort order */);
+ HAS_WORD_PROJECTION, HAS_WORD_SELECTION_ONE_LOCALE,
+ new String[] {word, mLocale}, null /* sort order */);
}
try {
if (null == cursor) return false;
@@ -196,6 +197,7 @@ public class UserDictionaryAddWordContents {
public static class LocaleRenderer {
private final String mLocaleString;
private final String mDescription;
+
// LocaleString may NOT be null.
public LocaleRenderer(final Context context, final String localeString) {
mLocaleString = localeString;
@@ -207,13 +209,16 @@ public class UserDictionaryAddWordContents {
mDescription = Utils.createLocaleFromString(localeString).getDisplayName();
}
}
+
@Override
public String toString() {
return mDescription;
}
+
public String getLocaleString() {
return mLocaleString;
}
+
// "More languages..." is null ; "All languages" is the empty string.
public boolean isMoreLanguages() {
return null == mLocaleString;
@@ -229,7 +234,8 @@ public class UserDictionaryAddWordContents {
// Helper method to get the list of locales to display for this word
public ArrayList getLocalesList(final Activity activity) {
- final TreeSet locales = UserDictionaryList.getUserDictionaryLocalesSet(activity);
+ final TreeSet locales =
+ UserDictionaryListPreferenceController.getUserDictionaryLocalesSet(activity);
// Remove our locale if it's in, because we're always gonna put it at the top
locales.remove(mLocale); // mLocale may not be null
final String systemLocale = Locale.getDefault().toString();
diff --git a/src/com/android/settings/inputmethod/UserDictionaryList.java b/src/com/android/settings/inputmethod/UserDictionaryList.java
index 2f59dc90da6..46723bc4614 100644
--- a/src/com/android/settings/inputmethod/UserDictionaryList.java
+++ b/src/com/android/settings/inputmethod/UserDictionaryList.java
@@ -16,33 +16,17 @@
package com.android.settings.inputmethod;
-import android.app.Activity;
import android.content.Context;
import android.content.Intent;
-import android.database.Cursor;
import android.os.Bundle;
-import android.provider.UserDictionary;
-import android.support.annotation.NonNull;
-import android.support.v7.preference.Preference;
-import android.support.v7.preference.PreferenceGroup;
-import android.text.TextUtils;
-import android.view.inputmethod.InputMethodInfo;
-import android.view.inputmethod.InputMethodManager;
-import android.view.inputmethod.InputMethodSubtype;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
-import com.android.settings.SettingsPreferenceFragment;
-import com.android.settings.Utils;
+import com.android.settings.dashboard.DashboardFragment;
-import java.util.List;
-import java.util.Locale;
-import java.util.TreeSet;
+public class UserDictionaryList extends DashboardFragment {
-public class UserDictionaryList extends SettingsPreferenceFragment {
- public static final String USER_DICTIONARY_SETTINGS_INTENT_ACTION =
- "android.settings.USER_DICTIONARY_SETTINGS";
- private String mLocale;
+ private static final String TAG = "UserDictionaryList";
@Override
public int getMetricsCategory() {
@@ -50,15 +34,8 @@ public class UserDictionaryList extends SettingsPreferenceFragment {
}
@Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- setPreferenceScreen(getPreferenceManager().createPreferenceScreen(getActivity()));
- }
-
- @Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
- getActivity().getActionBar().setTitle(R.string.user_dict_settings_title);
+ public void onAttach(Context context) {
+ super.onAttach(context);
final Intent intent = getActivity().getIntent();
final String localeFromIntent =
@@ -76,122 +53,17 @@ public class UserDictionaryList extends SettingsPreferenceFragment {
} else {
locale = null;
}
- mLocale = locale;
- }
- @NonNull
- public static TreeSet getUserDictionaryLocalesSet(Context context) {
- final Cursor cursor = context.getContentResolver().query(
- UserDictionary.Words.CONTENT_URI, new String[]{UserDictionary.Words.LOCALE},
- null, null, null);
- final TreeSet localeSet = new TreeSet<>();
- if (cursor == null) {
- // The user dictionary service is not present or disabled. Return empty set.
- return localeSet;
- }
- try {
- if (cursor.moveToFirst()) {
- final int columnIndex = cursor.getColumnIndex(UserDictionary.Words.LOCALE);
- do {
- final String locale = cursor.getString(columnIndex);
- localeSet.add(null != locale ? locale : "");
- } while (cursor.moveToNext());
- }
- } finally {
- cursor.close();
- }
-
- // CAVEAT: Keep this for consistency of the implementation between Keyboard and Settings
- // if (!UserDictionarySettings.IS_SHORTCUT_API_SUPPORTED) {
- // // For ICS, we need to show "For all languages" in case that the keyboard locale
- // // is different from the system locale
- // localeSet.add("");
- // }
-
- final InputMethodManager imm =
- (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
- final List imis = imm.getEnabledInputMethodList();
- for (final InputMethodInfo imi : imis) {
- final List subtypes =
- imm.getEnabledInputMethodSubtypeList(
- imi, true /* allowsImplicitlySelectedSubtypes */);
- for (InputMethodSubtype subtype : subtypes) {
- final String locale = subtype.getLocale();
- if (!TextUtils.isEmpty(locale)) {
- localeSet.add(locale);
- }
- }
- }
-
- // We come here after we have collected locales from existing user dictionary entries and
- // enabled subtypes. If we already have the locale-without-country version of the system
- // locale, we don't add the system locale to avoid confusion even though it's technically
- // correct to add it.
- if (!localeSet.contains(Locale.getDefault().getLanguage().toString())) {
- localeSet.add(Locale.getDefault().toString());
- }
-
- return localeSet;
- }
-
- /**
- * Creates the entries that allow the user to go into the user dictionary for each locale.
- *
- * @param userDictGroup The group to put the settings in.
- */
- protected void createUserDictSettings(PreferenceGroup userDictGroup) {
- final Activity activity = getActivity();
- userDictGroup.removeAll();
- final TreeSet localeSet =
- UserDictionaryList.getUserDictionaryLocalesSet(activity);
- if (mLocale != null) {
- // If the caller explicitly specify empty string as a locale, we'll show "all languages"
- // in the list.
- localeSet.add(mLocale);
- }
- if (localeSet.size() > 1) {
- // Have an "All languages" entry in the languages list if there are two or more active
- // languages
- localeSet.add("");
- }
-
- if (localeSet.isEmpty()) {
- userDictGroup.addPreference(createUserDictionaryPreference(null, activity));
- } else {
- for (String locale : localeSet) {
- userDictGroup.addPreference(createUserDictionaryPreference(locale, activity));
- }
- }
- }
-
- /**
- * Create a single User Dictionary Preference object, with its parameters set.
- *
- * @param locale The locale for which this user dictionary is for.
- * @return The corresponding preference.
- */
- protected Preference createUserDictionaryPreference(String locale, Activity activity) {
- final Preference newPref = new Preference(getPrefContext());
- final Intent intent = new Intent(USER_DICTIONARY_SETTINGS_INTENT_ACTION);
- if (null == locale) {
- newPref.setTitle(Locale.getDefault().getDisplayName());
- } else {
- if ("".equals(locale)) {
- newPref.setTitle(getString(R.string.user_dict_settings_all_languages));
- } else {
- newPref.setTitle(Utils.createLocaleFromString(locale).getDisplayName());
- }
- intent.putExtra("locale", locale);
- newPref.getExtras().putString("locale", locale);
- }
- newPref.setIntent(intent);
- newPref.setFragment(UserDictionarySettings.class.getName());
- return newPref;
+ use(UserDictionaryListPreferenceController.class).setLocale(locale);
}
@Override
- public void onResume() {
- super.onResume();
- createUserDictSettings(getPreferenceScreen());
+ protected int getPreferenceScreenResId() {
+ return R.xml.user_dictionary_list_fragment;
+ }
+
+ @Override
+ protected String getLogTag() {
+ return TAG;
}
}
diff --git a/src/com/android/settings/inputmethod/UserDictionaryListPreferenceController.java b/src/com/android/settings/inputmethod/UserDictionaryListPreferenceController.java
new file mode 100644
index 00000000000..715246aa17f
--- /dev/null
+++ b/src/com/android/settings/inputmethod/UserDictionaryListPreferenceController.java
@@ -0,0 +1,211 @@
+/*
+ * 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.inputmethod;
+
+import android.content.Context;
+import android.content.Intent;
+import android.database.Cursor;
+import android.provider.UserDictionary;
+import android.support.annotation.NonNull;
+import android.support.annotation.VisibleForTesting;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.text.TextUtils;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.InputMethodSubtype;
+
+import com.android.settings.R;
+import com.android.settings.Utils;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+
+import java.util.List;
+import java.util.Locale;
+import java.util.TreeSet;
+
+public class UserDictionaryListPreferenceController extends BasePreferenceController implements
+ LifecycleObserver, OnStart {
+
+ public static final String USER_DICTIONARY_SETTINGS_INTENT_ACTION =
+ "android.settings.USER_DICTIONARY_SETTINGS";
+ private final String KEY_ALL_LANGUAGE = "all_languages";
+ private String mLocale;
+ private PreferenceScreen mScreen;
+
+ public UserDictionaryListPreferenceController(Context context, String key) {
+ super(context, key);
+ }
+
+ public void setLocale(String locale) {
+ mLocale = locale;
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return AVAILABLE;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ // This is to make newly inserted languages being sorted alphabetically when updating
+ // the existing preferenceScreen, and for "For all languages" to be always on the top.
+ screen.setOrderingAsAdded(false);
+ mScreen = screen;
+ }
+
+ @Override
+ public void onStart() {
+ createUserDictSettings();
+ }
+
+ @NonNull
+ public static TreeSet getUserDictionaryLocalesSet(Context context) {
+ final Cursor cursor = context.getContentResolver().query(
+ UserDictionary.Words.CONTENT_URI, new String[] {UserDictionary.Words.LOCALE},
+ null, null, null);
+ final TreeSet localeSet = new TreeSet<>();
+ if (cursor == null) {
+ // The user dictionary service is not present or disabled. Return empty set.
+ return localeSet;
+ }
+ try {
+ if (cursor.moveToFirst()) {
+ final int columnIndex = cursor.getColumnIndex(UserDictionary.Words.LOCALE);
+ do {
+ final String locale = cursor.getString(columnIndex);
+ localeSet.add(null != locale ? locale : "");
+ } while (cursor.moveToNext());
+ }
+ } finally {
+ cursor.close();
+ }
+
+ // CAVEAT: Keep this for consistency of the implementation between Keyboard and Settings
+ // if (!UserDictionarySettings.IS_SHORTCUT_API_SUPPORTED) {
+ // // For ICS, we need to show "For all languages" in case that the keyboard locale
+ // // is different from the system locale
+ // localeSet.add("");
+ // }
+
+ final InputMethodManager imm =
+ (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
+ final List imis = imm.getEnabledInputMethodList();
+ for (final InputMethodInfo imi : imis) {
+ final List subtypes =
+ imm.getEnabledInputMethodSubtypeList(
+ imi, true /* allowsImplicitlySelectedSubtypes */);
+ for (InputMethodSubtype subtype : subtypes) {
+ final String locale = subtype.getLocale();
+ if (!TextUtils.isEmpty(locale)) {
+ localeSet.add(locale);
+ }
+ }
+ }
+
+ // We come here after we have collected locales from existing user dictionary entries and
+ // enabled subtypes. If we already have the locale-without-country version of the system
+ // locale, we don't add the system locale to avoid confusion even though it's technically
+ // correct to add it.
+ if (!localeSet.contains(Locale.getDefault().getLanguage().toString())) {
+ localeSet.add(Locale.getDefault().toString());
+ }
+
+ return localeSet;
+ }
+
+ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+ TreeSet getUserDictLocalesSet(Context context) {
+ return getUserDictionaryLocalesSet(context);
+ }
+
+ /**
+ * Creates the entries that allow the user to go into the user dictionary for each locale.
+ */
+ private void createUserDictSettings() {
+
+ final TreeSet localeSet = getUserDictLocalesSet(mContext);
+ final int prefCount = mScreen.getPreferenceCount();
+ String prefKey;
+
+ if (mLocale != null) {
+ // If the caller explicitly specify empty string as a locale, we'll show "all languages"
+ // in the list.
+ localeSet.add(mLocale);
+ }
+ if (localeSet.size() > 1) {
+ // Have an "All languages" entry in the languages list if there are two or more active
+ // languages
+ localeSet.add("");
+ }
+
+ // Update the existing preferenceScreen according to the corresponding data set.
+ if (prefCount > 0) {
+ for (int i = prefCount - 1; i >= 0; i--) {
+ prefKey = mScreen.getPreference(i).getKey();
+ if (KEY_ALL_LANGUAGE.equals(prefKey)) {
+ prefKey = "";
+ }
+ if (!localeSet.isEmpty() && localeSet.contains(prefKey)) {
+ localeSet.remove(prefKey);
+ continue;
+ }
+ mScreen.removePreference(mScreen.findPreference(prefKey));
+ }
+ }
+
+ if (localeSet.isEmpty() && prefCount == 0) {
+ mScreen.addPreference(createUserDictionaryPreference(null));
+ } else {
+ for (String locale : localeSet) {
+ mScreen.addPreference(createUserDictionaryPreference(locale));
+ }
+ }
+ }
+
+ /**
+ * Create a single User Dictionary Preference object, with its parameters set.
+ *
+ * @param locale The locale for which this user dictionary is for.
+ * @return The corresponding preference.
+ */
+ private Preference createUserDictionaryPreference(String locale) {
+ final String KEY_LOCALE = "locale";
+ final Preference newPref = new Preference(mScreen.getContext());
+ final Intent intent = new Intent(USER_DICTIONARY_SETTINGS_INTENT_ACTION);
+ if (locale == null) {
+ newPref.setTitle(Locale.getDefault().getDisplayName());
+ newPref.setKey(Locale.getDefault().toString());
+ } else {
+ if (TextUtils.isEmpty(locale)) {
+ newPref.setTitle(mContext.getString(R.string.user_dict_settings_all_languages));
+ newPref.setKey(KEY_ALL_LANGUAGE);
+ newPref.setOrder(0);
+ } else {
+ newPref.setTitle(Utils.createLocaleFromString(locale).getDisplayName());
+ newPref.setKey(locale);
+ }
+ intent.putExtra(KEY_LOCALE, locale);
+ newPref.getExtras().putString(KEY_LOCALE, locale);
+ }
+ newPref.setIntent(intent);
+ newPref.setFragment(UserDictionarySettings.class.getName());
+ return newPref;
+ }
+}
diff --git a/src/com/android/settings/language/UserDictionaryPreferenceController.java b/src/com/android/settings/language/UserDictionaryPreferenceController.java
index 3a1d6e0ff47..fa6dce6c924 100644
--- a/src/com/android/settings/language/UserDictionaryPreferenceController.java
+++ b/src/com/android/settings/language/UserDictionaryPreferenceController.java
@@ -23,6 +23,7 @@ import android.support.v7.preference.Preference;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.inputmethod.UserDictionaryList;
+import com.android.settings.inputmethod.UserDictionaryListPreferenceController;
import com.android.settings.inputmethod.UserDictionarySettings;
import com.android.settingslib.core.AbstractPreferenceController;
@@ -61,10 +62,10 @@ public class UserDictionaryPreferenceController extends AbstractPreferenceContro
// parameter in the extras. This will be interpreted by the
// UserDictionarySettings class as meaning
// "the current locale". Note that with the current code for
- // UserDictionaryList#getUserDictionaryLocalesSet()
+ // UserDictionaryListPreferenceController#getUserDictionaryLocalesSet()
// the locale list always has at least one element, since it
// always includes the current locale explicitly.
- // @see UserDictionaryList.getUserDictionaryLocalesSet().
+ // @see UserDictionaryListPreferenceController.getUserDictionaryLocalesSet().
extras.putString("locale", localeSet.first());
}
targetFragment = UserDictionarySettings.class;
@@ -75,6 +76,6 @@ public class UserDictionaryPreferenceController extends AbstractPreferenceContro
}
protected TreeSet getDictionaryLocales() {
- return UserDictionaryList.getUserDictionaryLocalesSet(mContext);
+ return UserDictionaryListPreferenceController.getUserDictionaryLocalesSet(mContext);
}
}
diff --git a/src/com/android/settings/network/ApnEditor.java b/src/com/android/settings/network/ApnEditor.java
index d0ecb71f681..e2853a64d95 100644
--- a/src/com/android/settings/network/ApnEditor.java
+++ b/src/com/android/settings/network/ApnEditor.java
@@ -28,6 +28,7 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.provider.Telephony;
+import android.support.annotation.VisibleForTesting;
import android.support.v14.preference.MultiSelectListPreference;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.EditTextPreference;
@@ -47,7 +48,6 @@ import android.view.MenuItem;
import android.view.View;
import android.view.View.OnKeyListener;
-import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.util.ArrayUtils;
@@ -309,6 +309,16 @@ public class ApnEditor extends SettingsPreferenceFragment
fillUI(icicle == null);
}
+ @VisibleForTesting
+ static String formatInteger(String value) {
+ try {
+ final int intValue = Integer.parseInt(value);
+ return String.format("%d", intValue);
+ } catch (NumberFormatException e) {
+ return value;
+ }
+ }
+
/**
* Check if passed in array of APN types indicates all APN types
* @param apnTypes array of APN types. "*" indicates all types.
@@ -547,8 +557,8 @@ public class ApnEditor extends SettingsPreferenceFragment
mMmsProxy.setSummary(checkNull(mMmsProxy.getText()));
mMmsPort.setSummary(checkNull(mMmsPort.getText()));
mMmsc.setSummary(checkNull(mMmsc.getText()));
- mMcc.setSummary(checkNull(mMcc.getText()));
- mMnc.setSummary(checkNull(mMnc.getText()));
+ mMcc.setSummary(formatInteger(checkNull(mMcc.getText())));
+ mMnc.setSummary(formatInteger(checkNull(mMnc.getText())));
mApnType.setSummary(checkNull(mApnType.getText()));
String authVal = mAuthType.getValue();
@@ -598,20 +608,6 @@ public class ApnEditor extends SettingsPreferenceFragment
}
}
- private String bearerDescription(String raw) {
- int mBearerIndex = mBearerMulti.findIndexOfValue(raw);
- if (mBearerIndex == -1) {
- return null;
- } else {
- String[] values = getResources().getStringArray(R.array.bearer_entries);
- try {
- return values[mBearerIndex];
- } catch (ArrayIndexOutOfBoundsException e) {
- return null;
- }
- }
- }
-
private String bearerMultiDescription(Set raw) {
String[] values = getResources().getStringArray(R.array.bearer_entries);
StringBuilder retVal = new StringBuilder();
diff --git a/src/com/android/settings/network/NetworkDashboardFragment.java b/src/com/android/settings/network/NetworkDashboardFragment.java
index c51c6f8f906..f6a739135b6 100644
--- a/src/com/android/settings/network/NetworkDashboardFragment.java
+++ b/src/com/android/settings/network/NetworkDashboardFragment.java
@@ -23,6 +23,7 @@ import android.app.AlertDialog;
import android.app.Dialog;
import android.app.Fragment;
import android.content.Context;
+import android.icu.text.ListFormatter;
import android.provider.SearchIndexableResource;
import android.support.annotation.VisibleForTesting;
import android.text.BidiFormatter;
@@ -175,25 +176,22 @@ public class NetworkDashboardFragment extends DashboardFragment implements
@Override
public void setListening(boolean listening) {
if (listening) {
- String summary = BidiFormatter.getInstance()
- .unicodeWrap(mContext.getString(R.string.wifi_settings_title));
+ final List summaries = new ArrayList<>();
+
+ summaries.add(BidiFormatter.getInstance()
+ .unicodeWrap(mContext.getString(R.string.wifi_settings_title)));
if (mMobileNetworkPreferenceController.isAvailable()) {
- final String mobileSettingSummary = mContext.getString(
- R.string.network_dashboard_summary_mobile);
- summary = mContext.getString(R.string.join_many_items_middle, summary,
- mobileSettingSummary);
+ summaries.add(mContext.getString(
+ R.string.network_dashboard_summary_mobile));
}
final String dataUsageSettingSummary = mContext.getString(
R.string.network_dashboard_summary_data_usage);
- summary = mContext.getString(R.string.join_many_items_middle, summary,
- dataUsageSettingSummary);
+ summaries.add(dataUsageSettingSummary);
if (mTetherPreferenceController.isAvailable()) {
- final String hotspotSettingSummary = mContext.getString(
- R.string.network_dashboard_summary_hotspot);
- summary = mContext.getString(R.string.join_many_items_middle, summary,
- hotspotSettingSummary);
+ summaries.add(mContext.getString(
+ R.string.network_dashboard_summary_hotspot));
}
- mSummaryLoader.setSummary(this, summary);
+ mSummaryLoader.setSummary(this, ListFormatter.getInstance().format(summaries));
}
}
}
diff --git a/src/com/android/settings/notification/AppNotificationSettings.java b/src/com/android/settings/notification/AppNotificationSettings.java
index c028298e0bd..67769319993 100644
--- a/src/com/android/settings/notification/AppNotificationSettings.java
+++ b/src/com/android/settings/notification/AppNotificationSettings.java
@@ -125,7 +125,7 @@ public class AppNotificationSettings extends NotificationSettingsBase {
mControllers.add(new VibrationPreferenceController(context, mBackend));
mControllers.add(new VisibilityPreferenceController(context, new LockPatternUtils(context),
mBackend));
- mControllers.add(new DndPreferenceController(context, getLifecycle(), mBackend));
+ mControllers.add(new DndPreferenceController(context, mBackend));
mControllers.add(new AppLinkPreferenceController(context));
mControllers.add(new DescriptionPreferenceController(context));
mControllers.add(new NotificationsOffPreferenceController(context));
diff --git a/src/com/android/settings/notification/ChannelNotificationSettings.java b/src/com/android/settings/notification/ChannelNotificationSettings.java
index a13842956d2..bd9771a3784 100644
--- a/src/com/android/settings/notification/ChannelNotificationSettings.java
+++ b/src/com/android/settings/notification/ChannelNotificationSettings.java
@@ -18,13 +18,16 @@ package com.android.settings.notification;
import android.content.Context;
import android.content.Intent;
+import android.os.Bundle;
import android.preference.PreferenceManager;
+import android.support.v7.preference.PreferenceScreen;
import android.text.TextUtils;
import android.util.Log;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R;
+import com.android.settings.applications.AppInfoBase;
import com.android.settingslib.core.AbstractPreferenceController;
import java.util.ArrayList;
@@ -38,6 +41,19 @@ public class ChannelNotificationSettings extends NotificationSettingsBase {
return MetricsEvent.NOTIFICATION_TOPIC_NOTIFICATION;
}
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ final PreferenceScreen screen = getPreferenceScreen();
+ Bundle args = getArguments();
+ // If linking to this screen from an external app, expand settings
+ if (screen != null && args != null) {
+ if (!args.getBoolean(ARG_FROM_SETTINGS, false)) {
+ screen.setInitialExpandedChildrenCount(Integer.MAX_VALUE);
+ }
+ }
+ }
+
@Override
public void onResume() {
super.onResume();
@@ -92,7 +108,7 @@ public class ChannelNotificationSettings extends NotificationSettingsBase {
mBackend));
mControllers.add(new LightsPreferenceController(context, mBackend));
mControllers.add(new BadgePreferenceController(context, mBackend));
- mControllers.add(new DndPreferenceController(context, getLifecycle(), mBackend));
+ mControllers.add(new DndPreferenceController(context, mBackend));
mControllers.add(new NotificationsOffPreferenceController(context));
return new ArrayList<>(mControllers);
}
diff --git a/src/com/android/settings/notification/ConfigureNotificationSettings.java b/src/com/android/settings/notification/ConfigureNotificationSettings.java
index 37256aaff19..27637767619 100644
--- a/src/com/android/settings/notification/ConfigureNotificationSettings.java
+++ b/src/com/android/settings/notification/ConfigureNotificationSettings.java
@@ -26,14 +26,12 @@ import android.os.UserHandle;
import android.provider.SearchIndexableResource;
import android.support.annotation.VisibleForTesting;
import android.support.v7.preference.Preference;
-import android.text.TextUtils;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.RingtonePreference;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.dashboard.SummaryLoader;
-import com.android.settings.gestures.SwipeToNotificationPreferenceController;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settingslib.core.AbstractPreferenceController;
@@ -97,21 +95,17 @@ public class ConfigureNotificationSettings extends DashboardFragment {
final List controllers = new ArrayList<>();
final BadgingNotificationPreferenceController badgeController =
new BadgingNotificationPreferenceController(context);
- final PulseNotificationPreferenceController pulseController =
- new PulseNotificationPreferenceController(context);
final LockScreenNotificationPreferenceController lockScreenNotificationController =
new LockScreenNotificationPreferenceController(context,
KEY_LOCKSCREEN,
KEY_LOCKSCREEN_WORK_PROFILE_HEADER,
KEY_LOCKSCREEN_WORK_PROFILE);
if (lifecycle != null) {
- lifecycle.addObserver(pulseController);
lifecycle.addObserver(lockScreenNotificationController);
}
controllers.add(new RecentNotifyingAppsPreferenceController(
context, new NotificationBackend(), app, host));
controllers.add(badgeController);
- controllers.add(pulseController);
controllers.add(lockScreenNotificationController);
controllers.add(new NotificationRingtonePreferenceController(context) {
@Override
diff --git a/src/com/android/settings/notification/DndPreferenceController.java b/src/com/android/settings/notification/DndPreferenceController.java
index d4c7a101d22..899c5851674 100644
--- a/src/com/android/settings/notification/DndPreferenceController.java
+++ b/src/com/android/settings/notification/DndPreferenceController.java
@@ -28,17 +28,12 @@ import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnResume;
public class DndPreferenceController extends NotificationPreferenceController
- implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener,
- LifecycleObserver {
+ implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener {
private static final String KEY_BYPASS_DND = "bypass_dnd";
- public DndPreferenceController(Context context, Lifecycle lifecycle,
- NotificationBackend backend) {
+ public DndPreferenceController(Context context, NotificationBackend backend) {
super(context, backend);
- if (lifecycle != null) {
- lifecycle.addObserver(this);
- }
}
@Override
diff --git a/src/com/android/settings/notification/NotificationSettingsBase.java b/src/com/android/settings/notification/NotificationSettingsBase.java
index 6436de63c25..7eb0ba4e503 100644
--- a/src/com/android/settings/notification/NotificationSettingsBase.java
+++ b/src/com/android/settings/notification/NotificationSettingsBase.java
@@ -58,6 +58,7 @@ import java.util.List;
abstract public class NotificationSettingsBase extends DashboardFragment {
private static final String TAG = "NotifiSettingsBase";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ protected static final String ARG_FROM_SETTINGS = "fromSettings";
protected PackageManager mPm;
protected NotificationBackend mBackend = new NotificationBackend();
@@ -249,6 +250,7 @@ abstract public class NotificationSettingsBase extends DashboardFragment {
channelArgs.putInt(AppInfoBase.ARG_PACKAGE_UID, mUid);
channelArgs.putString(AppInfoBase.ARG_PACKAGE_NAME, mPkg);
channelArgs.putString(Settings.EXTRA_CHANNEL_ID, channel.getId());
+ channelArgs.putBoolean(ARG_FROM_SETTINGS, true);
channelPref.setIntent(new SubSettingLauncher(getActivity())
.setDestination(ChannelNotificationSettings.class.getName())
.setArguments(channelArgs)
diff --git a/src/com/android/settings/notification/PulseNotificationPreferenceController.java b/src/com/android/settings/notification/PulseNotificationPreferenceController.java
index 4a8b8204f47..c39f482fd25 100644
--- a/src/com/android/settings/notification/PulseNotificationPreferenceController.java
+++ b/src/com/android/settings/notification/PulseNotificationPreferenceController.java
@@ -24,33 +24,28 @@ import android.os.Handler;
import android.provider.Settings;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
-import android.support.v7.preference.TwoStatePreference;
-import android.util.Log;
-import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settingslib.core.AbstractPreferenceController;
-import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settings.core.TogglePreferenceController;
import com.android.settingslib.core.lifecycle.events.OnPause;
import com.android.settingslib.core.lifecycle.events.OnResume;
import static android.provider.Settings.System.NOTIFICATION_LIGHT_PULSE;
-public class PulseNotificationPreferenceController extends AbstractPreferenceController
- implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener,
- LifecycleObserver, OnResume, OnPause {
+public class PulseNotificationPreferenceController extends TogglePreferenceController
+ implements OnResume, OnPause {
- private static final String TAG = "PulseNotifPrefContr";
- private static final String KEY_NOTIFICATION_PULSE = "notification_pulse";
+ private static final int ON = 1;
+ private static final int OFF = 0;
private SettingObserver mSettingObserver;
- public PulseNotificationPreferenceController(Context context) {
- super(context);
+ public PulseNotificationPreferenceController(Context context, String key) {
+ super(context, key);
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
- Preference preference = screen.findPreference(KEY_NOTIFICATION_PULSE);
+ Preference preference = screen.findPreference(getPreferenceKey());
if (preference != null) {
mSettingObserver = new SettingObserver(preference);
}
@@ -71,32 +66,22 @@ public class PulseNotificationPreferenceController extends AbstractPreferenceCon
}
@Override
- public String getPreferenceKey() {
- return KEY_NOTIFICATION_PULSE;
+ public int getAvailabilityStatus() {
+ return mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_intrusiveNotificationLed) ? AVAILABLE
+ : DISABLED_UNSUPPORTED;
}
@Override
- public boolean isAvailable() {
- return mContext.getResources()
- .getBoolean(com.android.internal.R.bool.config_intrusiveNotificationLed);
+ public boolean isChecked() {
+ return Settings.System.getInt(mContext.getContentResolver(), NOTIFICATION_LIGHT_PULSE, OFF)
+ == ON;
}
@Override
- public void updateState(Preference preference) {
- try {
- final boolean checked = Settings.System.getInt(mContext.getContentResolver(),
- NOTIFICATION_LIGHT_PULSE) == 1;
- ((TwoStatePreference) preference).setChecked(checked);
- } catch (Settings.SettingNotFoundException snfe) {
- Log.e(TAG, NOTIFICATION_LIGHT_PULSE + " not found");
- }
- }
-
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- final boolean val = (Boolean) newValue;
- return Settings.System.putInt(mContext.getContentResolver(),
- NOTIFICATION_LIGHT_PULSE, val ? 1 : 0);
+ public boolean setChecked(boolean isChecked) {
+ return Settings.System.putInt(mContext.getContentResolver(), NOTIFICATION_LIGHT_PULSE,
+ isChecked ? ON : OFF);
}
class SettingObserver extends ContentObserver {
diff --git a/src/com/android/settings/notification/RingVolumePreferenceController.java b/src/com/android/settings/notification/RingVolumePreferenceController.java
index ea071fa6fd7..e74b1104d8c 100644
--- a/src/com/android/settings/notification/RingVolumePreferenceController.java
+++ b/src/com/android/settings/notification/RingVolumePreferenceController.java
@@ -17,6 +17,8 @@
package com.android.settings.notification;
import android.app.NotificationManager;
+import android.arch.lifecycle.LifecycleObserver;
+import android.arch.lifecycle.OnLifecycleEvent;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -31,6 +33,7 @@ import android.os.Vibrator;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.Utils;
+import com.android.settingslib.core.lifecycle.Lifecycle;
import java.util.Objects;
@@ -58,6 +61,7 @@ public class RingVolumePreferenceController extends VolumeSeekBarPreferenceContr
updateRingerMode();
}
+ @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
@Override
public void onResume() {
super.onResume();
@@ -66,6 +70,7 @@ public class RingVolumePreferenceController extends VolumeSeekBarPreferenceContr
updatePreferenceIcon();
}
+ @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
@Override
public void onPause() {
super.onPause();
@@ -118,11 +123,10 @@ public class RingVolumePreferenceController extends VolumeSeekBarPreferenceContr
private void updatePreferenceIcon() {
if (mPreference != null) {
- mPreference.showIcon(mSuppressor != null
- ? com.android.internal.R.drawable.ic_audio_ring_notif_mute
- : mRingerMode == AudioManager.RINGER_MODE_VIBRATE || wasRingerModeVibrate()
- ? com.android.internal.R.drawable.ic_audio_ring_notif_vibrate
- : com.android.internal.R.drawable.ic_audio_ring_notif);
+ mPreference.showIcon(
+ mRingerMode == AudioManager.RINGER_MODE_VIBRATE || wasRingerModeVibrate()
+ ? com.android.internal.R.drawable.ic_audio_ring_notif_vibrate
+ : com.android.internal.R.drawable.ic_audio_ring_notif);
}
}
diff --git a/src/com/android/settings/notification/SoundSettings.java b/src/com/android/settings/notification/SoundSettings.java
index afb3633a0c6..287c57f3757 100644
--- a/src/com/android/settings/notification/SoundSettings.java
+++ b/src/com/android/settings/notification/SoundSettings.java
@@ -148,10 +148,16 @@ public class SoundSettings extends DashboardFragment {
@Override
public void onAttach(Context context) {
super.onAttach(context);
- use(AlarmVolumePreferenceController.class).setCallback(mVolumeCallback);
- use(MediaVolumePreferenceController.class).setCallback(mVolumeCallback);
- use(RingVolumePreferenceController.class).setCallback(mVolumeCallback);
- use(NotificationVolumePreferenceController.class).setCallback(mVolumeCallback);
+ ArrayList volumeControllers = new ArrayList<>();
+ volumeControllers.add(use(AlarmVolumePreferenceController.class));
+ volumeControllers.add(use(MediaVolumePreferenceController.class));
+ volumeControllers.add(use(RingVolumePreferenceController.class));
+ volumeControllers.add(use(NotificationVolumePreferenceController.class));
+
+ for (VolumeSeekBarPreferenceController controller : volumeControllers) {
+ controller.setCallback(mVolumeCallback);
+ getLifecycle().addObserver(controller);
+ }
}
// === Volumes ===
@@ -207,8 +213,6 @@ public class SoundSettings extends DashboardFragment {
new DialPadTonePreferenceController(context, fragment, lifecycle);
final ScreenLockSoundPreferenceController screenLockSoundPreferenceController =
new ScreenLockSoundPreferenceController(context, fragment, lifecycle);
- final ChargingSoundPreferenceController chargingSoundPreferenceController =
- new ChargingSoundPreferenceController(context, fragment, lifecycle);
final DockingSoundPreferenceController dockingSoundPreferenceController =
new DockingSoundPreferenceController(context, fragment, lifecycle);
final TouchSoundPreferenceController touchSoundPreferenceController =
@@ -224,7 +228,6 @@ public class SoundSettings extends DashboardFragment {
controllers.add(dialPadTonePreferenceController);
controllers.add(screenLockSoundPreferenceController);
- controllers.add(chargingSoundPreferenceController);
controllers.add(dockingSoundPreferenceController);
controllers.add(touchSoundPreferenceController);
controllers.add(vibrateOnTouchPreferenceController);
@@ -235,7 +238,6 @@ public class SoundSettings extends DashboardFragment {
"other_sounds_and_vibrations_category").setChildren(
Arrays.asList(dialPadTonePreferenceController,
screenLockSoundPreferenceController,
- chargingSoundPreferenceController,
dockingSoundPreferenceController,
touchSoundPreferenceController,
vibrateOnTouchPreferenceController,
diff --git a/src/com/android/settings/notification/VolumeSeekBarPreference.java b/src/com/android/settings/notification/VolumeSeekBarPreference.java
index 8a48e95c166..d7b5e521a50 100644
--- a/src/com/android/settings/notification/VolumeSeekBarPreference.java
+++ b/src/com/android/settings/notification/VolumeSeekBarPreference.java
@@ -196,8 +196,7 @@ public class VolumeSeekBarPreference extends SeekBarPreference {
if (mSuppressionTextView != null && mSeekBar != null) {
mSuppressionTextView.setText(mSuppressionText);
final boolean showSuppression = !TextUtils.isEmpty(mSuppressionText);
- mSuppressionTextView.setVisibility(showSuppression ? View.VISIBLE : View.INVISIBLE);
- mSeekBar.setVisibility(showSuppression ? View.INVISIBLE : View.VISIBLE);
+ mSuppressionTextView.setVisibility(showSuppression ? View.VISIBLE : View.GONE);
}
}
diff --git a/src/com/android/settings/notification/ZenAutomaticRuleHeaderPreferenceController.java b/src/com/android/settings/notification/ZenAutomaticRuleHeaderPreferenceController.java
index 9eab8bb1827..b4ca87e12a9 100644
--- a/src/com/android/settings/notification/ZenAutomaticRuleHeaderPreferenceController.java
+++ b/src/com/android/settings/notification/ZenAutomaticRuleHeaderPreferenceController.java
@@ -75,7 +75,7 @@ public class ZenAutomaticRuleHeaderPreferenceController extends AbstractZenModeP
.newInstance(mFragment.getActivity(), mFragment,
pref.findViewById(R.id.entity_header));
- mController.setEditZenRuleNameListener(new View.OnClickListener() {
+ mController.setEditListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ZenRuleNameDialog.show(mFragment, mRule.getName(), null,
@@ -89,7 +89,7 @@ public class ZenAutomaticRuleHeaderPreferenceController extends AbstractZenModeP
.setPackageName(mRule.getOwner().getPackageName())
.setUid(mContext.getUserId())
.setHasAppInfoLink(false)
- .setButtonActions(EntityHeaderController.ActionType.ACTION_DND_RULE_PREFERENCE,
+ .setButtonActions(EntityHeaderController.ActionType.ACTION_EDIT_PREFERENCE,
EntityHeaderController.ActionType.ACTION_NONE)
.done(mFragment.getActivity(), mContext);
diff --git a/src/com/android/settings/notification/ZenModeVisEffectPreferenceController.java b/src/com/android/settings/notification/ZenModeVisEffectPreferenceController.java
index 23723c5c779..67fd822755c 100644
--- a/src/com/android/settings/notification/ZenModeVisEffectPreferenceController.java
+++ b/src/com/android/settings/notification/ZenModeVisEffectPreferenceController.java
@@ -24,6 +24,7 @@ import android.support.v7.preference.PreferenceScreen;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settings.widget.DisabledCheckBoxPreference;
public class ZenModeVisEffectPreferenceController
extends AbstractZenModePreferenceController
@@ -78,9 +79,9 @@ public class ZenModeVisEffectPreferenceController
if (parentSuppressed) {
((CheckBoxPreference) preference).setChecked(parentSuppressed);
onPreferenceChange(preference, parentSuppressed);
- preference.setEnabled(false);
+ ((DisabledCheckBoxPreference) preference).enableCheckbox(false);
} else {
- preference.setEnabled(true);
+ ((DisabledCheckBoxPreference) preference).enableCheckbox(true);
((CheckBoxPreference) preference).setChecked(suppressed);
}
}
diff --git a/src/com/android/settings/security/LockdownButtonPreferenceController.java b/src/com/android/settings/security/LockdownButtonPreferenceController.java
index 89605020b39..dd6e0d0f7c2 100644
--- a/src/com/android/settings/security/LockdownButtonPreferenceController.java
+++ b/src/com/android/settings/security/LockdownButtonPreferenceController.java
@@ -19,8 +19,6 @@ package com.android.settings.security;
import android.content.Context;
import android.os.UserHandle;
import android.provider.Settings;
-import android.support.v7.preference.Preference;
-import android.support.v7.preference.TwoStatePreference;
import com.android.internal.widget.LockPatternUtils;
import com.android.settings.core.BasePreferenceController;
@@ -28,12 +26,10 @@ import com.android.settings.core.TogglePreferenceController;
public class LockdownButtonPreferenceController extends TogglePreferenceController {
- private static final String KEY_LOCKDOWN_ENALBED = "security_setting_lockdown_enabled";
-
private final LockPatternUtils mLockPatternUtils;
- public LockdownButtonPreferenceController(Context context) {
- super(context, KEY_LOCKDOWN_ENALBED);
+ public LockdownButtonPreferenceController(Context context, String key) {
+ super(context, key);
mLockPatternUtils = new LockPatternUtils(context);
}
diff --git a/src/com/android/settings/security/LockscreenDashboardFragment.java b/src/com/android/settings/security/LockscreenDashboardFragment.java
index 3cf5ba6c409..209eb0179b6 100644
--- a/src/com/android/settings/security/LockscreenDashboardFragment.java
+++ b/src/com/android/settings/security/LockscreenDashboardFragment.java
@@ -93,7 +93,6 @@ public class LockscreenDashboardFragment extends DashboardFragment
mOwnerInfoPreferenceController =
new OwnerInfoPreferenceController(context, this, lifecycle);
controllers.add(mOwnerInfoPreferenceController);
- controllers.add(new LockdownButtonPreferenceController(context));
return controllers;
}
@@ -124,7 +123,6 @@ public class LockscreenDashboardFragment extends DashboardFragment
KEY_ADD_USER_FROM_LOCK_SCREEN, null /* lifecycle */));
controllers.add(new OwnerInfoPreferenceController(
context, null /* fragment */, null /* lifecycle */));
- controllers.add(new LockdownButtonPreferenceController(context));
return controllers;
}
diff --git a/src/com/android/settings/slices/SettingsSliceProvider.java b/src/com/android/settings/slices/SettingsSliceProvider.java
index 1a73ea760e5..70e9d763f64 100644
--- a/src/com/android/settings/slices/SettingsSliceProvider.java
+++ b/src/com/android/settings/slices/SettingsSliceProvider.java
@@ -18,19 +18,27 @@ package com.android.settings.slices;
import android.app.PendingIntent;
import android.app.slice.SliceManager;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.net.wifi.WifiManager;
+import android.provider.Settings;
+import android.provider.SettingsSlicesContract;
import android.support.annotation.VisibleForTesting;
import android.support.v4.graphics.drawable.IconCompat;
+import android.text.TextUtils;
import android.util.Log;
+import android.util.Pair;
import com.android.settings.R;
import com.android.settingslib.utils.ThreadUtils;
import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
@@ -144,11 +152,90 @@ public class SettingsSliceProvider extends SliceProvider {
return SliceBuilderUtils.buildSlice(getContext(), cachedSliceData);
}
+ /**
+ * Get a list of all valid Uris based on the keys indexed in the Slices database.
+ *
+ * This will return a list of {@link Uri uris} depending on {@param uri}, following:
+ * 1. Authority & Full Path -> Only {@param uri}. It is only a prefix for itself.
+ * 2. Authority & No path -> A list of authority/action/$KEY$, where
+ * {@code $KEY$} is a list of all Slice-enabled keys for the authority.
+ * 3. Authority & action path -> A list of authority/action/$KEY$, where
+ * {@code $KEY$} is a list of all Slice-enabled keys for the authority.
+ * 4. Empty authority & path -> A list of Uris with all keys for both supported authorities.
+ * 5. Else -> Empty list.
+ *
+ * Note that the authority will stay consistent with {@param uri}, and the list of valid Slice
+ * keys depends on if the authority is {@link SettingsSlicesContract#AUTHORITY} or
+ * {@link #SLICE_AUTHORITY}.
+ *
+ * @param uri The uri to look for descendants under.
+ * @returns all valid Settings uris for which {@param uri} is a prefix.
+ */
+ @Override
+ public Collection onGetSliceDescendants(Uri uri) {
+ final List descendants = new ArrayList<>();
+ final Pair pathData = SliceBuilderUtils.getPathData(uri);
+
+ if (pathData != null) {
+ // Uri has a full path and will not have any descendants.
+ descendants.add(uri);
+ return descendants;
+ }
+
+ final String authority = uri.getAuthority();
+ final String pathPrefix = uri.getPath();
+ final boolean isPathEmpty = pathPrefix.isEmpty();
+
+ // No path nor authority. Return all possible Uris.
+ if (isPathEmpty && TextUtils.isEmpty(authority)) {
+ final List platformKeys = mSlicesDatabaseAccessor.getSliceKeys(
+ true /* isPlatformSlice */);
+ final List oemKeys = mSlicesDatabaseAccessor.getSliceKeys(
+ false /* isPlatformSlice */);
+ final List allUris = buildUrisFromKeys(platformKeys,
+ SettingsSlicesContract.AUTHORITY);
+ allUris.addAll(buildUrisFromKeys(oemKeys, SettingsSliceProvider.SLICE_AUTHORITY));
+
+ return allUris;
+ }
+
+ // Path is anything but empty, "action", or "intent". Return empty list.
+ if (!isPathEmpty
+ && !TextUtils.equals(pathPrefix, "/" + SettingsSlicesContract.PATH_SETTING_ACTION)
+ && !TextUtils.equals(pathPrefix,
+ "/" + SettingsSlicesContract.PATH_SETTING_INTENT)) {
+ // Invalid path prefix, there are no valid Uri descendants.
+ return descendants;
+ }
+
+ // Can assume authority belongs to the provider. Return all Uris for the authority.
+ final boolean isPlatformUri = TextUtils.equals(authority, SettingsSlicesContract.AUTHORITY);
+ final List keys = mSlicesDatabaseAccessor.getSliceKeys(isPlatformUri);
+ return buildUrisFromKeys(keys, authority);
+ }
+
+ private List buildUrisFromKeys(List keys, String authority) {
+ final List descendants = new ArrayList<>();
+
+ final Uri.Builder builder = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(authority)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION);
+
+ final String newUriPathPrefix = SettingsSlicesContract.PATH_SETTING_ACTION + "/";
+ for (String key : keys) {
+ builder.path(newUriPathPrefix + key);
+ descendants.add(builder.build());
+ }
+
+ return descendants;
+ }
+
@VisibleForTesting
void loadSlice(Uri uri) {
long startBuildTime = System.currentTimeMillis();
- SliceData sliceData = mSlicesDatabaseAccessor.getSliceDataFromUri(uri);
+ final SliceData sliceData = mSlicesDatabaseAccessor.getSliceDataFromUri(uri);
mSliceDataCache.put(uri, sliceData);
getContext().getContentResolver().notifyChange(uri, null /* content observer */);
@@ -204,13 +291,14 @@ public class SettingsSliceProvider extends SliceProvider {
.addEndItem(new SliceAction(getBroadcastIntent(ACTION_WIFI_CHANGED),
null, finalWifiEnabled))
.setPrimaryAction(
- new SliceAction(getIntent(Intent.ACTION_MAIN),
+ new SliceAction(getIntent(Settings.ACTION_WIFI_SETTINGS),
(IconCompat) null, null)))
.build();
}
private PendingIntent getIntent(String action) {
Intent intent = new Intent(action);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pi = PendingIntent.getActivity(getContext(), 0, intent, 0);
return pi;
}
diff --git a/src/com/android/settings/slices/SliceBroadcastReceiver.java b/src/com/android/settings/slices/SliceBroadcastReceiver.java
index 80b7519430a..47a7f5a45bd 100644
--- a/src/com/android/settings/slices/SliceBroadcastReceiver.java
+++ b/src/com/android/settings/slices/SliceBroadcastReceiver.java
@@ -54,16 +54,17 @@ public class SliceBroadcastReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
final String key = intent.getStringExtra(EXTRA_SLICE_KEY);
- final boolean isPlatformDefined = intent.getBooleanExtra(EXTRA_SLICE_PLATFORM_DEFINED,
+ final boolean isPlatformSlice = intent.getBooleanExtra(EXTRA_SLICE_PLATFORM_DEFINED,
false /* default */);
switch (action) {
case ACTION_TOGGLE_CHANGED:
- handleToggleAction(context, key, isPlatformDefined);
+ final boolean isChecked = intent.getBooleanExtra(Slice.EXTRA_TOGGLE_STATE, false);
+ handleToggleAction(context, key, isChecked, isPlatformSlice);
break;
case ACTION_SLIDER_CHANGED:
- int newPosition = intent.getIntExtra(Slice.EXTRA_RANGE_VALUE, -1);
- handleSliderAction(context, key, newPosition);
+ final int newPosition = intent.getIntExtra(Slice.EXTRA_RANGE_VALUE, -1);
+ handleSliderAction(context, key, newPosition, isPlatformSlice);
break;
case ACTION_WIFI_CHANGED:
WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
@@ -81,7 +82,8 @@ public class SliceBroadcastReceiver extends BroadcastReceiver {
}
}
- private void handleToggleAction(Context context, String key, boolean isPlatformSlice) {
+ private void handleToggleAction(Context context, String key, boolean isChecked,
+ boolean isPlatformSlice) {
if (TextUtils.isEmpty(key)) {
throw new IllegalStateException("No key passed to Intent for toggle controller");
}
@@ -95,19 +97,19 @@ public class SliceBroadcastReceiver extends BroadcastReceiver {
if (!controller.isAvailable()) {
Log.w(TAG, "Can't update " + key + " since the setting is unavailable");
updateUri(context, key, isPlatformSlice);
+ return;
}
// TODO post context.getContentResolver().notifyChanged(uri, null) in the Toggle controller
// so that it's automatically broadcast to any slice.
final TogglePreferenceController toggleController = (TogglePreferenceController) controller;
- final boolean currentValue = toggleController.isChecked();
- final boolean newValue = !currentValue;
- toggleController.setChecked(newValue);
- logSliceValueChange(context, key, newValue ? 1 : 0);
+ toggleController.setChecked(isChecked);
+ logSliceValueChange(context, key, isChecked ? 1 : 0);
updateUri(context, key, isPlatformSlice);
}
- private void handleSliderAction(Context context, String key, int newPosition) {
+ private void handleSliderAction(Context context, String key, int newPosition,
+ boolean isPlatformSlice) {
if (TextUtils.isEmpty(key)) {
throw new IllegalArgumentException(
"No key passed to Intent for slider controller. Use extra: " + EXTRA_SLICE_KEY);
@@ -123,6 +125,12 @@ public class SliceBroadcastReceiver extends BroadcastReceiver {
throw new IllegalArgumentException("Slider action passed for a non-slider key: " + key);
}
+ if (!controller.isAvailable()) {
+ Log.w(TAG, "Can't update " + key + " since the setting is unavailable");
+ updateUri(context, key, isPlatformSlice);
+ return;
+ }
+
final SliderPreferenceController sliderController = (SliderPreferenceController) controller;
final int maxSteps = sliderController.getMaxSteps();
if (newPosition < 0 || newPosition > maxSteps) {
diff --git a/src/com/android/settings/slices/SliceBuilderUtils.java b/src/com/android/settings/slices/SliceBuilderUtils.java
index a2479a2da05..cdc8d594bc3 100644
--- a/src/com/android/settings/slices/SliceBuilderUtils.java
+++ b/src/com/android/settings/slices/SliceBuilderUtils.java
@@ -16,8 +16,6 @@
package com.android.settings.slices;
-import static androidx.slice.builders.ListBuilder.ICON_IMAGE;
-
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
import static com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING;
import static com.android.settings.core.BasePreferenceController.DISABLED_FOR_USER;
@@ -31,7 +29,6 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
-import android.graphics.drawable.Icon;
import android.net.Uri;
import android.provider.SettingsSlicesContract;
import android.text.TextUtils;
@@ -63,6 +60,9 @@ public class SliceBuilderUtils {
private static final String TAG = "SliceBuilder";
+ // A Slice should not be store for longer than 60,000 milliseconds / 1 minute.
+ public static final long SLICE_TTL_MILLIS = 60000;
+
/**
* Build a Slice from {@link SliceData}.
*
@@ -113,13 +113,13 @@ public class SliceBuilderUtils {
* - key
*
* Examples of valid paths are:
- * - intent/wifi
- * - intent/bluetooth
- * - action/wifi
- * - action/accessibility/servicename
+ * - /intent/wifi
+ * - /intent/bluetooth
+ * - /action/wifi
+ * - /action/accessibility/servicename
*
* @param uri of the Slice. Follows pattern outlined in {@link SettingsSliceProvider}.
- * @return Pair whose first element {@code true} if the path is prepended with "action", and
+ * @return Pair whose first element {@code true} if the path is prepended with "intent", and
* second is a key.
*/
public static Pair getPathData(Uri uri) {
@@ -130,13 +130,13 @@ public class SliceBuilderUtils {
// Example: "/action/wifi" -> [{}, "action", "wifi"]
// "/action/longer/path" -> [{}, "action", "longer/path"]
if (split.length != 3) {
- throw new IllegalArgumentException("Uri (" + uri + ") has incomplete path: " + path);
+ return null;
}
- final boolean isInline = TextUtils.equals(SettingsSlicesContract.PATH_SETTING_ACTION,
+ final boolean isIntent = TextUtils.equals(SettingsSlicesContract.PATH_SETTING_INTENT,
split[1]);
- return new Pair<>(isInline, split[2]);
+ return new Pair<>(isIntent, split[2]);
}
/**
@@ -215,8 +215,8 @@ public class SliceBuilderUtils {
static Intent getContentIntent(Context context, SliceData sliceData) {
final Uri contentUri = new Uri.Builder().appendPath(sliceData.getKey()).build();
final Intent intent = DatabaseIndexingUtils.buildSearchResultPageIntent(context,
- sliceData.getFragmentClassName(), sliceData.getKey(), sliceData.getScreenTitle(),
- 0 /* TODO */);
+ sliceData.getFragmentClassName(), sliceData.getKey(),
+ sliceData.getScreenTitle().toString(), 0 /* TODO */);
intent.setClassName(context.getPackageName(), SubSettings.class.getName());
intent.setData(contentUri);
return intent;
@@ -225,19 +225,19 @@ public class SliceBuilderUtils {
private static Slice buildToggleSlice(Context context, SliceData sliceData,
BasePreferenceController controller) {
final PendingIntent contentIntent = getContentPendingIntent(context, sliceData);
- final Icon icon = Icon.createWithResource(context, sliceData.getIconResource());
+ final IconCompat icon = IconCompat.createWithResource(context, sliceData.getIconResource());
final CharSequence subtitleText = getSubtitleText(context, controller, sliceData);
final TogglePreferenceController toggleController =
(TogglePreferenceController) controller;
final SliceAction sliceAction = getToggleAction(context, sliceData,
toggleController.isChecked());
- return new ListBuilder(context, sliceData.getUri())
+ return new ListBuilder(context, sliceData.getUri(), SLICE_TTL_MILLIS)
.addRow(rowBuilder -> rowBuilder
.setTitle(sliceData.getTitle())
- .setTitleItem(icon, ICON_IMAGE)
.setSubtitle(subtitleText)
- .setPrimaryAction(new SliceAction(contentIntent, (IconCompat) null, null))
+ .setPrimaryAction(
+ new SliceAction(contentIntent, icon, sliceData.getTitle()))
.addEndItem(sliceAction))
.build();
}
@@ -245,29 +245,34 @@ public class SliceBuilderUtils {
private static Slice buildIntentSlice(Context context, SliceData sliceData,
BasePreferenceController controller) {
final PendingIntent contentIntent = getContentPendingIntent(context, sliceData);
- final Icon icon = Icon.createWithResource(context, sliceData.getIconResource());
+ final IconCompat icon = IconCompat.createWithResource(context, sliceData.getIconResource());
final CharSequence subtitleText = getSubtitleText(context, controller, sliceData);
- return new ListBuilder(context, sliceData.getUri())
+ return new ListBuilder(context, sliceData.getUri(), SLICE_TTL_MILLIS)
.addRow(rowBuilder -> rowBuilder
.setTitle(sliceData.getTitle())
- .setTitleItem(icon, ICON_IMAGE)
.setSubtitle(subtitleText)
- .setPrimaryAction(new SliceAction(contentIntent, (IconCompat) null, null)))
+ .setPrimaryAction(
+ new SliceAction(contentIntent, icon, sliceData.getTitle())))
.build();
}
private static Slice buildSliderSlice(Context context, SliceData sliceData,
BasePreferenceController controller) {
- final SliderPreferenceController sliderController =
- (SliderPreferenceController) controller;
+ final SliderPreferenceController sliderController = (SliderPreferenceController) controller;
final PendingIntent actionIntent = getSliderAction(context, sliceData);
- return new ListBuilder(context, sliceData.getUri())
+ final PendingIntent contentIntent = getContentPendingIntent(context, sliceData);
+ final IconCompat icon = IconCompat.createWithResource(context, sliceData.getIconResource());
+ final SliceAction primaryAction = new SliceAction(contentIntent, icon,
+ sliceData.getTitle());
+
+ return new ListBuilder(context, sliceData.getUri(), SLICE_TTL_MILLIS)
.addInputRange(builder -> builder
.setTitle(sliceData.getTitle())
.setMax(sliderController.getMaxSteps())
.setValue(sliderController.getSliderPosition())
- .setAction(actionIntent))
+ .setInputAction(actionIntent)
+ .setPrimaryAction(primaryAction))
.build();
}
@@ -311,32 +316,30 @@ public class SliceBuilderUtils {
final String title = data.getTitle();
final String summary;
final SliceAction primaryAction;
+ final IconCompat icon = IconCompat.createWithResource(context, data.getIconResource());
switch (controller.getAvailabilityStatus()) {
case DISABLED_UNSUPPORTED:
summary = context.getString(R.string.unsupported_setting_summary);
- primaryAction = new SliceAction(getSettingsIntent(context),
- (IconCompat) null /* actionIcon */,
- null /* actionTitle */);
+ primaryAction = new SliceAction(getSettingsIntent(context), icon, title);
break;
case DISABLED_FOR_USER:
summary = context.getString(R.string.disabled_for_user_setting_summary);
- primaryAction = new SliceAction(getContentPendingIntent(context, data),
- (IconCompat) null /* actionIcon */, null /* actionTitle */);
+ primaryAction = new SliceAction(getContentPendingIntent(context, data), icon,
+ title);
break;
case DISABLED_DEPENDENT_SETTING:
summary = context.getString(R.string.disabled_dependent_setting_summary);
- primaryAction = new SliceAction(getContentPendingIntent(context, data),
- (IconCompat) null /* actionIcon */, null /* actionTitle */);
+ primaryAction = new SliceAction(getContentPendingIntent(context, data), icon,
+ title);
break;
case UNAVAILABLE_UNKNOWN:
default:
summary = context.getString(R.string.unknown_unavailability_setting_summary);
- primaryAction = new SliceAction(getSettingsIntent(context),
- (IconCompat) null /* actionIcon */, null /* actionTitle */);
+ primaryAction = new SliceAction(getSettingsIntent(context), icon, title);
}
- return new ListBuilder(context, data.getUri())
+ return new ListBuilder(context, data.getUri(), SLICE_TTL_MILLIS)
.addRow(builder -> builder
.setTitle(title)
.setSubtitle(summary)
diff --git a/src/com/android/settings/slices/SliceData.java b/src/com/android/settings/slices/SliceData.java
index c02b1135699..2caf6e6be17 100644
--- a/src/com/android/settings/slices/SliceData.java
+++ b/src/com/android/settings/slices/SliceData.java
@@ -57,7 +57,7 @@ public class SliceData {
private final String mSummary;
- private final String mScreenTitle;
+ private final CharSequence mScreenTitle;
private final int mIconResource;
@@ -84,7 +84,7 @@ public class SliceData {
return mSummary;
}
- public String getScreenTitle() {
+ public CharSequence getScreenTitle() {
return mScreenTitle;
}
@@ -146,7 +146,7 @@ public class SliceData {
private String mSummary;
- private String mScreenTitle;
+ private CharSequence mScreenTitle;
private int mIconResource;
@@ -175,7 +175,7 @@ public class SliceData {
return this;
}
- public Builder setScreenTitle(String screenTitle) {
+ public Builder setScreenTitle(CharSequence screenTitle) {
mScreenTitle = screenTitle;
return this;
}
diff --git a/src/com/android/settings/slices/SliceDataConverter.java b/src/com/android/settings/slices/SliceDataConverter.java
index 7cf1994f9ed..27724bfddf5 100644
--- a/src/com/android/settings/slices/SliceDataConverter.java
+++ b/src/com/android/settings/slices/SliceDataConverter.java
@@ -23,7 +23,12 @@ import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_PLATFO
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_SUMMARY;
import static com.android.settings.core.PreferenceXmlParserUtils.METADATA_TITLE;
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.content.ComponentName;
import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.os.Bundle;
@@ -32,9 +37,14 @@ import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Xml;
+import android.view.accessibility.AccessibilityManager;
+import com.android.settings.accessibility.AccessibilitySlicePreferenceController;
import com.android.settings.core.PreferenceXmlParserUtils;
import com.android.settings.core.PreferenceXmlParserUtils.MetadataFlag;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.R;
+import com.android.settings.accessibility.AccessibilitySettings;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.search.DatabaseIndexingUtils;
@@ -46,10 +56,16 @@ import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
/**
- * Converts {@link DashboardFragment} to {@link SliceData}.
+ * Converts all Slice sources into {@link SliceData}.
+ * This includes:
+ * - All {@link DashboardFragment DashboardFragments} indexed by settings search
+ * - Accessibility services
*/
class SliceDataConverter {
@@ -101,6 +117,8 @@ class SliceDataConverter {
mSliceData.addAll(providerSliceData);
}
+ final List a11ySliceData = getAccessibilitySliceData();
+ mSliceData.addAll(a11ySliceData);
return mSliceData;
}
@@ -208,4 +226,58 @@ class SliceDataConverter {
}
return xmlSliceData;
}
+
+ private List getAccessibilitySliceData() {
+ final List sliceData = new ArrayList<>();
+
+ final String accessibilityControllerClassName =
+ AccessibilitySlicePreferenceController.class.getName();
+ final String fragmentClassName = AccessibilitySettings.class.getName();
+ final CharSequence screenTitle = mContext.getText(R.string.accessibility_settings);
+
+ final SliceData.Builder sliceDataBuilder = new SliceData.Builder()
+ .setFragmentName(fragmentClassName)
+ .setScreenTitle(screenTitle)
+ .setPreferenceControllerClassName(accessibilityControllerClassName);
+
+ final Set a11yServiceNames = new HashSet<>();
+ Collections.addAll(a11yServiceNames, mContext.getResources()
+ .getStringArray(R.array.config_settings_slices_accessibility_components));
+ final List installedServices = getAccessibilityServiceInfoList();
+ final PackageManager packageManager = mContext.getPackageManager();
+
+ for (AccessibilityServiceInfo a11yServiceInfo : installedServices) {
+ final ResolveInfo resolveInfo = a11yServiceInfo.getResolveInfo();
+ final ServiceInfo serviceInfo = resolveInfo.serviceInfo;
+ final String packageName = serviceInfo.packageName;
+ final ComponentName componentName = new ComponentName(packageName, serviceInfo.name);
+ final String flattenedName = componentName.flattenToString();
+
+ if (!a11yServiceNames.contains(flattenedName)) {
+ continue;
+ }
+
+ final String title = resolveInfo.loadLabel(packageManager).toString();
+ int iconResource = resolveInfo.getIconResource();
+ if (iconResource == 0) {
+ iconResource = R.mipmap.ic_accessibility_generic;
+ }
+
+ sliceDataBuilder.setKey(flattenedName)
+ .setTitle(title)
+ .setIcon(iconResource)
+ .setSliceType(SliceData.SliceType.SWITCH);
+
+ sliceData.add(sliceDataBuilder.build());
+ }
+
+ return sliceData;
+ }
+
+ @VisibleForTesting
+ List getAccessibilityServiceInfoList() {
+ final AccessibilityManager accessibilityManager = AccessibilityManager.getInstance(
+ mContext);
+ return accessibilityManager.getInstalledAccessibilityServiceList();
+ }
}
\ No newline at end of file
diff --git a/src/com/android/settings/slices/SlicesDatabaseAccessor.java b/src/com/android/settings/slices/SlicesDatabaseAccessor.java
index 82b3506f739..432be36b77c 100644
--- a/src/com/android/settings/slices/SlicesDatabaseAccessor.java
+++ b/src/com/android/settings/slices/SlicesDatabaseAccessor.java
@@ -29,6 +29,9 @@ import android.util.Pair;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.slices.SlicesDatabaseHelper.IndexColumns;
+import java.util.ArrayList;
+import java.util.List;
+
import androidx.slice.Slice;
/**
@@ -51,10 +54,12 @@ public class SlicesDatabaseAccessor {
// Cursor value for boolean true
private final int TRUE = 1;
- Context mContext;
+ private final Context mContext;
+ private final SlicesDatabaseHelper mHelper;
public SlicesDatabaseAccessor(Context context) {
mContext = context;
+ mHelper = SlicesDatabaseHelper.getInstance(mContext);
}
/**
@@ -76,19 +81,47 @@ public class SlicesDatabaseAccessor {
*/
public SliceData getSliceDataFromKey(String key) {
Cursor cursor = getIndexedSliceData(key);
- return buildSliceData(cursor, null /* uri */, false /* isInlineOnly */);
+ return buildSliceData(cursor, null /* uri */, false /* isIntentOnly */);
+ }
+
+ /**
+ * @return a list of keys in the Slices database matching on {@param isPlatformSlice}.
+ */
+ public List getSliceKeys(boolean isPlatformSlice) {
+ final String whereClause;
+
+ if (isPlatformSlice) {
+ whereClause = IndexColumns.PLATFORM_SLICE + " = 1";
+ } else {
+ whereClause = IndexColumns.PLATFORM_SLICE + " = 0";
+ }
+
+ final SQLiteDatabase database = mHelper.getReadableDatabase();
+ final String[] columns = new String[]{IndexColumns.KEY};
+ final List keys = new ArrayList<>();
+
+ try (final Cursor resultCursor = database.query(TABLE_SLICES_INDEX, columns, whereClause,
+ null /* selection */, null /* groupBy */, null /* having */, null /* orderBy */)) {
+ if (!resultCursor.moveToFirst()) {
+ return keys;
+ }
+
+ do {
+ keys.add(resultCursor.getString(0 /* key index */));
+ } while (resultCursor.moveToNext());
+ }
+
+ return keys;
}
private Cursor getIndexedSliceData(String path) {
verifyIndexing();
final String whereClause = buildKeyMatchWhereClause();
- final SlicesDatabaseHelper helper = SlicesDatabaseHelper.getInstance(mContext);
- final SQLiteDatabase database = helper.getReadableDatabase();
+ final SQLiteDatabase database = mHelper.getReadableDatabase();
final String[] selection = new String[]{path};
-
- Cursor resultCursor = database.query(TABLE_SLICES_INDEX, SELECT_COLUMNS_ALL, whereClause,
- selection, null /* groupBy */, null /* having */, null /* orderBy */);
+ final Cursor resultCursor = database.query(TABLE_SLICES_INDEX, SELECT_COLUMNS_ALL,
+ whereClause, selection, null /* groupBy */, null /* having */, null /* orderBy */);
int numResults = resultCursor.getCount();
@@ -111,7 +144,7 @@ public class SlicesDatabaseAccessor {
.toString();
}
- private SliceData buildSliceData(Cursor cursor, Uri uri, boolean isInlineOnly) {
+ private SliceData buildSliceData(Cursor cursor, Uri uri, boolean isIntentOnly) {
final String key = cursor.getString(cursor.getColumnIndex(IndexColumns.KEY));
final String title = cursor.getString(cursor.getColumnIndex(IndexColumns.TITLE));
final String summary = cursor.getString(cursor.getColumnIndex(IndexColumns.SUMMARY));
@@ -127,7 +160,7 @@ public class SlicesDatabaseAccessor {
int sliceType = cursor.getInt(
cursor.getColumnIndex(IndexColumns.SLICE_TYPE));
- if (!isInlineOnly) {
+ if (isIntentOnly) {
sliceType = SliceData.SliceType.INTENT;
}
diff --git a/src/com/android/settings/slices/SlicesIndexer.java b/src/com/android/settings/slices/SlicesIndexer.java
index d7de7bc27a9..e2ab40d407d 100644
--- a/src/com/android/settings/slices/SlicesIndexer.java
+++ b/src/com/android/settings/slices/SlicesIndexer.java
@@ -104,7 +104,7 @@ class SlicesIndexer implements Runnable {
values.put(IndexColumns.KEY, dataRow.getKey());
values.put(IndexColumns.TITLE, dataRow.getTitle());
values.put(IndexColumns.SUMMARY, dataRow.getSummary());
- values.put(IndexColumns.SCREENTITLE, dataRow.getScreenTitle());
+ values.put(IndexColumns.SCREENTITLE, dataRow.getScreenTitle().toString());
values.put(IndexColumns.ICON_RESOURCE, dataRow.getIconResource());
values.put(IndexColumns.FRAGMENT, dataRow.getFragmentClassName());
values.put(IndexColumns.CONTROLLER, dataRow.getPreferenceController());
diff --git a/src/com/android/settings/sound/AudioSwitchPreferenceController.java b/src/com/android/settings/sound/AudioSwitchPreferenceController.java
index 25a0518a3f2..28ad3f5f3d3 100644
--- a/src/com/android/settings/sound/AudioSwitchPreferenceController.java
+++ b/src/com/android/settings/sound/AudioSwitchPreferenceController.java
@@ -193,8 +193,12 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont
public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) {
}
+ protected boolean isStreamFromOutputDevice(int streamType, int device) {
+ return mAudioManager.getDevicesForStream(streamType) == device;
+ }
+
protected boolean isOngoingCallStatus() {
- int audioMode = mAudioManager.getMode();
+ final int audioMode = mAudioManager.getMode();
return audioMode == AudioManager.MODE_RINGTONE
|| audioMode == AudioManager.MODE_IN_CALL
|| audioMode == AudioManager.MODE_IN_COMMUNICATION;
diff --git a/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceController.java b/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceController.java
index b0b3dc503d6..2f21f1b0023 100644
--- a/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceController.java
+++ b/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceController.java
@@ -16,6 +16,9 @@
package com.android.settings.sound;
+import static android.media.AudioManager.STREAM_VOICE_CALL;
+import static android.media.AudioSystem.DEVICE_OUT_USB_HEADSET;
+
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.support.v7.preference.Preference;
@@ -76,7 +79,7 @@ public class HandsFreeProfileOutputPreferenceController extends
// Setup devices entries, select active connected device
setupPreferenceEntries(mediaOutputs, mediaValues, activeDevice);
- if (mAudioManager.isWiredHeadsetOn() && !mAudioManager.isBluetoothScoOn()) {
+ if (isStreamFromOutputDevice(STREAM_VOICE_CALL, DEVICE_OUT_USB_HEADSET)) {
// If wired headset is plugged in and active, select to default device.
mSelectedIndex = getDefaultDeviceIndex();
}
diff --git a/src/com/android/settings/sound/MediaOutputPreferenceController.java b/src/com/android/settings/sound/MediaOutputPreferenceController.java
index 2e52f77b066..df07dc5fa68 100644
--- a/src/com/android/settings/sound/MediaOutputPreferenceController.java
+++ b/src/com/android/settings/sound/MediaOutputPreferenceController.java
@@ -16,12 +16,13 @@
package com.android.settings.sound;
-import static android.media.MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY;
+import static android.media.AudioManager.STREAM_MUSIC;
+import static android.media.AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
+import static android.media.AudioSystem.DEVICE_OUT_USB_HEADSET;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.media.AudioManager;
-import android.media.MediaRouter;
import android.support.v7.preference.Preference;
import com.android.internal.util.ArrayUtils;
@@ -49,8 +50,7 @@ public class MediaOutputPreferenceController extends AudioSwitchPreferenceContro
return;
}
- if (mAudioManager.isMusicActiveRemotely() || isCastDevice(mMediaRouter)) {
- // TODO(76455906): Workaround for cast mode, need a solid way to identify cast mode.
+ if (isStreamFromOutputDevice(STREAM_MUSIC, DEVICE_OUT_REMOTE_SUBMIX)) {
// In cast mode, disable switch entry.
preference.setEnabled(false);
preference.setSummary(mContext.getText(R.string.media_output_summary_unavailable));
@@ -91,7 +91,7 @@ public class MediaOutputPreferenceController extends AudioSwitchPreferenceContro
// Setup devices entries, select active connected device
setupPreferenceEntries(mediaOutputs, mediaValues, activeDevice);
- if (mAudioManager.isWiredHeadsetOn() && !mAudioManager.isBluetoothA2dpOn()) {
+ if (isStreamFromOutputDevice(STREAM_MUSIC, DEVICE_OUT_USB_HEADSET)) {
// If wired headset is plugged in and active, select to default device.
mSelectedIndex = getDefaultDeviceIndex();
}
@@ -106,11 +106,4 @@ public class MediaOutputPreferenceController extends AudioSwitchPreferenceContro
mProfileManager.getA2dpProfile().setActiveDevice(device);
}
}
-
- private static boolean isCastDevice(MediaRouter mediaRouter) {
- final MediaRouter.RouteInfo selected = mediaRouter.getSelectedRoute(
- ROUTE_TYPE_REMOTE_DISPLAY);
- return selected != null && selected.getPresentationDisplay() != null
- && selected.getPresentationDisplay().isValid();
- }
}
diff --git a/src/com/android/settings/wallpaper/WallpaperTypePreferenceController.java b/src/com/android/settings/wallpaper/WallpaperTypePreferenceController.java
new file mode 100644
index 00000000000..5b8d7239877
--- /dev/null
+++ b/src/com/android/settings/wallpaper/WallpaperTypePreferenceController.java
@@ -0,0 +1,122 @@
+/*
+ * 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.wallpaper;
+
+import android.app.Fragment;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.text.TextUtils;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class WallpaperTypePreferenceController extends BasePreferenceController
+ implements LifecycleObserver, OnStart {
+ private Fragment mParentFragment;
+ private PreferenceScreen mScreen;
+
+ public WallpaperTypePreferenceController(Context context, String key) {
+ super(context, key);
+ }
+
+ public void setParentFragment(Fragment parentFragment) {
+ mParentFragment = parentFragment;
+ }
+
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mScreen = screen;
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return AVAILABLE;
+ }
+
+ @Override
+ public boolean handlePreferenceTreeClick(Preference preference) {
+ if (preference.getIntent() == null) {
+ return super.handlePreferenceTreeClick(preference);
+ }
+ mParentFragment.startActivity(preference.getIntent());
+ mParentFragment.getActivity().finish();
+ return true;
+ }
+
+ @Override
+ public void onStart() {
+ populateWallpaperTypes();
+ }
+
+ private void populateWallpaperTypes() {
+ // Search for activities that satisfy the ACTION_SET_WALLPAPER action
+ final Intent intent = new Intent(Intent.ACTION_SET_WALLPAPER);
+ final PackageManager pm = mContext.getPackageManager();
+ final List rList = pm.queryIntentActivities(intent,
+ PackageManager.MATCH_DEFAULT_ONLY);
+
+ removeUselessExistingPreference(rList);
+ mScreen.setOrderingAsAdded(false);
+ // Add Preference items for each of the matching activities
+ for (ResolveInfo info : rList) {
+ final String packageName = info.activityInfo.packageName;
+ Preference pref = mScreen.findPreference(packageName);
+ if (pref == null) {
+ pref = new Preference(mScreen.getContext());
+ }
+ final Intent prefIntent = new Intent(intent).addFlags(
+ Intent.FLAG_ACTIVITY_FORWARD_RESULT);
+ prefIntent.setComponent(new ComponentName(packageName, info.activityInfo.name));
+ pref.setIntent(prefIntent);
+ pref.setKey(packageName);
+ CharSequence label = info.loadLabel(pm);
+ if (label == null) {
+ label = packageName;
+ }
+ pref.setTitle(label);
+ pref.setIcon(info.loadIcon(pm));
+ mScreen.addPreference(pref);
+ }
+ }
+
+ private void removeUselessExistingPreference(List rList) {
+ final int count = mScreen.getPreferenceCount();
+ if (count <= 0) {
+ return;
+ }
+ for (int i = count - 1; i >= 0; i--) {
+ final Preference pref = mScreen.getPreference(i);
+ final List result = rList.stream().filter(
+ rInfo -> TextUtils.equals(pref.getKey(),
+ rInfo.activityInfo.packageName)).collect(Collectors.toList());
+ if (result.isEmpty()) {
+ mScreen.removePreference(pref);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/com/android/settings/wallpaper/WallpaperTypeSettings.java b/src/com/android/settings/wallpaper/WallpaperTypeSettings.java
index 9d565e4aa7b..ca42ddaef48 100644
--- a/src/com/android/settings/wallpaper/WallpaperTypeSettings.java
+++ b/src/com/android/settings/wallpaper/WallpaperTypeSettings.java
@@ -16,20 +16,15 @@
package com.android.settings.wallpaper;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
-import android.os.Bundle;
-import android.support.v7.preference.Preference;
-import android.support.v7.preference.PreferenceScreen;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
-import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
-import com.android.settings.search.Indexable;
import com.android.settings.search.SearchIndexableRaw;
import com.android.settingslib.search.SearchIndexable;
@@ -37,7 +32,8 @@ import java.util.ArrayList;
import java.util.List;
@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
-public class WallpaperTypeSettings extends SettingsPreferenceFragment implements Indexable {
+public class WallpaperTypeSettings extends DashboardFragment {
+ private static final String TAG = "WallpaperTypeSettings";
@Override
public int getMetricsCategory() {
@@ -50,52 +46,26 @@ public class WallpaperTypeSettings extends SettingsPreferenceFragment implements
}
@Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- addPreferencesFromResource(R.xml.wallpaper_settings);
- populateWallpaperTypes();
- }
-
- private void populateWallpaperTypes() {
- // Search for activities that satisfy the ACTION_SET_WALLPAPER action
- final Intent intent = new Intent(Intent.ACTION_SET_WALLPAPER);
- final PackageManager pm = getPackageManager();
- final List rList = pm.queryIntentActivities(intent,
- PackageManager.MATCH_DEFAULT_ONLY);
-
- final PreferenceScreen parent = getPreferenceScreen();
- parent.setOrderingAsAdded(false);
- // Add Preference items for each of the matching activities
- for (ResolveInfo info : rList) {
- Preference pref = new Preference(getPrefContext());
- Intent prefIntent = new Intent(intent).addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
- prefIntent.setComponent(new ComponentName(
- info.activityInfo.packageName, info.activityInfo.name));
- pref.setIntent(prefIntent);
- CharSequence label = info.loadLabel(pm);
- if (label == null) label = info.activityInfo.packageName;
- pref.setTitle(label);
- pref.setIcon(info.loadIcon(pm));
- parent.addPreference(pref);
- }
+ protected String getLogTag() {
+ return TAG;
}
@Override
- public boolean onPreferenceTreeClick(Preference preference) {
- if (preference.getIntent() == null) {
- return super.onPreferenceTreeClick(preference);
- }
- startActivity(preference.getIntent());
- finish();
- return true;
+ protected int getPreferenceScreenResId() {
+ return R.xml.wallpaper_settings;
+ }
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ use(WallpaperTypePreferenceController.class).setParentFragment(this);
}
public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
public List getRawDataToIndex(Context context, boolean enabled) {
- final List result = new ArrayList();
+ final List result = new ArrayList<>();
final Intent intent = new Intent(Intent.ACTION_SET_WALLPAPER);
final PackageManager pm = context.getPackageManager();
@@ -110,9 +80,10 @@ public class WallpaperTypeSettings extends SettingsPreferenceFragment implements
continue;
}
CharSequence label = info.loadLabel(pm);
- if (label == null) label = info.activityInfo.packageName;
-
- SearchIndexableRaw data = new SearchIndexableRaw(context);
+ if (label == null) {
+ label = info.activityInfo.packageName;
+ }
+ final SearchIndexableRaw data = new SearchIndexableRaw(context);
data.title = label.toString();
data.key = "wallpaper_type_settings";
data.screenTitle = context.getResources().getString(
diff --git a/src/com/android/settings/widget/DisabledCheckBoxPreference.java b/src/com/android/settings/widget/DisabledCheckBoxPreference.java
index 482cff337ba..e441e213308 100644
--- a/src/com/android/settings/widget/DisabledCheckBoxPreference.java
+++ b/src/com/android/settings/widget/DisabledCheckBoxPreference.java
@@ -17,46 +17,85 @@
package com.android.settings.widget;
import android.content.Context;
+import android.content.res.TypedArray;
+import android.support.v7.preference.CheckBoxPreference;
+import android.support.v7.preference.PreferenceViewHolder;
import android.util.AttributeSet;
import android.view.View;
-import android.support.v7.preference.CheckBoxPreference;
-import android.support.v7.preference.PreferenceViewHolder;
-
/**
- * A CheckboxPreference with a disabled checkbox. Differs from CheckboxPreference.setDisabled()
- * in that the text is not dimmed.
+ * A CheckboxPreference that can disable its checkbox separate from its text.
+ * Differs from CheckboxPreference.setDisabled() in that the text is not dimmed.
*/
public class DisabledCheckBoxPreference extends CheckBoxPreference {
+ private PreferenceViewHolder mViewHolder;
+ private View mCheckBox;
+ private boolean mEnabledCheckBox;
- public DisabledCheckBoxPreference(Context context, AttributeSet attrs,
- int defStyleAttr, int defStyleRes) {
+ public DisabledCheckBoxPreference(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
+ setupDisabledCheckBoxPreference(context, attrs, defStyleAttr, defStyleRes);
}
public DisabledCheckBoxPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
+ setupDisabledCheckBoxPreference(context, attrs, defStyleAttr, 0);
}
public DisabledCheckBoxPreference(Context context, AttributeSet attrs) {
super(context, attrs);
+ setupDisabledCheckBoxPreference(context, attrs, 0, 0);
}
public DisabledCheckBoxPreference(Context context) {
super(context);
+ setupDisabledCheckBoxPreference(context, null, 0, 0);
+ }
+
+ private void setupDisabledCheckBoxPreference(Context context, AttributeSet attrs,
+ int defStyleAttr, int defStyleRes) {
+ final TypedArray a = context.obtainStyledAttributes(
+ attrs, com.android.internal.R.styleable.Preference, defStyleAttr, defStyleRes);
+ for (int i = a.getIndexCount() - 1; i >= 0; i--) {
+ int attr = a.getIndex(i);
+ switch (attr) {
+ case com.android.internal.R.styleable.Preference_enabled:
+ mEnabledCheckBox = a.getBoolean(attr, true);
+ break;
+ }
+ }
+ a.recycle();
+
+ // Always tell super class this preference is enabled.
+ // We manually enable/disable checkbox using enableCheckBox.
+ super.setEnabled(true);
+ enableCheckbox(mEnabledCheckBox);
+ }
+
+ public void enableCheckbox(boolean enabled) {
+ mEnabledCheckBox = enabled;
+ if (mViewHolder != null && mCheckBox != null) {
+ mCheckBox.setEnabled(mEnabledCheckBox);
+ mViewHolder.itemView.setEnabled(mEnabledCheckBox);
+ }
}
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
+ mViewHolder = holder;
+ mCheckBox = holder.findViewById(android.R.id.checkbox);
- View view = holder.findViewById(android.R.id.checkbox);
- view.setEnabled(false);
- holder.itemView.setEnabled(false);
+ enableCheckbox(mEnabledCheckBox);
}
@Override
protected void performClick(View view) {
- // Do nothing
+ // only perform clicks if the checkbox is enabled
+ if (mEnabledCheckBox) {
+ super.performClick(view);
+ }
}
+
}
diff --git a/src/com/android/settings/widget/EntityHeaderController.java b/src/com/android/settings/widget/EntityHeaderController.java
index bf59dc9b269..f9d16cde101 100644
--- a/src/com/android/settings/widget/EntityHeaderController.java
+++ b/src/com/android/settings/widget/EntityHeaderController.java
@@ -61,13 +61,13 @@ public class EntityHeaderController {
@IntDef({ActionType.ACTION_NONE,
ActionType.ACTION_APP_PREFERENCE,
ActionType.ACTION_NOTIF_PREFERENCE,
- ActionType.ACTION_DND_RULE_PREFERENCE,})
+ ActionType.ACTION_EDIT_PREFERENCE,})
@Retention(RetentionPolicy.SOURCE)
public @interface ActionType {
int ACTION_NONE = 0;
int ACTION_APP_PREFERENCE = 1;
int ACTION_NOTIF_PREFERENCE = 2;
- int ACTION_DND_RULE_PREFERENCE = 3;
+ int ACTION_EDIT_PREFERENCE = 3;
}
public static final String PREF_KEY_APP_HEADER = "pref_app_header";
@@ -100,7 +100,7 @@ public class EntityHeaderController {
private boolean mIsInstantApp;
- private View.OnClickListener mEditRuleNameOnClickListener;
+ private View.OnClickListener mEditOnClickListener;
/**
* Creates a new instance of the controller.
@@ -227,8 +227,8 @@ public class EntityHeaderController {
return this;
}
- public EntityHeaderController setEditZenRuleNameListener(View.OnClickListener listener) {
- this.mEditRuleNameOnClickListener = listener;
+ public EntityHeaderController setEditListener(View.OnClickListener listener) {
+ this.mEditOnClickListener = listener;
return this;
}
@@ -345,13 +345,13 @@ public class EntityHeaderController {
return;
}
switch (action) {
- case ActionType.ACTION_DND_RULE_PREFERENCE: {
- if (mEditRuleNameOnClickListener == null) {
+ case ActionType.ACTION_EDIT_PREFERENCE: {
+ if (mEditOnClickListener == null) {
button.setVisibility(View.GONE);
} else {
button.setImageResource(R.drawable.ic_mode_edit);
button.setVisibility(View.VISIBLE);
- button.setOnClickListener(mEditRuleNameOnClickListener);
+ button.setOnClickListener(mEditOnClickListener);
}
return;
}
diff --git a/src/com/android/settings/widget/HotspotApBandSelectionPreference.java b/src/com/android/settings/widget/HotspotApBandSelectionPreference.java
new file mode 100644
index 00000000000..4f127eb9193
--- /dev/null
+++ b/src/com/android/settings/widget/HotspotApBandSelectionPreference.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.widget;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.net.wifi.WifiConfiguration;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.support.annotation.VisibleForTesting;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
+import android.widget.LinearLayout;
+
+import com.android.settings.R;
+import com.android.settingslib.CustomDialogPreference;
+
+import java.util.ArrayList;
+
+public class HotspotApBandSelectionPreference extends CustomDialogPreference implements
+ CompoundButton.OnCheckedChangeListener, DialogInterface.OnShowListener {
+ private static final int UNSET = Integer.MIN_VALUE;
+
+ @VisibleForTesting
+ static final String KEY_CHECKED_BANDS = "checked_bands";
+ @VisibleForTesting
+ static final String KEY_HOTSPOT_SUPER_STATE = "hotspot_super_state";
+
+ @VisibleForTesting
+ CheckBox mBox2G;
+ @VisibleForTesting
+ CheckBox mBox5G;
+ @VisibleForTesting
+ ArrayList mRestoredBands;
+ @VisibleForTesting
+ boolean mShouldRestore;
+
+ private String[] mBandEntries;
+ private int mExistingConfigValue = UNSET;
+
+ public HotspotApBandSelectionPreference(Context context) {
+ super(context);
+ }
+
+ public HotspotApBandSelectionPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public HotspotApBandSelectionPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ public HotspotApBandSelectionPreference(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Parcelable state) {
+ SavedState myState = (SavedState) state;
+
+ super.onRestoreInstanceState(myState.getSuperState());
+
+ mShouldRestore = myState.shouldRestore;
+ if (mShouldRestore) {
+ mRestoredBands = new ArrayList<>();
+ if (myState.enabled2G) {
+ mRestoredBands.add(WifiConfiguration.AP_BAND_2GHZ);
+ }
+ if (myState.enabled5G) {
+ mRestoredBands.add(WifiConfiguration.AP_BAND_5GHZ);
+ }
+ } else {
+ mRestoredBands = null;
+ }
+ updatePositiveButton();
+ }
+
+ @Override
+ protected void onBindDialogView(View view) {
+ super.onBindDialogView(view);
+ final Context context = getContext();
+
+ // Register so we can adjust the buttons if needed once the dialog is available.
+ setOnShowListener(this);
+
+ mBandEntries = context.getResources().getStringArray(R.array.wifi_ap_band_config_full);
+ // add a checkbox for every band entry.
+ addApBandViews((LinearLayout) view);
+ // try to update the button just in case we already missed the onShow call.
+ updatePositiveButton();
+ // clear any saved state so it doesn't leak across multiple rotations/dialog closings
+ mRestoredBands = null;
+ mShouldRestore = false;
+ }
+
+ @Override
+ protected Parcelable onSaveInstanceState() {
+ final Parcelable superState = super.onSaveInstanceState();
+
+ SavedState myState = new SavedState(superState);
+ myState.shouldRestore = getDialog() != null;
+ myState.enabled2G = mBox2G.isChecked();
+ myState.enabled5G = mBox5G.isChecked();
+ return myState;
+ }
+
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ if (!(buttonView instanceof CheckBox)) {
+ return;
+ }
+ updatePositiveButton();
+ }
+
+ @Override
+ protected void onClick(DialogInterface dialog, int which) {
+ // we only want to persist our enabled bands if apply is clicked
+ if (which == DialogInterface.BUTTON_POSITIVE) {
+ if (mBox2G.isChecked() || mBox5G.isChecked()) {
+ int wifiBand = getWifiBand();
+ mExistingConfigValue = wifiBand;
+ callChangeListener(wifiBand);
+ }
+ }
+ }
+
+ /**
+ * Used to set the band selection for the preference if one already exists
+ * @param band the band to set it to from {@link WifiConfiguration}
+ */
+ public void setExistingConfigValue(int band) {
+ mExistingConfigValue = band;
+ }
+
+ private void addApBandViews(LinearLayout view) {
+ mBox2G = view.findViewById(R.id.box_2g);
+ mBox2G.setText(mBandEntries[WifiConfiguration.AP_BAND_2GHZ]);
+ mBox2G.setChecked(restoreBandIfNeeded(WifiConfiguration.AP_BAND_2GHZ));
+ mBox2G.setOnCheckedChangeListener(this);
+
+ mBox5G = view.findViewById(R.id.box_5g);
+ mBox5G.setText(mBandEntries[WifiConfiguration.AP_BAND_5GHZ]);
+ mBox5G.setChecked(restoreBandIfNeeded(WifiConfiguration.AP_BAND_5GHZ));
+ mBox5G.setOnCheckedChangeListener(this);
+ }
+
+ private boolean restoreBandIfNeeded(int band) {
+ // Only use the provided config if we aren't restoring, restore if state available
+ return (isBandPreviouslySelected(band) && !mShouldRestore)
+ || (mShouldRestore && mRestoredBands.contains(band));
+ }
+
+ private void updatePositiveButton() {
+ AlertDialog dialog = (AlertDialog) getDialog();
+ Button button = dialog == null ? null : dialog.getButton(DialogInterface.BUTTON_POSITIVE);
+ if (button != null && mBox5G != null && mBox2G != null) {
+ button.setEnabled(mBox2G.isChecked() || mBox5G.isChecked());
+ }
+ }
+
+ @VisibleForTesting
+ int getWifiBand() {
+ final boolean checked_2g = mBox2G.isChecked();
+ final boolean checked_5g = mBox5G.isChecked();
+ if (checked_2g && checked_5g) {
+ return WifiConfiguration.AP_BAND_ANY;
+ } else if (checked_2g && !checked_5g) {
+ return WifiConfiguration.AP_BAND_2GHZ;
+ } else if (checked_5g && !checked_2g) {
+ return WifiConfiguration.AP_BAND_5GHZ;
+ } else {
+ throw new IllegalStateException("Wifi Config only supports selecting one or all bands");
+ }
+ }
+
+ private boolean isBandPreviouslySelected(int bandIndex) {
+ switch(mExistingConfigValue) {
+ case WifiConfiguration.AP_BAND_ANY:
+ return true;
+ case WifiConfiguration.AP_BAND_2GHZ:
+ return bandIndex == 0;
+ case WifiConfiguration.AP_BAND_5GHZ:
+ return bandIndex == 1;
+ case UNSET:
+ default:
+ return false;
+ }
+ }
+
+ @Override
+ public void onShow(DialogInterface dialog) {
+ updatePositiveButton();
+ }
+
+ private static class SavedState extends BaseSavedState {
+ boolean shouldRestore;
+ boolean enabled2G;
+ boolean enabled5G;
+
+ public SavedState(Parcelable source) {
+ super(source);
+ }
+
+ private SavedState(Parcel in) {
+ super(in);
+ shouldRestore = in.readByte() == 1;
+ enabled2G = in.readByte() == 1;
+ enabled5G = in.readByte() == 1;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeByte((byte) (shouldRestore ? 1 : 0));
+ dest.writeByte((byte) (enabled2G ? 1: 0));
+ dest.writeByte((byte) (enabled5G ? 1 : 0));
+ }
+
+ @Override
+ public String toString() {
+ return "HotspotApBandSelectionPreference.SavedState{"
+ + Integer.toHexString(System.identityHashCode(this))
+ + " shouldRestore=" + shouldRestore
+ + " enabled2G=" + enabled2G
+ + " enabled5G=" + enabled5G + "}";
+ }
+
+ public static final Parcelable.Creator CREATOR
+ = new Parcelable.Creator() {
+ public SavedState createFromParcel(Parcel in) {
+ return new SavedState(in);
+ }
+
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+ }
+}
diff --git a/src/com/android/settings/widget/ValidatedEditTextPreference.java b/src/com/android/settings/widget/ValidatedEditTextPreference.java
index a5bab1cd980..707da000f14 100644
--- a/src/com/android/settings/widget/ValidatedEditTextPreference.java
+++ b/src/com/android/settings/widget/ValidatedEditTextPreference.java
@@ -74,7 +74,7 @@ public class ValidatedEditTextPreference extends CustomEditTextPreference {
editText.removeTextChangedListener(mTextWatcher);
if (mIsPassword) {
editText.setInputType(
- InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
+ InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
editText.setMaxLines(1);
}
editText.addTextChangedListener(mTextWatcher);
diff --git a/src/com/android/settings/wifi/WifiSettings.java b/src/com/android/settings/wifi/WifiSettings.java
index c5f0d24315e..e2a7f25f1b9 100644
--- a/src/com/android/settings/wifi/WifiSettings.java
+++ b/src/com/android/settings/wifi/WifiSettings.java
@@ -914,7 +914,7 @@ public class WifiSettings extends RestrictedSettingsFragment
private void launchNetworkDetailsFragment(ConnectedAccessPointPreference pref) {
new SubSettingLauncher(getContext())
- .setTitle(getContext().getString(R.string.pref_title_network_details))
+ .setTitle(R.string.pref_title_network_details)
.setDestination(WifiNetworkDetailsFragment.class.getName())
.setArguments(pref.getExtras())
.setSourceMetricsCategory(getMetricsCategory())
diff --git a/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceController.java b/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceController.java
index 4c47a0d02a3..b107777f67f 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceController.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceController.java
@@ -18,31 +18,34 @@ package com.android.settings.wifi.tether;
import static android.net.wifi.WifiConfiguration.AP_BAND_2GHZ;
import static android.net.wifi.WifiConfiguration.AP_BAND_5GHZ;
-import static android.net.wifi.WifiConfiguration.AP_BAND_ANY;
import android.content.Context;
+import android.content.res.Resources;
+import android.icu.text.ListFormatter;
import android.net.wifi.WifiConfiguration;
-import android.support.v7.preference.ListPreference;
import android.support.v7.preference.Preference;
import android.util.Log;
import com.android.settings.R;
+import com.android.settings.widget.HotspotApBandSelectionPreference;
public class WifiTetherApBandPreferenceController extends WifiTetherBasePreferenceController {
private static final String TAG = "WifiTetherApBandPref";
private static final String PREF_KEY = "wifi_tether_network_ap_band";
- private static final String[] BAND_VALUES =
- {String.valueOf(AP_BAND_ANY), String.valueOf(AP_BAND_2GHZ),
- String.valueOf(AP_BAND_5GHZ)};
+ public static final String[] BAND_VALUES =
+ {String.valueOf(AP_BAND_2GHZ), String.valueOf(AP_BAND_5GHZ)};
private final String[] mBandEntries;
+ private final String[] mBandSummaries;
private int mBandIndex;
public WifiTetherApBandPreferenceController(Context context,
OnTetherConfigUpdateListener listener) {
super(context, listener);
- mBandEntries = mContext.getResources().getStringArray(R.array.wifi_ap_band_config_full);
+ Resources res = mContext.getResources();
+ mBandEntries = res.getStringArray(R.array.wifi_ap_band_config_full);
+ mBandSummaries = res.getStringArray(R.array.wifi_ap_band_summary_full);
}
@Override
@@ -60,18 +63,25 @@ public class WifiTetherApBandPreferenceController extends WifiTetherBasePreferen
mBandIndex = config.apBand;
Log.d(TAG, "5Ghz not supported, updating band index to " + mBandIndex);
}
- ListPreference preference = (ListPreference) mPreference;
+ HotspotApBandSelectionPreference preference =
+ (HotspotApBandSelectionPreference) mPreference;
+
if (!is5GhzBandSupported()) {
preference.setEnabled(false);
preference.setSummary(R.string.wifi_ap_choose_2G);
} else {
- preference.setEntries(mBandEntries);
- preference.setEntryValues(BAND_VALUES);
- preference.setSummary(mBandEntries[mBandIndex + 1]);
- preference.setValue(String.valueOf(mBandIndex));
+ preference.setExistingConfigValue(config.apBand);
+ preference.setSummary(getConfigSummary());
}
}
+ String getConfigSummary() {
+ if (mBandIndex == WifiConfiguration.AP_BAND_ANY) {
+ return ListFormatter.getInstance().format((Object[]) mBandSummaries);
+ }
+ return mBandSummaries[mBandIndex];
+ }
+
@Override
public String getPreferenceKey() {
return PREF_KEY;
@@ -79,9 +89,9 @@ public class WifiTetherApBandPreferenceController extends WifiTetherBasePreferen
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
- mBandIndex = Integer.parseInt((String) newValue);
+ mBandIndex = (Integer) newValue;
Log.d(TAG, "Band preference changed, updating band index to " + mBandIndex);
- preference.setSummary(mBandEntries[mBandIndex + 1]);
+ preference.setSummary(getConfigSummary());
mListener.onTetherConfigUpdated();
return true;
}
diff --git a/src/com/android/settings/wifi/tether/WifiTetherPasswordPreferenceController.java b/src/com/android/settings/wifi/tether/WifiTetherPasswordPreferenceController.java
index b38558c1aeb..5ba0583b6ab 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherPasswordPreferenceController.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherPasswordPreferenceController.java
@@ -55,6 +55,7 @@ public class WifiTetherPasswordPreferenceController extends WifiTetherBasePrefer
mPassword = generateRandomPassword();
}
((ValidatedEditTextPreference) mPreference).setValidator(this);
+ ((ValidatedEditTextPreference) mPreference).setIsPassword(true);
((ValidatedEditTextPreference) mPreference).setIsSummaryPassword(true);
updatePasswordDisplay((EditTextPreference) mPreference);
}
diff --git a/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java b/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java
index ab08fdb6299..bf203e61f05 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherSwitchBarController.java
@@ -36,15 +36,17 @@ import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
public class WifiTetherSwitchBarController implements SwitchWidgetController.OnSwitchChangeListener,
- LifecycleObserver, OnStart, OnStop {
+ LifecycleObserver, OnStart, OnStop, DataSaverBackend.Listener {
private static final IntentFilter WIFI_INTENT_FILTER;
private final Context mContext;
private final SwitchWidgetController mSwitchBar;
private final ConnectivityManager mConnectivityManager;
- private final DataSaverBackend mDataSaverBackend;
private final WifiManager mWifiManager;
+
+ @VisibleForTesting
+ final DataSaverBackend mDataSaverBackend;
@VisibleForTesting
final ConnectivityManager.OnStartTetheringCallback mOnStartTetheringCallback =
new ConnectivityManager.OnStartTetheringCallback() {
@@ -75,12 +77,14 @@ public class WifiTetherSwitchBarController implements SwitchWidgetController.OnS
@Override
public void onStart() {
+ mDataSaverBackend.addListener(this);
mSwitchBar.startListening();
mContext.registerReceiver(mReceiver, WIFI_INTENT_FILTER);
}
@Override
public void onStop() {
+ mDataSaverBackend.remListener(this);
mSwitchBar.stopListening();
mContext.unregisterReceiver(mReceiver);
}
@@ -157,4 +161,19 @@ public class WifiTetherSwitchBarController implements SwitchWidgetController.OnS
mSwitchBar.setEnabled(false);
}
}
+
+ @Override
+ public void onDataSaverChanged(boolean isDataSaving) {
+ updateWifiSwitch();
+ }
+
+ @Override
+ public void onWhitelistStatusChanged(int uid, boolean isWhitelisted) {
+ // we don't care, since we just want to read the value
+ }
+
+ @Override
+ public void onBlacklistStatusChanged(int uid, boolean isBlacklisted) {
+ // we don't care, since we just want to read the value
+ }
}
diff --git a/tests/robotests/assets/grandfather_not_implementing_index_provider b/tests/robotests/assets/grandfather_not_implementing_index_provider
index 4c9bf60eaf4..e6744ded37d 100644
--- a/tests/robotests/assets/grandfather_not_implementing_index_provider
+++ b/tests/robotests/assets/grandfather_not_implementing_index_provider
@@ -9,6 +9,7 @@ com.android.settings.fuelgauge.AdvancedPowerUsageDetail
com.android.settings.development.featureflags.FeatureFlagsDashboard
com.android.settings.development.qstile.DevelopmentTileConfigFragment
com.android.settings.deviceinfo.StorageProfileFragment
+com.android.settings.inputmethod.UserDictionaryList
com.android.settings.notification.ChannelNotificationSettings
com.android.settings.notification.ChannelGroupNotificationSettings
com.android.settings.notification.AppNotificationSettings
@@ -19,6 +20,7 @@ com.android.settings.enterprise.ApplicationListFragment$AdminGrantedPermissionLo
com.android.settings.enterprise.ApplicationListFragment$AdminGrantedPermissionMicrophone
com.android.settings.enterprise.ApplicationListFragment$EnterpriseInstalledPackages
com.android.settings.enterprise.EnterpriseSetDefaultAppsListFragment
+com.android.settings.inputmethod.KeyboardLayoutPickerFragment
com.android.settings.wifi.tether.WifiTetherSettings
com.android.settings.wifi.SavedAccessPointsWifiSettings
com.android.settings.notification.ZenModeEventRuleSettings
diff --git a/tests/robotests/assets/grandfather_not_implementing_indexable b/tests/robotests/assets/grandfather_not_implementing_indexable
index 918cb4c788d..9e8952e92de 100644
--- a/tests/robotests/assets/grandfather_not_implementing_indexable
+++ b/tests/robotests/assets/grandfather_not_implementing_indexable
@@ -1,7 +1,5 @@
com.android.settings.accessibility.ToggleScreenMagnificationPreferenceFragment
-com.android.settings.deviceinfo.PrivateVolumeForget
com.android.settings.inputmethod.SpellCheckersSettings
-com.android.settings.inputmethod.KeyboardLayoutPickerFragment
com.android.settings.fuelgauge.InactiveApps
com.android.settings.accessibility.CaptionPropertiesFragment
com.android.settings.accessibility.AccessibilitySettingsForSetupWizard
@@ -12,7 +10,6 @@ com.android.settings.fingerprint.FingerprintSettings$FingerprintSettingsFragment
com.android.settings.applications.ProcessStatsDetail
com.android.settings.wifi.WifiInfo
com.android.settings.applications.VrListenerSettings
-com.android.settings.inputmethod.UserDictionaryList
com.android.settings.datausage.DataSaverSummary
com.android.settings.datausage.AppDataUsage
com.android.settings.accessibility.FontSizePreferenceFragmentForSetupWizard
@@ -45,7 +42,6 @@ com.android.settings.accessibility.ToggleAccessibilityServicePreferenceFragment
com.android.settings.print.PrintServiceSettingsFragment
com.android.settings.deviceinfo.PrivateVolumeSettings
com.android.settings.users.AppRestrictionsFragment
-com.android.settings.deviceinfo.PrivateVolumeUnmount
com.android.settings.notification.ZenAccessSettings
com.android.settings.accessibility.ToggleFontSizePreferenceFragment
com.android.settings.applications.PremiumSmsAccess
@@ -58,7 +54,6 @@ com.android.settings.applications.appinfo.ExternalSourcesDetails
com.android.settings.applications.appinfo.PictureInPictureSettings
com.android.settings.applications.appinfo.PictureInPictureDetails
com.android.settings.network.ApnSettings
-com.android.settings.PrivacySettings
com.android.settings.wifi.calling.WifiCallingSettingsForSub
com.android.settings.password.SetupChooseLockGeneric$SetupChooseLockGenericFragment
com.android.settings.SetupRedactionInterstitial$SetupRedactionInterstitialFragment
diff --git a/tests/robotests/assets/grandfather_slice_controller_not_in_xml b/tests/robotests/assets/grandfather_slice_controller_not_in_xml
index 5a0999739df..d2274e65faf 100644
--- a/tests/robotests/assets/grandfather_slice_controller_not_in_xml
+++ b/tests/robotests/assets/grandfather_slice_controller_not_in_xml
@@ -1,2 +1,4 @@
com.android.settings.testutils.FakeToggleController
-com.android.settings.testutils.FakeSliderController
\ No newline at end of file
+com.android.settings.testutils.FakeSliderController
+com.android.settings.core.TogglePreferenceControllerTest$FakeToggle
+com.android.settings.accessibility.AccessibilitySlicePreferenceController
diff --git a/tests/robotests/res/values-mcc999/config.xml b/tests/robotests/res/values-mcc999/config.xml
index 39620d8e0a5..cecc9c59c59 100644
--- a/tests/robotests/res/values-mcc999/config.xml
+++ b/tests/robotests/res/values-mcc999/config.xml
@@ -62,4 +62,9 @@
false
false
true
+
+
+
+ - fake_package/fake_service
+
diff --git a/tests/robotests/src/com/android/settings/LegalSettingsTest.java b/tests/robotests/src/com/android/settings/LegalSettingsTest.java
index af0b757a182..28eac07704d 100644
--- a/tests/robotests/src/com/android/settings/LegalSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/LegalSettingsTest.java
@@ -16,7 +16,6 @@
package com.android.settings;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.spy;
import android.content.Context;
@@ -28,57 +27,25 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
-import org.robolectric.annotation.Config;
import java.util.List;
@RunWith(SettingsRobolectricTestRunner.class)
public class LegalSettingsTest {
- private Context mContext;
- private LegalSettings mFragment;
- private boolean mWallpaperRemoved;
-
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mContext = spy(RuntimeEnvironment.application);
- mFragment = new LegalSettings() {
- @Override
- public boolean removePreference(String key) {
- if (LegalSettings.KEY_WALLPAPER_ATTRIBUTIONS.equals(key)) {
- mWallpaperRemoved = true;
-
- return true;
- }
- return false;
- }
- };
}
@Test
- public void testNonIndexableKeys_existInXmlLayout() {
+ public void getNonIndexableKeys_existInXmlLayout() {
final Context context = RuntimeEnvironment.application;
final List niks =
- LegalSettings.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(context);
+ LegalSettings.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(context);
final List keys = XmlTestUtils.getKeysFromPreferenceXml(context, R.xml.about_legal);
assertThat(keys).containsAllIn(niks);
}
-
- @Test
- public void testWallpaperAttributions_byDefault_shouldBeShown() {
- mFragment.checkWallpaperAttributionAvailability(mContext);
-
- assertThat(mWallpaperRemoved).isEqualTo(false);
- }
-
- @Test
- @Config(qualifiers = "mcc999")
- public void testWallpaperAttributions_ifDisabled_shouldNotBeShown() {
- mFragment.checkWallpaperAttributionAvailability(mContext);
-
- assertThat(mWallpaperRemoved).isEqualTo(true);
- }
}
diff --git a/tests/robotests/src/com/android/settings/PrivacySettingsTest.java b/tests/robotests/src/com/android/settings/PrivacySettingsTest.java
deleted file mode 100644
index 24defa1b769..00000000000
--- a/tests/robotests/src/com/android/settings/PrivacySettingsTest.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2016 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;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import android.support.v14.preference.SwitchPreference;
-import android.support.v7.preference.Preference;
-import android.support.v7.preference.PreferenceScreen;
-
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-public class PrivacySettingsTest {
-
- @Mock
- private PreferenceScreen mScreen;
- private PrivacySettings mSettings;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- when(mScreen.findPreference(PrivacySettings.BACKUP_DATA))
- .thenReturn(mock(Preference.class));
- when(mScreen.findPreference(PrivacySettings.CONFIGURE_ACCOUNT))
- .thenReturn(mock(Preference.class));
- when(mScreen.findPreference(PrivacySettings.DATA_MANAGEMENT))
- .thenReturn(mock(Preference.class));
- when(mScreen.findPreference(PrivacySettings.AUTO_RESTORE))
- .thenReturn(mock(SwitchPreference.class));
- mSettings = new PrivacySettings();
- }
-
- @Test
- public void testSetPreference_noCrash() {
- mSettings.setPreferenceReferences(mScreen);
- }
-}
diff --git a/tests/robotests/src/com/android/settings/RestrictedSettingsFragmentTest.java b/tests/robotests/src/com/android/settings/RestrictedSettingsFragmentTest.java
new file mode 100644
index 00000000000..e370cda5c96
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/RestrictedSettingsFragmentTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+package com.android.settings;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.isNull;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class RestrictedSettingsFragmentTest {
+
+ @Mock
+ private AlertDialog mAlertDialog;
+ private RestrictedSettingsFragment mFragment;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void onActivityResult_dismissesDialogOnOk() {
+ mFragment = new RestrictedSettingsFragment("fake_key") {
+ @Override
+ public int getMetricsCategory() {
+ return 0;
+ }
+ };
+ doReturn(true).when(mAlertDialog).isShowing();
+ mFragment.mActionDisabledDialog = mAlertDialog;
+ mFragment.onActivityResult(RestrictedSettingsFragment.REQUEST_PIN_CHALLENGE,
+ Activity.RESULT_OK,
+ null);
+
+ // dialog should be gone
+ verify(mAlertDialog, times(1)).setOnDismissListener(isNull());
+ verify(mAlertDialog, times(1)).dismiss();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySlicePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySlicePreferenceControllerTest.java
new file mode 100644
index 00000000000..fe6d1a3f5fd
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySlicePreferenceControllerTest.java
@@ -0,0 +1,148 @@
+/*
+ * 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.accessibility;
+
+import static com.android.settings.core.BasePreferenceController.AVAILABLE;
+import static com.android.settings.core.BasePreferenceController.DISABLED_UNSUPPORTED;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.provider.Settings;
+import android.view.accessibility.AccessibilityManager;
+
+import com.android.settings.accessibility.AccessibilitySlicePreferenceController;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.accessibility.AccessibilityUtils;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.robolectric.shadow.api.Shadow;
+import org.robolectric.shadows.ShadowAccessibilityManager;
+import org.xmlpull.v1.XmlPullParserException;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class AccessibilitySlicePreferenceControllerTest {
+
+ private final String PACKAGE_NAME = "com.android.settings.fake";
+ private final String CLASS_NAME = "com.android.settings.fake.classname";
+ private final String SERVICE_NAME = PACKAGE_NAME + "/" + CLASS_NAME;
+
+ private Context mContext;
+
+ private AccessibilitySlicePreferenceController mController;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+
+ final ContentResolver contentResolver = mContext.getContentResolver();
+ Settings.Secure.putInt(contentResolver, Settings.Secure.ACCESSIBILITY_ENABLED, 1 /* on */);
+ Settings.Secure.putString(contentResolver, Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
+ SERVICE_NAME);
+
+ // Register the fake a11y Service
+ ShadowAccessibilityManager shadowAccessibilityManager = Shadow.extract(
+ RuntimeEnvironment.application.getSystemService(AccessibilityManager.class));
+ shadowAccessibilityManager.setInstalledAccessibilityServiceList(getFakeServiceList());
+
+ mController = new AccessibilitySlicePreferenceController(mContext, SERVICE_NAME);
+ }
+
+ @Test
+ public void getAvailability_availableService_returnsAvailable() {
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+ }
+
+ @Test
+ public void getAvailability_unknownService_returnsUnsupported() {
+ AccessibilitySlicePreferenceController controller =
+ new AccessibilitySlicePreferenceController(mContext, "fake_service/name");
+
+ assertThat(controller.getAvailabilityStatus()).isEqualTo(DISABLED_UNSUPPORTED);
+ }
+
+ @Test
+ public void setChecked_availableService_serviceIsEnabled() {
+ mController.setChecked(true);
+
+ assertThat(mController.isChecked()).isTrue();
+ }
+
+ @Test
+ public void setNotChecked_availableService_serviceIsDisabled() {
+ mController.setChecked(false);
+
+ assertThat(mController.isChecked()).isFalse();
+ }
+
+ @Test
+ public void isChecked_serviceEnabled_returnsTrue() {
+ AccessibilityUtils.setAccessibilityServiceState(mContext,
+ ComponentName.unflattenFromString(mController.getPreferenceKey()), true);
+
+ assertThat(mController.isChecked()).isTrue();
+ }
+
+ @Test
+ public void isChecked_serviceNotEnabled_returnsFalse() {
+ AccessibilitySlicePreferenceController controller =
+ new AccessibilitySlicePreferenceController(mContext, "fake_service/name");
+
+ assertThat(controller.isChecked()).isFalse();
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void illegalServiceName_exceptionThrown() {
+ new AccessibilitySlicePreferenceController(mContext, "not_split_by_slash");
+ }
+
+ private List getFakeServiceList() {
+ final List infoList = new ArrayList<>();
+
+ final ServiceInfo serviceInfo = new ServiceInfo();
+ serviceInfo.packageName = PACKAGE_NAME;
+ serviceInfo.name = CLASS_NAME;
+
+ final ResolveInfo resolveInfo = new ResolveInfo();
+ resolveInfo.serviceInfo = serviceInfo;
+
+ try {
+ final AccessibilityServiceInfo info = new AccessibilityServiceInfo(resolveInfo,
+ mContext);
+ ComponentName componentName = new ComponentName(PACKAGE_NAME, CLASS_NAME);
+ info.setComponentName(componentName);
+ infoList.add(info);
+ } catch (XmlPullParserException | IOException e) {
+
+ }
+
+ return infoList;
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/backup/AutoRestorePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/backup/AutoRestorePreferenceControllerTest.java
new file mode 100644
index 00000000000..0fc0826a01e
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/backup/AutoRestorePreferenceControllerTest.java
@@ -0,0 +1,89 @@
+/*
+ * 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.backup;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.support.v14.preference.SwitchPreference;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(shadows = {ShadowPrivacySettingsUtils.class})
+public class AutoRestorePreferenceControllerTest {
+ private Context mContext;
+ private AutoRestorePreferenceController mController;
+ private PrivacySettingsConfigData mPSCD;
+ private SwitchPreference mPreference;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mPSCD = new PrivacySettingsConfigData();
+ mController = new AutoRestorePreferenceController(mContext,
+ PrivacySettingsUtils.AUTO_RESTORE);
+ mPreference = new SwitchPreference(mContext);
+ }
+
+ @After
+ public void tearDown() {
+ ShadowPrivacySettingsUtils.reset();
+ }
+
+ @Test
+ public void updateState_backupEnabled_prefShouldBeEnabled() {
+ mPSCD.setBackupEnabled(true);
+ mPSCD.setBackupGray(false);
+ mController.setPrivacySettingsConfigData(mPSCD);
+ mController.updateState(mPreference);
+ assertThat(mPreference.isEnabled()).isTrue();
+ }
+
+ @Test
+ public void getAvailabilityStatus_isAdmiUser_isnotInvisibleKey_shouldBeAvailable() {
+ ShadowPrivacySettingsUtils.setIsAdminUser(true);
+ ShadowPrivacySettingsUtils.setIsInvisibleKey(false);
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.AVAILABLE);
+ }
+
+ @Test
+ public void getAvailabilityStatus_isnotAdmiUser_shouldBeDisabledForUser() {
+ ShadowPrivacySettingsUtils.setIsAdminUser(false);
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.DISABLED_FOR_USER);
+ }
+
+ @Test
+ public void getAvailabilityStatus_isAdmiUser_isInvisibleKey_shouldBeDisabledUnsupported() {
+ ShadowPrivacySettingsUtils.setIsAdminUser(true);
+ ShadowPrivacySettingsUtils.setIsInvisibleKey(true);
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.DISABLED_UNSUPPORTED);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/backup/BackupDataPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/backup/BackupDataPreferenceControllerTest.java
new file mode 100644
index 00000000000..fa254738b96
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/backup/BackupDataPreferenceControllerTest.java
@@ -0,0 +1,111 @@
+/*
+ * 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.backup;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.os.UserManager;
+import android.support.v7.preference.Preference;
+
+import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(shadows = {ShadowPrivacySettingsUtils.class})
+public class BackupDataPreferenceControllerTest {
+ private Context mContext;
+ private BackupDataPreferenceController mController;
+ private PrivacySettingsConfigData mPSCD;
+ private Preference mPreference;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mPSCD = new PrivacySettingsConfigData();
+ mController = new BackupDataPreferenceController(mContext,
+ PrivacySettingsUtils.BACKUP_DATA);
+ mPreference = new Preference(mContext);
+ }
+
+ @After
+ public void tearDown() {
+ ShadowPrivacySettingsUtils.reset();
+ }
+
+ @Test
+ public void updateState_backupEnabled_prefShouldBeEnabled() {
+ mPSCD.setBackupEnabled(true);
+ mPSCD.setBackupGray(false);
+ mController.setPrivacySettingsConfigData(mPSCD);
+ mController.updateState(mPreference);
+ assertThat(mPreference.isEnabled()).isTrue();
+ }
+
+ @Test
+ public void updateState_backupEnabled_prefShouldDisplayOnSummary() {
+ mPSCD.setBackupEnabled(true);
+ mPSCD.setBackupGray(false);
+ mController.setPrivacySettingsConfigData(mPSCD);
+ mController.updateState(mPreference);
+ assertThat(mPreference.getSummary())
+ .isEqualTo(mContext.getString(R.string.accessibility_feature_state_on));
+ }
+
+ @Test
+ public void updateState_backupDisabled_prefShouldDisplayOffSummary() {
+ mPSCD.setBackupEnabled(false);
+ mPSCD.setBackupGray(false);
+ mController.setPrivacySettingsConfigData(mPSCD);
+ mController.updateState(mPreference);
+ assertThat(mPreference.getSummary())
+ .isEqualTo(mContext.getString(R.string.accessibility_feature_state_off));
+ }
+
+ @Test
+ public void getAvailabilityStatus_isAdmiUser_isnotInvisibleKey_shouldBeAvailable() {
+ ShadowPrivacySettingsUtils.setIsAdminUser(true);
+ ShadowPrivacySettingsUtils.setIsInvisibleKey(false);
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.AVAILABLE);
+ }
+
+ @Test
+ public void getAvailabilityStatus_isnotAdmiUser_shouldBeDisabledForUser() {
+ ShadowPrivacySettingsUtils.setIsAdminUser(false);
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.DISABLED_FOR_USER);
+ }
+
+ @Test
+ public void getAvailabilityStatus_isAdmiUser_isInvisibleKey_shouldBeDisabledUnsupported() {
+ ShadowPrivacySettingsUtils.setIsAdminUser(true);
+ ShadowPrivacySettingsUtils.setIsInvisibleKey(true);
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.DISABLED_UNSUPPORTED);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/backup/BackupInactivePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/backup/BackupInactivePreferenceControllerTest.java
new file mode 100644
index 00000000000..c17cc671e55
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/backup/BackupInactivePreferenceControllerTest.java
@@ -0,0 +1,77 @@
+/*
+ * 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.backup;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.support.v7.preference.Preference;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(shadows = {ShadowPrivacySettingsUtils.class})
+public class BackupInactivePreferenceControllerTest {
+ private Context mContext;
+ private BackupInactivePreferenceController mController;
+ private Preference mPreference;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mController = new BackupInactivePreferenceController(mContext,
+ PrivacySettingsUtils.BACKUP_INACTIVE);
+ }
+
+ @After
+ public void tearDown() {
+ ShadowPrivacySettingsUtils.reset();
+ }
+
+ @Test
+ public void getAvailabilityStatus_isAdmiUser_isnotInvisibleKey_shouldBeAvailable() {
+ ShadowPrivacySettingsUtils.setIsAdminUser(true);
+ ShadowPrivacySettingsUtils.setIsInvisibleKey(false);
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.AVAILABLE);
+ }
+
+ @Test
+ public void getAvailabilityStatus_isnotAdmiUser_shouldBeDisabledForUser() {
+ ShadowPrivacySettingsUtils.setIsAdminUser(false);
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.DISABLED_FOR_USER);
+ }
+
+ @Test
+ public void getAvailabilityStatus_isAdmiUser_isInvisibleKey_shouldBeDisabledUnsupported() {
+ ShadowPrivacySettingsUtils.setIsAdminUser(true);
+ ShadowPrivacySettingsUtils.setIsInvisibleKey(true);
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.DISABLED_UNSUPPORTED);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/backup/ConfigureAccountPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/backup/ConfigureAccountPreferenceControllerTest.java
new file mode 100644
index 00000000000..57cb4d56eb2
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/backup/ConfigureAccountPreferenceControllerTest.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.settings.backup;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.content.Intent;
+import android.support.v7.preference.Preference;
+
+import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(shadows = {ShadowPrivacySettingsUtils.class})
+public class ConfigureAccountPreferenceControllerTest {
+ private Context mContext;
+ private ConfigureAccountPreferenceController mController;
+ private PrivacySettingsConfigData mPSCD;
+ private Preference mPreference;
+ private String mTestSummary;
+
+ @Mock
+ private Intent mIntent;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mPSCD = new PrivacySettingsConfigData();
+ mController = new ConfigureAccountPreferenceController(mContext,
+ PrivacySettingsUtils.CONFIGURE_ACCOUNT);
+ mPreference = new Preference(mContext);
+ mTestSummary = "Summary";
+ }
+
+ @After
+ public void tearDown() {
+ ShadowPrivacySettingsUtils.reset();
+ }
+
+ @Test
+ public void updateState_backupEnabled_hadConfigIntent_prefShouldBeEnabled() {
+ mPSCD.setBackupEnabled(true);
+ mPSCD.setBackupGray(false);
+ mPSCD.setConfigIntent(mIntent);
+ mController.setPrivacySettingsConfigData(mPSCD);
+ mController.updateState(mPreference);
+ assertThat(mPreference.isEnabled()).isTrue();
+ }
+
+ @Test
+ public void
+ updateState_backupEnabled_hadConfigIntent_nullConfigSummary_prefDisplayDefaultSummary() {
+ mPSCD.setBackupEnabled(true);
+ mPSCD.setBackupGray(false);
+ mPSCD.setConfigIntent(mIntent);
+ mPSCD.setConfigSummary(null);
+ mController.setPrivacySettingsConfigData(mPSCD);
+ mController.updateState(mPreference);
+ assertThat(mPreference.getSummary())
+ .isEqualTo(mContext.getString(R.string.backup_configure_account_default_summary));
+ }
+
+ @Test
+ public void
+ updateState_backupEnabled_hadConfigIntent_hasConfigSummary_prefDisplayConfigSummary() {
+ mPSCD.setBackupEnabled(true);
+ mPSCD.setBackupGray(false);
+ mPSCD.setConfigIntent(mIntent);
+ mPSCD.setConfigSummary(mTestSummary);
+ mController.setPrivacySettingsConfigData(mPSCD);
+ mController.updateState(mPreference);
+ assertThat(mPreference.getSummary()).isEqualTo(mTestSummary);
+ }
+
+ @Test
+ public void getAvailabilityStatus_isAdmiUser_isnotInvisibleKey_shouldBeAvailable() {
+ ShadowPrivacySettingsUtils.setIsAdminUser(true);
+ ShadowPrivacySettingsUtils.setIsInvisibleKey(false);
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.AVAILABLE);
+ }
+
+ @Test
+ public void getAvailabilityStatus_isnotAdmiUser_shouldBeDisabledForUser() {
+ ShadowPrivacySettingsUtils.setIsAdminUser(false);
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.DISABLED_FOR_USER);
+ }
+
+ @Test
+ public void getAvailabilityStatus_isAdmiUser_isInvisibleKey_shouldBeDisabledUnsupported() {
+ ShadowPrivacySettingsUtils.setIsAdminUser(true);
+ ShadowPrivacySettingsUtils.setIsInvisibleKey(true);
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.DISABLED_UNSUPPORTED);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/backup/DataManagementPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/backup/DataManagementPreferenceControllerTest.java
new file mode 100644
index 00000000000..bd5bef4ecf1
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/backup/DataManagementPreferenceControllerTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.settings.backup;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.content.Intent;
+import android.support.v7.preference.Preference;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(shadows = {ShadowPrivacySettingsUtils.class})
+public class DataManagementPreferenceControllerTest {
+ private final String KEY = "data_management";
+ private Context mContext;
+ private DataManagementPreferenceController mController;
+ private PrivacySettingsConfigData mPSCD;
+ private Preference mPreference;
+ private String mTitle;
+
+ @Mock
+ private Intent mIntent;
+
+ @After
+ public void tearDown() {
+ ShadowPrivacySettingsUtils.reset();
+ }
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mPSCD = new PrivacySettingsConfigData();
+ mController = new DataManagementPreferenceController(mContext, KEY);
+ mPreference = new Preference(mContext);
+ mTitle = "Title";
+ }
+
+ @Test
+ public void updateState_backupEnabled_hadManageIntent_hasManageLable_prefShouldBeHasTitle() {
+ mPSCD.setBackupEnabled(true);
+ mPSCD.setBackupGray(false);
+ mPSCD.setManageIntent(mIntent);
+ mPSCD.setManageLabel(mTitle);
+ mController.setPrivacySettingsConfigData(mPSCD);
+ mController.updateState(mPreference);
+ assertThat(mPreference.getTitle())
+ .isEqualTo(mTitle);
+ }
+
+ @Test
+ public void getAvailabilityStatus_isAdmiUser_backupEnabled_hadManageIntent_shouldBeAvailable() {
+ ShadowPrivacySettingsUtils.setIsAdminUser(true);
+ mPSCD.setBackupEnabled(true);
+ mPSCD.setBackupGray(false);
+ mPSCD.setManageIntent(mIntent);
+ mPSCD.setManageLabel(mTitle);
+ mController.setPrivacySettingsConfigData(mPSCD);
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.AVAILABLE);
+ }
+
+ @Test
+ public void getAvailabilityStatus_isnotAdmiUser_shouldBeDisabledForUser() {
+ ShadowPrivacySettingsUtils.setIsAdminUser(false);
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.DISABLED_FOR_USER);
+ }
+
+ @Test
+ public void
+ getAvailabilityStatus_isAdmiUser_backupEnabled_nullManageIntent_shouldBeDisabledUnsupported() {
+ ShadowPrivacySettingsUtils.setIsAdminUser(true);
+ mPSCD.setBackupEnabled(true);
+ mPSCD.setBackupGray(false);
+ mPSCD.setManageIntent(null);
+ mPSCD.setManageLabel(mTitle);
+ mController.setPrivacySettingsConfigData(mPSCD);
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.DISABLED_UNSUPPORTED);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/backup/ShadowPrivacySettingsUtils.java b/tests/robotests/src/com/android/settings/backup/ShadowPrivacySettingsUtils.java
new file mode 100644
index 00000000000..74bf5348421
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/backup/ShadowPrivacySettingsUtils.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.settings.backup;
+
+import android.content.Context;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.annotation.Resetter;
+
+@Implements(PrivacySettingsUtils.class)
+public class ShadowPrivacySettingsUtils {
+ private static boolean sIsAdminUser;
+ private static boolean sIsInvisibleKey;
+
+ @Resetter
+ static void reset() {
+ sIsAdminUser = true;
+ sIsInvisibleKey = false;
+ }
+
+ @Implementation
+ public static boolean isAdminUser(final Context context) {
+ return sIsAdminUser;
+ }
+
+ @Implementation
+ public static boolean isInvisibleKey(final Context context, final String key) {
+ return sIsInvisibleKey;
+ }
+
+ public static void setIsAdminUser(boolean isAdminUser) {
+ sIsAdminUser = isAdminUser;
+ }
+
+ public static void setIsInvisibleKey(boolean isInvisibleKey) {
+ sIsInvisibleKey = isInvisibleKey;
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHeaderControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHeaderControllerTest.java
index 2567f534f66..8079592fc16 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHeaderControllerTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDetailsHeaderControllerTest.java
@@ -17,12 +17,19 @@
package com.android.settings.bluetooth;
import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.app.FragmentTransaction;
import android.graphics.drawable.Drawable;
+import android.view.View;
import com.android.settings.R;
import com.android.settings.applications.LayoutPreference;
@@ -39,6 +46,7 @@ import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
+import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.robolectric.annotation.Config;
@@ -97,6 +105,10 @@ public class BluetoothDetailsHeaderControllerTest extends BluetoothDetailsContro
verify(mHeaderController).setIconContentDescription(any(String.class));
verify(mHeaderController).setSummary(any(String.class));
verify(mHeaderController).setSecondSummary(any(String.class));
+ verify(mHeaderController).setEditListener(any(View.OnClickListener.class));
+ verify(mHeaderController).setButtonActions(
+ EntityHeaderController.ActionType.ACTION_EDIT_PREFERENCE,
+ EntityHeaderController.ActionType.ACTION_NONE);
verify(mHeaderController).done(mActivity, true);
}
@@ -119,4 +131,20 @@ public class BluetoothDetailsHeaderControllerTest extends BluetoothDetailsContro
inOrder.verify(mHeaderController)
.setSummary(mContext.getString(R.string.bluetooth_connecting));
}
+
+ @Test
+ public void invokeShowEditDeviceNameDialog_showDialog() {
+ showScreen(mController);
+
+ FragmentManager fragmentManager = mock(FragmentManager.class);
+ when(mFragment.getFragmentManager()).thenReturn(fragmentManager);
+ FragmentTransaction ft = mock(FragmentTransaction.class);
+ when(fragmentManager.beginTransaction()).thenReturn(ft);
+
+ ArgumentCaptor captor = ArgumentCaptor.forClass(Fragment.class);
+ mController.showEditDeviceNameDialog();
+ verify(ft).add(captor.capture(), eq(RemoteDeviceNameDialogFragment.TAG));
+ RemoteDeviceNameDialogFragment dialog = (RemoteDeviceNameDialogFragment) captor.getValue();
+ assertThat(dialog).isNotNull();
+ }
}
diff --git a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragmentTest.java b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragmentTest.java
index 4be27753f87..9a35345c11c 100644
--- a/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragmentTest.java
@@ -18,22 +18,13 @@ package com.android.settings.bluetooth;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.app.Fragment;
-import android.app.FragmentManager;
-import android.app.FragmentTransaction;
import android.content.Context;
import android.os.Bundle;
-import android.view.MenuInflater;
-import android.view.MenuItem;
-import com.android.settings.R;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
@@ -43,15 +34,15 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
-import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
-import org.robolectric.fakes.RoboMenu;
@RunWith(SettingsRobolectricTestRunner.class)
public class BluetoothDeviceDetailsFragmentTest {
+ private static final String TEST_ADDRESS = "55:66:77:88:99:AA";
+
private BluetoothDeviceDetailsFragment mFragment;
private Context mContext;
@@ -67,46 +58,21 @@ public class BluetoothDeviceDetailsFragmentTest {
mContext = spy(RuntimeEnvironment.application);
FakeFeatureFactory.setupForTest();
- String deviceAddress = "55:66:77:88:99:AA";
- mFragment = spy(BluetoothDeviceDetailsFragment.newInstance(deviceAddress));
+ mFragment = spy(BluetoothDeviceDetailsFragment.newInstance(TEST_ADDRESS));
doReturn(mLocalManager).when(mFragment).getLocalBluetoothManager(any());
doReturn(mCachedDevice).when(mFragment).getCachedDevice(any());
- when(mCachedDevice.getAddress()).thenReturn(deviceAddress);
+ when(mCachedDevice.getAddress()).thenReturn(TEST_ADDRESS);
Bundle args = new Bundle();
- args.putString(BluetoothDeviceDetailsFragment.KEY_DEVICE_ADDRESS, deviceAddress);
+ args.putString(BluetoothDeviceDetailsFragment.KEY_DEVICE_ADDRESS, TEST_ADDRESS);
mFragment.setArguments(args);
mFragment.onAttach(mContext);
}
@Test
- public void renameControlGetsAdded() {
- RoboMenu menu = new RoboMenu(mContext);
- MenuInflater inflater = new MenuInflater(mContext);
- mFragment.onCreateOptionsMenu(menu, inflater);
- MenuItem item = menu.getItem(0);
- assertThat(item.getTitle()).isEqualTo(mContext.getString(R.string.bluetooth_rename_button));
- assertThat(item.getIcon()).isEqualTo(mContext.getDrawable(R.drawable.ic_mode_edit));
- }
-
- @Test
- public void renameControlClicked() {
- RoboMenu menu = new RoboMenu(mContext);
- MenuInflater inflater = new MenuInflater(mContext);
- mFragment.onCreateOptionsMenu(menu, inflater);
- MenuItem item = menu.getItem(0);
- assertThat(item.getItemId())
- .isEqualTo(BluetoothDeviceDetailsFragment.EDIT_DEVICE_NAME_ITEM_ID);
-
- FragmentManager fragmentManager = mock(FragmentManager.class);
- when(mFragment.getFragmentManager()).thenReturn(fragmentManager);
- FragmentTransaction ft = mock(FragmentTransaction.class);
- when(fragmentManager.beginTransaction()).thenReturn(ft);
-
- ArgumentCaptor captor = ArgumentCaptor.forClass(Fragment.class);
- mFragment.onOptionsItemSelected(item);
- verify(ft).add(captor.capture(), eq(RemoteDeviceNameDialogFragment.TAG));
- RemoteDeviceNameDialogFragment dialog = (RemoteDeviceNameDialogFragment) captor.getValue();
- assertThat(dialog).isNotNull();
+ public void verifyOnAttachResult() {
+ assertThat(mFragment.mDeviceAddress).isEqualTo(TEST_ADDRESS);
+ assertThat(mFragment.mManager).isEqualTo(mLocalManager);
+ assertThat(mFragment.mCachedDevice).isEqualTo(mCachedDevice);
}
}
diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardFeatureProviderImplTest.java
index 4a09b408b6e..a0e5ed873bb 100644
--- a/tests/robotests/src/com/android/settings/dashboard/DashboardFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/DashboardFeatureProviderImplTest.java
@@ -297,7 +297,7 @@ public class DashboardFeatureProviderImplTest {
"content://com.android.settings/tile_icon");
mImpl.bindIcon(preference, tile);
- assertThat(tile.icon).isNotNull();
+ assertThat(preference.getIcon()).isNotNull();
}
@Test
diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryPreferenceTest.java b/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryPreferenceTest.java
index 20dce6c3aa7..c8e46be7e48 100644
--- a/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryPreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryPreferenceTest.java
@@ -26,6 +26,7 @@ import android.graphics.Typeface;
import android.net.NetworkTemplate;
import android.os.Bundle;
import android.support.v7.preference.PreferenceViewHolder;
+import android.telephony.SubscriptionManager;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
@@ -409,6 +410,31 @@ public class DataUsageSummaryPreferenceTest {
assertThat(mDataRemaining.getText()).isEqualTo("");
}
+ @Test
+ public void testSetAppIntent_toMdpApp_intentCorrect() {
+ final Activity activity = Robolectric.setupActivity(Activity.class);
+ final Intent intent = new Intent(SubscriptionManager.ACTION_MANAGE_SUBSCRIPTION_PLANS);
+ intent.setPackage("test-owner.example.com");
+ intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, 42);
+
+ mSummaryPreference.setUsageInfo(mCycleEnd, mUpdateTime, DUMMY_CARRIER, 0 /* numPlans */,
+ intent);
+
+ bindViewHolder();
+ assertThat(mLaunchButton.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mLaunchButton.getText())
+ .isEqualTo(mContext.getString(R.string.launch_mdp_app_text));
+
+ mLaunchButton.callOnClick();
+ ShadowActivity shadowActivity = Shadows.shadowOf(activity);
+ Intent startedIntent = shadowActivity.getNextStartedActivity();
+ assertThat(startedIntent.getAction())
+ .isEqualTo(SubscriptionManager.ACTION_MANAGE_SUBSCRIPTION_PLANS);
+ assertThat(startedIntent.getPackage()).isEqualTo("test-owner.example.com");
+ assertThat(startedIntent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, -1))
+ .isEqualTo(42);
+ }
+
@Test
public void testSetWifiMode_withUsageInfo_dataUsageShown() {
final int daysLeft = 3;
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/PrivateVolumeForgetTest.java b/tests/robotests/src/com/android/settings/deviceinfo/PrivateVolumeForgetTest.java
new file mode 100644
index 00000000000..7ce37f567ee
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/deviceinfo/PrivateVolumeForgetTest.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.deviceinfo;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.os.storage.VolumeRecord;
+import android.widget.Button;
+
+import com.android.settings.R;
+import com.android.settings.deviceinfo.PrivateVolumeForget.ForgetConfirmFragment;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowStorageManager;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(shadows = ShadowStorageManager.class)
+public class PrivateVolumeForgetTest {
+
+ private PrivateVolumeForget mFragment;
+ private Activity mActivity;
+
+ @Before
+ public void setUp() {
+ final Bundle bundle = new Bundle();
+ bundle.putString(VolumeRecord.EXTRA_FS_UUID, "id");
+ mFragment = Robolectric.buildFragment(PrivateVolumeForget.class,
+ bundle).create().start().resume().get();
+ mActivity = mFragment.getActivity();
+ }
+
+ @After
+ public void tearDown() {
+ ShadowStorageManager.reset();
+ }
+
+ @Test
+ public void OnClickListener_shouldCallForget() {
+ assertThat(ShadowStorageManager.isForgetCalled()).isFalse();
+
+ final Button confirm = mFragment.getView().findViewById(R.id.confirm);
+
+ confirm.performClick();
+ final ForgetConfirmFragment confirmFragment =
+ (ForgetConfirmFragment) mActivity.getFragmentManager().findFragmentByTag(
+ PrivateVolumeForget.TAG_FORGET_CONFIRM);
+
+ assertThat(confirmFragment).isNotNull();
+
+ final AlertDialog dialog = (AlertDialog) confirmFragment.getDialog();
+ final Button forget = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
+
+ forget.performClick();
+
+ assertThat(ShadowStorageManager.isForgetCalled()).isTrue();
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/PrivateVolumeFormatTest.java b/tests/robotests/src/com/android/settings/deviceinfo/PrivateVolumeFormatTest.java
new file mode 100644
index 00000000000..ec371facd18
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/deviceinfo/PrivateVolumeFormatTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.deviceinfo;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.robolectric.Shadows.shadowOf;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.storage.VolumeInfo;
+import android.widget.Button;
+
+import com.android.settings.R;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowStorageManager;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowActivity;
+
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(shadows = ShadowStorageManager.class)
+public class PrivateVolumeFormatTest {
+
+ private PrivateVolumeFormat mFragment;
+ private ShadowActivity mShadowActivity;
+
+ @Before
+ public void setUp() {
+ final Bundle bundle = new Bundle();
+ bundle.putString(VolumeInfo.EXTRA_VOLUME_ID, "id");
+ mFragment = Robolectric.buildFragment(PrivateVolumeFormat.class,
+ bundle).create().start().resume().get();
+ mShadowActivity = shadowOf(mFragment.getActivity());
+ }
+
+ @Test
+ public void OnClickListener_shouldStartStorageWizardFormatProgress() {
+ final Button confirm = mFragment.getView().findViewById(R.id.confirm);
+
+ confirm.performClick();
+ final Intent intent = mShadowActivity.getNextStartedActivity();
+
+ assertThat(intent.getComponent()).isEqualTo(
+ new ComponentName(RuntimeEnvironment.application.getPackageName(),
+ StorageWizardFormatProgress.class.getName()));
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/PrivateVolumeUnmountTest.java b/tests/robotests/src/com/android/settings/deviceinfo/PrivateVolumeUnmountTest.java
new file mode 100644
index 00000000000..77e60a1464a
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/deviceinfo/PrivateVolumeUnmountTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.deviceinfo;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.os.Bundle;
+import android.os.storage.VolumeInfo;
+import android.widget.Button;
+
+import com.android.settings.R;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowStorageManager;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.Robolectric;
+import org.robolectric.annotation.Config;
+
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(shadows = ShadowStorageManager.class)
+public class PrivateVolumeUnmountTest {
+
+ private PrivateVolumeUnmount mFragment;
+
+ @Before
+ public void setUp() {
+ Bundle bundle = new Bundle();
+ bundle.putString(VolumeInfo.EXTRA_VOLUME_ID, "id");
+ mFragment = Robolectric.buildFragment(PrivateVolumeUnmount.class,
+ bundle).create().start().resume().get();
+ }
+
+ @After
+ public void tearDown() {
+ ShadowStorageManager.reset();
+ }
+
+ @Test
+ public void OnClickListener_shouldCallUnmount() {
+ assertThat(ShadowStorageManager.isUnmountCalled()).isFalse();
+
+ Button confirm = (Button) mFragment.getView().findViewById(R.id.confirm);
+
+ confirm.performClick();
+
+ assertThat(ShadowStorageManager.isUnmountCalled()).isTrue();
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/legal/CopyrightPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/legal/CopyrightPreferenceControllerTest.java
new file mode 100644
index 00000000000..7ca00765fd6
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/deviceinfo/legal/CopyrightPreferenceControllerTest.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.settings.deviceinfo.legal;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class CopyrightPreferenceControllerTest {
+
+ @Mock
+ private PackageManager mPackageManager;
+ @Mock
+ private PreferenceScreen mScreen;
+
+ private Context mContext;
+ private CopyrightPreferenceController mController;
+ private Preference mPreference;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+ mPreference = new Preference(mContext);
+ mPreference.setIntent(new Intent());
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ when(mScreen.findPreference(anyString())).thenReturn(mPreference);
+ mController = new CopyrightPreferenceController(mContext, "pref_key");
+ mController.displayPreference(mScreen);
+ }
+
+ @Test
+ public void getIntent_shouldUseRightIntent() {
+ final Intent intent = mController.getIntent();
+ assertThat(intent.getAction()).isEqualTo("android.settings.COPYRIGHT");
+ }
+
+ @Test
+ public void getAvailabilityStatus_systemApp_shouldReturnTrue() {
+ final List testResolveInfos = new ArrayList<>();
+ testResolveInfos.add(getTestResolveInfo(true /* isSystemApp */));
+ when(mPackageManager.queryIntentActivities(any(Intent.class), anyInt()))
+ .thenReturn(testResolveInfos);
+
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.AVAILABLE);
+ }
+
+ @Test
+ public void getAvailabilityStatus_notSystemApp_shouldReturnFalseAndNoCrash() {
+ final List testResolveInfos = new ArrayList<>();
+ testResolveInfos.add(getTestResolveInfo(false /* isSystemApp */));
+ when(mPackageManager.queryIntentActivities(any(Intent.class), anyInt()))
+ .thenReturn(testResolveInfos);
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.DISABLED_UNSUPPORTED);
+
+ when(mPackageManager.queryIntentActivities(any(Intent.class), anyInt())).thenReturn(null);
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.DISABLED_UNSUPPORTED);
+ }
+
+ /**
+ * Returns a ResolveInfo object for testing
+ *
+ * @param isSystemApp If true, the application is a system app.
+ */
+ private ResolveInfo getTestResolveInfo(boolean isSystemApp) {
+ final ResolveInfo testResolveInfo = new ResolveInfo();
+ final ApplicationInfo testAppInfo = new ApplicationInfo();
+ if (isSystemApp) {
+ testAppInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
+ }
+ final ActivityInfo testActivityInfo = new ActivityInfo();
+ testActivityInfo.name = "TestActivityName";
+ testActivityInfo.packageName = "TestPackageName";
+ testActivityInfo.applicationInfo = testAppInfo;
+ testResolveInfo.activityInfo = testActivityInfo;
+ return testResolveInfo;
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/legal/LicensePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/legal/LicensePreferenceControllerTest.java
new file mode 100644
index 00000000000..f9dd8bd49d3
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/deviceinfo/legal/LicensePreferenceControllerTest.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.settings.deviceinfo.legal;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class LicensePreferenceControllerTest {
+
+ @Mock
+ private PackageManager mPackageManager;
+ @Mock
+ private PreferenceScreen mScreen;
+
+ private Context mContext;
+ private LicensePreferenceController mController;
+ private Preference mPreference;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+ mPreference = new Preference(mContext);
+ mPreference.setIntent(new Intent());
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ when(mScreen.findPreference(anyString())).thenReturn(mPreference);
+ mController = new LicensePreferenceController(mContext, "pref_key");
+ mController.displayPreference(mScreen);
+ }
+
+ @Test
+ public void getIntent_shouldUseRightIntent() {
+ final Intent intent = mController.getIntent();
+ assertThat(intent.getAction()).isEqualTo("android.settings.LICENSE");
+ }
+
+ @Test
+ public void getAvailabilityStatus_systemApp_shouldReturnTrue() {
+ final List testResolveInfos = new ArrayList<>();
+ testResolveInfos.add(getTestResolveInfo(true /* isSystemApp */));
+ when(mPackageManager.queryIntentActivities(any(Intent.class), anyInt()))
+ .thenReturn(testResolveInfos);
+
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.AVAILABLE);
+ }
+
+ @Test
+ public void getAvailabilityStatus_notSystemApp_shouldReturnFalseAndNoCrash() {
+ final List testResolveInfos = new ArrayList<>();
+ testResolveInfos.add(getTestResolveInfo(false /* isSystemApp */));
+ when(mPackageManager.queryIntentActivities(any(Intent.class), anyInt()))
+ .thenReturn(testResolveInfos);
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.DISABLED_UNSUPPORTED);
+
+ when(mPackageManager.queryIntentActivities(any(Intent.class), anyInt())).thenReturn(null);
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.DISABLED_UNSUPPORTED);
+ }
+
+ /**
+ * Returns a ResolveInfo object for testing
+ *
+ * @param isSystemApp If true, the application is a system app.
+ */
+ private ResolveInfo getTestResolveInfo(boolean isSystemApp) {
+ final ResolveInfo testResolveInfo = new ResolveInfo();
+ final ApplicationInfo testAppInfo = new ApplicationInfo();
+ if (isSystemApp) {
+ testAppInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
+ }
+ final ActivityInfo testActivityInfo = new ActivityInfo();
+ testActivityInfo.name = "TestActivityName";
+ testActivityInfo.packageName = "TestPackageName";
+ testActivityInfo.applicationInfo = testAppInfo;
+ testResolveInfo.activityInfo = testActivityInfo;
+ return testResolveInfo;
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/legal/TermsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/legal/TermsPreferenceControllerTest.java
new file mode 100644
index 00000000000..3a8eb660b19
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/deviceinfo/legal/TermsPreferenceControllerTest.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.settings.deviceinfo.legal;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class TermsPreferenceControllerTest {
+
+ @Mock
+ private PackageManager mPackageManager;
+ @Mock
+ private PreferenceScreen mScreen;
+
+ private Context mContext;
+ private TermsPreferenceController mController;
+ private Preference mPreference;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+ mPreference = new Preference(mContext);
+ mPreference.setIntent(new Intent());
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ when(mScreen.findPreference(anyString())).thenReturn(mPreference);
+ mController = new TermsPreferenceController(mContext, "pref_key");
+ mController.displayPreference(mScreen);
+ }
+
+ @Test
+ public void getIntent_shouldUseRightIntent() {
+ final Intent intent = mController.getIntent();
+ assertThat(intent.getAction()).isEqualTo("android.settings.TERMS");
+ }
+
+ @Test
+ public void getAvailabilityStatus_systemApp_shouldReturnTrue() {
+ final List testResolveInfos = new ArrayList<>();
+ testResolveInfos.add(getTestResolveInfo(true /* isSystemApp */));
+ when(mPackageManager.queryIntentActivities(any(Intent.class), anyInt()))
+ .thenReturn(testResolveInfos);
+
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.AVAILABLE);
+ }
+
+ @Test
+ public void getAvailabilityStatus_notSystemApp_shouldReturnFalseAndNoCrash() {
+ final List testResolveInfos = new ArrayList<>();
+ testResolveInfos.add(getTestResolveInfo(false /* isSystemApp */));
+ when(mPackageManager.queryIntentActivities(any(Intent.class), anyInt()))
+ .thenReturn(testResolveInfos);
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.DISABLED_UNSUPPORTED);
+
+ when(mPackageManager.queryIntentActivities(any(Intent.class), anyInt())).thenReturn(null);
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.DISABLED_UNSUPPORTED);
+ }
+
+ /**
+ * Returns a ResolveInfo object for testing
+ *
+ * @param isSystemApp If true, the application is a system app.
+ */
+ private ResolveInfo getTestResolveInfo(boolean isSystemApp) {
+ final ResolveInfo testResolveInfo = new ResolveInfo();
+ final ApplicationInfo testAppInfo = new ApplicationInfo();
+ if (isSystemApp) {
+ testAppInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
+ }
+ final ActivityInfo testActivityInfo = new ActivityInfo();
+ testActivityInfo.name = "TestActivityName";
+ testActivityInfo.packageName = "TestPackageName";
+ testActivityInfo.applicationInfo = testAppInfo;
+ testResolveInfo.activityInfo = testActivityInfo;
+ return testResolveInfo;
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/legal/WallpaperAttributionsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/legal/WallpaperAttributionsPreferenceControllerTest.java
new file mode 100644
index 00000000000..c4d5577a7f5
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/deviceinfo/legal/WallpaperAttributionsPreferenceControllerTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.settings.deviceinfo.legal;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class WallpaperAttributionsPreferenceControllerTest {
+
+ private Context mContext;
+ private WallpaperAttributionsPreferenceController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mController = new WallpaperAttributionsPreferenceController(mContext, "pref_key");
+ }
+
+ @Test
+ public void getAvailabilityStatus_byDefault_true() {
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.AVAILABLE);
+ }
+
+ @Test
+ @Config(qualifiers = "mcc999")
+ public void getAvailabilityStatus_ifNotVisible_false() {
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.DISABLED_UNSUPPORTED);
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/legal/WebViewLicensePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/legal/WebViewLicensePreferenceControllerTest.java
new file mode 100644
index 00000000000..982dc91ed20
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/deviceinfo/legal/WebViewLicensePreferenceControllerTest.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.settings.deviceinfo.legal;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class WebViewLicensePreferenceControllerTest {
+
+ @Mock
+ private PackageManager mPackageManager;
+ @Mock
+ private PreferenceScreen mScreen;
+
+ private Context mContext;
+ private WebViewLicensePreferenceController mController;
+ private Preference mPreference;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+ mPreference = new Preference(mContext);
+ mPreference.setIntent(new Intent());
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ when(mScreen.findPreference(anyString())).thenReturn(mPreference);
+ mController = new WebViewLicensePreferenceController(mContext, "pref_key");
+ mController.displayPreference(mScreen);
+ }
+
+ @Test
+ public void getIntent_shouldUseRightIntent() {
+ final Intent intent = mController.getIntent();
+ assertThat(intent.getAction()).isEqualTo("android.settings.WEBVIEW_LICENSE");
+ }
+
+ @Test
+ public void getAvailabilityStatus_systemApp_shouldReturnTrue() {
+ final List testResolveInfos = new ArrayList<>();
+ testResolveInfos.add(getTestResolveInfo(true /* isSystemApp */));
+ when(mPackageManager.queryIntentActivities(any(Intent.class), anyInt()))
+ .thenReturn(testResolveInfos);
+
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.AVAILABLE);
+ }
+
+ @Test
+ public void getAvailabilityStatus_notSystemApp_shouldReturnFalseAndNoCrash() {
+ final List testResolveInfos = new ArrayList<>();
+ testResolveInfos.add(getTestResolveInfo(false /* isSystemApp */));
+ when(mPackageManager.queryIntentActivities(any(Intent.class), anyInt()))
+ .thenReturn(testResolveInfos);
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.DISABLED_UNSUPPORTED);
+
+ when(mPackageManager.queryIntentActivities(any(Intent.class), anyInt())).thenReturn(null);
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.DISABLED_UNSUPPORTED);
+ }
+
+ /**
+ * Returns a ResolveInfo object for testing
+ *
+ * @param isSystemApp If true, the application is a system app.
+ */
+ private ResolveInfo getTestResolveInfo(boolean isSystemApp) {
+ final ResolveInfo testResolveInfo = new ResolveInfo();
+ final ApplicationInfo testAppInfo = new ApplicationInfo();
+ if (isSystemApp) {
+ testAppInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
+ }
+ final ActivityInfo testActivityInfo = new ActivityInfo();
+ testActivityInfo.name = "TestActivityName";
+ testActivityInfo.packageName = "TestPackageName";
+ testActivityInfo.applicationInfo = testAppInfo;
+ testResolveInfo.activityInfo = testActivityInfo;
+ return testResolveInfo;
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java
index 772bb8d6c1a..dc340161978 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryUtilsTest.java
@@ -564,6 +564,22 @@ public class BatteryUtilsTest {
HIGH_SDK_PACKAGE, AppOpsManager.MODE_IGNORED);
}
+ @Test
+ public void testIsForceAppStandbyEnabled_enabled_returnTrue() {
+ when(mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID,
+ PACKAGE_NAME)).thenReturn(AppOpsManager.MODE_IGNORED);
+
+ assertThat(mBatteryUtils.isForceAppStandbyEnabled(UID, PACKAGE_NAME)).isTrue();
+ }
+
+ @Test
+ public void testIsForceAppStandbyEnabled_disabled_returnFalse() {
+ when(mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_RUN_ANY_IN_BACKGROUND, UID,
+ PACKAGE_NAME)).thenReturn(AppOpsManager.MODE_ALLOWED);
+
+ assertThat(mBatteryUtils.isForceAppStandbyEnabled(UID, PACKAGE_NAME)).isFalse();
+ }
+
@Test
public void testIsAppHeavilyUsed_usageMoreThanThreshold_returnTrue() {
assertThat(mBatteryUtils.isAppHeavilyUsed(mBatteryStatsHelper, mUserManager, UID,
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
index 989c0332371..b20cf168261 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/PowerUsageSummaryTest.java
@@ -49,6 +49,7 @@ import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.applications.LayoutPreference;
import com.android.settings.fuelgauge.anomaly.Anomaly;
+import com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.XmlTestUtils;
@@ -187,7 +188,7 @@ public class PowerUsageSummaryTest {
}
@Test
- public void testUpdateLastFullChargePreference_noAverageTime_showLastFullChargeSummary() {
+ public void updateLastFullChargePreference_noAverageTime_showLastFullChargeSummary() {
mFragment.mBatteryInfo = null;
when(mFragment.getContext()).thenReturn(mRealContext);
doReturn(TIME_SINCE_LAST_FULL_CHARGE_MS).when(
@@ -200,7 +201,7 @@ public class PowerUsageSummaryTest {
}
@Test
- public void testUpdateLastFullChargePreference_hasAverageTime_showFullChargeLastSummary() {
+ public void updateLastFullChargePreference_hasAverageTime_showFullChargeLastSummary() {
mFragment.mBatteryInfo = mBatteryInfo;
mBatteryInfo.averageTimeToDischarge = TIME_SINCE_LAST_FULL_CHARGE_MS;
when(mFragment.getContext()).thenReturn(mRealContext);
@@ -212,7 +213,7 @@ public class PowerUsageSummaryTest {
}
@Test
- public void testNonIndexableKeys_MatchPreferenceKeys() {
+ public void nonIndexableKeys_MatchPreferenceKeys() {
final Context context = RuntimeEnvironment.application;
final List niks =
PowerUsageSummary.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(context);
@@ -224,7 +225,7 @@ public class PowerUsageSummaryTest {
}
@Test
- public void testPreferenceControllers_getPreferenceKeys_existInPreferenceScreen() {
+ public void preferenceControllers_getPreferenceKeys_existInPreferenceScreen() {
final Context context = RuntimeEnvironment.application;
final PowerUsageSummary fragment = new PowerUsageSummary();
final List preferenceScreenKeys =
@@ -239,7 +240,7 @@ public class PowerUsageSummaryTest {
}
@Test
- public void testUpdateAnomalySparseArray() {
+ public void updateAnomalySparseArray() {
mFragment.mAnomalySparseArray = new SparseArray<>();
final List anomalies = new ArrayList<>();
final Anomaly anomaly1 = new Anomaly.Builder().setUid(UID).build();
@@ -256,7 +257,7 @@ public class PowerUsageSummaryTest {
}
@Test
- public void testRestartBatteryTipLoader() {
+ public void restartBatteryTipLoader() {
//TODO: add policy logic here when BatteryTipPolicy is implemented
doReturn(mLoaderManager).when(mFragment).getLoaderManager();
@@ -267,7 +268,7 @@ public class PowerUsageSummaryTest {
}
@Test
- public void testShowBothEstimates_summariesAreBothModified() {
+ public void showBothEstimates_summariesAreBothModified() {
when(mFeatureFactory.powerUsageFeatureProvider.isEnhancedBatteryPredictionEnabled(any()))
.thenReturn(true);
doAnswer(new Answer() {
@@ -296,7 +297,7 @@ public class PowerUsageSummaryTest {
}
@Test
- public void testDebugMode() {
+ public void debugMode() {
doReturn(true).when(mFeatureFactory.powerUsageFeatureProvider).isEstimateDebugEnabled();
doReturn(new TextView(mRealContext)).when(mBatteryLayoutPref).findViewById(R.id.summary2);
@@ -315,7 +316,7 @@ public class PowerUsageSummaryTest {
}
@Test
- public void testRestartBatteryStatsLoader_notClearHeader_quickUpdateNotInvoked() {
+ public void restartBatteryStatsLoader_notClearHeader_quickUpdateNotInvoked() {
mFragment.mBatteryHeaderPreferenceController = mBatteryHeaderPreferenceController;
mFragment.restartBatteryStatsLoader(false /* clearHeader */);
@@ -324,7 +325,7 @@ public class PowerUsageSummaryTest {
}
@Test
- public void testOptionsMenu_advancedPageEnabled() {
+ public void optionsMenu_advancedPageEnabled() {
when(mFeatureFactory.powerUsageFeatureProvider.isPowerAccountingToggleEnabled())
.thenReturn(true);
@@ -335,7 +336,7 @@ public class PowerUsageSummaryTest {
}
@Test
- public void testOptionsMenu_clickAdvancedPage_fireIntent() {
+ public void optionsMenu_clickAdvancedPage_fireIntent() {
final ArgumentCaptor captor = ArgumentCaptor.forClass(Intent.class);
doAnswer(invocation -> {
// Get the intent in which it has the app info bundle
@@ -353,13 +354,27 @@ public class PowerUsageSummaryTest {
}
@Test
- public void testRefreshUi_deviceRotate_doNotUpdateBatteryTip() {
- mFragment.mNeedUpdateBatteryTip = false;
+ public void refreshUi_deviceRotate_doNotUpdateBatteryTip() {
+ mFragment.mBatteryTipPreferenceController = mock(BatteryTipPreferenceController.class);
+ when(mFragment.mBatteryTipPreferenceController.needUpdate()).thenReturn(false);
+ mFragment.updateBatteryTipFlag(new Bundle());
+
mFragment.refreshUi();
verify(mFragment, never()).restartBatteryTipLoader();
}
+ @Test
+ public void refreshUi_tipNeedUpdate_updateBatteryTip() {
+ mFragment.mBatteryTipPreferenceController = mock(BatteryTipPreferenceController.class);
+ when(mFragment.mBatteryTipPreferenceController.needUpdate()).thenReturn(true);
+ mFragment.updateBatteryTipFlag(new Bundle());
+
+ mFragment.refreshUi();
+
+ verify(mFragment).restartBatteryTipLoader();
+ }
+
public static class TestFragment extends PowerUsageSummary {
private Context mContext;
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/RestrictedAppDetailsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/RestrictedAppDetailsTest.java
index 94a690326df..0fad0a7635e 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/RestrictedAppDetailsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/RestrictedAppDetailsTest.java
@@ -28,10 +28,12 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.UserHandle;
+import android.support.v7.preference.CheckBoxPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceCategory;
import android.support.v7.preference.PreferenceManager;
import android.util.IconDrawableFactory;
+import android.widget.CheckBox;
import com.android.settings.SettingsActivity;
import com.android.settings.core.InstrumentedPreferenceFragment;
@@ -93,7 +95,7 @@ public class RestrictedAppDetailsTest {
mRestrictedAppDetails.mAppInfos = new ArrayList<>();
mRestrictedAppDetails.mAppInfos.add(mAppInfo);
mRestrictedAppDetails.mRestrictedAppListGroup = spy(new PreferenceCategory(mContext));
- mRestrictedAppDetails.mBatteryUtils = new BatteryUtils(mContext);
+ mRestrictedAppDetails.mBatteryUtils = spy(new BatteryUtils(mContext));
doReturn(mPreferenceManager).when(
mRestrictedAppDetails.mRestrictedAppListGroup).getPreferenceManager();
}
@@ -103,13 +105,16 @@ public class RestrictedAppDetailsTest {
doReturn(mApplicationInfo).when(mPackageManager)
.getApplicationInfoAsUser(PACKAGE_NAME, 0, USER_ID);
doReturn(APP_NAME).when(mPackageManager).getApplicationLabel(mApplicationInfo);
+ doReturn(true).when(mRestrictedAppDetails.mBatteryUtils).isForceAppStandbyEnabled(UID,
+ PACKAGE_NAME);
mRestrictedAppDetails.refreshUi();
assertThat(mRestrictedAppDetails.mRestrictedAppListGroup.getPreferenceCount()).isEqualTo(1);
- final Preference preference = mRestrictedAppDetails.mRestrictedAppListGroup.getPreference(
- 0);
+ final CheckBoxPreference preference =
+ (CheckBoxPreference) mRestrictedAppDetails.mRestrictedAppListGroup.getPreference(0);
assertThat(preference.getTitle()).isEqualTo(APP_NAME);
+ assertThat(preference.isChecked()).isTrue();
}
@Test
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTipTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTipTest.java
index cee647ec004..405e761c030 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTipTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterytip/tips/BatteryTipTest.java
@@ -74,6 +74,7 @@ public class BatteryTipTest {
assertThat(parcelTip.getTitle(mContext)).isEqualTo(TITLE);
assertThat(parcelTip.getSummary(mContext)).isEqualTo(SUMMARY);
assertThat(parcelTip.getIconId()).isEqualTo(ICON_ID);
+ assertThat(parcelTip.needUpdate()).isTrue();
}
@Test
diff --git a/tests/robotests/src/com/android/settings/inputmethod/KeyboardLayoutPickerControllerTest.java b/tests/robotests/src/com/android/settings/inputmethod/KeyboardLayoutPickerControllerTest.java
new file mode 100644
index 00000000000..a7df0a4a8bf
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/inputmethod/KeyboardLayoutPickerControllerTest.java
@@ -0,0 +1,191 @@
+/*
+ * 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.inputmethod;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.content.Context;
+import android.hardware.input.InputDeviceIdentifier;
+import android.hardware.input.InputManager;
+import android.hardware.input.KeyboardLayout;
+import android.support.v7.preference.PreferenceManager;
+import android.support.v7.preference.PreferenceScreen;
+import android.view.InputDevice;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowInputDevice;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.Robolectric;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowApplication;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class KeyboardLayoutPickerControllerTest {
+
+ @Mock
+ private Fragment mFragment;
+ @Mock
+ private InputManager mInputManager;
+
+ private Context mContext;
+ private InputDeviceIdentifier mInputDeviceIdentifier;
+ private KeyboardLayoutPickerController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ final ShadowApplication shadowContext = ShadowApplication.getInstance();
+ shadowContext.setSystemService(Context.INPUT_SERVICE, mInputManager);
+
+ mContext = RuntimeEnvironment.application;
+ mInputDeviceIdentifier = new InputDeviceIdentifier("descriptor", 1, 1);
+ mController = new KeyboardLayoutPickerController(mContext, "pref_key");
+
+ initializeOneLayout();
+ }
+
+ @Test
+ public void isAlwaysAvailable() {
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.AVAILABLE);
+ }
+
+ @Test
+ public void testLifecycle_onStart_shouldRegisterInputManager() {
+ final Activity activity = Robolectric.setupActivity(Activity.class);
+ when(mFragment.getActivity()).thenReturn(activity);
+
+ mController.onStart();
+
+ // Register is called, but unregister should not be called.
+ verify(mInputManager).registerInputDeviceListener(mController, null);
+ verify(mInputManager, never()).unregisterInputDeviceListener(mController);
+ }
+
+ @Test
+ public void testLifecycle_onStart_NoInputDevice_shouldFinish() {
+ final Activity activity = Robolectric.setupActivity(Activity.class);
+ when(mInputManager.getInputDeviceByDescriptor(anyString())).thenReturn(null);
+ when(mFragment.getActivity()).thenReturn(activity);
+
+ mController.onStart();
+ assertThat(activity.isFinishing()).isTrue();
+ }
+
+ @Test
+ public void testLifecycle_onStop_shouldCancelRegisterInputManager() {
+ mController.onStop();
+
+ // Unregister is called, but register should not be called.
+ verify(mInputManager).unregisterInputDeviceListener(mController);
+ verify(mInputManager, never()).registerInputDeviceListener(mController, null);
+ }
+
+ @Test
+ public void test_createPreferenceHierarchy_shouldAddOnePreference() {
+ final PreferenceManager preferenceManager = new PreferenceManager(mContext);
+ final PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext);
+
+ mController.displayPreference(screen);
+
+ // We cretate a keyboard layouts in initializeOneLayout()
+ assertThat(screen.getPreferenceCount()).isEqualTo(1);
+ }
+
+ @Test
+ public void test_createPreferenceHierarchy_shouldAddTwoPreference() {
+ initializeTwoLayouts();
+ final PreferenceManager preferenceManager = new PreferenceManager(mContext);
+ final PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext);
+
+ mController.displayPreference(screen);
+
+ // We cretate two keyboard layouts in initializeOneLayout()
+ assertThat(screen.getPreferenceCount()).isEqualTo(2);
+ }
+
+ @Test
+ @Config(shadows = ShadowInputDevice.class)
+ public void testOnDeviceRemove_getSameDevice_shouldFinish() {
+ final int TARGET_DEVICE_ID = 1;
+ final Activity activity = Robolectric.setupActivity(Activity.class);
+ final String[] enableKeyboardLayouts = {"layout1"};
+ final InputDevice device = ShadowInputDevice.makeInputDevicebyId(TARGET_DEVICE_ID);
+
+ when(mFragment.getActivity()).thenReturn(activity);
+ when(mInputManager.getInputDeviceByDescriptor(anyString())).thenReturn(device);
+ when(mInputManager.getEnabledKeyboardLayoutsForInputDevice(
+ any(InputDeviceIdentifier.class))).thenReturn(enableKeyboardLayouts);
+
+ mController.onStart();
+ mController.onInputDeviceRemoved(TARGET_DEVICE_ID);
+
+ assertThat(activity.isFinishing()).isTrue();
+ }
+
+ @Test
+ @Config(shadows = ShadowInputDevice.class)
+ public void testOnDeviceRemove_getDifferentDevice_shouldNotFinish() {
+ final int TARGET_DEVICE_ID = 1;
+ final int ANOTHER_DEVICE_ID = 2;
+ final Activity activity = Robolectric.setupActivity(Activity.class);
+ final String[] enableKeyboardLayouts = {"layout1"};
+ final InputDevice device = ShadowInputDevice.makeInputDevicebyId(TARGET_DEVICE_ID);
+
+ when(mFragment.getActivity()).thenReturn(activity);
+ when(mInputManager.getInputDeviceByDescriptor(anyString())).thenReturn(device);
+ when(mInputManager.getEnabledKeyboardLayoutsForInputDevice(
+ any(InputDeviceIdentifier.class))).thenReturn(enableKeyboardLayouts);
+
+ mController.onStart();
+ mController.onInputDeviceRemoved(ANOTHER_DEVICE_ID);
+
+ assertThat(activity.isFinishing()).isFalse();
+ }
+
+ private void initializeOneLayout() {
+ final KeyboardLayout[] keyboardLayouts = {new KeyboardLayout("", "", "", 1, null, 1, 1)};
+ when(mInputManager.getKeyboardLayoutsForInputDevice(
+ any(InputDeviceIdentifier.class))).thenReturn(
+ keyboardLayouts);
+
+ mController.initialize(mFragment, mInputDeviceIdentifier);
+ }
+
+ private void initializeTwoLayouts() {
+ final KeyboardLayout[] keyboardLayouts = {new KeyboardLayout("", "", "", 1, null, 1, 1),
+ new KeyboardLayout("", "", "", 2, null, 2, 2)};
+ when(mInputManager.getKeyboardLayoutsForInputDevice(any(InputDeviceIdentifier.class))).
+ thenReturn(keyboardLayouts);
+
+ mController.initialize(mFragment, mInputDeviceIdentifier);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/inputmethod/UserDictionaryListControllerTest.java b/tests/robotests/src/com/android/settings/inputmethod/UserDictionaryListControllerTest.java
new file mode 100644
index 00000000000..273a0054c79
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/inputmethod/UserDictionaryListControllerTest.java
@@ -0,0 +1,173 @@
+/*
+ * 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.inputmethod;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.net.Uri;
+import android.provider.UserDictionary;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceManager;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadows.ShadowContentResolver;
+
+import java.util.TreeSet;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class UserDictionaryListControllerTest {
+
+ private Preference mPreference;
+ private PreferenceScreen mPreferenceScreen;
+ private FakeProvider mContentProvider;
+ private UserDictionaryListPreferenceController mController;
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContentProvider = new FakeProvider();
+ ShadowContentResolver.registerProviderInternal(UserDictionary.AUTHORITY, mContentProvider);
+ mContext = RuntimeEnvironment.application;
+ mController = spy(new UserDictionaryListPreferenceController(mContext, "controller_key"));
+ mPreference = new Preference(mContext);
+ final PreferenceManager preferenceManager = new PreferenceManager(mContext);
+ mPreferenceScreen = preferenceManager.createPreferenceScreen(mContext);
+ }
+
+ @Test
+ public void userDictionaryList_byDefault_shouldBeShown() {
+ assertThat(mController.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void getUserDictionaryLocalesSet_noLocale_shouldReturnEmptySet() {
+ mContentProvider.hasDictionary = false;
+
+ assertThat(UserDictionaryListPreferenceController.getUserDictionaryLocalesSet(
+ mContext)).isEmpty();
+ }
+
+ @Test
+ public void displayPreference_isOrderingAsAdd_shouldBeFalse() {
+ mController.displayPreference(mPreferenceScreen);
+
+ assertThat(mPreferenceScreen.isOrderingAsAdded()).isFalse();
+ }
+
+ @Test
+ public void createUserDictSettings_emptyLocaleSetWithNewScreen_shouldAddOnePreference() {
+ final TreeSet locales = new TreeSet<>();
+
+ doReturn(locales).when(mController).getUserDictLocalesSet(mContext);
+
+ mController.setLocale(null);
+ mController.displayPreference(mPreferenceScreen);
+ mController.onStart();
+
+ assertThat(mPreferenceScreen.getPreferenceCount()).isEqualTo(1);
+ }
+
+ @Test
+ public void createUserDictSettings_emptyLocaleSetWithOldScreen_shouldNotAddNewPreference() {
+ final TreeSet locales = new TreeSet<>();
+
+ doReturn(locales).when(mController).getUserDictLocalesSet(mContext);
+ mPreferenceScreen.addPreference(mPreference);
+
+ mController.setLocale(null);
+ mController.displayPreference(mPreferenceScreen);
+ mController.onStart();
+
+ assertThat(mPreferenceScreen.getPreferenceCount()).isEqualTo(1);
+ }
+
+ @Test
+ public void createUserDictSettings_threeLocales_shouldAddFourPreference() {
+ //There will be 4 preferences : 3 locales + 1 "All languages" entry
+ final TreeSet locales = new TreeSet<>();
+ locales.add("en");
+ locales.add("es");
+ locales.add("fr");
+
+ doReturn(locales).when(mController).getUserDictLocalesSet(mContext);
+
+ mController.setLocale("en");
+ mController.displayPreference(mPreferenceScreen);
+ mController.onStart();
+
+ assertThat(mPreferenceScreen.getPreferenceCount()).isEqualTo(4);
+ }
+
+ public static class FakeProvider extends ContentProvider {
+
+ private boolean hasDictionary = true;
+
+ @Override
+ public boolean onCreate() {
+ return false;
+ }
+
+ @Override
+ public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
+ String sortOrder) {
+ if (hasDictionary) {
+ final MatrixCursor cursor = new MatrixCursor(
+ new String[] {UserDictionary.Words.LOCALE});
+ cursor.addRow(new Object[] {"en"});
+ cursor.addRow(new Object[] {"es"});
+ return cursor;
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public String getType(Uri uri) {
+ return null;
+ }
+
+ @Override
+ public Uri insert(Uri uri, ContentValues values) {
+ return null;
+ }
+
+ @Override
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
+ return 0;
+ }
+
+ @Override
+ public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
+ return 0;
+ }
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/inputmethod/UserDictionaryListTest.java b/tests/robotests/src/com/android/settings/inputmethod/UserDictionaryListTest.java
deleted file mode 100644
index eaf5b1d21e6..00000000000
--- a/tests/robotests/src/com/android/settings/inputmethod/UserDictionaryListTest.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.inputmethod;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.ContentProvider;
-import android.content.ContentValues;
-import android.content.Context;
-import android.database.Cursor;
-import android.database.MatrixCursor;
-import android.net.Uri;
-import android.provider.UserDictionary;
-
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.shadows.ShadowContentResolver;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-public class UserDictionaryListTest {
-
- private FakeProvider mContentProvider;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mContentProvider = new FakeProvider();
- ShadowContentResolver.registerProviderInternal(UserDictionary.AUTHORITY, mContentProvider);
- }
-
- @Test
- public void getUserDictionaryLocalesSet_noLocale_shouldReturnEmptySet() {
- mContentProvider.hasDictionary = false;
-
- final Context context = RuntimeEnvironment.application;
- assertThat(UserDictionaryList.getUserDictionaryLocalesSet(context)).isEmpty();
- }
-
- public static class FakeProvider extends ContentProvider {
-
- private boolean hasDictionary = true;
-
- @Override
- public boolean onCreate() {
- return false;
- }
-
- @Override
- public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
- String sortOrder) {
- if (hasDictionary) {
- final MatrixCursor cursor = new MatrixCursor(
- new String[]{UserDictionary.Words.LOCALE});
- cursor.addRow(new Object[]{"en"});
- cursor.addRow(new Object[]{"es"});
- return cursor;
- } else {
- return null;
- }
- }
-
- @Override
- public String getType(Uri uri) {
- return null;
- }
-
- @Override
- public Uri insert(Uri uri, ContentValues values) {
- return null;
- }
-
- @Override
- public int delete(Uri uri, String selection, String[] selectionArgs) {
- return 0;
- }
-
- @Override
- public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
- return 0;
- }
- }
-}
diff --git a/tests/robotests/src/com/android/settings/network/ApnEditorTest.java b/tests/robotests/src/com/android/settings/network/ApnEditorTest.java
index 1b34fd3f98b..35f68a06698 100644
--- a/tests/robotests/src/com/android/settings/network/ApnEditorTest.java
+++ b/tests/robotests/src/com/android/settings/network/ApnEditorTest.java
@@ -437,6 +437,16 @@ public class ApnEditorTest {
assertThat(str).isNull();
}
+ @Test
+ public void formatInteger_shouldParseString() {
+ assertThat(ApnEditor.formatInteger("42")).isEqualTo("42");
+ }
+
+ @Test
+ public void formatInteger_shouldIgnoreNonIntegers() {
+ assertThat(ApnEditor.formatInteger("not an int")).isEqualTo("not an int");
+ }
+
private void initCursor() {
doReturn(2).when(mCursor).getColumnCount();
doReturn(Integer.valueOf(2)).when(mCursor).getInt(CURSOR_INTEGER_INDEX);
diff --git a/tests/robotests/src/com/android/settings/network/NetworkDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/network/NetworkDashboardFragmentTest.java
index 06e334af886..187f0dc2882 100644
--- a/tests/robotests/src/com/android/settings/network/NetworkDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/network/NetworkDashboardFragmentTest.java
@@ -16,18 +16,14 @@
package com.android.settings.network;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.provider.SearchIndexableResource;
-import android.view.Menu;
-import com.android.settings.R;
import com.android.settings.dashboard.SummaryLoader;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.drawer.CategoryKey;
@@ -35,45 +31,41 @@ import com.android.settingslib.drawer.CategoryKey;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
import org.robolectric.RuntimeEnvironment;
-import org.robolectric.util.ReflectionHelpers;
import java.util.List;
@RunWith(SettingsRobolectricTestRunner.class)
public class NetworkDashboardFragmentTest {
- @Mock
private Context mContext;
private NetworkDashboardFragment mFragment;
@Before
public void setUp() {
- MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
mFragment = new NetworkDashboardFragment();
}
@Test
- public void testCategory_isNetwork() {
+ public void getCategoryKey_isNetwork() {
assertThat(mFragment.getCategoryKey()).isEqualTo(CategoryKey.CATEGORY_NETWORK);
}
@Test
- public void testSearchIndexProvider_shouldIndexResource() {
+ public void getXmlResourcesToIndex_shouldIncludeFragmentXml() {
final List indexRes =
NetworkDashboardFragment.SEARCH_INDEX_DATA_PROVIDER.getXmlResourcesToIndex(
- RuntimeEnvironment.application,
+ mContext,
true /* enabled */);
- assertThat(indexRes).isNotNull();
+ assertThat(indexRes).hasSize(1);
assertThat(indexRes.get(0).xmlResId).isEqualTo(mFragment.getPreferenceScreenResId());
}
@Test
- public void testSummaryProvider_hasMobileAndHotspot_shouldReturnMobileSummary() {
+ public void summaryProviderSetListening_hasMobileAndHotspot_shouldReturnMobileSummary() {
final MobileNetworkPreferenceController mobileNetworkPreferenceController =
mock(MobileNetworkPreferenceController.class);
final TetherPreferenceController tetherPreferenceController =
@@ -93,15 +85,11 @@ public class NetworkDashboardFragmentTest {
provider.setListening(true);
- verify(mContext).getString(R.string.wifi_settings_title);
- verify(mContext).getString(R.string.network_dashboard_summary_data_usage);
- verify(mContext).getString(R.string.network_dashboard_summary_hotspot);
- verify(mContext).getString(R.string.network_dashboard_summary_mobile);
- verify(mContext, times(3)).getString(R.string.join_many_items_middle, null, null);
+ verify(summaryLoader).setSummary(provider, "Wi\u2011Fi, mobile, data usage, and hotspot");
}
@Test
- public void testSummaryProvider_noMobileOrHotspot_shouldReturnSimpleSummary() {
+ public void summaryProviderSetListening_noMobileOrHotspot_shouldReturnSimpleSummary() {
final MobileNetworkPreferenceController mobileNetworkPreferenceController =
mock(MobileNetworkPreferenceController.class);
final TetherPreferenceController tetherPreferenceController =
@@ -121,8 +109,6 @@ public class NetworkDashboardFragmentTest {
provider.setListening(true);
- verify(mContext).getString(R.string.wifi_settings_title);
- verify(mContext).getString(R.string.network_dashboard_summary_data_usage);
- verify(mContext).getString(R.string.join_many_items_middle, null, null);
+ verify(summaryLoader).setSummary(provider, "Wi\u2011Fi and data usage");
}
-}
\ No newline at end of file
+}
diff --git a/tests/robotests/src/com/android/settings/notification/DndPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/DndPreferenceControllerTest.java
index 54dda6af881..ba612ac2ee8 100644
--- a/tests/robotests/src/com/android/settings/notification/DndPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/DndPreferenceControllerTest.java
@@ -64,8 +64,6 @@ public class DndPreferenceControllerTest {
private UserManager mUm;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private PreferenceScreen mScreen;
- @Mock
- private Lifecycle mLifecycle;
private DndPreferenceController mController;
@@ -76,7 +74,7 @@ public class DndPreferenceControllerTest {
shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNm);
shadowApplication.setSystemService(Context.USER_SERVICE, mUm);
mContext = RuntimeEnvironment.application;
- mController = spy(new DndPreferenceController(mContext, mLifecycle, mBackend));
+ mController = spy(new DndPreferenceController(mContext, mBackend));
}
@Test
diff --git a/tests/robotests/src/com/android/settings/notification/PulseNotificationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/PulseNotificationPreferenceControllerTest.java
index 0d4e6c46b12..905cb6f64eb 100644
--- a/tests/robotests/src/com/android/settings/notification/PulseNotificationPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/PulseNotificationPreferenceControllerTest.java
@@ -19,15 +19,19 @@ package com.android.settings.notification;
import static android.provider.Settings.System.NOTIFICATION_LIGHT_PULSE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
+import android.content.res.Resources;
import android.provider.Settings;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceScreen;
import android.support.v7.preference.TwoStatePreference;
+import com.android.settings.core.BasePreferenceController;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -40,8 +44,9 @@ import org.robolectric.RuntimeEnvironment;
@RunWith(RobolectricTestRunner.class)
public class PulseNotificationPreferenceControllerTest {
- @Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Context mContext;
+ @Mock
+ private Resources mResources;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private PreferenceScreen mScreen;
@@ -51,8 +56,11 @@ public class PulseNotificationPreferenceControllerTest {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mController = new PulseNotificationPreferenceController(mContext);
- mPreference = new Preference(RuntimeEnvironment.application);
+ mContext = spy(RuntimeEnvironment.application);
+ when(mContext.getResources()).thenReturn(mResources);
+
+ mController = new PulseNotificationPreferenceController(mContext, "testkey");
+ mPreference = new Preference(mContext);
mPreference.setKey(mController.getPreferenceKey());
when(mScreen.findPreference(mPreference.getKey())).thenReturn(mPreference);
}
@@ -62,6 +70,7 @@ public class PulseNotificationPreferenceControllerTest {
when(mContext.getResources().
getBoolean(com.android.internal.R.bool.config_intrusiveNotificationLed))
.thenReturn(true);
+
mController.displayPreference(mScreen);
assertThat(mPreference.isVisible()).isTrue();
@@ -84,7 +93,7 @@ public class PulseNotificationPreferenceControllerTest {
final Context context = RuntimeEnvironment.application;
Settings.System.putInt(context.getContentResolver(), NOTIFICATION_LIGHT_PULSE, 1);
- mController = new PulseNotificationPreferenceController(context);
+ mController = new PulseNotificationPreferenceController(context, "testkey");
mController.updateState(preference);
verify(preference).setChecked(true);
@@ -96,9 +105,65 @@ public class PulseNotificationPreferenceControllerTest {
final Context context = RuntimeEnvironment.application;
Settings.System.putInt(context.getContentResolver(), NOTIFICATION_LIGHT_PULSE, 0);
- mController = new PulseNotificationPreferenceController(context);
+ mController = new PulseNotificationPreferenceController(context, "testkey");
mController.updateState(preference);
verify(preference).setChecked(false);
}
+
+ @Test
+ public void isAvailable_configTrue_shouldReturnTrue() {
+ when(mContext.getResources().
+ getBoolean(com.android.internal.R.bool.config_intrusiveNotificationLed)).thenReturn(
+ true);
+
+ assertThat(mController.isAvailable()).isTrue();
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(
+ BasePreferenceController.AVAILABLE);
+ }
+
+ @Test
+ public void isAvailable_configFalse_shouldReturnFalse() {
+ when(mContext.getResources().
+ getBoolean(com.android.internal.R.bool.config_intrusiveNotificationLed)).thenReturn(
+ false);
+
+ assertThat(mController.isAvailable()).isFalse();
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(
+ BasePreferenceController.DISABLED_UNSUPPORTED);
+ }
+
+ @Test
+ public void isChecked_configOn_shouldReturnTrue() {
+ Settings.Secure.putInt(mContext.getContentResolver(), NOTIFICATION_LIGHT_PULSE, 1);
+
+ assertThat(mController.isChecked()).isTrue();
+ }
+
+ @Test
+ public void isChecked_configOff_shouldReturnFalse() {
+ Settings.Secure.putInt(mContext.getContentResolver(), NOTIFICATION_LIGHT_PULSE, 0);
+
+ assertThat(mController.isChecked()).isFalse();
+ }
+
+ @Test
+ public void testSetChecked_configIsSet_shouldReturnTrue() {
+ mController.setChecked(true);
+
+ assertThat(mController.isChecked()).isTrue();
+ assertThat(
+ Settings.Secure.getInt(mContext.getContentResolver(), NOTIFICATION_LIGHT_PULSE, 0))
+ .isEqualTo(1);
+ }
+
+ @Test
+ public void testSetChecked_configIsNotSet_shouldReturnFalse() {
+ mController.setChecked(false);
+
+ assertThat(mController.isChecked()).isFalse();
+ assertThat(
+ Settings.Secure.getInt(mContext.getContentResolver(), NOTIFICATION_LIGHT_PULSE, 1))
+ .isEqualTo(0);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/notification/ZenModeVisEffectPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ZenModeVisEffectPreferenceControllerTest.java
index 6ca04ba7c6f..29ced0b2ab0 100644
--- a/tests/robotests/src/com/android/settings/notification/ZenModeVisEffectPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ZenModeVisEffectPreferenceControllerTest.java
@@ -42,6 +42,7 @@ import android.support.v7.preference.PreferenceScreen;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settings.widget.DisabledCheckBoxPreference;
import org.junit.Before;
import org.junit.Test;
@@ -58,7 +59,7 @@ public class ZenModeVisEffectPreferenceControllerTest {
@Mock
private ZenModeBackend mBackend;
@Mock
- private CheckBoxPreference mockPref;
+ private DisabledCheckBoxPreference mockPref;
private Context mContext;
private FakeFeatureFactory mFeatureFactory;
@Mock
@@ -114,7 +115,7 @@ public class ZenModeVisEffectPreferenceControllerTest {
mController.updateState(mockPref);
verify(mockPref).setChecked(false);
- verify(mockPref).setEnabled(true);
+ verify(mockPref).enableCheckbox(true);
}
@Test
@@ -123,7 +124,7 @@ public class ZenModeVisEffectPreferenceControllerTest {
mController.updateState(mockPref);
verify(mockPref).setChecked(true);
- verify(mockPref).setEnabled(true);
+ verify(mockPref).enableCheckbox(true);
}
@Test
@@ -138,7 +139,7 @@ public class ZenModeVisEffectPreferenceControllerTest {
mController.updateState(mockPref);
verify(mockPref).setChecked(true);
- verify(mockPref).setEnabled(false);
+ verify(mockPref).enableCheckbox(false);
verify(mBackend, times(1)).saveVisualEffectsPolicy(SUPPRESSED_EFFECT_PEEK, true);
}
@@ -154,7 +155,7 @@ public class ZenModeVisEffectPreferenceControllerTest {
mController.updateState(mockPref);
verify(mockPref).setChecked(false);
- verify(mockPref).setEnabled(true);
+ verify(mockPref).enableCheckbox(true);
verify(mBackend, never()).saveVisualEffectsPolicy(SUPPRESSED_EFFECT_PEEK, true);
}
diff --git a/tests/robotests/src/com/android/settings/security/LockdownButtonPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/security/LockdownButtonPreferenceControllerTest.java
index 023324c1795..de44c4599be 100644
--- a/tests/robotests/src/com/android/settings/security/LockdownButtonPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/security/LockdownButtonPreferenceControllerTest.java
@@ -51,24 +51,24 @@ public class LockdownButtonPreferenceControllerTest {
mContext = RuntimeEnvironment.application;
mPreference = new SwitchPreference(mContext);
- mController = spy(new LockdownButtonPreferenceController(mContext));
+ mController = spy(new LockdownButtonPreferenceController(mContext, "TestKey"));
ReflectionHelpers.setField(mController, "mLockPatternUtils", mLockPatternUtils);
}
@Test
- public void isAvailable_lockSet_shouldReturnTrue() throws Exception {
+ public void isAvailable_lockSet_shouldReturnTrue() {
when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true);
assertThat(mController.isAvailable()).isTrue();
}
@Test
- public void isAvailable_lockUnset_shouldReturnFalse() throws Exception {
+ public void isAvailable_lockUnset_shouldReturnFalse() {
when(mLockPatternUtils.isSecure(anyInt())).thenReturn(false);
assertThat(mController.isAvailable()).isFalse();
}
@Test
- public void onPreferenceChange_settingIsUpdated() throws Exception {
+ public void onPreferenceChange_settingIsUpdated() {
boolean state = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.LOCKDOWN_IN_POWER_MENU, 0) != 0;
assertThat(mController.onPreferenceChange(mPreference, !state)).isTrue();
@@ -78,7 +78,7 @@ public class LockdownButtonPreferenceControllerTest {
}
@Test
- public void onSettingChange_preferenceIsUpdated() throws Exception {
+ public void onSettingChange_preferenceIsUpdated() {
boolean state = Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.LOCKDOWN_IN_POWER_MENU, 0) != 0;
mController.updateState(mPreference);
diff --git a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
index d54d16fc6a4..b5399eaa951 100644
--- a/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SettingsSliceProviderTest.java
@@ -17,6 +17,8 @@
package com.android.settings.slices;
+import static android.content.ContentResolver.SCHEME_CONTENT;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
@@ -41,6 +43,7 @@ import org.robolectric.RuntimeEnvironment;
import androidx.slice.Slice;
+import java.util.Collection;
import java.util.HashMap;
/**
@@ -114,7 +117,190 @@ public class SettingsSliceProviderTest {
assertThat(cachedData).isNull();
}
+ @Test
+ public void getDescendantUris_fullActionUri_returnsSelf() {
+ final Uri uri = SliceBuilderUtils.getUri(
+ SettingsSlicesContract.PATH_SETTING_ACTION + "/key", true);
+
+ final Collection descendants = mProvider.onGetSliceDescendants(uri);
+
+ assertThat(descendants).containsExactly(uri);
+ }
+
+ @Test
+ public void getDescendantUris_fullIntentUri_returnsSelf() {
+ final Uri uri = SliceBuilderUtils.getUri(
+ SettingsSlicesContract.PATH_SETTING_ACTION + "/key", true);
+
+ final Collection descendants = mProvider.onGetSliceDescendants(uri);
+
+ assertThat(descendants).containsExactly(uri);
+ }
+
+ @Test
+ public void getDescendantUris_wrongPath_returnsEmpty() {
+ final Uri uri = SliceBuilderUtils.getUri("invalid_path", true);
+
+ final Collection descendants = mProvider.onGetSliceDescendants(uri);
+
+ assertThat(descendants).isEmpty();
+ }
+
+ @Test
+ public void getDescendantUris_invalidPath_returnsEmpty() {
+ final String key = "platform_key";
+ insertSpecialCase(key, true /* isPlatformSlice */);
+ final Uri uri = new Uri.Builder()
+ .scheme(SCHEME_CONTENT)
+ .authority(SettingsSlicesContract.AUTHORITY)
+ .appendPath("invalid")
+ .build();
+
+ final Collection descendants = mProvider.onGetSliceDescendants(uri);
+
+ assertThat(descendants).isEmpty();
+ }
+
+ @Test
+ public void getDescendantUris_platformSlice_doesNotReturnOEMSlice() {
+ insertSpecialCase("oem_key", false /* isPlatformSlice */);
+ final Uri uri = new Uri.Builder()
+ .scheme(SCHEME_CONTENT)
+ .authority(SettingsSlicesContract.AUTHORITY)
+ .build();
+
+ final Collection descendants = mProvider.onGetSliceDescendants(uri);
+
+ assertThat(descendants).isEmpty();
+ }
+
+ @Test
+ public void getDescendantUris_oemSlice_doesNotReturnPlatformSlice() {
+ insertSpecialCase("platform_key", true /* isPlatformSlice */);
+ final Uri uri = new Uri.Builder()
+ .scheme(SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .build();
+
+ final Collection descendants = mProvider.onGetSliceDescendants(uri);
+
+ assertThat(descendants).isEmpty();
+ }
+
+ @Test
+ public void getDescendantUris_oemSlice_returnsOEMUriDescendant() {
+ final String key = "oem_key";
+ insertSpecialCase(key, false /* isPlatformSlice */);
+ final Uri uri = new Uri.Builder()
+ .scheme(SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .build();
+ final Uri expectedUri = new Uri.Builder()
+ .scheme(SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath(key)
+ .build();
+
+ final Collection descendants = mProvider.onGetSliceDescendants(uri);
+
+ assertThat(descendants).containsExactly(expectedUri);
+ }
+
+ @Test
+ public void getDescendantUris_oemSliceNoPath_returnsOEMUriDescendant() {
+ final String key = "oem_key";
+ insertSpecialCase(key, false /* isPlatformSlice */);
+ final Uri uri = new Uri.Builder()
+ .scheme(SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .build();
+ final Uri expectedUri = new Uri.Builder()
+ .scheme(SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath(key)
+ .build();
+
+ final Collection descendants = mProvider.onGetSliceDescendants(uri);
+
+ assertThat(descendants).containsExactly(expectedUri);
+ }
+
+ @Test
+ public void getDescendantUris_platformSlice_returnsPlatformUriDescendant() {
+ final String key = "platform_key";
+ insertSpecialCase(key, true /* isPlatformSlice */);
+ final Uri uri = new Uri.Builder()
+ .scheme(SCHEME_CONTENT)
+ .authority(SettingsSlicesContract.AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .build();
+ final Uri expectedUri = new Uri.Builder()
+ .scheme(SCHEME_CONTENT)
+ .authority(SettingsSlicesContract.AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath(key)
+ .build();
+
+ final Collection descendants = mProvider.onGetSliceDescendants(uri);
+
+ assertThat(descendants).containsExactly(expectedUri);
+ }
+
+ @Test
+ public void getDescendantUris_platformSliceNoPath_returnsPlatformUriDescendant() {
+ final String key = "platform_key";
+ insertSpecialCase(key, true /* isPlatformSlice */);
+ final Uri uri = new Uri.Builder()
+ .scheme(SCHEME_CONTENT)
+ .authority(SettingsSlicesContract.AUTHORITY)
+ .build();
+ final Uri expectedUri = new Uri.Builder()
+ .scheme(SCHEME_CONTENT)
+ .authority(SettingsSlicesContract.AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath(key)
+ .build();
+
+ final Collection descendants = mProvider.onGetSliceDescendants(uri);
+
+ assertThat(descendants).containsExactly(expectedUri);
+ }
+
+ @Test
+ public void getDescendantUris_noAuthorityNorPath_returnsAllUris() {
+ final String platformKey = "platform_key";
+ final String oemKey = "oemKey";
+ insertSpecialCase(platformKey, true /* isPlatformSlice */);
+ insertSpecialCase(oemKey, false /* isPlatformSlice */);
+ final Uri uri = new Uri.Builder()
+ .scheme(SCHEME_CONTENT)
+ .build();
+ final Uri expectedPlatformUri = new Uri.Builder()
+ .scheme(SCHEME_CONTENT)
+ .authority(SettingsSlicesContract.AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath(platformKey)
+ .build();
+ final Uri expectedOemUri = new Uri.Builder()
+ .scheme(SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath(oemKey)
+ .build();
+
+ final Collection descendants = mProvider.onGetSliceDescendants(uri);
+
+ assertThat(descendants).containsExactly(expectedPlatformUri, expectedOemUri);
+ }
+
private void insertSpecialCase(String key) {
+ insertSpecialCase(key, true);
+ }
+
+ private void insertSpecialCase(String key, boolean isPlatformSlice) {
ContentValues values = new ContentValues();
values.put(SlicesDatabaseHelper.IndexColumns.KEY, key);
values.put(SlicesDatabaseHelper.IndexColumns.TITLE, TITLE);
@@ -123,6 +309,8 @@ public class SettingsSliceProviderTest {
values.put(SlicesDatabaseHelper.IndexColumns.ICON_RESOURCE, 1234);
values.put(SlicesDatabaseHelper.IndexColumns.FRAGMENT, "test");
values.put(SlicesDatabaseHelper.IndexColumns.CONTROLLER, "test");
+ values.put(SlicesDatabaseHelper.IndexColumns.PLATFORM_SLICE, isPlatformSlice);
+ values.put(SlicesDatabaseHelper.IndexColumns.SLICE_TYPE, SliceData.SliceType.INTENT);
mDb.replaceOrThrow(SlicesDatabaseHelper.Tables.TABLE_SLICES_INDEX, null, values);
}
diff --git a/tests/robotests/src/com/android/settings/slices/SliceBroadcastReceiverTest.java b/tests/robotests/src/com/android/settings/slices/SliceBroadcastReceiverTest.java
index 0cdb2f43d59..0b6e4b5bb32 100644
--- a/tests/robotests/src/com/android/settings/slices/SliceBroadcastReceiverTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SliceBroadcastReceiverTest.java
@@ -18,17 +18,28 @@
package com.android.settings.slices;
import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.app.slice.Slice;
+import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
+import android.database.ContentObserver;
import android.database.sqlite.SQLiteDatabase;
+import android.net.Uri;
+import android.provider.Settings;
+import android.provider.SettingsSlicesContract;
import android.util.Pair;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.core.BasePreferenceController;
import com.android.settings.search.FakeIndexProvider;
import com.android.settings.search.SearchFeatureProvider;
import com.android.settings.search.SearchFeatureProviderImpl;
@@ -36,6 +47,7 @@ import com.android.settings.testutils.DatabaseTestUtils;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.FakeSliderController;
import com.android.settings.testutils.FakeToggleController;
+import com.android.settings.testutils.FakeUnavailablePreferenceController;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.After;
@@ -65,7 +77,7 @@ public class SliceBroadcastReceiverTest {
@Before
public void setUp() {
- mContext = RuntimeEnvironment.application;
+ mContext = spy(RuntimeEnvironment.application);
mDb = SlicesDatabaseHelper.getInstance(mContext).getWritableDatabase();
mReceiver = new SliceBroadcastReceiver();
SlicesDatabaseHelper helper = SlicesDatabaseHelper.getInstance(mContext);
@@ -192,6 +204,77 @@ public class SliceBroadcastReceiverTest {
mReceiver.onReceive(mContext, intent);
}
+ @Test
+ public void toggleUpdate_unavailableUriNotified() {
+ // Monitor the ContentResolver
+ final ContentResolver resolver = spy(mContext.getContentResolver());
+ doReturn(resolver).when(mContext).getContentResolver();
+
+ // Disable Setting
+ Settings.Global.putInt(mContext.getContentResolver(),
+ FakeToggleController.AVAILABILITY_KEY,
+ BasePreferenceController.DISABLED_UNSUPPORTED);
+
+ // Insert Fake Toggle into Database
+ final String key = "key";
+ mSearchFeatureProvider.getSearchIndexableResources().getProviderValues().clear();
+ insertSpecialCase(FakeToggleController.class, key);
+
+ // Turn on toggle setting
+ final FakeToggleController fakeToggleController = new FakeToggleController(mContext, key);
+ fakeToggleController.setChecked(true);
+
+ // Build Action
+ final Intent intent = new Intent(SettingsSliceProvider.ACTION_TOGGLE_CHANGED);
+ intent.putExtra(SettingsSliceProvider.EXTRA_SLICE_KEY, key);
+
+ // Trigger Slice change
+ mReceiver.onReceive(mContext, intent);
+
+ // Check the value is the same and the Uri has been notified.
+ assertThat(fakeToggleController.isChecked()).isTrue();
+ final Uri expectedUri = SliceBuilderUtils.getUri(
+ SettingsSlicesContract.PATH_SETTING_ACTION + "/" + key, false);
+ verify(resolver).notifyChange(eq(expectedUri), eq(null));
+ }
+
+ @Test
+ public void sliderUpdate_unavailableUriNotified() {
+ // Monitor the ContentResolver
+ final ContentResolver resolver = spy(mContext.getContentResolver());
+ doReturn(resolver).when(mContext).getContentResolver();
+
+ // Disable Setting
+ Settings.Global.putInt(mContext.getContentResolver(),
+ FakeSliderController.AVAILABILITY_KEY,
+ BasePreferenceController.DISABLED_UNSUPPORTED);
+
+ // Insert Fake Slider into Database
+ final String key = "key";
+ final int position = FakeSliderController.MAX_STEPS - 1;
+ final int oldPosition = FakeSliderController.MAX_STEPS;
+ mSearchFeatureProvider.getSearchIndexableResources().getProviderValues().clear();
+ insertSpecialCase(FakeSliderController.class, key);
+
+ // Set slider setting
+ final FakeSliderController fakeSliderController = new FakeSliderController(mContext, key);
+ fakeSliderController.setSliderPosition(oldPosition);
+
+ // Build action
+ final Intent intent = new Intent(SettingsSliceProvider.ACTION_SLIDER_CHANGED);
+ intent.putExtra(Slice.EXTRA_RANGE_VALUE, position);
+ intent.putExtra(SettingsSliceProvider.EXTRA_SLICE_KEY, key);
+
+ // Trigger Slice change
+ mReceiver.onReceive(mContext, intent);
+
+ // Check position is the same and the Uri has been notified.
+ assertThat(fakeSliderController.getSliderPosition()).isEqualTo(oldPosition);
+ final Uri expectedUri = SliceBuilderUtils.getUri(
+ SettingsSlicesContract.PATH_SETTING_ACTION + "/" + key, false);
+ verify(resolver).notifyChange(eq(expectedUri), eq(null));
+ }
+
private void insertSpecialCase(String key) {
insertSpecialCase(fakeControllerName, key);
}
diff --git a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
index 59eb7ceceaf..96cf1dc0bbc 100644
--- a/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
@@ -24,7 +24,6 @@ import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
-import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -40,6 +39,7 @@ import com.android.settings.core.BasePreferenceController;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.FakeSliderController;
import com.android.settings.testutils.FakeToggleController;
+import com.android.settings.testutils.FakeUnavailablePreferenceController;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.SliceTester;
@@ -277,7 +277,7 @@ public class SliceBuilderUtilsTest {
final Pair pathPair = SliceBuilderUtils.getPathData(uri);
- assertThat(pathPair.first).isFalse();
+ assertThat(pathPair.first).isTrue();
assertThat(pathPair.second).isEqualTo(KEY);
}
@@ -291,18 +291,20 @@ public class SliceBuilderUtilsTest {
final Pair pathPair = SliceBuilderUtils.getPathData(uri);
- assertThat(pathPair.first).isTrue();
+ assertThat(pathPair.first).isFalse();
assertThat(pathPair.second).isEqualTo(KEY);
}
- @Test(expected = IllegalArgumentException.class)
+ @Test
public void getPathData_noKey_returnsNull() {
final Uri uri = new Uri.Builder()
.authority(SettingsSliceProvider.SLICE_AUTHORITY)
.appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
.build();
- SliceBuilderUtils.getPathData(uri);
+ final Pair pathPair = SliceBuilderUtils.getPathData(uri);
+
+ assertThat(pathPair).isNull();
}
@Test
@@ -316,7 +318,7 @@ public class SliceBuilderUtilsTest {
final Pair pathPair = SliceBuilderUtils.getPathData(uri);
- assertThat(pathPair.first).isTrue();
+ assertThat(pathPair.first).isFalse();
assertThat(pathPair.second).isEqualTo(KEY + "/" + KEY);
}
@@ -324,7 +326,7 @@ public class SliceBuilderUtilsTest {
public void testUnsupportedSlice_validTitleSummary() {
final SliceData data = getDummyData(FakeUnavailablePreferenceController.class,
SliceData.SliceType.SWITCH);
- Settings.System.putInt(mContext.getContentResolver(),
+ Settings.Global.putInt(mContext.getContentResolver(),
FakeUnavailablePreferenceController.AVAILABILITY_KEY,
BasePreferenceController.DISABLED_UNSUPPORTED);
@@ -337,7 +339,7 @@ public class SliceBuilderUtilsTest {
public void testDisabledForUserSlice_validTitleSummary() {
final SliceData data = getDummyData(FakeUnavailablePreferenceController.class,
SliceData.SliceType.SWITCH);
- Settings.System.putInt(mContext.getContentResolver(),
+ Settings.Global.putInt(mContext.getContentResolver(),
FakeUnavailablePreferenceController.AVAILABILITY_KEY,
BasePreferenceController.DISABLED_FOR_USER);
@@ -350,7 +352,7 @@ public class SliceBuilderUtilsTest {
public void testDisabledDependentSettingSlice_validTitleSummary() {
final SliceData data = getDummyData(FakeUnavailablePreferenceController.class,
SliceData.SliceType.INTENT);
- Settings.System.putInt(mContext.getContentResolver(),
+ Settings.Global.putInt(mContext.getContentResolver(),
FakeUnavailablePreferenceController.AVAILABILITY_KEY,
BasePreferenceController.DISABLED_DEPENDENT_SETTING);
@@ -372,7 +374,7 @@ public class SliceBuilderUtilsTest {
public void testUnavailableUnknownSlice_validTitleSummary() {
final SliceData data = getDummyData(FakeUnavailablePreferenceController.class,
SliceData.SliceType.SWITCH);
- Settings.System.putInt(mContext.getContentResolver(),
+ Settings.Global.putInt(mContext.getContentResolver(),
FakeUnavailablePreferenceController.AVAILABILITY_KEY,
BasePreferenceController.UNAVAILABLE_UNKNOWN);
diff --git a/tests/robotests/src/com/android/settings/slices/SliceDataConverterTest.java b/tests/robotests/src/com/android/settings/slices/SliceDataConverterTest.java
index 36c27548c13..adc7a96e7e1 100644
--- a/tests/robotests/src/com/android/settings/slices/SliceDataConverterTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SliceDataConverterTest.java
@@ -17,8 +17,22 @@
package com.android.settings.slices;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.mock;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+
+import android.accessibilityservice.AccessibilityServiceInfo;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.text.TextUtils;
+
+import com.android.settings.R;
+import com.android.settings.accessibility.AccessibilitySettings;
+import com.android.settings.accessibility.AccessibilitySlicePreferenceController;
import com.android.settings.search.FakeIndexProvider;
import com.android.settings.search.SearchFeatureProvider;
import com.android.settings.search.SearchFeatureProviderImpl;
@@ -32,17 +46,29 @@ import org.junit.runner.RunWith;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
+import java.util.ArrayList;
import java.util.List;
@RunWith(SettingsRobolectricTestRunner.class)
public class SliceDataConverterTest {
- private final String fakeKey = "key";
- private final String fakeTitle = "title";
- private final String fakeSummary = "summary";
- private final String fakeScreenTitle = "screen_title";
- private final String fakeFragmentClassName = FakeIndexProvider.class.getName();
- private final String fakeControllerName = FakePreferenceController.class.getName();
+ private final String FAKE_KEY = "key";
+ private final String FAKE_TITLE = "title";
+ private final String FAKE_SUMMARY = "summary";
+ private final String FAKE_SCREEN_TITLE = "screen_title";
+ private final String FAKE_FRAGMENT_CLASSNAME = FakeIndexProvider.class.getName();
+ private final String FAKE_CONTROLLER_NAME = FakePreferenceController.class.getName();
+
+ private final String ACCESSIBILITY_FRAGMENT = AccessibilitySettings.class.getName();
+ private final String A11Y_CONTROLLER_NAME =
+ AccessibilitySlicePreferenceController.class.getName();
+ private final String FAKE_SERVICE_NAME = "fake_service";
+ private final String FAKE_ACCESSIBILITY_PACKAGE = "fake_package";
+ private final String FAKE_A11Y_SERVICE_NAME =
+ FAKE_ACCESSIBILITY_PACKAGE + "/" + FAKE_SERVICE_NAME;
+ private final int FAKE_ICON = 1234;
+
+ private Context mContext;
private SliceDataConverter mSliceDataConverter;
private SearchFeatureProvider mSearchFeatureProvider;
@@ -50,7 +76,8 @@ public class SliceDataConverterTest {
@Before
public void setUp() {
- mSliceDataConverter = new SliceDataConverter(RuntimeEnvironment.application);
+ mContext = RuntimeEnvironment.application;
+ mSliceDataConverter = spy(new SliceDataConverter(RuntimeEnvironment.application));
mSearchFeatureProvider = new SearchFeatureProviderImpl();
mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
mFakeFeatureFactory.searchFeatureProvider = mSearchFeatureProvider;
@@ -68,20 +95,64 @@ public class SliceDataConverterTest {
mSearchFeatureProvider.getSearchIndexableResources().getProviderValues()
.add(FakeIndexProvider.class);
+ doReturn(getFakeService()).when(mSliceDataConverter).getAccessibilityServiceInfoList();
+
List sliceDataList = mSliceDataConverter.getSliceData();
- assertThat(sliceDataList).hasSize(1);
- SliceData fakeSlice = sliceDataList.get(0);
+ assertThat(sliceDataList).hasSize(2);
+ SliceData fakeSlice0 = sliceDataList.get(0);
+ SliceData fakeSlice1 = sliceDataList.get(1);
- assertThat(fakeSlice.getKey()).isEqualTo(fakeKey);
- assertThat(fakeSlice.getTitle()).isEqualTo(fakeTitle);
- assertThat(fakeSlice.getSummary()).isEqualTo(fakeSummary);
- assertThat(fakeSlice.getScreenTitle()).isEqualTo(fakeScreenTitle);
+ // Should not assume the order of the data list.
+ if (TextUtils.equals(fakeSlice0.getKey(), FAKE_KEY)) {
+ assertFakeSlice(fakeSlice0);
+ assertFakeA11ySlice(fakeSlice1);
+ } else {
+ assertFakeSlice(fakeSlice1);
+ assertFakeA11ySlice(fakeSlice0);
+ }
+ }
+
+ private void assertFakeSlice(SliceData fakeSlice) {
+ assertThat(fakeSlice.getKey()).isEqualTo(FAKE_KEY);
+ assertThat(fakeSlice.getTitle()).isEqualTo(FAKE_TITLE);
+ assertThat(fakeSlice.getSummary()).isEqualTo(FAKE_SUMMARY);
+ assertThat(fakeSlice.getScreenTitle()).isEqualTo(FAKE_SCREEN_TITLE);
assertThat(fakeSlice.getIconResource()).isNotNull();
assertThat(fakeSlice.getUri()).isNull();
- assertThat(fakeSlice.getFragmentClassName()).isEqualTo(fakeFragmentClassName);
- assertThat(fakeSlice.getPreferenceController()).isEqualTo(fakeControllerName);
- assertThat(fakeSlice.getSliceType()).isEqualTo(SliceData.SliceType.SLIDER); // from XML
+ assertThat(fakeSlice.getFragmentClassName()).isEqualTo(FAKE_FRAGMENT_CLASSNAME);
+ assertThat(fakeSlice.getPreferenceController()).isEqualTo(FAKE_CONTROLLER_NAME);
+ assertThat(fakeSlice.getSliceType()).isEqualTo(SliceData.SliceType.SLIDER);
assertThat(fakeSlice.isPlatformDefined()).isTrue(); // from XML
}
+
+ private void assertFakeA11ySlice(SliceData fakeSlice) {
+ assertThat(fakeSlice.getKey()).isEqualTo(FAKE_A11Y_SERVICE_NAME);
+ assertThat(fakeSlice.getTitle()).isEqualTo(FAKE_TITLE);
+ assertThat(fakeSlice.getSummary()).isNull();
+ assertThat(fakeSlice.getScreenTitle()).isEqualTo(
+ mContext.getString(R.string.accessibility_settings));
+ assertThat(fakeSlice.getIconResource()).isEqualTo(FAKE_ICON);
+ assertThat(fakeSlice.getUri()).isNull();
+ assertThat(fakeSlice.getFragmentClassName()).isEqualTo(ACCESSIBILITY_FRAGMENT);
+ assertThat(fakeSlice.getPreferenceController()).isEqualTo(A11Y_CONTROLLER_NAME);
+ }
+
+ // This is fragile. Should be replaced by a proper fake Service if possible.
+ private List getFakeService() {
+ List serviceInfoList = new ArrayList<>();
+ AccessibilityServiceInfo serviceInfo = spy(new AccessibilityServiceInfo());
+
+ ResolveInfo resolveInfo = spy(new ResolveInfo());
+ resolveInfo.serviceInfo = new ServiceInfo();
+ resolveInfo.serviceInfo.name = FAKE_SERVICE_NAME;
+ resolveInfo.serviceInfo.packageName = FAKE_ACCESSIBILITY_PACKAGE;
+ doReturn(FAKE_TITLE).when(resolveInfo).loadLabel(any(PackageManager.class));
+ doReturn(FAKE_ICON).when(resolveInfo).getIconResource();
+
+ doReturn(resolveInfo).when(serviceInfo).getResolveInfo();
+ serviceInfoList.add(serviceInfo);
+
+ return serviceInfoList;
+ }
}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/slices/SlicesDatabaseAccessorTest.java b/tests/robotests/src/com/android/settings/slices/SlicesDatabaseAccessorTest.java
index 77c9891da18..45ec06430b2 100644
--- a/tests/robotests/src/com/android/settings/slices/SlicesDatabaseAccessorTest.java
+++ b/tests/robotests/src/com/android/settings/slices/SlicesDatabaseAccessorTest.java
@@ -18,6 +18,7 @@
package com.android.settings.slices;
import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.Mockito.spy;
import android.content.ContentValues;
@@ -35,15 +36,17 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RuntimeEnvironment;
+import java.util.List;
+
@RunWith(SettingsRobolectricTestRunner.class)
public class SlicesDatabaseAccessorTest {
- private final String fakeTitle = "title";
- private final String fakeSummary = "summary";
- private final String fakeScreenTitle = "screen_title";
- private final int fakeIcon = 1234;
- private final String fakeFragmentClassName = FakeIndexProvider.class.getName();
- private final String fakeControllerName = FakePreferenceController.class.getName();
+ private final String FAKE_TITLE = "title";
+ private final String FAKE_SUMMARY = "summary";
+ private final String FAKE_SCREEN_TITLE = "screen_title";
+ private final int FAKE_ICON = 1234;
+ private final String FAKE_FRAGMENT_NAME = FakeIndexProvider.class.getName();
+ private final String FAKE_CONTROLLER_NAME = FakePreferenceController.class.getName();
private Context mContext;
private SQLiteDatabase mDb;
@@ -70,13 +73,13 @@ public class SlicesDatabaseAccessorTest {
SliceData data = mAccessor.getSliceDataFromKey(key);
assertThat(data.getKey()).isEqualTo(key);
- assertThat(data.getTitle()).isEqualTo(fakeTitle);
- assertThat(data.getSummary()).isEqualTo(fakeSummary);
- assertThat(data.getScreenTitle()).isEqualTo(fakeScreenTitle);
- assertThat(data.getIconResource()).isEqualTo(fakeIcon);
- assertThat(data.getFragmentClassName()).isEqualTo(fakeFragmentClassName);
+ assertThat(data.getTitle()).isEqualTo(FAKE_TITLE);
+ assertThat(data.getSummary()).isEqualTo(FAKE_SUMMARY);
+ assertThat(data.getScreenTitle()).isEqualTo(FAKE_SCREEN_TITLE);
+ assertThat(data.getIconResource()).isEqualTo(FAKE_ICON);
+ assertThat(data.getFragmentClassName()).isEqualTo(FAKE_FRAGMENT_NAME);
assertThat(data.getUri()).isNull();
- assertThat(data.getPreferenceController()).isEqualTo(fakeControllerName);
+ assertThat(data.getPreferenceController()).isEqualTo(FAKE_CONTROLLER_NAME);
}
@Test(expected = IllegalStateException.class)
@@ -96,13 +99,13 @@ public class SlicesDatabaseAccessorTest {
SliceData data = mAccessor.getSliceDataFromUri(uri);
assertThat(data.getKey()).isEqualTo(key);
- assertThat(data.getTitle()).isEqualTo(fakeTitle);
- assertThat(data.getSummary()).isEqualTo(fakeSummary);
- assertThat(data.getScreenTitle()).isEqualTo(fakeScreenTitle);
- assertThat(data.getIconResource()).isEqualTo(fakeIcon);
- assertThat(data.getFragmentClassName()).isEqualTo(fakeFragmentClassName);
+ assertThat(data.getTitle()).isEqualTo(FAKE_TITLE);
+ assertThat(data.getSummary()).isEqualTo(FAKE_SUMMARY);
+ assertThat(data.getScreenTitle()).isEqualTo(FAKE_SCREEN_TITLE);
+ assertThat(data.getIconResource()).isEqualTo(FAKE_ICON);
+ assertThat(data.getFragmentClassName()).isEqualTo(FAKE_FRAGMENT_NAME);
assertThat(data.getUri()).isEqualTo(uri);
- assertThat(data.getPreferenceController()).isEqualTo(fakeControllerName);
+ assertThat(data.getPreferenceController()).isEqualTo(FAKE_CONTROLLER_NAME);
}
@Test(expected = IllegalStateException.class)
@@ -111,15 +114,62 @@ public class SlicesDatabaseAccessorTest {
mAccessor.getSliceDataFromUri(uri);
}
+ @Test
+ public void getDescendantUris_platformSlice_doesNotReturnOEMSlice() {
+ final String key = "oem_key";
+ final boolean isPlatformSlice = false;
+ insertSpecialCase(key, isPlatformSlice);
+ final List keys = mAccessor.getSliceKeys(!isPlatformSlice);
+
+ assertThat(keys).isEmpty();
+ }
+
+ @Test
+ public void getDescendantUris_oemSlice_doesNotReturnPlatformSlice() {
+ final String key = "platform_key";
+ final boolean isPlatformSlice = true;
+ insertSpecialCase(key, isPlatformSlice);
+ final List keys = mAccessor.getSliceKeys(!isPlatformSlice);
+
+ assertThat(keys).isEmpty();
+ }
+
+ @Test
+ public void getDescendantUris_oemSlice_returnsOEMUriDescendant() {
+ final String key = "oem_key";
+ final boolean isPlatformSlice = false;
+ insertSpecialCase(key, isPlatformSlice);
+ final List keys = mAccessor.getSliceKeys(isPlatformSlice);
+
+ assertThat(keys).containsExactly(key);
+ }
+
+ @Test
+ public void getDescendantUris_platformSlice_returnsPlatformUriDescendant() {
+ final String key = "platform_key";
+ final boolean isPlatformSlice = true;
+ insertSpecialCase(key, isPlatformSlice);
+ final List keys = mAccessor.getSliceKeys(isPlatformSlice);
+
+ assertThat(keys).containsExactly(key);
+ }
+
private void insertSpecialCase(String key) {
+ insertSpecialCase(key, true);
+ }
+
+ private void insertSpecialCase(String key, boolean isPlatformSlice) {
ContentValues values = new ContentValues();
values.put(SlicesDatabaseHelper.IndexColumns.KEY, key);
- values.put(SlicesDatabaseHelper.IndexColumns.TITLE, fakeTitle);
- values.put(SlicesDatabaseHelper.IndexColumns.SUMMARY, fakeSummary);
- values.put(SlicesDatabaseHelper.IndexColumns.SCREENTITLE, fakeScreenTitle);
- values.put(SlicesDatabaseHelper.IndexColumns.ICON_RESOURCE, fakeIcon);
- values.put(SlicesDatabaseHelper.IndexColumns.FRAGMENT, fakeFragmentClassName);
- values.put(SlicesDatabaseHelper.IndexColumns.CONTROLLER, fakeControllerName);
+ values.put(SlicesDatabaseHelper.IndexColumns.TITLE, FAKE_TITLE);
+ values.put(SlicesDatabaseHelper.IndexColumns.SUMMARY, FAKE_SUMMARY);
+ values.put(SlicesDatabaseHelper.IndexColumns.SCREENTITLE, FAKE_SCREEN_TITLE);
+ values.put(SlicesDatabaseHelper.IndexColumns.ICON_RESOURCE, FAKE_ICON);
+ values.put(SlicesDatabaseHelper.IndexColumns.FRAGMENT, FAKE_FRAGMENT_NAME);
+ values.put(SlicesDatabaseHelper.IndexColumns.CONTROLLER, FAKE_CONTROLLER_NAME);
+ values.put(SlicesDatabaseHelper.IndexColumns.PLATFORM_SLICE, isPlatformSlice);
+ values.put(SlicesDatabaseHelper.IndexColumns.SLICE_TYPE, SliceData.SliceType.INTENT);
+
mDb.replaceOrThrow(SlicesDatabaseHelper.Tables.TABLE_SLICES_INDEX, null, values);
}
diff --git a/tests/robotests/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceControllerTest.java
index c6c4b451c23..f3f1c835787 100644
--- a/tests/robotests/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceControllerTest.java
@@ -17,6 +17,8 @@
package com.android.settings.sound;
+import static android.media.AudioSystem.DEVICE_OUT_USB_HEADSET;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
@@ -205,10 +207,9 @@ public class HandsFreeProfileOutputPreferenceControllerTest {
* Preference summary should be "This device"
*/
@Test
- public void hapBtDevicesAreAvailableButWiredHeadsetIsActivated_shouldSetDefaultSummary() {
+ public void updateState_withAvailableDevicesWiredHeadsetActivated_shouldSetDefaultSummary() {
mShadowAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
- mShadowAudioManager.setWiredHeadsetOn(true);
- mShadowAudioManager.setBluetoothScoOn(false);
+ mShadowAudioManager.setStream(DEVICE_OUT_USB_HEADSET);
when(mHeadsetProfile.getConnectedDevices()).thenReturn(mConnectedDevices);
when(mHeadsetProfile.getActiveDevice()).thenReturn(
mBluetoothDevice); // BT device is still activated in this case
@@ -226,7 +227,7 @@ public class HandsFreeProfileOutputPreferenceControllerTest {
* Preference summary should be "This device"
*/
@Test
- public void noAvailableHeadsetBtDevices_preferenceEnableIsFalse_shouldSetDefaultSummary() {
+ public void updateState_noAvailableHeadsetBtDevices_shouldSetDefaultSummary() {
mShadowAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
List emptyDeviceList = new ArrayList<>();
when(mHeadsetProfile.getConnectedDevices()).thenReturn(emptyDeviceList);
diff --git a/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java
index 2b15b8e0145..1c7c1c4c7b6 100644
--- a/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java
@@ -17,6 +17,9 @@
package com.android.settings.sound;
+import static android.media.AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
+import static android.media.AudioSystem.DEVICE_OUT_USB_HEADSET;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
@@ -196,7 +199,7 @@ public class MediaOutputPreferenceControllerTest {
*/
@Test
public void updateState_mediaStreamIsCapturedByCast_shouldDisableAndSetDefaultSummary() {
- mShadowAudioManager.setMusicActiveRemotely(true);
+ mShadowAudioManager.setStream(DEVICE_OUT_REMOTE_SUBMIX);
mController.updateState(mPreference);
@@ -256,8 +259,7 @@ public class MediaOutputPreferenceControllerTest {
@Test
public void updateState_a2dpDevicesAvailableWiredHeadsetIsActivated_shouldSetDefaultSummary() {
mShadowAudioManager.setMode(AudioManager.MODE_NORMAL);
- mShadowAudioManager.setWiredHeadsetOn(true);
- mShadowAudioManager.setBluetoothA2dpOn(false);
+ mShadowAudioManager.setStream(DEVICE_OUT_USB_HEADSET);
when(mA2dpProfile.getConnectedDevices()).thenReturn(mConnectedDevices);
when(mA2dpProfile.getActiveDevice()).thenReturn(
mBluetoothDevice); // BT device is still activated in this case
diff --git a/tests/robotests/src/com/android/settings/testutils/FakeSliderController.java b/tests/robotests/src/com/android/settings/testutils/FakeSliderController.java
index f4f91ed2382..530bdee97f3 100644
--- a/tests/robotests/src/com/android/settings/testutils/FakeSliderController.java
+++ b/tests/robotests/src/com/android/settings/testutils/FakeSliderController.java
@@ -19,13 +19,14 @@ package com.android.settings.testutils;
import android.content.Context;
import android.provider.Settings;
-import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.SliderPreferenceController;
public class FakeSliderController extends SliderPreferenceController {
private final String settingKey = "fake_slider_key";
+ public static final String AVAILABILITY_KEY = "fake_slider_availability_key";
+
public static final int MAX_STEPS = 9;
public FakeSliderController(Context context, String key) {
@@ -49,6 +50,7 @@ public class FakeSliderController extends SliderPreferenceController {
@Override
public int getAvailabilityStatus() {
- return BasePreferenceController.AVAILABLE;
+ return Settings.Global.getInt(mContext.getContentResolver(),
+ AVAILABILITY_KEY, AVAILABLE);
}
}
diff --git a/tests/robotests/src/com/android/settings/testutils/FakeToggleController.java b/tests/robotests/src/com/android/settings/testutils/FakeToggleController.java
index c984c6ceca4..d0ce76fe60a 100644
--- a/tests/robotests/src/com/android/settings/testutils/FakeToggleController.java
+++ b/tests/robotests/src/com/android/settings/testutils/FakeToggleController.java
@@ -26,6 +26,8 @@ public class FakeToggleController extends TogglePreferenceController {
private String settingKey = "toggle_key";
+ public static final String AVAILABILITY_KEY = "fake_toggle_availability_key";
+
private final int ON = 1;
private final int OFF = 0;
@@ -47,6 +49,7 @@ public class FakeToggleController extends TogglePreferenceController {
@Override
public int getAvailabilityStatus() {
- return AVAILABLE;
+ return Settings.Global.getInt(mContext.getContentResolver(),
+ AVAILABILITY_KEY, AVAILABLE);
}
}
diff --git a/tests/robotests/src/com/android/settings/slices/FakeUnavailablePreferenceController.java b/tests/robotests/src/com/android/settings/testutils/FakeUnavailablePreferenceController.java
similarity index 82%
rename from tests/robotests/src/com/android/settings/slices/FakeUnavailablePreferenceController.java
rename to tests/robotests/src/com/android/settings/testutils/FakeUnavailablePreferenceController.java
index a7e5d7562aa..1ceaad864e1 100644
--- a/tests/robotests/src/com/android/settings/slices/FakeUnavailablePreferenceController.java
+++ b/tests/robotests/src/com/android/settings/testutils/FakeUnavailablePreferenceController.java
@@ -1,4 +1,4 @@
-package com.android.settings.slices;
+package com.android.settings.testutils;
import android.content.Context;
import android.provider.Settings;
@@ -15,7 +15,7 @@ public class FakeUnavailablePreferenceController extends BasePreferenceControlle
@Override
public int getAvailabilityStatus() {
- return Settings.System.getInt(mContext.getContentResolver(),
+ return Settings.Global.getInt(mContext.getContentResolver(),
AVAILABILITY_KEY, 0);
}
}
diff --git a/tests/robotests/src/com/android/settings/testutils/SliceTester.java b/tests/robotests/src/com/android/settings/testutils/SliceTester.java
index 905277ee18d..86721649bbf 100644
--- a/tests/robotests/src/com/android/settings/testutils/SliceTester.java
+++ b/tests/robotests/src/com/android/settings/testutils/SliceTester.java
@@ -115,8 +115,9 @@ public class SliceTester {
sliceData.getIconResource());
// Check primary intent
- final SliceAction primaryAction = metadata.getPrimaryAction();
- assertThat(primaryAction).isNull();
+ final PendingIntent primaryPendingIntent = metadata.getPrimaryAction().getAction();
+ assertThat(primaryPendingIntent).isEqualTo(
+ SliceBuilderUtils.getContentPendingIntent(context, sliceData));
final List sliceItems = slice.getItems();
assertTitle(sliceItems, sliceData.getTitle());
@@ -158,11 +159,15 @@ public class SliceTester {
private static void assertTitle(List sliceItems, String title) {
boolean hasTitle = false;
for (SliceItem item : sliceItems) {
- List titles = SliceQuery.findAll(item, FORMAT_TEXT, HINT_TITLE,
+ List titleItems = SliceQuery.findAll(item, FORMAT_TEXT, HINT_TITLE,
null /* non-hints */);
- if (titles != null & titles.size() == 1) {
- assertThat(titles.get(0).getText()).isEqualTo(title);
- hasTitle = true;
+ if (titleItems == null) {
+ continue;
+ }
+
+ hasTitle = true;
+ for (SliceItem subTitleItem : titleItems) {
+ assertThat(subTitleItem.getText()).isEqualTo(title);
}
}
assertThat(hasTitle).isTrue();
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAudioManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAudioManager.java
index 6817648f09b..0de2156ce38 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAudioManager.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowAudioManager.java
@@ -16,6 +16,15 @@
package com.android.settings.testutils.shadow;
+import static android.media.AudioManager.STREAM_ACCESSIBILITY;
+import static android.media.AudioManager.STREAM_ALARM;
+import static android.media.AudioManager.STREAM_MUSIC;
+import static android.media.AudioManager.STREAM_NOTIFICATION;
+import static android.media.AudioManager.STREAM_RING;
+import static android.media.AudioManager.STREAM_SYSTEM;
+import static android.media.AudioManager.STREAM_VOICE_CALL;
+import static android.media.AudioManager.STREAM_DTMF;
+
import static org.robolectric.RuntimeEnvironment.application;
import android.media.AudioDeviceCallback;
@@ -32,6 +41,7 @@ import java.util.ArrayList;
@Implements(value = AudioManager.class, inheritImplementationMethods = true)
public class ShadowAudioManager extends org.robolectric.shadows.ShadowAudioManager {
private int mRingerMode;
+ private int mStream;
private boolean mMusicActiveRemotely = false;
private ArrayList mDeviceCallbacks = new ArrayList();
@@ -48,10 +58,12 @@ public class ShadowAudioManager extends org.robolectric.shadows.ShadowAudioManag
mRingerMode = mode;
}
+ @Implementation
public void registerAudioDeviceCallback(AudioDeviceCallback callback, Handler handler) {
mDeviceCallbacks.add(callback);
}
+ @Implementation
public void unregisterAudioDeviceCallback(AudioDeviceCallback callback) {
if (mDeviceCallbacks.contains(callback)) {
mDeviceCallbacks.remove(callback);
@@ -62,10 +74,32 @@ public class ShadowAudioManager extends org.robolectric.shadows.ShadowAudioManag
mMusicActiveRemotely = flag;
}
+ @Implementation
public boolean isMusicActiveRemotely() {
return mMusicActiveRemotely;
}
+ public void setStream(int stream) {
+ mStream = stream;
+ }
+
+ @Implementation
+ public int getDevicesForStream(int streamType) {
+ switch (streamType) {
+ case STREAM_VOICE_CALL:
+ case STREAM_SYSTEM:
+ case STREAM_RING:
+ case STREAM_MUSIC:
+ case STREAM_ALARM:
+ case STREAM_NOTIFICATION:
+ case STREAM_DTMF:
+ case STREAM_ACCESSIBILITY:
+ return mStream;
+ default:
+ return 0;
+ }
+ }
+
@Resetter
public void reset() {
mDeviceCallbacks.clear();
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowInputDevice.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowInputDevice.java
index ecb1b71e678..4dec502d483 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowInputDevice.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowInputDevice.java
@@ -21,6 +21,7 @@ import android.view.InputDevice;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.Resetter;
+import org.robolectric.shadow.api.Shadow;
import java.util.HashMap;
import java.util.Map;
@@ -32,6 +33,8 @@ public class ShadowInputDevice extends org.robolectric.shadows.ShadowInputDevice
private static Map sDeviceMap = new HashMap<>();
+ private int mDeviceId;
+
@Implementation
public static int[] getDeviceIds() {
return sDeviceIds;
@@ -51,4 +54,22 @@ public class ShadowInputDevice extends org.robolectric.shadows.ShadowInputDevice
sDeviceIds = null;
sDeviceMap.clear();
}
+
+ @Implementation
+ public int getId() {
+ return mDeviceId;
+ }
+
+ public static InputDevice makeInputDevicebyId(int id) {
+ final InputDevice inputDevice = Shadow.newInstanceOf(InputDevice.class);
+ final ShadowInputDevice shadowInputDevice = Shadow.extract(inputDevice);
+ shadowInputDevice.setId(id);
+ return inputDevice;
+ }
+
+ public void setId(int id) {
+ mDeviceId = id;
+ }
+
}
+
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowStorageManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowStorageManager.java
new file mode 100644
index 00000000000..4b60c1672ee
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowStorageManager.java
@@ -0,0 +1,84 @@
+/*
+ * 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.testutils.shadow;
+
+import android.os.storage.DiskInfo;
+import android.os.storage.StorageManager;
+import android.os.storage.VolumeInfo;
+import android.os.storage.VolumeRecord;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.annotation.Resetter;
+
+@Implements(StorageManager.class)
+public class ShadowStorageManager {
+
+ private static boolean sIsUnmountCalled;
+ private static boolean sIsForgetCalled;
+
+ public static boolean isUnmountCalled() {
+ return sIsUnmountCalled;
+ }
+
+ public static boolean isForgetCalled() {
+ return sIsForgetCalled;
+ }
+
+ @Resetter
+ public static void reset() {
+ sIsUnmountCalled = false;
+ sIsForgetCalled = false;
+
+ }
+
+ @Implementation
+ public VolumeInfo findVolumeById(String id) {
+ return createVolumeInfo(id);
+ }
+
+ @Implementation
+ public DiskInfo findDiskById(String id) {
+ return new DiskInfo(id, DiskInfo.FLAG_SD);
+ }
+
+ @Implementation
+ public VolumeRecord findRecordByUuid(String fsUuid) {
+ return createVolumeRecord(fsUuid);
+ }
+
+ @Implementation
+ public void unmount(String volId) {
+ sIsUnmountCalled = true;
+ }
+
+ @Implementation
+ public void forgetVolume(String fsUuid) {
+ sIsForgetCalled = true;
+ }
+
+ private VolumeInfo createVolumeInfo(String volumeId) {
+ final DiskInfo disk = new DiskInfo("fakeid", 0);
+ return new VolumeInfo(volumeId, 0, disk, "guid");
+ }
+
+ private VolumeRecord createVolumeRecord(String fsUuid) {
+ VolumeRecord record = new VolumeRecord(VolumeRecord.USER_FLAG_INITED, fsUuid);
+ record.nickname = "nickname";
+ return record;
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/wallpaper/WallpaperTypePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wallpaper/WallpaperTypePreferenceControllerTest.java
new file mode 100644
index 00000000000..fa6ecaf58d5
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/wallpaper/WallpaperTypePreferenceControllerTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.wallpaper;
+
+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.spy;
+import static org.mockito.Mockito.when;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.content.Context;
+import android.content.Intent;
+import android.support.v7.preference.Preference;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.Robolectric;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class WallpaperTypePreferenceControllerTest {
+
+ @Mock
+ private Fragment mFragment;
+
+ private Context mContext;
+ private Activity mActivity;
+ private WallpaperTypePreferenceController mController;
+ private Preference mPreference;
+ private Intent mIntent;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mActivity = spy(Robolectric.buildActivity(Activity.class).get());
+ mController = new WallpaperTypePreferenceController(mContext, "pref_key");
+ mController.setParentFragment(mFragment);
+ mIntent = new Intent();
+ mPreference = new Preference(mContext);
+ }
+
+ @Test
+ public void getAvailabilityStatus_byDefault_shouldBeShown() {
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.AVAILABLE);
+ }
+
+ @Test
+ public void testhandlePreferenceTreeClick_intentNull_shouldDoNothing() {
+ mPreference.setIntent(null);
+
+ final boolean handled = mController.handlePreferenceTreeClick(mPreference);
+
+ assertThat(handled).isFalse();
+ }
+
+ @Test
+ public void testhandlePreferenceTreeClick_shouldLaunchIntent() {
+ mPreference.setIntent(mIntent);
+ doNothing().when(mFragment).startActivity(any(Intent.class));
+ when(mFragment.getActivity()).thenReturn(mActivity);
+ doNothing().when(mActivity).finish();
+
+ final boolean handled = mController.handlePreferenceTreeClick(mPreference);
+
+ assertThat(handled).isTrue();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/wallpaper/WallpaperTypeSettingsTest.java b/tests/robotests/src/com/android/settings/wallpaper/WallpaperTypeSettingsTest.java
deleted file mode 100644
index a39ad9fec4f..00000000000
--- a/tests/robotests/src/com/android/settings/wallpaper/WallpaperTypeSettingsTest.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package com.android.settings.wallpaper;
-
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.robolectric.RuntimeEnvironment.application;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.support.v7.preference.Preference;
-
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.robolectric.Robolectric;
-
-@RunWith(SettingsRobolectricTestRunner.class)
-public class WallpaperTypeSettingsTest {
-
- private Preference mPreference;
-
- private Intent mIntent;
-
- @Before
- public void setUp() {
- mIntent = new Intent();
- mPreference = new Preference(application);
- }
-
- @Test
- public void testOnPreferenceTreeClick_intentNull_shouldDoNothing() {
- Activity activity = Robolectric.setupActivity(Activity.class);
- WallpaperTypeSettings fragment = spy(new WallpaperTypeSettings());
- doReturn(activity).when(fragment).getActivity();
-
- boolean handled = fragment.onPreferenceTreeClick(mPreference);
-
- assertThat(handled).isFalse();
- }
-
- @Test
- public void testOnPreferenceTreeClick_shouldLaunchIntentAndFinish() {
- Activity activity = Robolectric.setupActivity(Activity.class);
- WallpaperTypeSettings fragment = spy(new WallpaperTypeSettings());
- doReturn(activity).when(fragment).getActivity();
- mPreference.setIntent(mIntent);
- doNothing().when(fragment).finish();
- ArgumentCaptor intent = ArgumentCaptor.forClass(Intent.class);
- doNothing().when(fragment).startActivity(intent.capture());
-
- boolean handled = fragment.onPreferenceTreeClick(mPreference);
-
- assertThat(handled).isTrue();
- verify(fragment, times(1)).finish();
- assertThat(intent.getValue()).isSameAs(mIntent);
- }
-}
diff --git a/tests/robotests/src/com/android/settings/widget/DisabledCheckBoxPreferenceTest.java b/tests/robotests/src/com/android/settings/widget/DisabledCheckBoxPreferenceTest.java
index 5ab7013686a..ff10833492b 100644
--- a/tests/robotests/src/com/android/settings/widget/DisabledCheckBoxPreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/widget/DisabledCheckBoxPreferenceTest.java
@@ -21,6 +21,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.content.Context;
@@ -70,14 +71,28 @@ public class DisabledCheckBoxPreferenceTest {
}
@Test
- public void checkboxOnClick_doesNothing() {
+ public void checkboxOnClick_checkboxDisabled() {
Preference.OnPreferenceClickListener onClick =
mock(Preference.OnPreferenceClickListener.class);
mPref.setOnPreferenceClickListener(onClick);
inflatePreference();
+ mPref.enableCheckbox(false);
mPref.performClick(mRootView);
verify(onClick, never()).onPreferenceClick(any());
}
+
+ @Test
+ public void checkboxOnClick_checkboxEnabled() {
+ Preference.OnPreferenceClickListener onClick =
+ mock(Preference.OnPreferenceClickListener.class);
+ mPref.setOnPreferenceClickListener(onClick);
+ inflatePreference();
+
+ mPref.enableCheckbox(true);
+ mPref.performClick(mRootView);
+
+ verify(onClick, times(1)).onPreferenceClick(any());
+ }
}
diff --git a/tests/robotests/src/com/android/settings/widget/EntityHeaderControllerTest.java b/tests/robotests/src/com/android/settings/widget/EntityHeaderControllerTest.java
index e32ef77c4f3..a82f49d63c4 100644
--- a/tests/robotests/src/com/android/settings/widget/EntityHeaderControllerTest.java
+++ b/tests/robotests/src/com/android/settings/widget/EntityHeaderControllerTest.java
@@ -169,7 +169,7 @@ public class EntityHeaderControllerTest {
}
@Test
- public void bindButton_hasEditRuleNameClickListener_shouldShowButton() {
+ public void bindButton_hasEditClickListener_shouldShowButton() {
final ResolveInfo info = new ResolveInfo();
info.activityInfo = new ActivityInfo();
info.activityInfo.packageName = "123";
@@ -179,13 +179,13 @@ public class EntityHeaderControllerTest {
when(mActivity.getApplicationContext()).thenReturn(mContext);
mController = EntityHeaderController.newInstance(mActivity, mFragment, view);
- mController.setEditZenRuleNameListener(new View.OnClickListener() {
+ mController.setEditListener(new View.OnClickListener() {
public void onClick(View v) {
// do nothing
}
});
mController.setButtonActions(
- EntityHeaderController.ActionType.ACTION_DND_RULE_PREFERENCE,
+ EntityHeaderController.ActionType.ACTION_EDIT_PREFERENCE,
EntityHeaderController.ActionType.ACTION_NONE);
mController.done(mActivity);
@@ -197,7 +197,7 @@ public class EntityHeaderControllerTest {
}
@Test
- public void bindButton_noEditRuleNameClickListener_shouldNotShowButton() {
+ public void bindButton_noEditClickListener_shouldNotShowButton() {
final ResolveInfo info = new ResolveInfo();
info.activityInfo = new ActivityInfo();
info.activityInfo.packageName = "123";
@@ -207,7 +207,7 @@ public class EntityHeaderControllerTest {
mController = EntityHeaderController.newInstance(mActivity, mFragment, view);
mController.setButtonActions(
- EntityHeaderController.ActionType.ACTION_DND_RULE_PREFERENCE,
+ EntityHeaderController.ActionType.ACTION_EDIT_PREFERENCE,
EntityHeaderController.ActionType.ACTION_NONE);
mController.done(mActivity);
diff --git a/tests/robotests/src/com/android/settings/widget/HotspotApBandSelectionPreferenceTest.java b/tests/robotests/src/com/android/settings/widget/HotspotApBandSelectionPreferenceTest.java
new file mode 100644
index 00000000000..6bfc968a12a
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/widget/HotspotApBandSelectionPreferenceTest.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.widget;
+
+import static com.android.settingslib.CustomDialogPreference.CustomPreferenceDialogFragment;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.net.wifi.WifiConfiguration;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.LinearLayout;
+
+import com.android.settings.R;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.util.ReflectionHelpers;
+
+import java.util.List;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class HotspotApBandSelectionPreferenceTest {
+ private HotspotApBandSelectionPreference mPreference;
+ private Context mContext;
+ private Button mSaveButton;
+ private View mLayout;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ mSaveButton = spy(new Button(mContext));
+
+ final CustomPreferenceDialogFragment fragment = mock(CustomPreferenceDialogFragment.class);
+ final AlertDialog dialog = mock(AlertDialog.class);
+ when(fragment.getDialog()).thenReturn(dialog);
+ when(dialog.getButton(anyInt())).thenReturn(mSaveButton);
+
+ mPreference = new HotspotApBandSelectionPreference(mContext);
+ ReflectionHelpers.setField(mPreference, "mFragment", fragment);
+
+ final LayoutInflater inflater = LayoutInflater.from(mContext);
+ mLayout = inflater.inflate(R.layout.hotspot_ap_band_selection_dialog,
+ new LinearLayout(mContext), false);
+ }
+
+ @Test
+ public void getWifiBand_updatesBandPresetConfigProvided() {
+ mPreference.setExistingConfigValue(WifiConfiguration.AP_BAND_ANY);
+ mPreference.onBindDialogView(mLayout);
+
+ // check that the boxes are set correctly when a pre-existing config is set
+ assertThat(mPreference.getWifiBand()).isEqualTo(WifiConfiguration.AP_BAND_ANY);
+ }
+
+ @Test
+ public void getWifiBand_updatesBandWhenBoxesToggled() {
+ mPreference.setExistingConfigValue(WifiConfiguration.AP_BAND_ANY);
+ mPreference.onBindDialogView(mLayout);
+
+ assertThat(mPreference.getWifiBand()).isEqualTo(WifiConfiguration.AP_BAND_ANY);
+
+ // make sure we have the expected box then toggle it
+ mPreference.mBox2G.setChecked(false);
+
+ // check that band is updated
+ assertThat(mPreference.getWifiBand()).isEqualTo(WifiConfiguration.AP_BAND_5GHZ);
+ }
+
+ @Test
+ public void onSaveInstanceState_skipWhenDialogGone() {
+ mPreference.setExistingConfigValue(WifiConfiguration.AP_BAND_2GHZ);
+ mPreference.onBindDialogView(mLayout);
+ // remove the fragment to make the dialog unavailable
+ ReflectionHelpers.setField(mPreference, "mFragment", null);
+
+ mPreference.setExistingConfigValue(WifiConfiguration.AP_BAND_ANY);
+ mPreference.onBindDialogView(mLayout);
+
+ // state should only be saved when the dialog is available
+ Parcelable parcelable = mPreference.onSaveInstanceState();
+ mPreference.onRestoreInstanceState(parcelable);
+ assertThat(mPreference.mShouldRestore).isFalse();
+ }
+
+ @Test
+ public void onSaveInstanceState_presentWhenDialogPresent() {
+ mPreference.setExistingConfigValue(WifiConfiguration.AP_BAND_2GHZ);
+ mPreference.onBindDialogView(mLayout);
+
+ Parcelable parcelable = mPreference.onSaveInstanceState();
+ mPreference.onRestoreInstanceState(parcelable);
+ assertThat(mPreference.mShouldRestore).isTrue();
+ }
+
+ @Test
+ public void positiveButton_updatedCorrectly() {
+ mPreference.setExistingConfigValue(WifiConfiguration.AP_BAND_ANY);
+ mPreference.onBindDialogView(mLayout);
+
+ // button is enabled whole time so far since we have a pre-existing selection
+ verify(mSaveButton, never()).setEnabled(false);
+
+ // clear all boxes and make sure it stays enabled until empty
+ mPreference.mBox2G.setChecked(false);
+ mPreference.mBox5G.setChecked(false);
+
+ // button should be disabled now
+ verify(mSaveButton, times(1)).setEnabled(false);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/widget/ValidatedEditTextPreferenceTest.java b/tests/robotests/src/com/android/settings/widget/ValidatedEditTextPreferenceTest.java
index 5ba9f8abe58..865422c9354 100644
--- a/tests/robotests/src/com/android/settings/widget/ValidatedEditTextPreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/widget/ValidatedEditTextPreferenceTest.java
@@ -116,7 +116,7 @@ public class ValidatedEditTextPreferenceTest {
mPreference.onBindDialogView(mView);
assertThat(editText.getInputType()
- & (InputType.TYPE_TEXT_VARIATION_PASSWORD | InputType.TYPE_CLASS_TEXT))
+ & (InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD | InputType.TYPE_CLASS_TEXT))
.isNotEqualTo(0);
}
diff --git a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceControllerTest.java
index 3f364f94544..d9c867cf2a6 100644
--- a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherApBandPreferenceControllerTest.java
@@ -24,12 +24,13 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.net.ConnectivityManager;
+import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
-import android.support.v7.preference.ListPreference;
import android.support.v7.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.widget.HotspotApBandSelectionPreference;
import org.junit.Before;
import org.junit.Test;
@@ -42,6 +43,7 @@ import org.robolectric.RuntimeEnvironment;
@RunWith(SettingsRobolectricTestRunner.class)
public class WifiTetherApBandPreferenceControllerTest {
+ private static final String ALL_BANDS = "2.4 GHz and 5.0 GHz";
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Context mContext;
@Mock
@@ -54,18 +56,21 @@ public class WifiTetherApBandPreferenceControllerTest {
private PreferenceScreen mScreen;
private WifiTetherApBandPreferenceController mController;
- private ListPreference mListPreference;
+ private HotspotApBandSelectionPreference mPreference;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mListPreference = new ListPreference(RuntimeEnvironment.application);
+ mPreference = new HotspotApBandSelectionPreference(RuntimeEnvironment.application);
when(mContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(mWifiManager);
when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
.thenReturn(mConnectivityManager);
when(mConnectivityManager.getTetherableWifiRegexs()).thenReturn(new String[]{"1", "2"});
when(mContext.getResources()).thenReturn(RuntimeEnvironment.application.getResources());
- when(mScreen.findPreference(anyString())).thenReturn(mListPreference);
+ when(mScreen.findPreference(anyString())).thenReturn(mPreference);
+ WifiConfiguration config = new WifiConfiguration();
+ config.apBand = WifiConfiguration.AP_BAND_ANY;
+ when(mWifiManager.getWifiApConfiguration()).thenReturn(new WifiConfiguration());
mController = new WifiTetherApBandPreferenceController(mContext, mListener);
}
@@ -76,8 +81,9 @@ public class WifiTetherApBandPreferenceControllerTest {
when(mWifiManager.isDualBandSupported()).thenReturn(true);
mController.displayPreference(mScreen);
+ mController.onPreferenceChange(mPreference, -1);
- assertThat(mListPreference.getEntries().length).isEqualTo(3);
+ assertThat(mPreference.getSummary()).isEqualTo(ALL_BANDS);
}
@Test
@@ -87,9 +93,8 @@ public class WifiTetherApBandPreferenceControllerTest {
mController.displayPreference(mScreen);
- assertThat(mListPreference.getEntries()).isNull();
- assertThat(mListPreference.isEnabled()).isFalse();
- assertThat(mListPreference.getSummary())
+ assertThat(mPreference.isEnabled()).isFalse();
+ assertThat(mPreference.getSummary())
.isEqualTo(RuntimeEnvironment.application.getString(R.string.wifi_ap_choose_2G));
}
@@ -99,9 +104,8 @@ public class WifiTetherApBandPreferenceControllerTest {
mController.displayPreference(mScreen);
- assertThat(mListPreference.getEntries()).isNull();
- assertThat(mListPreference.isEnabled()).isFalse();
- assertThat(mListPreference.getSummary())
+ assertThat(mPreference.isEnabled()).isFalse();
+ assertThat(mPreference.getSummary())
.isEqualTo(RuntimeEnvironment.application.getString(R.string.wifi_ap_choose_2G));
}
@@ -112,14 +116,17 @@ public class WifiTetherApBandPreferenceControllerTest {
mController.displayPreference(mScreen);
// -1 is WifiConfiguration.AP_BAND_ANY, for 'Auto' option.
- mController.onPreferenceChange(mListPreference, "-1");
+ mController.onPreferenceChange(mPreference, -1);
assertThat(mController.getBandIndex()).isEqualTo(-1);
+ assertThat(mPreference.getSummary()).isEqualTo(ALL_BANDS);
- mController.onPreferenceChange(mListPreference, "1");
+ mController.onPreferenceChange(mPreference, 1);
assertThat(mController.getBandIndex()).isEqualTo(1);
+ assertThat(mPreference.getSummary()).isEqualTo("5.0 GHz");
- mController.onPreferenceChange(mListPreference, "0");
+ mController.onPreferenceChange(mPreference, 0);
assertThat(mController.getBandIndex()).isEqualTo(0);
+ assertThat(mPreference.getSummary()).isEqualTo("2.4 GHz");
verify(mListener, times(3)).onTetherConfigUpdated();
}
@@ -129,7 +136,7 @@ public class WifiTetherApBandPreferenceControllerTest {
// Set controller band index to 1 and verify is set.
when(mWifiManager.is5GHzBandSupported()).thenReturn(true);
mController.displayPreference(mScreen);
- mController.onPreferenceChange(mListPreference, "1");
+ mController.onPreferenceChange(mPreference, 1);
assertThat(mController.getBandIndex()).isEqualTo(1);
// Disable 5Ghz band
diff --git a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherPasswordPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherPasswordPreferenceControllerTest.java
index 60faa2e0702..7e757ad5f84 100644
--- a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherPasswordPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherPasswordPreferenceControllerTest.java
@@ -145,4 +145,21 @@ public class WifiTetherPasswordPreferenceControllerTest {
assertThat(mController.getSecuritySettingForPassword())
.isEqualTo(WifiConfiguration.KeyMgmt.WPA2_PSK);
}
+
+ @Test
+ public void updateDisplay_shouldSetInputType() {
+ // Set controller password to anything and verify is set.
+ mController.displayPreference(mScreen);
+ mController.onPreferenceChange(mPreference, "1");
+ assertThat(mController.getPassword()).isEqualTo("1");
+
+ // Create a new config using different password
+ final WifiConfiguration config = new WifiConfiguration();
+ config.preSharedKey = "test_1234";
+ when(mWifiManager.getWifiApConfiguration()).thenReturn(config);
+
+ // Call updateDisplay and verify it's changed.
+ mController.updateDisplay();
+ assertThat(mPreference.isPassword()).isTrue();
+ }
}
diff --git a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSwitchBarControllerTest.java b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSwitchBarControllerTest.java
index db8baab6cb4..943a66521fc 100644
--- a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSwitchBarControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSwitchBarControllerTest.java
@@ -88,4 +88,20 @@ public class WifiTetherSwitchBarControllerTest {
assertThat(mSwitchBar.isChecked()).isFalse();
assertThat(mSwitchBar.isEnabled()).isTrue();
}
+
+ @Test
+ public void testOnDataSaverChanged_setsEnabledCorrectly() {
+ assertThat(mSwitchBar.isEnabled()).isTrue();
+
+ // try to turn data saver on
+ when(mNetworkPolicyManager.getRestrictBackground()).thenReturn(true);
+ mController.onDataSaverChanged(true);
+ assertThat(mSwitchBar.isEnabled()).isFalse();
+
+ // lets turn data saver off again
+ when(mNetworkPolicyManager.getRestrictBackground()).thenReturn(false);
+ mController.onDataSaverChanged(false);
+ assertThat(mSwitchBar.isEnabled()).isTrue();
+
+ }
}
diff --git a/tests/uitests/src/com/android/settings/ui/HomepageDisplayTests.java b/tests/uitests/src/com/android/settings/ui/HomepageDisplayTests.java
index 3b7b006e628..4eccd8b5571 100644
--- a/tests/uitests/src/com/android/settings/ui/HomepageDisplayTests.java
+++ b/tests/uitests/src/com/android/settings/ui/HomepageDisplayTests.java
@@ -54,8 +54,7 @@ public class HomepageDisplayTests {
"Security & location",
"Accounts",
"Accessibility",
- "System",
- "Support & tips"
+ "System"
};
private UiDevice mDevice;