diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 5a310e980f3..062ebdce45f 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1247,7 +1247,7 @@
+ android:value="com.android.settings.security.SecuritySettings" />
@@ -1289,7 +1289,7 @@
android:exported="true"
android:targetActivity="Settings$SecuritySettingsActivity">
+ android:value="com.android.settings.security.SecuritySettings" />
+ android:value="com.android.settings.security.CryptKeeperSettings" />
-
-
+ android:paddingStart="@dimen/preference_no_icon_padding_start"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:orientation="vertical">
+ android:layout_weight="1">
+ android:orientation="vertical">
+ android:text="@string/crypt_keeper_desc" />
+ android:visibility="gone" />
+ android:visibility="gone" />
-
-
+ android:layout_gravity="end"
+ android:text="@string/crypt_keeper_button_text" />
diff --git a/res/layout/dialog_firmware_version.xml b/res/layout/dialog_firmware_version.xml
new file mode 100644
index 00000000000..e49255f2183
--- /dev/null
+++ b/res/layout/dialog_firmware_version.xml
@@ -0,0 +1,89 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/layout/dialog_imei_info.xml b/res/layout/dialog_imei_info.xml
new file mode 100644
index 00000000000..b19d336410e
--- /dev/null
+++ b/res/layout/dialog_imei_info.xml
@@ -0,0 +1,114 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/dialog_sim_status.xml b/res/layout/dialog_sim_status.xml
new file mode 100644
index 00000000000..068a889def4
--- /dev/null
+++ b/res/layout/dialog_sim_status.xml
@@ -0,0 +1,132 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 8b848496e8e..cd4c63c3ca1 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -2622,6 +2622,8 @@
Android version
+
+ Android
Android security patch level
@@ -2661,6 +2663,10 @@
Unmount USB storage, view available storage
Unmount SD card, view available storage
+
+ IMEI (sim slot 1)
+
+ IMEI (sim slot 2)
IMEI
@@ -2671,12 +2677,20 @@
MDN
Phone number
+
+ MDN on SIM
+
+ Phone number on SIM
MIN
MSID
PRL version
+
+ MEID (sim slot 1)
+
+ MEID (sim slot 2)
MEID
@@ -6430,6 +6444,10 @@
No SIM cards inserted
SIM status
+
+ SIM status (sim slot 1)
+
+ SIM status (sim slot 2)
Call back from default SIM
@@ -6555,6 +6573,7 @@
pay, tap, payments
backup, back up
gesture
+ imei, meid
diff --git a/res/values/styles.xml b/res/values/styles.xml
index c9ef22cfb97..8815bb3c762 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -478,4 +478,14 @@
- @dimen/search_bar_text_size
+
+
+
+
diff --git a/res/xml/device_info_settings_v2.xml b/res/xml/device_info_settings_v2.xml
index 0553f1ebc5c..2edfdce8fbb 100644
--- a/res/xml/device_info_settings_v2.xml
+++ b/res/xml/device_info_settings_v2.xml
@@ -28,22 +28,37 @@
android:title="@string/status_number"
android:summary="@string/summary_placeholder"/>
-
+
+
+
+
+
-
+
+
+
+
diff --git a/res/xml/encryption_and_credential.xml b/res/xml/encryption_and_credential.xml
index 715ea141158..3e3130cdc14 100644
--- a/res/xml/encryption_and_credential.xml
+++ b/res/xml/encryption_and_credential.xml
@@ -14,45 +14,72 @@
limitations under the License.
-->
-
+
-
+
-
+
-
+
-
+
-
+
-
+
+
+
+
+
+
+
-
+
-
+
diff --git a/res/xml/security_settings_encrypted.xml b/res/xml/security_settings_encrypted.xml
deleted file mode 100644
index fd7cbce9fbb..00000000000
--- a/res/xml/security_settings_encrypted.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/res/xml/security_settings_misc.xml b/res/xml/security_settings_misc.xml
index 6a71033ea8c..bc737b01408 100644
--- a/res/xml/security_settings_misc.xml
+++ b/res/xml/security_settings_misc.xml
@@ -69,7 +69,7 @@
+ android:fragment="com.android.settings.security.trustagent.TrustAgentSettings"/>
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/com/android/settings/DeviceInfoSettings.java b/src/com/android/settings/DeviceInfoSettings.java
index 4479eaadb81..3ae5455a48d 100644
--- a/src/com/android/settings/DeviceInfoSettings.java
+++ b/src/com/android/settings/DeviceInfoSettings.java
@@ -32,11 +32,16 @@ import com.android.settings.deviceinfo.DeviceModelPreferenceController;
import com.android.settings.deviceinfo.FccEquipmentIdPreferenceController;
import com.android.settings.deviceinfo.FeedbackPreferenceController;
import com.android.settings.deviceinfo.FirmwareVersionPreferenceController;
+import com.android.settings.deviceinfo.imei.ImeiInfoDualSimPreferenceController;
+import com.android.settings.deviceinfo.imei.ImeiInfoPreferenceControllerV2;
import com.android.settings.deviceinfo.KernelVersionPreferenceController;
import com.android.settings.deviceinfo.ManualPreferenceController;
import com.android.settings.deviceinfo.RegulatoryInfoPreferenceController;
import com.android.settings.deviceinfo.SafetyInfoPreferenceController;
import com.android.settings.deviceinfo.SecurityPatchPreferenceController;
+import com.android.settings.deviceinfo.simstatus.SimStatusDualSimPreferenceController;
+import com.android.settings.deviceinfo.simstatus.SimStatusPreferenceControllerV2;
+import com.android.settings.deviceinfo.firmwareversion.FirmwareVersionPreferenceControllerV2;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settingslib.core.AbstractPreferenceController;
@@ -120,18 +125,21 @@ public class DeviceInfoSettings extends DashboardFragment implements Indexable {
Activity activity, Fragment fragment, Lifecycle lifecycle) {
if (FeatureFlagUtils.isEnabled(DEVICE_INFO_V2_FEATURE_FLAG)) {
final List controllers = new ArrayList<>();
-
// Device name
// Phone number
- // SIM status
+ controllers.add(new SimStatusPreferenceControllerV2(context, fragment));
+
+ controllers.add(new SimStatusDualSimPreferenceController(context, fragment));
controllers.add(new DeviceModelPreferenceController(context, fragment));
- // IMEI
+ controllers.add(new ImeiInfoPreferenceControllerV2(context, fragment));
- // Android version
+ controllers.add(new ImeiInfoDualSimPreferenceController(context, fragment));
+
+ controllers.add(new FirmwareVersionPreferenceControllerV2(context, fragment));
// IP address
diff --git a/src/com/android/settings/TrustAgentUtils.java b/src/com/android/settings/TrustAgentUtils.java
deleted file mode 100644
index b3d560f612e..00000000000
--- a/src/com/android/settings/TrustAgentUtils.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2014 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 android.content.ComponentName;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.content.res.XmlResourceParser;
-import android.service.trust.TrustAgentService;
-import android.util.AttributeSet;
-import android.util.Slog;
-import android.util.Xml;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
-
-import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
-
-// TODO(b/34461256): Refactor TrustAgentUtils into TrustAgentManager.
-public class TrustAgentUtils {
- static final String TAG = "TrustAgentUtils";
-
- private static final String TRUST_AGENT_META_DATA = TrustAgentService.TRUST_AGENT_META_DATA;
-
- public static class TrustAgentComponentInfo {
- ComponentName componentName;
- String title;
- String summary;
- EnforcedAdmin admin = null;
- }
-
- public static ComponentName getComponentName(ResolveInfo resolveInfo) {
- if (resolveInfo == null || resolveInfo.serviceInfo == null) return null;
- return new ComponentName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name);
- }
-
- public static TrustAgentComponentInfo getSettingsComponent(
- PackageManager pm, ResolveInfo resolveInfo) {
- if (resolveInfo == null || resolveInfo.serviceInfo == null
- || resolveInfo.serviceInfo.metaData == null) return null;
- String cn = null;
- TrustAgentComponentInfo trustAgentComponentInfo = new TrustAgentComponentInfo();
- XmlResourceParser parser = null;
- Exception caughtException = null;
- try {
- parser = resolveInfo.serviceInfo.loadXmlMetaData(pm, TRUST_AGENT_META_DATA);
- if (parser == null) {
- Slog.w(TAG, "Can't find " + TRUST_AGENT_META_DATA + " meta-data");
- return null;
- }
- Resources res = pm.getResourcesForApplication(resolveInfo.serviceInfo.applicationInfo);
- AttributeSet attrs = Xml.asAttributeSet(parser);
- int type;
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
- && type != XmlPullParser.START_TAG) {
- }
- String nodeName = parser.getName();
- if (!"trust-agent".equals(nodeName)) {
- Slog.w(TAG, "Meta-data does not start with trust-agent tag");
- return null;
- }
- TypedArray sa =
- res.obtainAttributes(attrs, com.android.internal.R.styleable.TrustAgent);
- trustAgentComponentInfo.summary =
- sa.getString(com.android.internal.R.styleable.TrustAgent_summary);
- trustAgentComponentInfo.title =
- sa.getString(com.android.internal.R.styleable.TrustAgent_title);
- cn = sa.getString(com.android.internal.R.styleable.TrustAgent_settingsActivity);
- sa.recycle();
- } catch (PackageManager.NameNotFoundException e) {
- caughtException = e;
- } catch (IOException e) {
- caughtException = e;
- } catch (XmlPullParserException e) {
- caughtException = e;
- } finally {
- if (parser != null) parser.close();
- }
- if (caughtException != null) {
- Slog.w(TAG, "Error parsing : " + resolveInfo.serviceInfo.packageName, caughtException);
- return null;
- }
- if (cn != null && cn.indexOf('/') < 0) {
- cn = resolveInfo.serviceInfo.packageName + "/" + cn;
- }
- trustAgentComponentInfo.componentName = (cn == null) ? null : ComponentName.unflattenFromString(cn);
- return trustAgentComponentInfo;
- }
-}
diff --git a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
index bb2959f4a21..e6479547d1e 100644
--- a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
@@ -28,8 +28,7 @@ import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.widget.SwitchBar;
import com.android.settings.widget.ToggleSwitch;
-public abstract class ToggleFeaturePreferenceFragment
- extends SettingsPreferenceFragment {
+public abstract class ToggleFeaturePreferenceFragment extends SettingsPreferenceFragment {
protected SwitchBar mSwitchBar;
protected ToggleSwitch mToggleSwitch;
@@ -43,9 +42,7 @@ public abstract class ToggleFeaturePreferenceFragment
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final int resId = getPreferenceScreenResId();
- if (usePreferenceScreenTitle() && resId > 0) {
- addPreferencesFromResource(resId);
- } else {
+ if (!usePreferenceScreenTitle() || resId <= 0) {
PreferenceScreen preferenceScreen = getPreferenceManager().createPreferenceScreen(
getActivity());
setPreferenceScreen(preferenceScreen);
diff --git a/src/com/android/settings/applications/DefaultAppSettings.java b/src/com/android/settings/applications/DefaultAppSettings.java
index 1487da3092e..34b635b0eb5 100644
--- a/src/com/android/settings/applications/DefaultAppSettings.java
+++ b/src/com/android/settings/applications/DefaultAppSettings.java
@@ -30,12 +30,12 @@ import com.android.settings.applications.defaultapps.DefaultPaymentSettingsPrefe
import com.android.settings.applications.defaultapps.DefaultPhonePreferenceController;
import com.android.settings.applications.defaultapps.DefaultSmsPreferenceController;
import com.android.settings.applications.defaultapps.DefaultWorkBrowserPreferenceController;
-import com.android.settings.widget.WorkOnlyCategoryPreferenceController;
import com.android.settings.applications.defaultapps.DefaultWorkPhonePreferenceController;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.dashboard.SummaryLoader;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
+import com.android.settings.widget.PreferenceCategoryController;
import com.android.settingslib.core.AbstractPreferenceController;
import java.util.ArrayList;
@@ -75,7 +75,7 @@ public class DefaultAppSettings extends DashboardFragment {
workControllers.add(new DefaultWorkPhonePreferenceController(context));
workControllers.add(new DefaultWorkBrowserPreferenceController(context));
controllers.addAll(workControllers);
- controllers.add(new WorkOnlyCategoryPreferenceController(
+ controllers.add(new PreferenceCategoryController(
context, KEY_DEFAULT_WORK_CATEGORY, workControllers));
controllers.add(new DefaultAssistPreferenceController(context, KEY_ASSIST_VOICE_INPUT,
false /* showSetting */));
diff --git a/src/com/android/settings/applications/ManageDomainUrls.java b/src/com/android/settings/applications/ManageDomainUrls.java
index ce919e118fb..53cad4aff4f 100644
--- a/src/com/android/settings/applications/ManageDomainUrls.java
+++ b/src/com/android/settings/applications/ManageDomainUrls.java
@@ -63,9 +63,7 @@ public class ManageDomainUrls extends SettingsPreferenceFragment
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setAnimationAllowed(true);
- if (usePreferenceScreenTitle()) {
- addPreferencesFromResource(R.xml.manage_domain_url_settings);
- } else {
+ if (!usePreferenceScreenTitle()) {
setPreferenceScreen(getPreferenceManager().createPreferenceScreen(getContext()));
}
mApplicationsState = ApplicationsState.getInstance(
@@ -74,6 +72,11 @@ public class ManageDomainUrls extends SettingsPreferenceFragment
setHasOptionsMenu(true);
}
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.manage_domain_url_settings;
+ }
+
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index 588e465b641..3b5604b039f 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -18,7 +18,6 @@ package com.android.settings.core.gateway;
import com.android.settings.ApnEditor;
import com.android.settings.ApnSettings;
-import com.android.settings.CryptKeeperSettings;
import com.android.settings.DateTimeSettings;
import com.android.settings.DeviceAdminSettings;
import com.android.settings.DeviceInfoSettings;
@@ -26,7 +25,6 @@ import com.android.settings.DisplaySettings;
import com.android.settings.IccLockSettings;
import com.android.settings.MasterClear;
import com.android.settings.PrivacySettings;
-import com.android.settings.SecuritySettings;
import com.android.settings.Settings;
import com.android.settings.TestingSettings;
import com.android.settings.TetherSettings;
@@ -45,7 +43,6 @@ import com.android.settings.applications.DefaultAppSettings;
import com.android.settings.applications.DrawOverlayDetails;
import com.android.settings.applications.ExternalSourcesDetails;
import com.android.settings.applications.InstalledAppDetails;
-import com.android.settings.applications.manageapplications.ManageApplications;
import com.android.settings.applications.ManageDomainUrls;
import com.android.settings.applications.NotificationApps;
import com.android.settings.applications.PictureInPictureDetails;
@@ -56,6 +53,7 @@ import com.android.settings.applications.UsageAccessDetails;
import com.android.settings.applications.VrListenerSettings;
import com.android.settings.applications.WriteSettingsDetails;
import com.android.settings.applications.assist.ManageAssist;
+import com.android.settings.applications.manageapplications.ManageApplications;
import com.android.settings.bluetooth.BluetoothDeviceDetailsFragment;
import com.android.settings.bluetooth.BluetoothSettings;
import com.android.settings.connecteddevice.ConnectedDeviceDashboardFragment;
@@ -106,8 +104,8 @@ import com.android.settings.notification.NotificationAccessSettings;
import com.android.settings.notification.NotificationStation;
import com.android.settings.notification.SoundSettings;
import com.android.settings.notification.ZenAccessSettings;
-import com.android.settings.notification.ZenModeBehaviorSettings;
import com.android.settings.notification.ZenModeAutomationSettings;
+import com.android.settings.notification.ZenModeBehaviorSettings;
import com.android.settings.notification.ZenModeEventRuleSettings;
import com.android.settings.notification.ZenModeScheduleRuleSettings;
import com.android.settings.notification.ZenModeSettings;
@@ -115,7 +113,9 @@ import com.android.settings.password.ChooseLockPassword;
import com.android.settings.password.ChooseLockPattern;
import com.android.settings.print.PrintJobSettingsFragment;
import com.android.settings.print.PrintSettingsFragment;
+import com.android.settings.security.CryptKeeperSettings;
import com.android.settings.security.LockscreenDashboardFragment;
+import com.android.settings.security.SecuritySettings;
import com.android.settings.sim.SimSettings;
import com.android.settings.support.SupportDashboardActivity;
import com.android.settings.system.ResetDashboardFragment;
diff --git a/src/com/android/settings/dashboard/DashboardFragmentRegistry.java b/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
index 07448620b61..42eea2deffd 100644
--- a/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
+++ b/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
@@ -19,7 +19,6 @@ package com.android.settings.dashboard;
import android.util.ArrayMap;
import com.android.settings.DisplaySettings;
-import com.android.settings.SecuritySettings;
import com.android.settings.Settings;
import com.android.settings.accounts.AccountDetailDashboardFragment;
import com.android.settings.accounts.UserAndAccountDashboardFragment;
@@ -35,6 +34,7 @@ import com.android.settings.network.NetworkDashboardFragment;
import com.android.settings.notification.ConfigureNotificationSettings;
import com.android.settings.notification.SoundSettings;
import com.android.settings.security.LockscreenDashboardFragment;
+import com.android.settings.security.SecuritySettings;
import com.android.settings.system.SystemDashboardFragment;
import com.android.settingslib.drawer.CategoryKey;
diff --git a/src/com/android/settings/dashboard/DashboardSummary.java b/src/com/android/settings/dashboard/DashboardSummary.java
index b7c87150fc2..8f66b67f4d9 100644
--- a/src/com/android/settings/dashboard/DashboardSummary.java
+++ b/src/com/android/settings/dashboard/DashboardSummary.java
@@ -24,6 +24,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.service.settings.suggestions.Suggestion;
import android.support.annotation.VisibleForTesting;
+import android.support.annotation.WorkerThread;
import android.support.v7.widget.LinearLayoutManager;
import android.util.Log;
import android.view.LayoutInflater;
@@ -50,6 +51,7 @@ import com.android.settingslib.drawer.SettingsDrawerActivity.CategoryListener;
import com.android.settingslib.drawer.Tile;
import com.android.settingslib.suggestions.SuggestionList;
import com.android.settingslib.suggestions.SuggestionParser;
+import com.android.settingslib.utils.ThreadUtils;
import java.util.ArrayList;
import java.util.List;
@@ -181,12 +183,6 @@ public class DashboardSummary extends InstrumentedFragment
}
}
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
- return inflater.inflate(R.layout.dashboard, container, false);
- }
-
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
@@ -198,9 +194,10 @@ public class DashboardSummary extends InstrumentedFragment
}
@Override
- public void onViewCreated(View view, Bundle bundle) {
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) {
long startTime = System.currentTimeMillis();
- mDashboard = view.findViewById(R.id.dashboard_container);
+ final View root = inflater.inflate(R.layout.dashboard, container, false);
+ mDashboard = root.findViewById(R.id.dashboard_container);
mLayoutManager = new LinearLayoutManager(getContext());
mLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
if (bundle != null) {
@@ -218,19 +215,19 @@ public class DashboardSummary extends InstrumentedFragment
mSummaryLoader.setSummaryConsumer(mAdapter);
ActionBarShadowController.attachToRecyclerView(
getActivity().findViewById(R.id.search_bar_container), getLifecycle(), mDashboard);
-
+ rebuildUI();
if (DEBUG_TIMING) {
- Log.d(TAG, "onViewCreated took "
+ Log.d(TAG, "onCreateView took "
+ (System.currentTimeMillis() - startTime) + " ms");
}
- rebuildUI();
+ return root;
}
@VisibleForTesting
void rebuildUI() {
if (!mSuggestionFeatureProvider.isSuggestionEnabled(getContext())) {
Log.d(TAG, "Suggestion v1 feature is disabled, skipping suggestion v1");
- updateCategory();
+ ThreadUtils.postOnBackgroundThread(() -> updateCategory());
} else {
new SuggestionLoader().execute();
// Set categories on their own if loading suggestions takes too long.
@@ -340,11 +337,12 @@ public class DashboardSummary extends InstrumentedFragment
}
}
+ @WorkerThread
void updateCategory() {
final DashboardCategory category = mDashboardFeatureProvider.getTilesForCategory(
CategoryKey.CATEGORY_HOMEPAGE);
mSummaryLoader.updateSummaryToCache(category);
- mAdapter.setCategory(category);
+ ThreadUtils.postOnMainThread(() -> mAdapter.setCategory(category));
}
/**
diff --git a/src/com/android/settings/dashboard/SummaryLoader.java b/src/com/android/settings/dashboard/SummaryLoader.java
index 5816bba8237..fe55be802a9 100644
--- a/src/com/android/settings/dashboard/SummaryLoader.java
+++ b/src/com/android/settings/dashboard/SummaryLoader.java
@@ -60,23 +60,6 @@ public class SummaryLoader {
private boolean mWorkerListening;
private ArraySet mReceivers = new ArraySet<>();
- public SummaryLoader(Activity activity, List categories) {
- mDashboardFeatureProvider = FeatureFactory.getFactory(activity)
- .getDashboardFeatureProvider(activity);
- mCategoryKey = null;
- mWorkerThread = new HandlerThread("SummaryLoader", Process.THREAD_PRIORITY_BACKGROUND);
- mWorkerThread.start();
- mWorker = new Worker(mWorkerThread.getLooper());
- mActivity = activity;
- for (int i = 0; i < categories.size(); i++) {
- List tiles = categories.get(i).tiles;
- for (int j = 0; j < tiles.size(); j++) {
- Tile tile = tiles.get(j);
- mWorker.obtainMessage(Worker.MSG_GET_PROVIDER, tile).sendToTarget();
- }
- }
- }
-
public SummaryLoader(Activity activity, String categoryKey) {
mDashboardFeatureProvider = FeatureFactory.getFactory(activity)
.getDashboardFeatureProvider(activity);
@@ -85,17 +68,6 @@ public class SummaryLoader {
mWorkerThread.start();
mWorker = new Worker(mWorkerThread.getLooper());
mActivity = activity;
-
- final DashboardCategory category =
- mDashboardFeatureProvider.getTilesForCategory(categoryKey);
- if (category == null || category.tiles == null) {
- return;
- }
-
- List tiles = category.tiles;
- for (Tile tile : tiles) {
- mWorker.obtainMessage(Worker.MSG_GET_PROVIDER, tile).sendToTarget();
- }
}
public void release() {
@@ -153,15 +125,32 @@ public class SummaryLoader {
* Only call from the main thread.
*/
public void setListening(boolean listening) {
- if (mListening == listening) return;
+ if (mListening == listening) {
+ return;
+ }
mListening = listening;
// Unregister listeners immediately.
for (int i = 0; i < mReceivers.size(); i++) {
mActivity.unregisterReceiver(mReceivers.valueAt(i));
}
mReceivers.clear();
+
mWorker.removeMessages(Worker.MSG_SET_LISTENING);
- mWorker.obtainMessage(Worker.MSG_SET_LISTENING, listening ? 1 : 0, 0).sendToTarget();
+ if (!listening) {
+ // Stop listen
+ mWorker.obtainMessage(Worker.MSG_SET_LISTENING, 0 /* listening */).sendToTarget();
+ } else {
+ // Start listen
+ if (mSummaryProviderMap.isEmpty()) {
+ // Category not initialized yet, init before starting to listen
+ if (!mWorker.hasMessages(Worker.MSG_GET_CATEGORY_TILES_AND_SET_LISTENING)) {
+ mWorker.sendEmptyMessage(Worker.MSG_GET_CATEGORY_TILES_AND_SET_LISTENING);
+ }
+ } else {
+ // Category already initialized, start listening immediately
+ mWorker.obtainMessage(Worker.MSG_SET_LISTENING, 1 /* listening */).sendToTarget();
+ }
+ }
}
private SummaryProvider getSummaryProvider(Tile tile) {
@@ -236,9 +225,13 @@ public class SummaryLoader {
}
private synchronized void setListeningW(boolean listening) {
- if (mWorkerListening == listening) return;
+ if (mWorkerListening == listening) {
+ return;
+ }
mWorkerListening = listening;
- if (DEBUG) Log.d(TAG, "Listening " + listening);
+ if (DEBUG) {
+ Log.d(TAG, "Listening " + listening);
+ }
for (SummaryProvider p : mSummaryProviderMap.keySet()) {
try {
p.setListening(listening);
@@ -271,7 +264,6 @@ public class SummaryLoader {
}
-
public interface SummaryProvider {
void setListening(boolean listening);
}
@@ -285,8 +277,9 @@ public class SummaryLoader {
}
private class Worker extends Handler {
- private static final int MSG_GET_PROVIDER = 1;
- private static final int MSG_SET_LISTENING = 2;
+ private static final int MSG_GET_CATEGORY_TILES_AND_SET_LISTENING = 1;
+ private static final int MSG_GET_PROVIDER = 2;
+ private static final int MSG_SET_LISTENING = 3;
public Worker(Looper looper) {
super(looper);
@@ -295,6 +288,18 @@ public class SummaryLoader {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
+ case MSG_GET_CATEGORY_TILES_AND_SET_LISTENING:
+ final DashboardCategory category =
+ mDashboardFeatureProvider.getTilesForCategory(mCategoryKey);
+ if (category == null || category.tiles == null) {
+ return;
+ }
+ final List tiles = category.tiles;
+ for (Tile tile : tiles) {
+ makeProviderW(tile);
+ }
+ setListeningW(true);
+ break;
case MSG_GET_PROVIDER:
Tile tile = (Tile) msg.obj;
makeProviderW(tile);
diff --git a/src/com/android/settings/datausage/UnrestrictedDataAccess.java b/src/com/android/settings/datausage/UnrestrictedDataAccess.java
index 6771abc6dde..2bf2e012c3f 100644
--- a/src/com/android/settings/datausage/UnrestrictedDataAccess.java
+++ b/src/com/android/settings/datausage/UnrestrictedDataAccess.java
@@ -59,7 +59,9 @@ public class UnrestrictedDataAccess extends SettingsPreferenceFragment
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setAnimationAllowed(true);
- addPreferencesFromResource(R.xml.unrestricted_data_access_settings);
+ if (!usePreferenceScreenTitle()) {
+ addPreferencesFromResource(R.xml.unrestricted_data_access_settings);
+ }
mApplicationsState = ApplicationsState.getInstance(
(Application) getContext().getApplicationContext());
mDataSaverBackend = new DataSaverBackend(getContext());
@@ -208,6 +210,11 @@ public class UnrestrictedDataAccess extends SettingsPreferenceFragment
return MetricsEvent.DATA_USAGE_UNRESTRICTED_ACCESS;
}
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.unrestricted_data_access_settings;
+ }
+
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (preference instanceof AccessPreference) {
diff --git a/src/com/android/settings/deviceinfo/FirmwareVersionPreferenceController.java b/src/com/android/settings/deviceinfo/FirmwareVersionPreferenceController.java
index fd73ed55847..8c9a2f1a4ee 100644
--- a/src/com/android/settings/deviceinfo/FirmwareVersionPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/FirmwareVersionPreferenceController.java
@@ -27,13 +27,17 @@ import android.text.TextUtils;
import android.util.Log;
import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.deviceinfo.firmwareversion.FirmwareVersionPreferenceControllerV2;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnResume;
-
+/**
+ * deprecated in favor of {@link FirmwareVersionPreferenceControllerV2}
+ */
+@Deprecated
public class FirmwareVersionPreferenceController extends AbstractPreferenceController implements
PreferenceControllerMixin, LifecycleObserver, OnResume {
diff --git a/src/com/android/settings/deviceinfo/ImeiInfoPreferenceController.java b/src/com/android/settings/deviceinfo/ImeiInfoPreferenceController.java
index f56473474a6..456dbfcce15 100644
--- a/src/com/android/settings/deviceinfo/ImeiInfoPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/ImeiInfoPreferenceController.java
@@ -19,8 +19,13 @@ package com.android.settings.deviceinfo;
import android.content.Context;
import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.deviceinfo.imei.ImeiInfoPreferenceControllerV2;
import com.android.settingslib.deviceinfo.AbstractSimStatusImeiInfoPreferenceController;
+/**
+ * deprecated in favour of {@link ImeiInfoPreferenceControllerV2}
+ */
+@Deprecated
public class ImeiInfoPreferenceController extends AbstractSimStatusImeiInfoPreferenceController
implements PreferenceControllerMixin {
diff --git a/src/com/android/settings/deviceinfo/ImeiInformation.java b/src/com/android/settings/deviceinfo/ImeiInformation.java
index 9d4602b55ba..9f38f1b01bd 100644
--- a/src/com/android/settings/deviceinfo/ImeiInformation.java
+++ b/src/com/android/settings/deviceinfo/ImeiInformation.java
@@ -22,7 +22,6 @@ import android.support.v7.preference.PreferenceScreen;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.Spannable;
-import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextUtils;
@@ -34,7 +33,12 @@ import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.PhoneFactory;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.deviceinfo.imei.ImeiInfoPreferenceControllerV2;
+/**
+ * deprecated in favor of {@link ImeiInfoPreferenceControllerV2}
+ */
+@Deprecated
public class ImeiInformation extends SettingsPreferenceFragment {
private static final String KEY_PRL_VERSION = "prl_version";
diff --git a/src/com/android/settings/deviceinfo/SimStatus.java b/src/com/android/settings/deviceinfo/SimStatus.java
index c3d35478eac..768beb84318 100644
--- a/src/com/android/settings/deviceinfo/SimStatus.java
+++ b/src/com/android/settings/deviceinfo/SimStatus.java
@@ -73,7 +73,9 @@ import java.util.List;
* # Operator info (area update info cell broadcast)
* # Signal Strength
*
+ * deprecated in favor of {@link com.android.settings.deviceinfo.simstatus.SimStatusDialogFragment}
*/
+@Deprecated
public class SimStatus extends SettingsPreferenceFragment {
private static final String TAG = "SimStatus";
diff --git a/src/com/android/settings/deviceinfo/SimStatusPreferenceController.java b/src/com/android/settings/deviceinfo/SimStatusPreferenceController.java
index 99441b5c810..ca531ea50c6 100644
--- a/src/com/android/settings/deviceinfo/SimStatusPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/SimStatusPreferenceController.java
@@ -19,8 +19,13 @@ package com.android.settings.deviceinfo;
import android.content.Context;
import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.deviceinfo.simstatus.SimStatusPreferenceControllerV2;
import com.android.settingslib.deviceinfo.AbstractSimStatusImeiInfoPreferenceController;
+/**
+ * deprecated in favor of {@link SimStatusPreferenceControllerV2}
+ */
+@Deprecated
public class SimStatusPreferenceController extends AbstractSimStatusImeiInfoPreferenceController
implements PreferenceControllerMixin {
diff --git a/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionDialogFragment.java b/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionDialogFragment.java
new file mode 100644
index 00000000000..3af21a93f53
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionDialogFragment.java
@@ -0,0 +1,59 @@
+/*
+ * 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.deviceinfo.firmwareversion;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.R;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+
+public class FirmwareVersionDialogFragment extends InstrumentedDialogFragment {
+
+ private static final String TAG = "firmwareVersionDialog";
+
+ public static void show(Fragment host) {
+ final FragmentManager manager = host.getChildFragmentManager();
+ if (manager.findFragmentByTag(TAG) == null) {
+ final FirmwareVersionDialogFragment dialog = new FirmwareVersionDialogFragment();
+ dialog.show(manager, TAG);
+ }
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsProto.MetricsEvent.DIALOG_FIRMWARE_VERSION;
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
+ .setTitle(R.string.firmware_title)
+ .setPositiveButton(android.R.string.ok, null /* listener */);
+
+ final View view = LayoutInflater.from(getActivity()).inflate(
+ R.layout.dialog_firmware_version, null /* parent */);
+
+ return builder.setView(view).create();
+ }
+}
diff --git a/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionPreferenceControllerV2.java b/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionPreferenceControllerV2.java
new file mode 100644
index 00000000000..3ce9ee1cdc6
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionPreferenceControllerV2.java
@@ -0,0 +1,71 @@
+/*
+ * 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.deviceinfo.firmwareversion;
+
+import android.app.Fragment;
+import android.content.Context;
+import android.os.Build;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.text.TextUtils;
+
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+public class FirmwareVersionPreferenceControllerV2 extends AbstractPreferenceController implements
+ PreferenceControllerMixin {
+
+ private final static String FIRMWARE_VERSION_KEY = "firmware_version";
+
+ private final Fragment mFragment;
+
+ public FirmwareVersionPreferenceControllerV2(Context context, Fragment fragment) {
+ super(context);
+
+ mFragment = fragment;
+ }
+
+
+ @Override
+ public boolean isAvailable() {
+ return true;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ final Preference pref = screen.findPreference(getPreferenceKey());
+ if (pref != null) {
+ pref.setSummary(Build.VERSION.RELEASE);
+ }
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return FIRMWARE_VERSION_KEY;
+ }
+
+ @Override
+ public boolean handlePreferenceTreeClick(Preference preference) {
+ if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
+ return false;
+ }
+
+ FirmwareVersionDialogFragment.show(mFragment);
+ return true;
+ }
+}
diff --git a/src/com/android/settings/deviceinfo/imei/AbstractImeiInfoPreferenceController.java b/src/com/android/settings/deviceinfo/imei/AbstractImeiInfoPreferenceController.java
new file mode 100644
index 00000000000..a9871a0f76a
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/imei/AbstractImeiInfoPreferenceController.java
@@ -0,0 +1,99 @@
+/*
+ * 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.deviceinfo.imei;
+
+import static android.telephony.TelephonyManager.PHONE_TYPE_CDMA;
+
+import android.app.Fragment;
+import android.content.Context;
+import android.support.annotation.VisibleForTesting;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.deviceinfo.AbstractSimStatusImeiInfoPreferenceController;
+
+/**
+ * Controller that manages preference for single and dual sim devices.
+ */
+public abstract class AbstractImeiInfoPreferenceController extends
+ AbstractSimStatusImeiInfoPreferenceController implements PreferenceControllerMixin {
+
+ protected final boolean mIsMultiSim;
+ protected final TelephonyManager mTelephonyManager;
+
+ private Preference mPreference;
+ private Fragment mFragment;
+
+ public AbstractImeiInfoPreferenceController(Context context, Fragment fragment) {
+ super(context);
+
+ mFragment = fragment;
+ mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+ mIsMultiSim = mTelephonyManager.getPhoneCount() > 1;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPreference = screen.findPreference(getPreferenceKey());
+ if (mPreference == null) {
+ return;
+ }
+ final int phoneType = mTelephonyManager.getPhoneType();
+ if (phoneType == PHONE_TYPE_CDMA) {
+ mPreference.setTitle(getTitleForCdmaPhone());
+ mPreference.setSummary(getMeid());
+ } else {
+ // GSM phone
+ mPreference.setTitle(getTitleForGsmPhone());
+ mPreference.setSummary(mTelephonyManager.getImei(getSimSlot()));
+ }
+ }
+
+ @Override
+ public boolean handlePreferenceTreeClick(Preference preference) {
+ if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
+ return false;
+ }
+
+ ImeiInfoDialogFragment.show(mFragment, getSimSlot(), mPreference.getTitle().toString());
+ return true;
+ }
+
+ /**
+ * @return The preference title for phones based on CDMA technology.
+ */
+ protected abstract String getTitleForCdmaPhone();
+
+ /**
+ * @return The preference title for phones based on GSM technology.
+ */
+ protected abstract String getTitleForGsmPhone();
+
+ /**
+ * @return The sim slot to retrieve IMEI/CDMA information about.
+ */
+ protected abstract int getSimSlot();
+
+ @VisibleForTesting
+ String getMeid() {
+ return mTelephonyManager.getMeid(getSimSlot());
+ }
+}
diff --git a/src/com/android/settings/deviceinfo/imei/ImeiInfoDialogController.java b/src/com/android/settings/deviceinfo/imei/ImeiInfoDialogController.java
new file mode 100644
index 00000000000..542b630725c
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/imei/ImeiInfoDialogController.java
@@ -0,0 +1,160 @@
+/*
+ * 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.deviceinfo.imei;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.support.annotation.NonNull;
+import android.support.annotation.VisibleForTesting;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.text.Spannable;
+import android.text.SpannableStringBuilder;
+import android.text.Spanned;
+import android.text.TextUtils;
+import android.text.style.TtsSpan;
+
+import com.android.internal.telephony.PhoneConstants;
+import com.android.settings.R;
+
+import java.util.List;
+
+public class ImeiInfoDialogController {
+
+ @VisibleForTesting
+ static final int ID_PRL_VERSION_VALUE = R.id.prl_version_value;
+ private static final int ID_MIN_NUMBER_LABEL = R.id.min_number_label;
+ @VisibleForTesting
+ static final int ID_MIN_NUMBER_VALUE = R.id.min_number_value;
+ @VisibleForTesting
+ static final int ID_MEID_NUMBER_VALUE = R.id.meid_number_value;
+ @VisibleForTesting
+ static final int ID_ICC_ID_LABEL = R.id.icc_id_label;
+ @VisibleForTesting
+ static final int ID_ICC_ID_VALUE = R.id.icc_id_value;
+ @VisibleForTesting
+ static final int ID_IMEI_VALUE = R.id.imei_value;
+ @VisibleForTesting
+ static final int ID_IMEI_SV_VALUE = R.id.imei_sv_value;
+ @VisibleForTesting
+ static final int ID_CDMA_SETTINGS = R.id.cdma_settings;
+ @VisibleForTesting
+ static final int ID_GSM_SETTINGS = R.id.gsm_settings;
+
+ private static CharSequence getTextAsDigits(CharSequence text) {
+ if (TextUtils.isDigitsOnly(text)) {
+ final Spannable spannable = new SpannableStringBuilder(text);
+ final TtsSpan span = new TtsSpan.DigitsBuilder(text.toString()).build();
+ spannable.setSpan(span, 0, spannable.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+ text = spannable;
+ }
+ return text;
+ }
+
+ private final ImeiInfoDialogFragment mDialog;
+ private final TelephonyManager mTelephonyManager;
+ private final SubscriptionInfo mSubscriptionInfo;
+ private final int mSlotId;
+
+ public ImeiInfoDialogController(@NonNull ImeiInfoDialogFragment dialog, int slotId) {
+ mDialog = dialog;
+ mSlotId = slotId;
+ final Context context = dialog.getContext();
+ mTelephonyManager = (TelephonyManager) context.getSystemService(
+ Context.TELEPHONY_SERVICE);
+ mSubscriptionInfo = getSubscriptionInfo(context, slotId);
+ }
+
+ /**
+ * Sets IMEI/MEID information based on whether the device is CDMA or GSM.
+ */
+ public void populateImeiInfo() {
+ if (mSubscriptionInfo == null) {
+ return;
+ }
+ if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
+ updateDialogForCdmaPhone();
+ } else {
+ updateDialogForGsmPhone();
+ }
+ }
+
+ private void updateDialogForCdmaPhone() {
+ final Resources res = mDialog.getContext().getResources();
+ mDialog.setText(ID_MEID_NUMBER_VALUE, getMeid());
+ mDialog.setText(ID_MIN_NUMBER_VALUE,
+ mTelephonyManager.getCdmaMin(mSubscriptionInfo.getSubscriptionId()));
+
+ if (res.getBoolean(R.bool.config_msid_enable)) {
+ mDialog.setText(ID_MIN_NUMBER_LABEL,
+ res.getString(R.string.status_msid_number));
+ }
+
+ mDialog.setText(ID_PRL_VERSION_VALUE, getCdmaPrlVersion());
+
+ if (isCdmaLteEnabled()) {
+ // Show ICC ID and IMEI for LTE device
+ mDialog.setText(ID_ICC_ID_VALUE, mSubscriptionInfo.getIccId());
+ mDialog.setText(ID_IMEI_VALUE,
+ getTextAsDigits(mTelephonyManager.getImei(mSlotId)));
+ mDialog.setText(ID_IMEI_SV_VALUE,
+ getTextAsDigits(mTelephonyManager.getDeviceSoftwareVersion(mSlotId)));
+ } else {
+ // device is not GSM/UMTS, do not display GSM/UMTS features
+ mDialog.removeViewFromScreen(ID_GSM_SETTINGS);
+ mDialog.removeViewFromScreen(ID_ICC_ID_LABEL);
+ mDialog.removeViewFromScreen(ID_ICC_ID_VALUE);
+ }
+ }
+
+ private void updateDialogForGsmPhone() {
+ mDialog.setText(ID_IMEI_VALUE, getTextAsDigits(mTelephonyManager.getImei(mSlotId)));
+ mDialog.setText(ID_IMEI_SV_VALUE,
+ getTextAsDigits(mTelephonyManager.getDeviceSoftwareVersion(mSlotId)));
+ // device is not CDMA, do not display CDMA features
+ mDialog.removeViewFromScreen(ID_CDMA_SETTINGS);
+ mDialog.removeViewFromScreen(ID_ICC_ID_LABEL);
+ mDialog.removeViewFromScreen(ID_ICC_ID_VALUE);
+ }
+
+ private SubscriptionInfo getSubscriptionInfo(Context context, int slotId) {
+ final List subscriptionInfoList = SubscriptionManager.from(context)
+ .getActiveSubscriptionInfoList();
+ if (subscriptionInfoList == null) {
+ return null;
+ }
+
+ return subscriptionInfoList.get(slotId);
+ }
+
+ @VisibleForTesting
+ String getCdmaPrlVersion() {
+ return mTelephonyManager.getCdmaPrlVersion();
+ }
+
+ @VisibleForTesting
+ boolean isCdmaLteEnabled() {
+ return mTelephonyManager.getLteOnCdmaMode(mSubscriptionInfo.getSubscriptionId())
+ == PhoneConstants.LTE_ON_CDMA_TRUE;
+ }
+
+ @VisibleForTesting
+ String getMeid() {
+ return mTelephonyManager.getMeid(mSlotId);
+ }
+}
diff --git a/src/com/android/settings/deviceinfo/imei/ImeiInfoDialogFragment.java b/src/com/android/settings/deviceinfo/imei/ImeiInfoDialogFragment.java
new file mode 100644
index 00000000000..11e66f1c722
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/imei/ImeiInfoDialogFragment.java
@@ -0,0 +1,94 @@
+/*
+ * 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.deviceinfo.imei;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.VisibleForTesting;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.R;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+
+public class ImeiInfoDialogFragment extends InstrumentedDialogFragment {
+
+ @VisibleForTesting
+ static final String TAG = "ImeiInfoDialog";
+
+ private static final String SLOT_ID_BUNDLE_KEY = "arg_key_slot_id";
+ private static final String DIALOG_TITLE_BUNDLE_KEY = "arg_key_dialog_title";
+
+ private View mRootView;
+
+ public static void show(@NonNull Fragment host, int slotId, String dialogTitle) {
+ final FragmentManager manager = host.getChildFragmentManager();
+ if (manager.findFragmentByTag(TAG) == null) {
+ final Bundle bundle = new Bundle();
+ bundle.putInt(SLOT_ID_BUNDLE_KEY, slotId);
+ bundle.putString(DIALOG_TITLE_BUNDLE_KEY, dialogTitle);
+ final ImeiInfoDialogFragment dialog = new ImeiInfoDialogFragment();
+ dialog.setArguments(bundle);
+ dialog.show(manager, TAG);
+ }
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsProto.MetricsEvent.DIALOG_IMEI_INFO;
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final Bundle bundle = getArguments();
+ final int slotId = bundle.getInt(SLOT_ID_BUNDLE_KEY);
+ final String dialogTitle = bundle.getString(DIALOG_TITLE_BUNDLE_KEY);
+
+ final ImeiInfoDialogController controller = new ImeiInfoDialogController(this, slotId);
+ final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
+ .setTitle(dialogTitle)
+ .setPositiveButton(android.R.string.ok, null);
+ mRootView = LayoutInflater.from(builder.getContext())
+ .inflate(R.layout.dialog_imei_info, null /* parent */);
+ controller.populateImeiInfo();
+ return builder.setView(mRootView).create();
+ }
+
+ public void removeViewFromScreen(int viewId) {
+ final View view = mRootView.findViewById(viewId);
+ if (view != null) {
+ view.setVisibility(View.GONE);
+ }
+ }
+
+ public void setText(int viewId, CharSequence text) {
+ final TextView textView = mRootView.findViewById(viewId);
+ if (TextUtils.isEmpty(text)) {
+ text = getResources().getString(R.string.device_info_default);
+ }
+ if (textView != null) {
+ textView.setText(text);
+ }
+ }
+}
diff --git a/src/com/android/settings/deviceinfo/imei/ImeiInfoDualSimPreferenceController.java b/src/com/android/settings/deviceinfo/imei/ImeiInfoDualSimPreferenceController.java
new file mode 100644
index 00000000000..61d99b966f0
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/imei/ImeiInfoDualSimPreferenceController.java
@@ -0,0 +1,57 @@
+/*
+ * 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.deviceinfo.imei;
+
+import android.app.Fragment;
+import android.content.Context;
+
+import com.android.settings.R;
+
+public class ImeiInfoDualSimPreferenceController extends AbstractImeiInfoPreferenceController {
+
+ private static final String KEY_IMEI_INFO_DUAL_SIM = "imei_info_sim_slot_2";
+ private static final int SIM_SLOT = 1;
+
+ public ImeiInfoDualSimPreferenceController(Context context, Fragment fragment) {
+ super(context, fragment);
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return super.isAvailable() && mIsMultiSim;
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY_IMEI_INFO_DUAL_SIM;
+ }
+
+ @Override
+ protected String getTitleForCdmaPhone() {
+ return mContext.getResources().getString(R.string.meid_multi_sim_sim_slot_2);
+ }
+
+ @Override
+ protected String getTitleForGsmPhone() {
+ return mContext.getResources().getString(R.string.imei_multi_sim_slot_2);
+ }
+
+ @Override
+ protected int getSimSlot() {
+ return SIM_SLOT;
+ }
+}
diff --git a/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceControllerV2.java b/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceControllerV2.java
new file mode 100644
index 00000000000..74448bb123e
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceControllerV2.java
@@ -0,0 +1,55 @@
+/*
+ * 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.deviceinfo.imei;
+
+import android.app.Fragment;
+import android.content.Context;
+
+import com.android.settings.R;
+
+public class ImeiInfoPreferenceControllerV2 extends AbstractImeiInfoPreferenceController {
+
+ public static final int SIM_SLOT = 0;
+
+ private static final String KEY_IMEI_INFO = "imei_info_sim_slot_1";
+
+ public ImeiInfoPreferenceControllerV2(Context context, Fragment fragment) {
+ super(context, fragment);
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY_IMEI_INFO;
+ }
+
+ @Override
+ protected String getTitleForCdmaPhone() {
+ return mIsMultiSim ? mContext.getResources().getString(R.string.meid_multi_sim_sim_slot_1)
+ : mContext.getResources().getString(R.string.status_meid_number);
+ }
+
+ @Override
+ protected String getTitleForGsmPhone() {
+ return mIsMultiSim ? mContext.getResources().getString(R.string.imei_multi_sim_slot_1)
+ : mContext.getResources().getString(R.string.status_imei);
+ }
+
+ @Override
+ protected int getSimSlot() {
+ return SIM_SLOT;
+ }
+}
diff --git a/src/com/android/settings/deviceinfo/simstatus/AbstractSimStatusPreferenceController.java b/src/com/android/settings/deviceinfo/simstatus/AbstractSimStatusPreferenceController.java
new file mode 100644
index 00000000000..6107bf51b05
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/simstatus/AbstractSimStatusPreferenceController.java
@@ -0,0 +1,98 @@
+/*
+ * 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.deviceinfo.simstatus;
+
+import android.app.Fragment;
+import android.content.Context;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+
+import com.android.settings.R;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.deviceinfo.AbstractSimStatusImeiInfoPreferenceController;
+
+import java.util.List;
+
+public abstract class AbstractSimStatusPreferenceController extends
+ AbstractSimStatusImeiInfoPreferenceController implements PreferenceControllerMixin {
+
+ protected final boolean mIsMultiSim;
+ protected final TelephonyManager mTelephonyManager;
+ private final SubscriptionManager mSubscriptionManager;
+ private final Fragment mFragment;
+
+ private Preference mPreference;
+
+ public AbstractSimStatusPreferenceController(Context context, Fragment fragment) {
+ super(context);
+
+ mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+ mSubscriptionManager = (SubscriptionManager) context.getSystemService(
+ Context.TELEPHONY_SUBSCRIPTION_SERVICE);
+ mFragment = fragment;
+ mIsMultiSim = mTelephonyManager.getPhoneCount() > 1;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPreference = screen.findPreference(getPreferenceKey());
+ if (mPreference == null) {
+ return;
+ }
+
+ mPreference.setTitle(getPreferenceTitle());
+ mPreference.setSummary(getCarrierName());
+ }
+
+ @Override
+ public boolean handlePreferenceTreeClick(Preference preference) {
+ if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
+ return false;
+ }
+
+ SimStatusDialogFragment.show(mFragment, getSimSlot(), getPreferenceTitle());
+ return true;
+ }
+
+ /**
+ * @return The preference title for the displayed preference.
+ */
+ protected abstract String getPreferenceTitle();
+
+ /**
+ * @return The sim slot to retrieve sim status information about.
+ */
+ protected abstract int getSimSlot();
+
+ private CharSequence getCarrierName() {
+ final List subscriptionInfoList =
+ mSubscriptionManager.getActiveSubscriptionInfoList();
+ if (subscriptionInfoList != null) {
+ for (SubscriptionInfo info : subscriptionInfoList) {
+ if (info.getSimSlotIndex() == getSimSlot()) {
+ return info.getCarrierName();
+ }
+ }
+ }
+ return mContext.getText(R.string.device_info_not_available);
+ }
+}
diff --git a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java
new file mode 100644
index 00000000000..a6cc28f1857
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java
@@ -0,0 +1,375 @@
+/*
+ * 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.deviceinfo.simstatus;
+
+import static android.content.Context.TELEPHONY_SERVICE;
+
+import android.Manifest;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.support.annotation.NonNull;
+import android.support.annotation.VisibleForTesting;
+import android.telephony.CellBroadcastMessage;
+import android.telephony.PhoneStateListener;
+import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.settings.R;
+import com.android.settingslib.DeviceInfoUtils;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnPause;
+import com.android.settingslib.core.lifecycle.events.OnResume;
+
+import java.util.List;
+
+public class SimStatusDialogController implements LifecycleObserver, OnResume, OnPause {
+
+ private final static String TAG = "SimStatusDialogCtrl";
+
+ @VisibleForTesting
+ final static int NETWORK_PROVIDER_VALUE_ID = R.id.operator_name_value;
+ @VisibleForTesting
+ final static int PHONE_NUMBER_VALUE_ID = R.id.number_value;
+ @VisibleForTesting
+ final static int CELLULAR_NETWORK_STATE = R.id.data_state_value;
+ @VisibleForTesting
+ final static int OPERATOR_INFO_LABEL_ID = R.id.latest_area_info_label;
+ @VisibleForTesting
+ final static int OPERATOR_INFO_VALUE_ID = R.id.latest_area_info_value;
+ @VisibleForTesting
+ final static int SERVICE_STATE_VALUE_ID = R.id.service_state_value;
+ @VisibleForTesting
+ final static int SIGNAL_STRENGTH_VALUE_ID = R.id.signal_strength_value;
+ @VisibleForTesting
+ final static int CELLULAR_NETWORK_TYPE_VALUE_ID = R.id.network_type_value;
+ @VisibleForTesting
+ final static int ROAMING_INFO_VALUE_ID = R.id.roaming_state_value;
+
+ private final static String CB_AREA_INFO_RECEIVED_ACTION =
+ "com.android.cellbroadcastreceiver.CB_AREA_INFO_RECEIVED";
+ private final static String GET_LATEST_CB_AREA_INFO_ACTION =
+ "com.android.cellbroadcastreceiver.GET_LATEST_CB_AREA_INFO";
+ private final static String CELL_BROADCAST_RECEIVER_APP = "com.android.cellbroadcastreceiver";
+
+ private final SimStatusDialogFragment mDialog;
+ private final SubscriptionInfo mSubscriptionInfo;
+ private final TelephonyManager mTelephonyManager;
+ private final Resources mRes;
+ private final Context mContext;
+
+ private boolean mShowLatestAreaInfo;
+
+ private final BroadcastReceiver mAreaInfoReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ if (TextUtils.equals(action, CB_AREA_INFO_RECEIVED_ACTION)) {
+ final Bundle extras = intent.getExtras();
+ if (extras == null) {
+ return;
+ }
+ final CellBroadcastMessage cbMessage = (CellBroadcastMessage) extras.get("message");
+ if (cbMessage != null
+ && mSubscriptionInfo.getSubscriptionId() == cbMessage.getSubId()) {
+ final String latestAreaInfo = cbMessage.getMessageBody();
+ mDialog.setText(OPERATOR_INFO_VALUE_ID, latestAreaInfo);
+ }
+ }
+ }
+ };
+
+
+ private PhoneStateListener mPhoneStateListener;
+
+ public SimStatusDialogController(@NonNull SimStatusDialogFragment dialog, Lifecycle lifecycle,
+ int slotId) {
+ mDialog = dialog;
+ mContext = dialog.getContext();
+ mSubscriptionInfo = getPhoneSubscriptionInfo(slotId);
+ mTelephonyManager = (TelephonyManager) mContext.getSystemService(
+ TELEPHONY_SERVICE);
+ mRes = mContext.getResources();
+
+ if (lifecycle != null) {
+ lifecycle.addObserver(this);
+ }
+ }
+
+ public void initialize() {
+ if (mSubscriptionInfo == null) {
+ return;
+ }
+
+ mPhoneStateListener = getPhoneStateListener();
+
+ final ServiceState serviceState = getCurrentServiceState();
+ updateNetworkProvider(serviceState);
+ updatePhoneNumber();
+ updateLatestAreaInfo();
+ updateServiceState(serviceState);
+ updateSignalStrength(getSignalStrength());
+ updateNetworkType();
+ updateRoamingStatus(serviceState);
+ }
+
+ @Override
+ public void onResume() {
+ if (mSubscriptionInfo == null) {
+ return;
+ }
+
+ mTelephonyManager.listen(mPhoneStateListener,
+ PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
+ | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
+ | PhoneStateListener.LISTEN_SERVICE_STATE);
+
+ if (mShowLatestAreaInfo) {
+ mContext.registerReceiver(mAreaInfoReceiver,
+ new IntentFilter(CB_AREA_INFO_RECEIVED_ACTION),
+ Manifest.permission.RECEIVE_EMERGENCY_BROADCAST, null /* scheduler */);
+ // Ask CellBroadcastReceiver to broadcast the latest area info received
+ final Intent getLatestIntent = new Intent(GET_LATEST_CB_AREA_INFO_ACTION);
+ getLatestIntent.setPackage(CELL_BROADCAST_RECEIVER_APP);
+ mContext.sendBroadcastAsUser(getLatestIntent, UserHandle.ALL,
+ Manifest.permission.RECEIVE_EMERGENCY_BROADCAST);
+ }
+ }
+
+ @Override
+ public void onPause() {
+ if (mSubscriptionInfo == null) {
+ return;
+ }
+
+ mTelephonyManager.listen(mPhoneStateListener,
+ PhoneStateListener.LISTEN_NONE);
+
+ if (mShowLatestAreaInfo) {
+ mContext.unregisterReceiver(mAreaInfoReceiver);
+ }
+ }
+
+ private void updateNetworkProvider(ServiceState serviceState) {
+ mDialog.setText(NETWORK_PROVIDER_VALUE_ID, serviceState.getOperatorAlphaLong());
+ }
+
+ private void updatePhoneNumber() {
+ // If formattedNumber is null or empty, it'll display as "Unknown".
+ mDialog.setText(PHONE_NUMBER_VALUE_ID, getPhoneNumber());
+ }
+
+ private void updateDataState(int state) {
+ String networkStateValue;
+
+ switch (state) {
+ case TelephonyManager.DATA_CONNECTED:
+ networkStateValue = mRes.getString(R.string.radioInfo_data_connected);
+ break;
+ case TelephonyManager.DATA_SUSPENDED:
+ networkStateValue = mRes.getString(R.string.radioInfo_data_suspended);
+ break;
+ case TelephonyManager.DATA_CONNECTING:
+ networkStateValue = mRes.getString(R.string.radioInfo_data_connecting);
+ break;
+ case TelephonyManager.DATA_DISCONNECTED:
+ networkStateValue = mRes.getString(R.string.radioInfo_data_disconnected);
+ break;
+ default:
+ networkStateValue = mRes.getString(R.string.radioInfo_unknown);
+ break;
+ }
+
+ mDialog.setText(CELLULAR_NETWORK_STATE, networkStateValue);
+ }
+
+
+ private void updateLatestAreaInfo() {
+ mShowLatestAreaInfo = Resources.getSystem().getBoolean(
+ com.android.internal.R.bool.config_showAreaUpdateInfoSettings)
+ && mTelephonyManager.getPhoneType() != TelephonyManager.PHONE_TYPE_CDMA;
+
+ if (!mShowLatestAreaInfo) {
+ mDialog.removeSettingFromScreen(OPERATOR_INFO_LABEL_ID);
+ mDialog.removeSettingFromScreen(OPERATOR_INFO_VALUE_ID);
+ }
+ }
+
+ private void updateServiceState(ServiceState serviceState) {
+ final int state = serviceState.getState();
+ if (state == ServiceState.STATE_OUT_OF_SERVICE || state == ServiceState.STATE_POWER_OFF) {
+ resetSignalStrength();
+ }
+
+ String serviceStateValue;
+
+ switch (state) {
+ case ServiceState.STATE_IN_SERVICE:
+ serviceStateValue = mRes.getString(R.string.radioInfo_service_in);
+ break;
+ case ServiceState.STATE_OUT_OF_SERVICE:
+ case ServiceState.STATE_EMERGENCY_ONLY:
+ // Set summary string of service state to radioInfo_service_out when
+ // service state is both STATE_OUT_OF_SERVICE & STATE_EMERGENCY_ONLY
+ serviceStateValue = mRes.getString(R.string.radioInfo_service_out);
+ break;
+ case ServiceState.STATE_POWER_OFF:
+ serviceStateValue = mRes.getString(R.string.radioInfo_service_off);
+ break;
+ default:
+ serviceStateValue = mRes.getString(R.string.radioInfo_unknown);
+ break;
+ }
+
+ mDialog.setText(SERVICE_STATE_VALUE_ID, serviceStateValue);
+ }
+
+ private void updateSignalStrength(SignalStrength signalStrength) {
+ final int state = getCurrentServiceState().getState();
+
+ if ((ServiceState.STATE_OUT_OF_SERVICE == state) ||
+ (ServiceState.STATE_POWER_OFF == state)) {
+ return;
+ }
+
+ int signalDbm = getDbm(signalStrength);
+ int signalAsu = getAsuLevel(signalStrength);
+
+ if (signalDbm == -1) {
+ signalDbm = 0;
+ }
+
+ if (signalAsu == -1) {
+ signalAsu = 0;
+ }
+
+ mDialog.setText(SIGNAL_STRENGTH_VALUE_ID, mRes.getString(R.string.sim_signal_strength,
+ signalDbm, signalAsu));
+ }
+
+ private void resetSignalStrength() {
+ mDialog.setText(SIGNAL_STRENGTH_VALUE_ID, "0");
+ }
+
+ private void updateNetworkType() {
+ // Whether EDGE, UMTS, etc...
+ String networktype = null;
+ final int subId = mSubscriptionInfo.getSubscriptionId();
+ final int actualDataNetworkType = mTelephonyManager.getDataNetworkType(subId);
+ final int actualVoiceNetworkType = mTelephonyManager.getVoiceNetworkType(subId);
+ if (TelephonyManager.NETWORK_TYPE_UNKNOWN != actualDataNetworkType) {
+ networktype = mTelephonyManager.getNetworkTypeName(actualDataNetworkType);
+ } else if (TelephonyManager.NETWORK_TYPE_UNKNOWN != actualVoiceNetworkType) {
+ networktype = mTelephonyManager.getNetworkTypeName(actualVoiceNetworkType);
+ }
+
+ boolean show4GForLTE = false;
+ try {
+ final Context con = mContext.createPackageContext(
+ "com.android.systemui", 0 /* flags */);
+ final int id = con.getResources().getIdentifier("config_show4GForLTE",
+ "bool" /* default type */, "com.android.systemui" /* default package */);
+ show4GForLTE = con.getResources().getBoolean(id);
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, "NameNotFoundException for show4GFotLTE");
+ }
+
+ if (TextUtils.equals(networktype, "LTE") && show4GForLTE) {
+ networktype = "4G";
+ }
+ mDialog.setText(CELLULAR_NETWORK_TYPE_VALUE_ID, networktype);
+ }
+
+ private void updateRoamingStatus(ServiceState serviceState) {
+ if (serviceState.getRoaming()) {
+ mDialog.setText(ROAMING_INFO_VALUE_ID, mRes.getString(R.string.radioInfo_roaming_in));
+ } else {
+ mDialog.setText(ROAMING_INFO_VALUE_ID, mRes.getString(R.string.radioInfo_roaming_not));
+ }
+ }
+
+ private SubscriptionInfo getPhoneSubscriptionInfo(int slotId) {
+ final List subscriptionInfoList = SubscriptionManager.from(
+ mContext).getActiveSubscriptionInfoList();
+ if (subscriptionInfoList != null && subscriptionInfoList.size() > slotId) {
+ return subscriptionInfoList.get(slotId);
+ } else {
+ return null;
+ }
+ }
+
+ @VisibleForTesting
+ ServiceState getCurrentServiceState() {
+ return mTelephonyManager.getServiceStateForSubscriber(
+ mSubscriptionInfo.getSubscriptionId());
+ }
+
+ @VisibleForTesting
+ int getDbm(SignalStrength signalStrength) {
+ return signalStrength.getDbm();
+ }
+
+ @VisibleForTesting
+ int getAsuLevel(SignalStrength signalStrength) {
+ return signalStrength.getAsuLevel();
+ }
+
+ @VisibleForTesting
+ PhoneStateListener getPhoneStateListener() {
+ return new PhoneStateListener(
+ mSubscriptionInfo.getSubscriptionId()) {
+ @Override
+ public void onDataConnectionStateChanged(int state) {
+ updateDataState(state);
+ updateNetworkType();
+ }
+
+ @Override
+ public void onSignalStrengthsChanged(SignalStrength signalStrength) {
+ updateSignalStrength(signalStrength);
+ }
+
+ @Override
+ public void onServiceStateChanged(ServiceState serviceState) {
+ updateNetworkProvider(serviceState);
+ updateServiceState(serviceState);
+ updateRoamingStatus(serviceState);
+ }
+ };
+ }
+
+ @VisibleForTesting
+ String getPhoneNumber() {
+ return DeviceInfoUtils.getFormattedPhoneNumber(mContext, mSubscriptionInfo);
+ }
+
+ @VisibleForTesting
+ SignalStrength getSignalStrength() {
+ return mTelephonyManager.getSignalStrength();
+ }
+}
diff --git a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogFragment.java b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogFragment.java
new file mode 100644
index 00000000000..a15cb81e011
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogFragment.java
@@ -0,0 +1,92 @@
+/*
+ * 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.deviceinfo.simstatus;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.settings.R;
+import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
+
+public class SimStatusDialogFragment extends InstrumentedDialogFragment {
+
+ private static final String SIM_SLOT_BUNDLE_KEY = "arg_key_sim_slot";
+ private static final String DIALOG_TITLE_BUNDLE_KEY = "arg_key_dialog_title";
+
+ private static final String TAG = "SimStatusDialog";
+
+ private View mRootView;
+ private SimStatusDialogController mController;
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsProto.MetricsEvent.DIALOG_SIM_STATUS;
+ }
+
+ public static void show(Fragment host, int slotId, String dialogTitle) {
+ final FragmentManager manager = host.getChildFragmentManager();
+ if (manager.findFragmentByTag(TAG) == null) {
+ final Bundle bundle = new Bundle();
+ bundle.putInt(SIM_SLOT_BUNDLE_KEY, slotId);
+ bundle.putString(DIALOG_TITLE_BUNDLE_KEY, dialogTitle);
+ final SimStatusDialogFragment dialog =
+ new SimStatusDialogFragment();
+ dialog.setArguments(bundle);
+ dialog.show(manager, TAG);
+ }
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final Bundle bundle = getArguments();
+ final int slotId = bundle.getInt(SIM_SLOT_BUNDLE_KEY);
+ final String dialogTitle = bundle.getString(DIALOG_TITLE_BUNDLE_KEY);
+ mController = new SimStatusDialogController(this, mLifecycle, slotId);
+ final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())
+ .setTitle(dialogTitle)
+ .setPositiveButton(android.R.string.ok, null /* onClickListener */);
+ mRootView = LayoutInflater.from(builder.getContext())
+ .inflate(R.layout.dialog_sim_status, null /* parent */);
+ mController.initialize();
+ return builder.setView(mRootView).create();
+ }
+
+ public void removeSettingFromScreen(int viewId) {
+ final View view = mRootView.findViewById(viewId);
+ if (view != null) {
+ view.setVisibility(View.GONE);
+ }
+ }
+
+ public void setText(int viewId, CharSequence text) {
+ final TextView textView = mRootView.findViewById(viewId);
+ if (TextUtils.isEmpty(text)) {
+ text = getResources().getString(R.string.device_info_default);
+ }
+ if (textView != null) {
+ textView.setText(text);
+ }
+ }
+}
diff --git a/src/com/android/settings/deviceinfo/simstatus/SimStatusDualSimPreferenceController.java b/src/com/android/settings/deviceinfo/simstatus/SimStatusDualSimPreferenceController.java
new file mode 100644
index 00000000000..ce73a294247
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/simstatus/SimStatusDualSimPreferenceController.java
@@ -0,0 +1,52 @@
+/*
+ * 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.deviceinfo.simstatus;
+
+import android.app.Fragment;
+import android.content.Context;
+
+import com.android.settings.R;
+
+public class SimStatusDualSimPreferenceController extends AbstractSimStatusPreferenceController {
+
+ private static final int SIM_SLOT = 1;
+ private static final String SIM_STATUS_DUAL_SIM_KEY = "sim_status_sim_2";
+
+ public SimStatusDualSimPreferenceController(Context context, Fragment fragment) {
+ super(context, fragment);
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return super.isAvailable() && mIsMultiSim;
+ }
+
+ @Override
+ protected String getPreferenceTitle() {
+ return mContext.getResources().getString(R.string.sim_status_title_sim_slot_2);
+ }
+
+ @Override
+ protected int getSimSlot() {
+ return SIM_SLOT;
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return SIM_STATUS_DUAL_SIM_KEY;
+ }
+}
diff --git a/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceControllerV2.java b/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceControllerV2.java
new file mode 100644
index 00000000000..ee16eac5bf3
--- /dev/null
+++ b/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceControllerV2.java
@@ -0,0 +1,49 @@
+/*
+ * 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.deviceinfo.simstatus;
+
+import android.app.Fragment;
+import android.content.Context;
+
+import com.android.settings.R;
+
+public class SimStatusPreferenceControllerV2 extends AbstractSimStatusPreferenceController {
+
+ public static final int SIM_SLOT = 0;
+
+ private static final String KEY_SIM_1_STATUS = "sim_status_sim_1";
+
+ public SimStatusPreferenceControllerV2(Context context, Fragment fragment) {
+ super(context, fragment);
+ }
+
+ @Override
+ protected String getPreferenceTitle() {
+ return mIsMultiSim ? mContext.getResources().getString(R.string.sim_status_title_sim_slot_1)
+ : mContext.getResources().getString(R.string.sim_status_title);
+ }
+
+ @Override
+ protected int getSimSlot() {
+ return SIM_SLOT;
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY_SIM_1_STATUS;
+ }
+}
diff --git a/src/com/android/settings/nfc/PaymentSettings.java b/src/com/android/settings/nfc/PaymentSettings.java
index 66d110397a2..a30cea36176 100644
--- a/src/com/android/settings/nfc/PaymentSettings.java
+++ b/src/com/android/settings/nfc/PaymentSettings.java
@@ -51,6 +51,11 @@ public class PaymentSettings extends SettingsPreferenceFragment implements Index
return MetricsEvent.NFC_PAYMENT;
}
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.nfc_payment_settings;
+ }
+
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
@@ -60,7 +65,6 @@ public class PaymentSettings extends SettingsPreferenceFragment implements Index
final PreferenceScreen screen;
if (usePreferenceScreenTitle()) {
- addPreferencesFromResource(R.xml.nfc_payment_settings);
screen = getPreferenceScreen();
} else {
PreferenceManager manager = getPreferenceManager();
diff --git a/src/com/android/settings/search/SearchIndexableResources.java b/src/com/android/settings/search/SearchIndexableResources.java
index 69b2f9fa5d3..ebba99a63e5 100644
--- a/src/com/android/settings/search/SearchIndexableResources.java
+++ b/src/com/android/settings/search/SearchIndexableResources.java
@@ -25,7 +25,6 @@ import com.android.settings.DeviceInfoSettings;
import com.android.settings.DisplaySettings;
import com.android.settings.LegalSettings;
import com.android.settings.ScreenPinningSettings;
-import com.android.settings.SecuritySettings;
import com.android.settings.accessibility.AccessibilitySettings;
import com.android.settings.accessibility.AccessibilityShortcutPreferenceFragment;
import com.android.settings.accessibility.MagnificationPreferenceFragment;
@@ -76,6 +75,7 @@ import com.android.settings.notification.ZenModeSettings;
import com.android.settings.print.PrintSettingsFragment;
import com.android.settings.security.EncryptionAndCredential;
import com.android.settings.security.LockscreenDashboardFragment;
+import com.android.settings.security.SecuritySettings;
import com.android.settings.sim.SimSettings;
import com.android.settings.support.SupportDashboardActivity;
import com.android.settings.system.ResetDashboardFragment;
diff --git a/src/com/android/settings/security/CredentialStoragePreferenceController.java b/src/com/android/settings/security/CredentialStoragePreferenceController.java
new file mode 100644
index 00000000000..53f11f53986
--- /dev/null
+++ b/src/com/android/settings/security/CredentialStoragePreferenceController.java
@@ -0,0 +1,48 @@
+/*
+ * 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.security;
+
+import android.content.Context;
+import android.os.UserManager;
+import android.security.KeyStore;
+import android.support.v7.preference.Preference;
+
+import com.android.settings.R;
+
+public class CredentialStoragePreferenceController extends
+ RestrictedEncryptionPreferenceController {
+
+ private static final String KEY_CREDENTIAL_STORAGE_TYPE = "credential_storage_type";
+ private final KeyStore mKeyStore;
+
+ public CredentialStoragePreferenceController(Context context) {
+ super(context, UserManager.DISALLOW_CONFIG_CREDENTIALS);
+ mKeyStore = KeyStore.getInstance();
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY_CREDENTIAL_STORAGE_TYPE;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ preference.setSummary(mKeyStore.isHardwareBacked()
+ ? R.string.credential_storage_type_hardware
+ : R.string.credential_storage_type_software);
+ }
+}
diff --git a/src/com/android/settings/CryptKeeperSettings.java b/src/com/android/settings/security/CryptKeeperSettings.java
similarity index 98%
rename from src/com/android/settings/CryptKeeperSettings.java
rename to src/com/android/settings/security/CryptKeeperSettings.java
index e11bccd7cc0..7d5ee9d4357 100644
--- a/src/com/android/settings/CryptKeeperSettings.java
+++ b/src/com/android/settings/security/CryptKeeperSettings.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.settings;
+package com.android.settings.security;
import android.app.Activity;
import android.app.AlertDialog;
@@ -36,6 +36,9 @@ import android.view.ViewGroup;
import android.widget.Button;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.settings.CryptKeeperConfirm;
+import com.android.settings.R;
+import com.android.settings.SettingsActivity;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.password.ConfirmLockPattern;
diff --git a/src/com/android/settings/security/EncryptionAndCredential.java b/src/com/android/settings/security/EncryptionAndCredential.java
index 0972e3e6e47..301742b05f7 100644
--- a/src/com/android/settings/security/EncryptionAndCredential.java
+++ b/src/com/android/settings/security/EncryptionAndCredential.java
@@ -16,52 +16,29 @@
package com.android.settings.security;
-import android.app.admin.DevicePolicyManager;
import android.content.Context;
-import android.content.Intent;
-import android.os.UserHandle;
import android.os.UserManager;
import android.provider.SearchIndexableResource;
-import android.security.KeyStore;
-import android.support.v7.preference.PreferenceGroup;
-import android.support.v7.preference.PreferenceScreen;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
-import com.android.settingslib.RestrictedLockUtils;
-import com.android.settingslib.RestrictedPreference;
+import com.android.settings.widget.PreferenceCategoryController;
import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.core.lifecycle.Lifecycle;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
/**
* Encryption and Credential settings.
- * TODO: Extends this from {@link DashboardFragment} instead
*/
public class EncryptionAndCredential extends DashboardFragment {
private static final String TAG = "EncryptionAndCredential";
- // Misc Settings
- private static final String KEY_CREDENTIAL_STORAGE_TYPE = "credential_storage_type";
- private static final String KEY_USER_CREDENTIALS = "user_credentials";
- private static final String KEY_RESET_CREDENTIALS = "credentials_reset";
- private static final String KEY_CREDENTIALS_INSTALL = "credentials_install";
- private static final String KEY_CREDENTIALS_MANAGER = "credentials_management";
-
- private static final int MY_USER_ID = UserHandle.myUserId();
-
- private UserManager mUm;
-
- private KeyStore mKeyStore;
- private RestrictedPreference mResetCredentials;
-
- private boolean mIsAdmin;
-
@Override
public int getMetricsCategory() {
return MetricsEvent.ENCRYPTION_AND_CREDENTIAL;
@@ -74,99 +51,28 @@ public class EncryptionAndCredential extends DashboardFragment {
@Override
protected List getPreferenceControllers(Context context) {
- mUm = (UserManager) context.getSystemService(Context.USER_SERVICE);
- return null;
+ return buildPreferenceControllers(context, getLifecycle());
}
@Override
protected int getPreferenceScreenResId() {
- return 0;
+ return R.xml.encryption_and_credential;
}
- /**
- * Important!
- *
- * Don't forget to update the SecuritySearchIndexProvider if you are doing any change in the
- * logic or adding/removing preferences here.
- */
- private PreferenceScreen createPreferenceHierarchy() {
- PreferenceScreen root = getPreferenceScreen();
- if (root != null) {
- root.removeAll();
- }
- addPreferencesFromResource(R.xml.encryption_and_credential);
- root = getPreferenceScreen();
-
- // Add options for device encryption
- mIsAdmin = mUm.isAdminUser();
-
- if (mIsAdmin) {
- if (LockPatternUtils.isDeviceEncryptionEnabled()) {
- // The device is currently encrypted.
- addPreferencesFromResource(R.xml.security_settings_encrypted);
- } else {
- // This device supports encryption but isn't encrypted.
- addPreferencesFromResource(R.xml.security_settings_unencrypted);
- }
- }
-
- // Credential storage
- mKeyStore = KeyStore.getInstance(); // needs to be initialized for onResume()
-
- if (!RestrictedLockUtils.hasBaseUserRestriction(getActivity(),
- UserManager.DISALLOW_CONFIG_CREDENTIALS, MY_USER_ID)) {
- RestrictedPreference userCredentials = (RestrictedPreference) root.findPreference(
- KEY_USER_CREDENTIALS);
- userCredentials.checkRestrictionAndSetDisabled(
- UserManager.DISALLOW_CONFIG_CREDENTIALS);
- RestrictedPreference credentialStorageType = (RestrictedPreference) root.findPreference(
- KEY_CREDENTIAL_STORAGE_TYPE);
- credentialStorageType.checkRestrictionAndSetDisabled(
- UserManager.DISALLOW_CONFIG_CREDENTIALS);
- RestrictedPreference installCredentials = (RestrictedPreference) root.findPreference(
- KEY_CREDENTIALS_INSTALL);
- installCredentials.checkRestrictionAndSetDisabled(
- UserManager.DISALLOW_CONFIG_CREDENTIALS);
- mResetCredentials = (RestrictedPreference) root.findPreference(KEY_RESET_CREDENTIALS);
- mResetCredentials.checkRestrictionAndSetDisabled(
- UserManager.DISALLOW_CONFIG_CREDENTIALS);
-
- final int storageSummaryRes =
- mKeyStore.isHardwareBacked() ? R.string.credential_storage_type_hardware
- : R.string.credential_storage_type_software;
- credentialStorageType.setSummary(storageSummaryRes);
- } else {
- PreferenceGroup credentialsManager = (PreferenceGroup)
- root.findPreference(KEY_CREDENTIALS_MANAGER);
- credentialsManager.removePreference(root.findPreference(KEY_RESET_CREDENTIALS));
- credentialsManager.removePreference(root.findPreference(KEY_CREDENTIALS_INSTALL));
- credentialsManager.removePreference(root.findPreference(KEY_CREDENTIAL_STORAGE_TYPE));
- credentialsManager.removePreference(root.findPreference(KEY_USER_CREDENTIALS));
- }
-
- return root;
- }
-
- @Override
- public void onResume() {
- super.onResume();
-
- // Make sure we reload the preference hierarchy since some of these settings
- // depend on others...
- createPreferenceHierarchy();
-
- if (mResetCredentials != null && !mResetCredentials.isDisabledByAdmin()) {
- mResetCredentials.setEnabled(!mKeyStore.isEmpty());
- }
- }
-
- /**
- * see confirmPatternThenDisableAndClear
- */
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- createPreferenceHierarchy();
+ private static List buildPreferenceControllers(Context context,
+ Lifecycle lifecycle) {
+ final List controllers = new ArrayList<>();
+ final EncryptionStatusPreferenceController encryptStatusController =
+ new EncryptionStatusPreferenceController(context);
+ controllers.add(encryptStatusController);
+ controllers.add(new PreferenceCategoryController(context,
+ "encryption_and_credentials_status_category",
+ Arrays.asList(encryptStatusController)));
+ controllers.add(new CredentialStoragePreferenceController(context));
+ controllers.add(new UserCredentialsPreferenceController(context));
+ controllers.add(new ResetCredentialsPreferenceController(context, lifecycle));
+ controllers.add(new InstallCredentialsPreferenceController(context));
+ return controllers;
}
@Override
@@ -185,14 +91,14 @@ public class EncryptionAndCredential extends DashboardFragment {
@Override
public List getXmlResourcesToIndex(
Context context, boolean enabled) {
- final List index = new ArrayList<>();
+ final SearchIndexableResource sir = new SearchIndexableResource(context);
+ sir.xmlResId = R.xml.encryption_and_credential;
+ return Arrays.asList(sir);
+ }
- // Add everything. We will suppress some of them in getNonIndexableKeys()
- index.add(getSearchResource(context, R.xml.encryption_and_credential));
- index.add(getSearchResource(context, R.xml.security_settings_encrypted));
- index.add(getSearchResource(context, R.xml.security_settings_unencrypted));
-
- return index;
+ @Override
+ public List getPreferenceControllers(Context context) {
+ return buildPreferenceControllers(context, null /* lifecycle */);
}
@Override
@@ -200,46 +106,5 @@ public class EncryptionAndCredential extends DashboardFragment {
final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
return um.isAdminUser();
}
-
- private SearchIndexableResource getSearchResource(Context context, int xmlResId) {
- final SearchIndexableResource sir = new SearchIndexableResource(context);
- sir.xmlResId = xmlResId;
- return sir;
- }
-
- @Override
- public List getNonIndexableKeys(Context context) {
- final List keys = super.getNonIndexableKeys(context);
- if (!isPageSearchEnabled(context)) {
- return keys;
- }
- final UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
-
- if (um.hasUserRestriction(UserManager.DISALLOW_CONFIG_CREDENTIALS)) {
- keys.add(KEY_CREDENTIALS_MANAGER);
- keys.add(KEY_RESET_CREDENTIALS);
- keys.add(KEY_CREDENTIALS_INSTALL);
- keys.add(KEY_CREDENTIAL_STORAGE_TYPE);
- keys.add(KEY_USER_CREDENTIALS);
- }
-
- final DevicePolicyManager dpm = (DevicePolicyManager)
- context.getSystemService(Context.DEVICE_POLICY_SERVICE);
- switch (dpm.getStorageEncryptionStatus()) {
- case DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE:
- // The device is currently encrypted. Disable security_settings_unencrypted
- keys.addAll(getNonIndexableKeysFromXml(
- context, R.xml.security_settings_unencrypted));
- break;
- default:
- // This device supports encryption but isn't encrypted.
- keys.addAll(getNonIndexableKeysFromXml(
- context, R.xml.security_settings_encrypted));
- break;
- }
-
- return keys;
- }
}
-
}
diff --git a/src/com/android/settings/security/EncryptionStatusPreferenceController.java b/src/com/android/settings/security/EncryptionStatusPreferenceController.java
new file mode 100644
index 00000000000..7d84421bbd1
--- /dev/null
+++ b/src/com/android/settings/security/EncryptionStatusPreferenceController.java
@@ -0,0 +1,61 @@
+/*
+ * 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.security;
+
+import android.content.Context;
+import android.os.UserManager;
+import android.support.v7.preference.Preference;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.settings.R;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+public class EncryptionStatusPreferenceController extends AbstractPreferenceController
+ implements PreferenceControllerMixin {
+
+ private static final String PREF_KEY = "encryption_and_credentials_encryption_status";
+
+ private final UserManager mUserManager;
+
+ public EncryptionStatusPreferenceController(Context context) {
+ super(context);
+ mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return mUserManager.isAdminUser();
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return PREF_KEY;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ final boolean encryptionEnabled = LockPatternUtils.isDeviceEncryptionEnabled();
+ if (encryptionEnabled) {
+ preference.setFragment(null);
+ preference.setSummary(R.string.crypt_keeper_encrypted_summary);
+ } else {
+ preference.setFragment(CryptKeeperSettings.class.getName());
+ preference.setSummary(R.string.summary_placeholder);
+ }
+ }
+}
diff --git a/src/com/android/settings/security/InstallCredentialsPreferenceController.java b/src/com/android/settings/security/InstallCredentialsPreferenceController.java
new file mode 100644
index 00000000000..ca9ed2657a5
--- /dev/null
+++ b/src/com/android/settings/security/InstallCredentialsPreferenceController.java
@@ -0,0 +1,35 @@
+/*
+ * 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.security;
+
+import android.content.Context;
+import android.os.UserManager;
+
+public class InstallCredentialsPreferenceController extends
+ RestrictedEncryptionPreferenceController {
+
+ private static final String KEY_CREDENTIALS_INSTALL = "credentials_install";
+
+ public InstallCredentialsPreferenceController(Context context) {
+ super(context, UserManager.DISALLOW_CONFIG_CREDENTIALS);
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY_CREDENTIALS_INSTALL;
+ }
+}
diff --git a/src/com/android/settings/security/ResetCredentialsPreferenceController.java b/src/com/android/settings/security/ResetCredentialsPreferenceController.java
new file mode 100644
index 00000000000..7b91b154152
--- /dev/null
+++ b/src/com/android/settings/security/ResetCredentialsPreferenceController.java
@@ -0,0 +1,63 @@
+/*
+ * 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.security;
+
+import android.content.Context;
+import android.os.UserManager;
+import android.security.KeyStore;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settingslib.RestrictedPreference;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnResume;
+
+public class ResetCredentialsPreferenceController extends RestrictedEncryptionPreferenceController
+ implements LifecycleObserver, OnResume {
+
+ private static final String KEY_RESET_CREDENTIALS = "credentials_reset";
+
+ private final KeyStore mKeyStore;
+
+ private RestrictedPreference mPreference;
+
+ public ResetCredentialsPreferenceController(Context context, Lifecycle lifecycle) {
+ super(context, UserManager.DISALLOW_CONFIG_CREDENTIALS);
+ mKeyStore = KeyStore.getInstance();
+ if (lifecycle != null) {
+ lifecycle.addObserver(this);
+ }
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY_RESET_CREDENTIALS;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPreference = (RestrictedPreference) screen.findPreference(getPreferenceKey());
+ }
+
+ @Override
+ public void onResume() {
+ if (mPreference != null && !mPreference.isDisabledByAdmin()) {
+ mPreference.setEnabled(!mKeyStore.isEmpty());
+ }
+ }
+}
diff --git a/src/com/android/settings/security/RestrictedEncryptionPreferenceController.java b/src/com/android/settings/security/RestrictedEncryptionPreferenceController.java
new file mode 100644
index 00000000000..2c5308fbc1b
--- /dev/null
+++ b/src/com/android/settings/security/RestrictedEncryptionPreferenceController.java
@@ -0,0 +1,45 @@
+/*
+ * 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.security;
+
+import android.content.Context;
+import android.os.UserHandle;
+import android.os.UserManager;
+
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+public abstract class RestrictedEncryptionPreferenceController extends
+ AbstractPreferenceController implements PreferenceControllerMixin {
+
+ protected final UserManager mUserManager;
+
+ private final UserHandle mUserHandle;
+ private final String mUserRestriction;
+
+ public RestrictedEncryptionPreferenceController(Context context, String userRestriction) {
+ super(context);
+ mUserHandle = UserHandle.of(UserHandle.myUserId());
+ mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+ mUserRestriction = userRestriction;
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return !mUserManager.hasBaseUserRestriction(mUserRestriction, mUserHandle);
+ }
+}
diff --git a/src/com/android/settings/security/SecurityFeatureProvider.java b/src/com/android/settings/security/SecurityFeatureProvider.java
index 23b4cf0c065..509446d13f9 100644
--- a/src/com/android/settings/security/SecurityFeatureProvider.java
+++ b/src/com/android/settings/security/SecurityFeatureProvider.java
@@ -19,7 +19,7 @@ package com.android.settings.security;
import android.content.Context;
import android.support.v7.preference.PreferenceScreen;
-import com.android.settings.trustagent.TrustAgentManager;
+import com.android.settings.security.trustagent.TrustAgentManager;
import com.android.settingslib.drawer.DashboardCategory;
diff --git a/src/com/android/settings/security/SecurityFeatureProviderImpl.java b/src/com/android/settings/security/SecurityFeatureProviderImpl.java
index b8cf689797f..29aaefe225d 100644
--- a/src/com/android/settings/security/SecurityFeatureProviderImpl.java
+++ b/src/com/android/settings/security/SecurityFeatureProviderImpl.java
@@ -30,8 +30,7 @@ import android.util.ArrayMap;
import android.util.Pair;
import com.android.settings.R;
-import com.android.settings.trustagent.TrustAgentManager;
-import com.android.settings.trustagent.TrustAgentManagerImpl;
+import com.android.settings.security.trustagent.TrustAgentManager;
import com.android.settingslib.drawer.DashboardCategory;
import com.android.settingslib.drawer.Tile;
import com.android.settingslib.drawer.TileUtils;
@@ -192,7 +191,7 @@ public class SecurityFeatureProviderImpl implements SecurityFeatureProvider {
@Override
public TrustAgentManager getTrustAgentManager() {
if (mTrustAgentManager == null) {
- mTrustAgentManager = new TrustAgentManagerImpl();
+ mTrustAgentManager = new TrustAgentManager();
}
return mTrustAgentManager;
}
diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/security/SecuritySettings.java
similarity index 75%
rename from src/com/android/settings/SecuritySettings.java
rename to src/com/android/settings/security/SecuritySettings.java
index 8b4bde01504..16ab1fc7d06 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/security/SecuritySettings.java
@@ -14,9 +14,8 @@
* limitations under the License.
*/
-package com.android.settings;
+package com.android.settings.security;
-import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import android.app.Activity;
@@ -24,12 +23,9 @@ import android.app.AlertDialog;
import android.app.Dialog;
import android.app.FragmentManager;
import android.app.admin.DevicePolicyManager;
-import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle;
@@ -39,7 +35,6 @@ import android.os.UserManager;
import android.os.storage.StorageManager;
import android.provider.SearchIndexableResource;
import android.provider.Settings;
-import android.service.trust.TrustAgentService;
import android.support.annotation.VisibleForTesting;
import android.support.v14.preference.SwitchPreference;
import android.support.v7.preference.Preference;
@@ -51,11 +46,12 @@ import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
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.TrustAgentUtils.TrustAgentComponentInfo;
+import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.Utils;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.dashboard.DashboardFeatureProvider;
import com.android.settings.dashboard.SummaryLoader;
@@ -71,9 +67,8 @@ import com.android.settings.password.ManagedLockPasswordProvider;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settings.search.SearchIndexableRaw;
-import com.android.settings.security.OwnerInfoPreferenceController;
-import com.android.settings.security.SecurityFeatureProvider;
-import com.android.settings.trustagent.TrustAgentManager;
+import com.android.settings.security.trustagent.TrustAgentManager;
+import com.android.settings.security.trustagent.TrustAgentManager.TrustAgentComponentInfo;
import com.android.settings.widget.GearPreference;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedPreference;
@@ -92,8 +87,6 @@ public class SecuritySettings extends SettingsPreferenceFragment
private static final String TAG = "SecuritySettings";
private static final String TRUST_AGENT_CLICK_INTENT = "trust_agent_click_intent";
- private static final Intent TRUST_AGENT_INTENT =
- new Intent(TrustAgentService.SERVICE_INTERFACE);
// Lock Settings
private static final String KEY_UNLOCK_SET_OR_CHANGE = "unlock_set_or_change";
@@ -127,11 +120,6 @@ public class SecuritySettings extends SettingsPreferenceFragment
private static final String KEY_SECURITY_STATUS = "security_status";
private static final String SECURITY_STATUS_KEY_PREFIX = "security_status_";
- // Package verifier Settings
- @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
- static final String KEY_PACKAGE_VERIFIER_STATUS = "security_status_package_verifier";
- private static final int PACKAGE_VERIFIER_STATE_ENABLED = 1;
-
// Device management settings
private static final String KEY_ENTERPRISE_PRIVACY = "enterprise_privacy";
private static final String KEY_MANAGE_DEVICE_ADMIN = "manage_device_admin";
@@ -141,9 +129,6 @@ public class SecuritySettings extends SettingsPreferenceFragment
KEY_SHOW_PASSWORD, KEY_UNIFICATION, KEY_VISIBLE_PATTERN_PROFILE
};
- // Only allow one trust agent on the platform.
- private static final boolean ONLY_ONE_TRUST_AGENT = true;
-
private static final int MY_USER_ID = UserHandle.myUserId();
private DashboardFeatureProvider mDashboardFeatureProvider;
@@ -225,9 +210,8 @@ public class SecuritySettings extends SettingsPreferenceFragment
= new LockScreenNotificationPreferenceController(activity);
}
- private static int getResIdForLockUnlockScreen(Context context,
- LockPatternUtils lockPatternUtils, ManagedLockPasswordProvider managedPasswordProvider,
- int userId) {
+ private static int getResIdForLockUnlockScreen(LockPatternUtils lockPatternUtils,
+ ManagedLockPasswordProvider managedPasswordProvider, int userId) {
final boolean isMyUser = userId == MY_USER_ID;
int resid = 0;
if (!lockPatternUtils.isSecure(userId)) {
@@ -281,7 +265,7 @@ public class SecuritySettings extends SettingsPreferenceFragment
addPreferencesFromResource(R.xml.security_settings_status);
// Add options for lock/unlock screen
- final int resid = getResIdForLockUnlockScreen(getActivity(), mLockPatternUtils,
+ final int resid = getResIdForLockUnlockScreen(mLockPatternUtils,
mManagedPasswordProvider, MY_USER_ID);
addPreferencesFromResource(resid);
@@ -293,9 +277,8 @@ public class SecuritySettings extends SettingsPreferenceFragment
&& mLockPatternUtils.isSeparateProfileChallengeAllowed(mProfileChallengeUserId)) {
addPreferencesFromResource(R.xml.security_settings_profile);
addPreferencesFromResource(R.xml.security_settings_unification);
- final int profileResid = getResIdForLockUnlockScreen(
- getActivity(), mLockPatternUtils, mManagedPasswordProvider,
- mProfileChallengeUserId);
+ final int profileResid = getResIdForLockUnlockScreen(mLockPatternUtils,
+ mManagedPasswordProvider, mProfileChallengeUserId);
addPreferencesFromResource(profileResid);
maybeAddFingerprintPreference(root, mProfileChallengeUserId);
if (!mLockPatternUtils.isSeparateProfileChallengeEnabled(mProfileChallengeUserId)) {
@@ -474,11 +457,10 @@ public class SecuritySettings extends SettingsPreferenceFragment
// Return the number of trust agents being added
private int addTrustAgentSettings(PreferenceGroup securityCategory) {
final boolean hasSecurity = mLockPatternUtils.isSecure(MY_USER_ID);
- ArrayList agents = getActiveTrustAgents(
- getActivity(), mTrustAgentManager, mLockPatternUtils, mDPM);
- for (int i = 0; i < agents.size(); i++) {
- final TrustAgentComponentInfo agent = agents.get(i);
- RestrictedPreference trustAgentPreference =
+ final List agents = mTrustAgentManager.getActiveTrustAgents(
+ getActivity(), mLockPatternUtils);
+ for (TrustAgentComponentInfo agent : agents) {
+ final RestrictedPreference trustAgentPreference =
new RestrictedPreference(securityCategory.getContext());
trustAgentPreference.setKey(KEY_TRUST_AGENT);
trustAgentPreference.setTitle(agent.title);
@@ -537,50 +519,6 @@ public class SecuritySettings extends SettingsPreferenceFragment
return false;
}
- private static ArrayList getActiveTrustAgents(Context context,
- TrustAgentManager trustAgentManager, LockPatternUtils utils,
- DevicePolicyManager dpm) {
- PackageManager pm = context.getPackageManager();
- ArrayList result = new ArrayList();
- List resolveInfos = pm.queryIntentServices(TRUST_AGENT_INTENT,
- PackageManager.GET_META_DATA);
- List enabledTrustAgents = utils.getEnabledTrustAgents(MY_USER_ID);
-
- EnforcedAdmin admin = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(context,
- DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS, UserHandle.myUserId());
-
- if (enabledTrustAgents != null && !enabledTrustAgents.isEmpty()) {
- for (int i = 0; i < resolveInfos.size(); i++) {
- ResolveInfo resolveInfo = resolveInfos.get(i);
- if (resolveInfo.serviceInfo == null) continue;
- if (!trustAgentManager.shouldProvideTrust(resolveInfo, pm)) {
- continue;
- }
- TrustAgentComponentInfo trustAgentComponentInfo =
- TrustAgentUtils.getSettingsComponent(pm, resolveInfo);
- if (trustAgentComponentInfo.componentName == null ||
- !enabledTrustAgents.contains(
- TrustAgentUtils.getComponentName(resolveInfo)) ||
- TextUtils.isEmpty(trustAgentComponentInfo.title)) continue;
- if (admin != null && dpm.getTrustAgentConfiguration(
- null, TrustAgentUtils.getComponentName(resolveInfo)) == null) {
- trustAgentComponentInfo.admin = admin;
- }
- result.add(trustAgentComponentInfo);
- if (ONLY_ONE_TRUST_AGENT) break;
- }
- }
- return result;
- }
-
- private static CharSequence getActiveTrustAgentLabel(Context context,
- TrustAgentManager trustAgentManager, LockPatternUtils utils,
- DevicePolicyManager dpm) {
- ArrayList agents = getActiveTrustAgents(context,
- trustAgentManager, utils, dpm);
- return agents.isEmpty() ? null : agents.get(0).title;
- }
-
@Override
public void onGearClick(GearPreference p) {
if (KEY_UNLOCK_SET_OR_CHANGE.equals(p.getKey())) {
@@ -842,7 +780,7 @@ public class SecuritySettings extends SettingsPreferenceFragment
|| lockPatternUtils.isSeparateProfileChallengeAllowed(profileUserId)
|| !isPasswordManaged(profileUserId, context, dpm))) {
// Add options for lock/unlock screen
- final int resId = getResIdForLockUnlockScreen(context, lockPatternUtils,
+ final int resId = getResIdForLockUnlockScreen(lockPatternUtils,
managedPasswordProvider, MY_USER_ID);
index.add(getSearchResource(context, resId));
}
@@ -850,12 +788,12 @@ public class SecuritySettings extends SettingsPreferenceFragment
if (profileUserId != UserHandle.USER_NULL
&& lockPatternUtils.isSeparateProfileChallengeAllowed(profileUserId)
&& !isPasswordManaged(profileUserId, context, dpm)) {
- index.add(getSearchResource(context, getResIdForLockUnlockScreen(context,
+ index.add(getSearchResource(context, getResIdForLockUnlockScreen(
lockPatternUtils, managedPasswordProvider, profileUserId)));
}
final SearchIndexableResource sir = getSearchResource(context,
- SecuritySubSettings.getResIdForLockUnlockSubScreen(context, lockPatternUtils,
+ SecuritySubSettings.getResIdForLockUnlockSubScreen(lockPatternUtils,
managedPasswordProvider));
sir.className = SecuritySubSettings.class.getName();
index.add(sir);
@@ -929,8 +867,7 @@ public class SecuritySettings extends SettingsPreferenceFragment
FeatureFactory.getFactory(context).getSecurityFeatureProvider()
.getTrustAgentManager();
final List agents =
- getActiveTrustAgents(context, trustAgentManager, lockPatternUtils,
- context.getSystemService(DevicePolicyManager.class));
+ trustAgentManager.getActiveTrustAgents(context, lockPatternUtils);
for (int i = 0; i < agents.size(); i++) {
final TrustAgentComponentInfo agent = agents.get(i);
data = new SearchIndexableRaw(context);
@@ -978,216 +915,6 @@ public class SecuritySettings extends SettingsPreferenceFragment
}
}
- public static class SecuritySubSettings extends SettingsPreferenceFragment
- implements OnPreferenceChangeListener, OwnerInfoPreferenceController.OwnerInfoCallback {
-
- private static final String KEY_VISIBLE_PATTERN = "visiblepattern";
- private static final String KEY_LOCK_AFTER_TIMEOUT = "lock_after_timeout";
- private static final String KEY_POWER_INSTANTLY_LOCKS = "power_button_instantly_locks";
-
- // These switch preferences need special handling since they're not all stored in Settings.
- private static final String SWITCH_PREFERENCE_KEYS[] = { KEY_LOCK_AFTER_TIMEOUT,
- KEY_VISIBLE_PATTERN, KEY_POWER_INSTANTLY_LOCKS };
-
- private TimeoutListPreference mLockAfter;
- private SwitchPreference mVisiblePattern;
- private SwitchPreference mPowerButtonInstantlyLocks;
-
- private TrustAgentManager mTrustAgentManager;
- private LockPatternUtils mLockPatternUtils;
- private DevicePolicyManager mDPM;
- private OwnerInfoPreferenceController mOwnerInfoPreferenceController;
-
- @Override
- public int getMetricsCategory() {
- return MetricsEvent.SECURITY;
- }
-
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
- SecurityFeatureProvider securityFeatureProvider =
- FeatureFactory.getFactory(getActivity()).getSecurityFeatureProvider();
- mTrustAgentManager = securityFeatureProvider.getTrustAgentManager();
- mLockPatternUtils = new LockPatternUtils(getContext());
- mDPM = getContext().getSystemService(DevicePolicyManager.class);
- mOwnerInfoPreferenceController =
- new OwnerInfoPreferenceController(getContext(), this, null /* lifecycle */);
- createPreferenceHierarchy();
- }
-
- @Override
- public void onResume() {
- super.onResume();
-
- createPreferenceHierarchy();
-
- if (mVisiblePattern != null) {
- mVisiblePattern.setChecked(mLockPatternUtils.isVisiblePatternEnabled(
- MY_USER_ID));
- }
- if (mPowerButtonInstantlyLocks != null) {
- mPowerButtonInstantlyLocks.setChecked(
- mLockPatternUtils.getPowerButtonInstantlyLocks(MY_USER_ID));
- }
-
- mOwnerInfoPreferenceController.updateSummary();
- }
-
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
-
- createPreferenceHierarchy();
- }
-
- private void createPreferenceHierarchy() {
- PreferenceScreen root = getPreferenceScreen();
- if (root != null) {
- root.removeAll();
- }
-
- final int resid = getResIdForLockUnlockSubScreen(getActivity(),
- new LockPatternUtils(getContext()),
- ManagedLockPasswordProvider.get(getContext(), MY_USER_ID));
- addPreferencesFromResource(resid);
-
- // lock after preference
- mLockAfter = (TimeoutListPreference) findPreference(KEY_LOCK_AFTER_TIMEOUT);
- if (mLockAfter != null) {
- setupLockAfterPreference();
- updateLockAfterPreferenceSummary();
- }
-
- // visible pattern
- mVisiblePattern = (SwitchPreference) findPreference(KEY_VISIBLE_PATTERN);
-
- // lock instantly on power key press
- mPowerButtonInstantlyLocks = (SwitchPreference) findPreference(
- KEY_POWER_INSTANTLY_LOCKS);
- CharSequence trustAgentLabel = getActiveTrustAgentLabel(getContext(),
- mTrustAgentManager, mLockPatternUtils, mDPM);
- if (mPowerButtonInstantlyLocks != null && !TextUtils.isEmpty(trustAgentLabel)) {
- mPowerButtonInstantlyLocks.setSummary(getString(
- R.string.lockpattern_settings_power_button_instantly_locks_summary,
- trustAgentLabel));
- }
-
- mOwnerInfoPreferenceController.displayPreference(getPreferenceScreen());
- mOwnerInfoPreferenceController.updateEnableState();
-
- for (int i = 0; i < SWITCH_PREFERENCE_KEYS.length; i++) {
- final Preference pref = findPreference(SWITCH_PREFERENCE_KEYS[i]);
- if (pref != null) pref.setOnPreferenceChangeListener(this);
- }
- }
-
- private void setupLockAfterPreference() {
- // Compatible with pre-Froyo
- long currentTimeout = Settings.Secure.getLong(getContentResolver(),
- Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, 5000);
- mLockAfter.setValue(String.valueOf(currentTimeout));
- mLockAfter.setOnPreferenceChangeListener(this);
- if (mDPM != null) {
- final EnforcedAdmin admin = RestrictedLockUtils.checkIfMaximumTimeToLockIsSet(
- getActivity());
- final long adminTimeout = mDPM
- .getMaximumTimeToLockForUserAndProfiles(UserHandle.myUserId());
- final long displayTimeout = Math.max(0,
- Settings.System.getInt(getContentResolver(), SCREEN_OFF_TIMEOUT, 0));
- // This setting is a slave to display timeout when a device policy is enforced.
- // As such, maxLockTimeout = adminTimeout - displayTimeout.
- // If there isn't enough time, shows "immediately" setting.
- final long maxTimeout = Math.max(0, adminTimeout - displayTimeout);
- mLockAfter.removeUnusableTimeouts(maxTimeout, admin);
- }
- }
-
- private void updateLockAfterPreferenceSummary() {
- final String summary;
- if (mLockAfter.isDisabledByAdmin()) {
- summary = getString(R.string.disabled_by_policy_title);
- } else {
- // Update summary message with current value
- long currentTimeout = Settings.Secure.getLong(getContentResolver(),
- Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, 5000);
- final CharSequence[] entries = mLockAfter.getEntries();
- final CharSequence[] values = mLockAfter.getEntryValues();
- int best = 0;
- for (int i = 0; i < values.length; i++) {
- long timeout = Long.valueOf(values[i].toString());
- if (currentTimeout >= timeout) {
- best = i;
- }
- }
-
- CharSequence trustAgentLabel = getActiveTrustAgentLabel(getContext(),
- mTrustAgentManager, mLockPatternUtils, mDPM);
- if (!TextUtils.isEmpty(trustAgentLabel)) {
- if (Long.valueOf(values[best].toString()) == 0) {
- summary = getString(R.string.lock_immediately_summary_with_exception,
- trustAgentLabel);
- } else {
- summary = getString(R.string.lock_after_timeout_summary_with_exception,
- entries[best], trustAgentLabel);
- }
- } else {
- summary = getString(R.string.lock_after_timeout_summary, entries[best]);
- }
- }
- mLockAfter.setSummary(summary);
- }
-
- @Override
- public void onOwnerInfoUpdated() {
- mOwnerInfoPreferenceController.updateSummary();
- }
-
- private static int getResIdForLockUnlockSubScreen(Context context,
- LockPatternUtils lockPatternUtils,
- ManagedLockPasswordProvider managedPasswordProvider) {
- if (lockPatternUtils.isSecure(MY_USER_ID)) {
- switch (lockPatternUtils.getKeyguardStoredPasswordQuality(MY_USER_ID)) {
- case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
- return R.xml.security_settings_pattern_sub;
- case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
- case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
- return R.xml.security_settings_pin_sub;
- case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
- case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
- case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
- return R.xml.security_settings_password_sub;
- case DevicePolicyManager.PASSWORD_QUALITY_MANAGED:
- return managedPasswordProvider.getResIdForLockUnlockSubScreen();
- }
- } else if (!lockPatternUtils.isLockScreenDisabled(MY_USER_ID)) {
- return R.xml.security_settings_slide_sub;
- }
- return 0;
- }
-
- @Override
- public boolean onPreferenceChange(Preference preference, Object value) {
- String key = preference.getKey();
- if (KEY_POWER_INSTANTLY_LOCKS.equals(key)) {
- mLockPatternUtils.setPowerButtonInstantlyLocks((Boolean) value, MY_USER_ID);
- } else if (KEY_LOCK_AFTER_TIMEOUT.equals(key)) {
- int timeout = Integer.parseInt((String) value);
- try {
- Settings.Secure.putInt(getContentResolver(),
- Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, timeout);
- } catch (NumberFormatException e) {
- Log.e("SecuritySettings", "could not persist lockAfter timeout setting", e);
- }
- setupLockAfterPreference();
- updateLockAfterPreferenceSummary();
- } else if (KEY_VISIBLE_PATTERN.equals(key)) {
- mLockPatternUtils.setVisiblePatternEnabled((Boolean) value, MY_USER_ID);
- }
- return true;
- }
- }
-
public static class UnificationConfirmationDialog extends InstrumentedDialogFragment {
private static final String EXTRA_COMPLIANT = "compliant";
diff --git a/src/com/android/settings/security/SecuritySubSettings.java b/src/com/android/settings/security/SecuritySubSettings.java
new file mode 100644
index 00000000000..5c5052bf3d4
--- /dev/null
+++ b/src/com/android/settings/security/SecuritySubSettings.java
@@ -0,0 +1,252 @@
+/*
+ * 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.security;
+
+import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.support.v14.preference.SwitchPreference;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
+import com.android.settings.TimeoutListPreference;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.password.ManagedLockPasswordProvider;
+import com.android.settings.security.trustagent.TrustAgentManager;
+import com.android.settingslib.RestrictedLockUtils;
+
+public class SecuritySubSettings extends SettingsPreferenceFragment
+ implements Preference.OnPreferenceChangeListener,
+ OwnerInfoPreferenceController.OwnerInfoCallback {
+
+ private static final String TAG = "SecuritySubSettings";
+
+ private static final String KEY_VISIBLE_PATTERN = "visiblepattern";
+ private static final String KEY_LOCK_AFTER_TIMEOUT = "lock_after_timeout";
+ private static final String KEY_POWER_INSTANTLY_LOCKS = "power_button_instantly_locks";
+
+ // These switch preferences need special handling since they're not all stored in Settings.
+ private static final String SWITCH_PREFERENCE_KEYS[] = {
+ KEY_LOCK_AFTER_TIMEOUT, KEY_VISIBLE_PATTERN, KEY_POWER_INSTANTLY_LOCKS};
+ private static final int MY_USER_ID = UserHandle.myUserId();
+
+ private TimeoutListPreference mLockAfter;
+ private SwitchPreference mVisiblePattern;
+ private SwitchPreference mPowerButtonInstantlyLocks;
+
+ private TrustAgentManager mTrustAgentManager;
+ private LockPatternUtils mLockPatternUtils;
+ private DevicePolicyManager mDPM;
+ private OwnerInfoPreferenceController mOwnerInfoPreferenceController;
+
+ @Override
+ public int getMetricsCategory() {
+ return MetricsProto.MetricsEvent.SECURITY;
+ }
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ mTrustAgentManager =
+ FeatureFactory.getFactory(
+ getActivity()).getSecurityFeatureProvider().getTrustAgentManager();
+ mLockPatternUtils = new LockPatternUtils(getContext());
+ mDPM = getContext().getSystemService(DevicePolicyManager.class);
+ mOwnerInfoPreferenceController =
+ new OwnerInfoPreferenceController(getContext(), this, null /* lifecycle */);
+ createPreferenceHierarchy();
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ createPreferenceHierarchy();
+
+ if (mVisiblePattern != null) {
+ mVisiblePattern.setChecked(mLockPatternUtils.isVisiblePatternEnabled(MY_USER_ID));
+ }
+ if (mPowerButtonInstantlyLocks != null) {
+ mPowerButtonInstantlyLocks.setChecked(
+ mLockPatternUtils.getPowerButtonInstantlyLocks(MY_USER_ID));
+ }
+
+ mOwnerInfoPreferenceController.updateSummary();
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+
+ createPreferenceHierarchy();
+ }
+
+ private void createPreferenceHierarchy() {
+ PreferenceScreen root = getPreferenceScreen();
+ if (root != null) {
+ root.removeAll();
+ }
+
+ final int resid = getResIdForLockUnlockSubScreen(new LockPatternUtils(getContext()),
+ ManagedLockPasswordProvider.get(getContext(), MY_USER_ID));
+ addPreferencesFromResource(resid);
+
+ // lock after preference
+ mLockAfter = (TimeoutListPreference) findPreference(KEY_LOCK_AFTER_TIMEOUT);
+ if (mLockAfter != null) {
+ setupLockAfterPreference();
+ updateLockAfterPreferenceSummary();
+ }
+
+ // visible pattern
+ mVisiblePattern = (SwitchPreference) findPreference(KEY_VISIBLE_PATTERN);
+
+ // lock instantly on power key press
+ mPowerButtonInstantlyLocks = (SwitchPreference) findPreference(
+ KEY_POWER_INSTANTLY_LOCKS);
+ final CharSequence trustAgentLabel = mTrustAgentManager.getActiveTrustAgentLabel(
+ getContext(), mLockPatternUtils);
+ if (mPowerButtonInstantlyLocks != null && !TextUtils.isEmpty(trustAgentLabel)) {
+ mPowerButtonInstantlyLocks.setSummary(getString(
+ R.string.lockpattern_settings_power_button_instantly_locks_summary,
+ trustAgentLabel));
+ }
+
+ mOwnerInfoPreferenceController.displayPreference(getPreferenceScreen());
+ mOwnerInfoPreferenceController.updateEnableState();
+
+ for (int i = 0; i < SWITCH_PREFERENCE_KEYS.length; i++) {
+ final Preference pref = findPreference(SWITCH_PREFERENCE_KEYS[i]);
+ if (pref != null) pref.setOnPreferenceChangeListener(this);
+ }
+ }
+
+ private void setupLockAfterPreference() {
+ // Compatible with pre-Froyo
+ long currentTimeout = Settings.Secure.getLong(getContentResolver(),
+ Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, 5000);
+ mLockAfter.setValue(String.valueOf(currentTimeout));
+ mLockAfter.setOnPreferenceChangeListener(this);
+ if (mDPM != null) {
+ final RestrictedLockUtils.EnforcedAdmin admin =
+ RestrictedLockUtils.checkIfMaximumTimeToLockIsSet(
+ getActivity());
+ final long adminTimeout = mDPM
+ .getMaximumTimeToLockForUserAndProfiles(UserHandle.myUserId());
+ final long displayTimeout = Math.max(0,
+ Settings.System.getInt(getContentResolver(), SCREEN_OFF_TIMEOUT, 0));
+ // This setting is a slave to display timeout when a device policy is enforced.
+ // As such, maxLockTimeout = adminTimeout - displayTimeout.
+ // If there isn't enough time, shows "immediately" setting.
+ final long maxTimeout = Math.max(0, adminTimeout - displayTimeout);
+ mLockAfter.removeUnusableTimeouts(maxTimeout, admin);
+ }
+ }
+
+ private void updateLockAfterPreferenceSummary() {
+ final String summary;
+ if (mLockAfter.isDisabledByAdmin()) {
+ summary = getString(R.string.disabled_by_policy_title);
+ } else {
+ // Update summary message with current value
+ long currentTimeout = Settings.Secure.getLong(getContentResolver(),
+ Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, 5000);
+ final CharSequence[] entries = mLockAfter.getEntries();
+ final CharSequence[] values = mLockAfter.getEntryValues();
+ int best = 0;
+ for (int i = 0; i < values.length; i++) {
+ long timeout = Long.valueOf(values[i].toString());
+ if (currentTimeout >= timeout) {
+ best = i;
+ }
+ }
+
+ final CharSequence trustAgentLabel = mTrustAgentManager
+ .getActiveTrustAgentLabel(getContext(), mLockPatternUtils);
+ if (!TextUtils.isEmpty(trustAgentLabel)) {
+ if (Long.valueOf(values[best].toString()) == 0) {
+ summary = getString(R.string.lock_immediately_summary_with_exception,
+ trustAgentLabel);
+ } else {
+ summary = getString(R.string.lock_after_timeout_summary_with_exception,
+ entries[best], trustAgentLabel);
+ }
+ } else {
+ summary = getString(R.string.lock_after_timeout_summary, entries[best]);
+ }
+ }
+ mLockAfter.setSummary(summary);
+ }
+
+ @Override
+ public void onOwnerInfoUpdated() {
+ mOwnerInfoPreferenceController.updateSummary();
+ }
+
+ static int getResIdForLockUnlockSubScreen(LockPatternUtils lockPatternUtils,
+ ManagedLockPasswordProvider managedPasswordProvider) {
+ if (lockPatternUtils.isSecure(MY_USER_ID)) {
+ switch (lockPatternUtils.getKeyguardStoredPasswordQuality(MY_USER_ID)) {
+ case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
+ return R.xml.security_settings_pattern_sub;
+ case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
+ case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
+ return R.xml.security_settings_pin_sub;
+ case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
+ case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
+ case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
+ return R.xml.security_settings_password_sub;
+ case DevicePolicyManager.PASSWORD_QUALITY_MANAGED:
+ return managedPasswordProvider.getResIdForLockUnlockSubScreen();
+ }
+ } else if (!lockPatternUtils.isLockScreenDisabled(MY_USER_ID)) {
+ return R.xml.security_settings_slide_sub;
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object value) {
+ String key = preference.getKey();
+ if (KEY_POWER_INSTANTLY_LOCKS.equals(key)) {
+ mLockPatternUtils.setPowerButtonInstantlyLocks((Boolean) value, MY_USER_ID);
+ } else if (KEY_LOCK_AFTER_TIMEOUT.equals(key)) {
+ int timeout = Integer.parseInt((String) value);
+ try {
+ Settings.Secure.putInt(getContentResolver(),
+ Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, timeout);
+ } catch (NumberFormatException e) {
+ Log.e(TAG, "could not persist lockAfter timeout setting", e);
+ }
+ setupLockAfterPreference();
+ updateLockAfterPreferenceSummary();
+ } else if (KEY_VISIBLE_PATTERN.equals(key)) {
+ mLockPatternUtils.setVisiblePatternEnabled((Boolean) value, MY_USER_ID);
+ }
+ return true;
+ }
+}
diff --git a/src/com/android/settings/security/UserCredentialsPreferenceController.java b/src/com/android/settings/security/UserCredentialsPreferenceController.java
new file mode 100644
index 00000000000..48503f8375b
--- /dev/null
+++ b/src/com/android/settings/security/UserCredentialsPreferenceController.java
@@ -0,0 +1,35 @@
+/*
+ * 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.security;
+
+import android.content.Context;
+import android.os.UserManager;
+
+public class UserCredentialsPreferenceController extends
+ RestrictedEncryptionPreferenceController {
+
+ private static final String KEY_USER_CREDENTIALS = "user_credentials";
+
+ public UserCredentialsPreferenceController(Context context) {
+ super(context, UserManager.DISALLOW_CONFIG_CREDENTIALS);
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY_USER_CREDENTIALS;
+ }
+}
diff --git a/src/com/android/settings/security/trustagent/TrustAgentManager.java b/src/com/android/settings/security/trustagent/TrustAgentManager.java
new file mode 100644
index 00000000000..371090502ae
--- /dev/null
+++ b/src/com/android/settings/security/trustagent/TrustAgentManager.java
@@ -0,0 +1,204 @@
+/*
+ * 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.security.trustagent;
+
+import static android.service.trust.TrustAgentService.TRUST_AGENT_META_DATA;
+
+import android.app.admin.DevicePolicyManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.os.UserHandle;
+import android.service.trust.TrustAgentService;
+import android.support.annotation.VisibleForTesting;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Slog;
+import android.util.Xml;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.settingslib.RestrictedLockUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+
+/** A manager for trust agent state. */
+public class TrustAgentManager {
+
+ // Only allow one trust agent on the platform.
+ private static final boolean ONLY_ONE_TRUST_AGENT = true;
+
+ public static class TrustAgentComponentInfo {
+ public ComponentName componentName;
+ public String title;
+ public String summary;
+ public RestrictedLockUtils.EnforcedAdmin admin = null;
+ }
+
+ private static final String TAG = "TrustAgentManager";
+ private static final Intent TRUST_AGENT_INTENT =
+ new Intent(TrustAgentService.SERVICE_INTERFACE);
+
+ @VisibleForTesting
+ static final String PERMISSION_PROVIDE_AGENT =
+ android.Manifest.permission.PROVIDE_TRUST_AGENT;
+
+ /**
+ * Determines if the service associated with a resolved trust agent intent is allowed to provide
+ * trust on this device.
+ *
+ * @param resolveInfo The entry corresponding to the matched trust agent intent.
+ * @param pm The package manager to be used to check for permissions.
+ * @return {@code true} if the associated service is allowed to provide a trust agent, and
+ * {@code false} if otherwise.
+ */
+ public boolean shouldProvideTrust(ResolveInfo resolveInfo, PackageManager pm) {
+ final String packageName = resolveInfo.serviceInfo.packageName;
+ if (pm.checkPermission(PERMISSION_PROVIDE_AGENT, packageName)
+ != PackageManager.PERMISSION_GRANTED) {
+ Log.w(TAG, "Skipping agent because package " + packageName
+ + " does not have permission " + PERMISSION_PROVIDE_AGENT + ".");
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Return the display label for active trust agent.
+ */
+ public CharSequence getActiveTrustAgentLabel(Context context, LockPatternUtils utils) {
+ final List agents = getActiveTrustAgents(context, utils);
+ return agents.isEmpty() ? null : agents.get(0).title;
+ }
+
+ /**
+ * Returns a list of trust agents.
+ *
+ * If {@link #ONLY_ONE_TRUST_AGENT} is set, the list will contain up to 1 agent instead of all
+ * available agents on device.
+ */
+ public List getActiveTrustAgents(Context context,
+ LockPatternUtils utils) {
+ final int myUserId = UserHandle.myUserId();
+ final DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
+ final PackageManager pm = context.getPackageManager();
+ final List result = new ArrayList<>();
+
+ final List resolveInfos = pm.queryIntentServices(TRUST_AGENT_INTENT,
+ PackageManager.GET_META_DATA);
+ final List enabledTrustAgents = utils.getEnabledTrustAgents(myUserId);
+ final RestrictedLockUtils.EnforcedAdmin admin = RestrictedLockUtils
+ .checkIfKeyguardFeaturesDisabled(
+ context, DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS, myUserId);
+
+ if (enabledTrustAgents != null && !enabledTrustAgents.isEmpty()) {
+ for (ResolveInfo resolveInfo : resolveInfos) {
+ if (resolveInfo.serviceInfo == null || !shouldProvideTrust(resolveInfo, pm)) {
+ continue;
+ }
+ final TrustAgentComponentInfo trustAgentComponentInfo =
+ getSettingsComponent(pm, resolveInfo);
+ if (trustAgentComponentInfo.componentName == null ||
+ !enabledTrustAgents.contains(getComponentName(resolveInfo)) ||
+ TextUtils.isEmpty(trustAgentComponentInfo.title)) {
+ continue;
+ }
+ if (admin != null && dpm.getTrustAgentConfiguration(
+ null, getComponentName(resolveInfo)) == null) {
+ trustAgentComponentInfo.admin = admin;
+ }
+ result.add(trustAgentComponentInfo);
+ if (ONLY_ONE_TRUST_AGENT) {
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
+ public ComponentName getComponentName(ResolveInfo resolveInfo) {
+ if (resolveInfo == null || resolveInfo.serviceInfo == null) return null;
+ return new ComponentName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name);
+ }
+
+ private TrustAgentComponentInfo getSettingsComponent(PackageManager pm,
+ ResolveInfo resolveInfo) {
+ if (resolveInfo == null || resolveInfo.serviceInfo == null
+ || resolveInfo.serviceInfo.metaData == null) {
+ return null;
+ }
+ String cn = null;
+ TrustAgentComponentInfo trustAgentComponentInfo = new TrustAgentComponentInfo();
+ XmlResourceParser parser = null;
+ Exception caughtException = null;
+ try {
+ parser = resolveInfo.serviceInfo.loadXmlMetaData(pm, TRUST_AGENT_META_DATA);
+ if (parser == null) {
+ Slog.w(TAG, "Can't find " + TRUST_AGENT_META_DATA + " meta-data");
+ return null;
+ }
+ Resources res = pm.getResourcesForApplication(resolveInfo.serviceInfo.applicationInfo);
+ AttributeSet attrs = Xml.asAttributeSet(parser);
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && type != XmlPullParser.START_TAG) {
+ }
+ String nodeName = parser.getName();
+ if (!"trust-agent".equals(nodeName)) {
+ Slog.w(TAG, "Meta-data does not start with trust-agent tag");
+ return null;
+ }
+ TypedArray sa =
+ res.obtainAttributes(attrs, com.android.internal.R.styleable.TrustAgent);
+ trustAgentComponentInfo.summary =
+ sa.getString(com.android.internal.R.styleable.TrustAgent_summary);
+ trustAgentComponentInfo.title =
+ sa.getString(com.android.internal.R.styleable.TrustAgent_title);
+ cn = sa.getString(com.android.internal.R.styleable.TrustAgent_settingsActivity);
+ sa.recycle();
+ } catch (PackageManager.NameNotFoundException e) {
+ caughtException = e;
+ } catch (IOException e) {
+ caughtException = e;
+ } catch (XmlPullParserException e) {
+ caughtException = e;
+ } finally {
+ if (parser != null) parser.close();
+ }
+ if (caughtException != null) {
+ Slog.w(TAG, "Error parsing : " + resolveInfo.serviceInfo.packageName, caughtException);
+ return null;
+ }
+ if (cn != null && cn.indexOf('/') < 0) {
+ cn = resolveInfo.serviceInfo.packageName + "/" + cn;
+ }
+ trustAgentComponentInfo.componentName =
+ (cn == null) ? null : ComponentName.unflattenFromString(cn);
+ return trustAgentComponentInfo;
+ }
+}
diff --git a/src/com/android/settings/TrustAgentSettings.java b/src/com/android/settings/security/trustagent/TrustAgentSettings.java
similarity index 96%
rename from src/com/android/settings/TrustAgentSettings.java
rename to src/com/android/settings/security/trustagent/TrustAgentSettings.java
index 0e5cd2c1971..c7001a03752 100644
--- a/src/com/android/settings/TrustAgentSettings.java
+++ b/src/com/android/settings/security/trustagent/TrustAgentSettings.java
@@ -14,7 +14,9 @@
* limitations under the License.
*/
-package com.android.settings;
+package com.android.settings.security.trustagent;
+
+import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
@@ -34,15 +36,14 @@ import android.util.ArraySet;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.widget.LockPatternUtils;
+import com.android.settings.R;
+import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.overlay.FeatureFactory;
-import com.android.settings.trustagent.TrustAgentManager;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedSwitchPreference;
import java.util.List;
-import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
-
public class TrustAgentSettings extends SettingsPreferenceFragment implements
Preference.OnPreferenceChangeListener {
private static final String SERVICE_INTERFACE = TrustAgentService.SERVICE_INTERFACE;
@@ -97,7 +98,7 @@ public class TrustAgentSettings extends SettingsPreferenceFragment implements
super.onResume();
removePreference("dummy_preference");
updateAgents();
- };
+ }
private void updateAgents() {
final Context context = getActivity();
@@ -152,7 +153,7 @@ public class TrustAgentSettings extends SettingsPreferenceFragment implements
UserHandle.myUserId());
}
- ArrayMap findAvailableTrustAgents() {
+ private ArrayMap findAvailableTrustAgents() {
PackageManager pm = getActivity().getPackageManager();
Intent trustAgentIntent = new Intent(SERVICE_INTERFACE);
List resolveInfos = pm.queryIntentServices(trustAgentIntent,
@@ -169,7 +170,7 @@ public class TrustAgentSettings extends SettingsPreferenceFragment implements
if (!mTrustAgentManager.shouldProvideTrust(resolveInfo, pm)) {
continue;
}
- ComponentName name = TrustAgentUtils.getComponentName(resolveInfo);
+ ComponentName name = mTrustAgentManager.getComponentName(resolveInfo);
AgentInfo agentInfo = new AgentInfo();
agentInfo.label = resolveInfo.loadLabel(pm);
agentInfo.icon = resolveInfo.loadIcon(pm);
diff --git a/src/com/android/settings/trustagent/TrustAgentManager.java b/src/com/android/settings/trustagent/TrustAgentManager.java
deleted file mode 100644
index 3335e17f193..00000000000
--- a/src/com/android/settings/trustagent/TrustAgentManager.java
+++ /dev/null
@@ -1,38 +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.trustagent;
-
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-
-
-/** A manager for trust agent state. */
-public interface TrustAgentManager {
-
- String PERMISSION_PROVIDE_AGENT = android.Manifest.permission.PROVIDE_TRUST_AGENT;
-
- /**
- * Determines if the service associated with a resolved trust agent intent is allowed to provide
- * trust on this device.
- *
- * @param resolveInfo The entry corresponding to the matched trust agent intent.
- * @param pm The package manager to be used to check for permissions.
- * @return {@code true} if the associated service is allowed to provide a trust agent, and
- * {@code false} if otherwise.
- */
- boolean shouldProvideTrust(ResolveInfo resolveInfo, PackageManager pm);
-}
diff --git a/src/com/android/settings/trustagent/TrustAgentManagerImpl.java b/src/com/android/settings/trustagent/TrustAgentManagerImpl.java
deleted file mode 100644
index cabda79657e..00000000000
--- a/src/com/android/settings/trustagent/TrustAgentManagerImpl.java
+++ /dev/null
@@ -1,39 +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.trustagent;
-
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.util.Log;
-
-/** Implementation for {@code SecurityFeatureProvider}. */
-public class TrustAgentManagerImpl implements TrustAgentManager {
-
- private static final String TAG = "TrustAgentFeature";
-
- @Override
- public boolean shouldProvideTrust(ResolveInfo resolveInfo, PackageManager pm) {
- final String packageName = resolveInfo.serviceInfo.packageName;
- if (pm.checkPermission(PERMISSION_PROVIDE_AGENT, packageName)
- != PackageManager.PERMISSION_GRANTED) {
- Log.w(TAG, "Skipping agent because package " + packageName
- + " does not have permission " + PERMISSION_PROVIDE_AGENT + ".");
- return false;
- }
- return true;
- }
-}
diff --git a/src/com/android/settings/widget/WorkOnlyCategoryPreferenceController.java b/src/com/android/settings/widget/PreferenceCategoryController.java
similarity index 82%
rename from src/com/android/settings/widget/WorkOnlyCategoryPreferenceController.java
rename to src/com/android/settings/widget/PreferenceCategoryController.java
index a308b2f1b10..98364769e47 100644
--- a/src/com/android/settings/widget/WorkOnlyCategoryPreferenceController.java
+++ b/src/com/android/settings/widget/PreferenceCategoryController.java
@@ -23,13 +23,18 @@ import com.android.settingslib.core.AbstractPreferenceController;
import java.util.List;
-public class WorkOnlyCategoryPreferenceController extends AbstractPreferenceController
+/**
+ * A controller for generic Preference categories. If all controllers for its children reports
+ * not-available, this controller will also report not-available, and subsequently will be hidden by
+ * UI.
+ */
+public class PreferenceCategoryController extends AbstractPreferenceController
implements PreferenceControllerMixin {
private final String mKey;
private final List mChildren;
- public WorkOnlyCategoryPreferenceController(Context context,
+ public PreferenceCategoryController(Context context,
String key, List childrenControllers) {
super(context);
mKey = key;
diff --git a/src/com/android/settings/wifi/WifiDialogActivity.java b/src/com/android/settings/wifi/WifiDialogActivity.java
index 4f9c7a634ae..e2e3d019cd1 100644
--- a/src/com/android/settings/wifi/WifiDialogActivity.java
+++ b/src/com/android/settings/wifi/WifiDialogActivity.java
@@ -22,7 +22,9 @@ import android.content.Intent;
import android.net.NetworkInfo;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiManager;
+import android.net.wifi.WifiManager.ActionListener;
import android.os.Bundle;
+import android.support.annotation.VisibleForTesting;
import android.util.Log;
import com.android.settings.SetupWizardUtils;
@@ -40,6 +42,15 @@ public class WifiDialogActivity extends Activity implements WifiDialog.WifiDialo
private static final String KEY_ACCESS_POINT_STATE = "access_point_state";
private static final String KEY_WIFI_CONFIGURATION = "wifi_configuration";
+ /**
+ * Boolean extra indicating whether this activity should connect to an access point on the
+ * caller's behalf. If this is set to false, the caller should check
+ * {@link #KEY_WIFI_CONFIGURATION} in the result data and save that using
+ * {@link WifiManager#connect(WifiConfiguration, ActionListener)}. Default is true.
+ */
+ @VisibleForTesting
+ static final String KEY_CONNECT_FOR_CALLER = "connect_for_caller";
+
@Override
protected void onCreate(Bundle savedInstanceState) {
final Intent intent = getIntent();
@@ -55,7 +66,8 @@ public class WifiDialogActivity extends Activity implements WifiDialog.WifiDialo
accessPoint = new AccessPoint(this, accessPointState);
}
- WifiDialog dialog = WifiDialog.createModal(this, this, accessPoint, WifiConfigUiBase.MODE_CONNECT);
+ WifiDialog dialog = WifiDialog.createModal(
+ this, this, accessPoint, WifiConfigUiBase.MODE_CONNECT);
dialog.show();
dialog.setOnDismissListener(this);
}
@@ -102,17 +114,19 @@ public class WifiDialogActivity extends Activity implements WifiDialog.WifiDialo
final AccessPoint accessPoint = dialog.getController().getAccessPoint();
final WifiManager wifiManager = getSystemService(WifiManager.class);
- if (config == null) {
- if (accessPoint != null && accessPoint.isSaved()) {
- wifiManager.connect(accessPoint.getConfig(), null /* listener */);
- }
- } else {
- wifiManager.save(config, null /* listener */);
- if (accessPoint != null) {
- // accessPoint is null for "Add network"
- NetworkInfo networkInfo = accessPoint.getNetworkInfo();
- if (networkInfo == null || !networkInfo.isConnected()) {
- wifiManager.connect(config, null /* listener */);
+ if (getIntent().getBooleanExtra(KEY_CONNECT_FOR_CALLER, true)) {
+ if (config == null) {
+ if (accessPoint != null && accessPoint.isSaved()) {
+ wifiManager.connect(accessPoint.getConfig(), null /* listener */);
+ }
+ } else {
+ wifiManager.save(config, null /* listener */);
+ if (accessPoint != null) {
+ // accessPoint is null for "Add network"
+ NetworkInfo networkInfo = accessPoint.getNetworkInfo();
+ if (networkInfo == null || !networkInfo.isConnected()) {
+ wifiManager.connect(config, null /* listener */);
+ }
}
}
}
diff --git a/tests/robotests/assets/grandfather_not_implementing_indexable b/tests/robotests/assets/grandfather_not_implementing_indexable
index 91a66497ae3..31b8f43d81f 100644
--- a/tests/robotests/assets/grandfather_not_implementing_indexable
+++ b/tests/robotests/assets/grandfather_not_implementing_indexable
@@ -71,13 +71,13 @@ com.android.settings.applications.ExternalSourcesDetails
com.android.settings.applications.PictureInPictureSettings
com.android.settings.applications.PictureInPictureDetails
com.android.settings.ApnSettings
-com.android.settings.SecuritySettings$SecuritySubSettings
+com.android.settings.security.SecuritySubSettings
com.android.settings.PrivacySettings
com.android.settings.WifiCallingSettings
com.android.settings.WifiCallingSettingsForSub
com.android.settings.password.SetupChooseLockGeneric$SetupChooseLockGenericFragment
com.android.settings.SetupRedactionInterstitial$SetupRedactionInterstitialFragment
-com.android.settings.TrustAgentSettings
+com.android.settings.security.trustagent.TrustAgentSettings
com.android.settings.password.ChooseLockGeneric$ChooseLockGenericFragment
com.android.settings.IccLockSettings
com.android.settings.TetherSettings
diff --git a/tests/robotests/src/com/android/settings/TestConfig.java b/tests/robotests/src/com/android/settings/TestConfig.java
index 3b2d2e46d42..d2d65a95ffa 100644
--- a/tests/robotests/src/com/android/settings/TestConfig.java
+++ b/tests/robotests/src/com/android/settings/TestConfig.java
@@ -16,10 +16,18 @@
package com.android.settings;
+import android.os.Build;
+
/**
* Constants for Robolectric config
*/
public class TestConfig {
+
+ /**
+ * @deprecated New tests should use {@link #SDK_VERSION_O}
+ */
+ @Deprecated
public static final int SDK_VERSION = 23;
+ public static final int SDK_VERSION_O = Build.VERSION_CODES.O;
public static final String MANIFEST_PATH = "packages/apps/Settings/AndroidManifest.xml";
}
diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java
new file mode 100644
index 00000000000..5ef5a12c36f
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java
@@ -0,0 +1,99 @@
+/*
+ * 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.accessibility;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.os.Bundle;
+import android.support.annotation.XmlRes;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.settings.R;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.SettingsShadowResources;
+import com.android.settings.widget.SwitchBar;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.FragmentTestUtil;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
+ shadows = {
+ SettingsShadowResources.class,
+ SettingsShadowResources.SettingsShadowTheme.class,
+ })
+public class ToggleFeaturePreferenceFragmentTest {
+
+ private ToggleFeaturePreferenceFragmentTestable mFragment;
+
+ @Test
+ public void createFragment_shouldOnlyAddPreferencesOnce() {
+ mFragment = spy(new ToggleFeaturePreferenceFragmentTestable());
+
+ FragmentTestUtil.startFragment(mFragment);
+
+ // execute exactly once
+ verify(mFragment).addPreferencesFromResource(R.xml.placeholder_prefs);
+ }
+
+
+ public static class ToggleFeaturePreferenceFragmentTestable
+ extends ToggleFeaturePreferenceFragment {
+
+ @Override
+ protected void onPreferenceToggled(String preferenceKey, boolean enabled) {}
+
+ @Override
+ public int getMetricsCategory() {
+ return 0;
+ }
+
+ @Override
+ public int getPreferenceScreenResId() {
+ return R.xml.placeholder_prefs;
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ return mock(View.class);
+ }
+
+ @Override
+ public void addPreferencesFromResource(@XmlRes int preferencesResId) {
+ // do nothing
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ // do nothing
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ mSwitchBar = mock(SwitchBar.class);
+ super.onActivityCreated(savedInstanceState);
+ }
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/dashboard/SummaryLoaderTest.java b/tests/robotests/src/com/android/settings/dashboard/SummaryLoaderTest.java
index 146be9c7acb..44b61398b23 100644
--- a/tests/robotests/src/com/android/settings/dashboard/SummaryLoaderTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/SummaryLoaderTest.java
@@ -16,6 +16,10 @@
package com.android.settings.dashboard;
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
+
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
@@ -23,6 +27,7 @@ import android.content.Intent;
import com.android.settings.TestConfig;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.drawer.CategoryKey;
import com.android.settingslib.drawer.DashboardCategory;
import com.android.settingslib.drawer.Tile;
@@ -35,12 +40,6 @@ import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.annotation.Config;
-import java.util.ArrayList;
-import java.util.List;
-
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.when;
-
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class SummaryLoaderTest {
@@ -65,14 +64,14 @@ public class SummaryLoaderTest {
mCallbackInvoked = false;
final Activity activity = Robolectric.buildActivity(Activity.class).get();
- final List categories = new ArrayList<>();
- mSummaryLoader = new SummaryLoader(activity, categories);
- mSummaryLoader.setSummaryConsumer(new SummaryLoader.SummaryConsumer() {
- @Override
- public void notifySummaryChanged(Tile tile) {
- mCallbackInvoked = true;
- }
- });
+
+ mSummaryLoader = new SummaryLoader(activity, CategoryKey.CATEGORY_HOMEPAGE);
+ mSummaryLoader.setSummaryConsumer(tile -> mCallbackInvoked = true);
+ }
+
+ @Test
+ public void newInstance_shouldNotLoadCategory() {
+ verifyZeroInteractions(mFeatureFactory.dashboardFeatureProvider);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionPreferenceControllerV2Test.java b/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionPreferenceControllerV2Test.java
new file mode 100644
index 00000000000..5fa8a913708
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/deviceinfo/firmwareversion/FirmwareVersionPreferenceControllerV2Test.java
@@ -0,0 +1,94 @@
+/*
+ * 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.deviceinfo.firmwareversion;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.content.Context;
+import android.os.Build;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class FirmwareVersionPreferenceControllerV2Test {
+
+ @Mock
+ private Preference mPreference;
+ @Mock
+ private PreferenceScreen mScreen;
+ @Mock
+ private Fragment mFragment;
+
+ private Context mContext;
+ private FirmwareVersionPreferenceControllerV2 mController;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mController = new FirmwareVersionPreferenceControllerV2(mContext, mFragment);
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
+ }
+
+ @Test
+ public void displayPreference_shouldSetSummaryToBuildNumber() {
+ mController.displayPreference(mScreen);
+
+ verify(mPreference).setSummary(Build.VERSION.RELEASE);
+ }
+
+ @Test
+ public void handlePreferenceTreeClick_samePreferenceKey_shouldStartDialogFragment() {
+ when(mPreference.getKey()).thenReturn(mController.getPreferenceKey());
+ when(mFragment.getChildFragmentManager()).thenReturn(
+ mock(FragmentManager.class, Answers.RETURNS_DEEP_STUBS));
+
+ mController.handlePreferenceTreeClick(mPreference);
+
+ verify(mFragment).getChildFragmentManager();
+ }
+
+ @Test
+ public void handlePreferenceTreeClick_unknownPreferenceKey_shouldDoNothingAndReturnFalse() {
+ when(mPreference.getKey()).thenReturn("foobar");
+
+ final boolean result = mController.handlePreferenceTreeClick(mPreference);
+
+ assertThat(result).isFalse();
+ verify(mFragment, never()).getChildFragmentManager();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/imei/AbstractImeiInfoPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/imei/AbstractImeiInfoPreferenceControllerTest.java
new file mode 100644
index 00000000000..51e6005d743
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/deviceinfo/imei/AbstractImeiInfoPreferenceControllerTest.java
@@ -0,0 +1,143 @@
+/*
+ * 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.deviceinfo.imei;
+
+import static android.telephony.TelephonyManager.PHONE_TYPE_CDMA;
+import static android.telephony.TelephonyManager.PHONE_TYPE_GSM;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+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.content.Context;
+import android.os.UserManager;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.telephony.TelephonyManager;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class AbstractImeiInfoPreferenceControllerTest {
+
+ @Mock
+ private Preference mPreference;
+ @Mock
+ private PreferenceScreen mScreen;
+ @Mock
+ private TelephonyManager mTelephonyManager;
+ @Mock
+ private UserManager mUserManager;
+ @Mock
+ private Fragment mFragment;
+
+ private Context mContext;
+ private AbstractImeiInfoPreferenceControllerImpl mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+ doReturn(mUserManager).when(mContext).getSystemService(UserManager.class);
+ mController = new AbstractImeiInfoPreferenceControllerImpl(mContext, mFragment);
+ ReflectionHelpers.setField(mController, "mTelephonyManager", mTelephonyManager);
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
+ when(mPreference.getKey()).thenReturn(mController.getPreferenceKey());
+ }
+
+ @Test
+ public void displayPreference_cdmaPhone_shouldSetCdmaTitleAndMeid() {
+ mController = spy(mController);
+ final String meid = "125132215123";
+ when(mTelephonyManager.getPhoneType()).thenReturn(PHONE_TYPE_CDMA);
+ doReturn(meid).when(mController).getMeid();
+
+ mController.displayPreference(mScreen);
+
+ verify(mPreference).setTitle(mController.getTitleForCdmaPhone());
+ verify(mPreference).setSummary(meid);
+ }
+
+ @Test
+ public void displayPreference_gsmPhone_shouldSetGsmTitleAndImei() {
+ final String imei = "125132215123";
+ when(mTelephonyManager.getPhoneType()).thenReturn(PHONE_TYPE_GSM);
+ when(mTelephonyManager.getImei(anyInt())).thenReturn(imei);
+
+ mController.displayPreference(mScreen);
+
+ verify(mPreference).setTitle(mController.getTitleForGsmPhone());
+ verify(mPreference).setSummary(imei);
+ }
+
+ @Test
+ public void handlePreferenceTreeClick_shouldStartDialogFragment() {
+ when(mFragment.getChildFragmentManager()).thenReturn(
+ mock(FragmentManager.class, Answers.RETURNS_DEEP_STUBS));
+ when(mPreference.getTitle()).thenReturn("SomeTitle");
+ mController.displayPreference(mScreen);
+
+ mController.handlePreferenceTreeClick(mPreference);
+
+ verify(mFragment).getChildFragmentManager();
+ }
+
+ public class AbstractImeiInfoPreferenceControllerImpl extends
+ AbstractImeiInfoPreferenceController {
+
+ public AbstractImeiInfoPreferenceControllerImpl(Context context, Fragment fragment) {
+ super(context, fragment);
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return "foobar";
+ }
+
+ @Override
+ protected String getTitleForCdmaPhone() {
+ return "foo";
+ }
+
+ @Override
+ protected String getTitleForGsmPhone() {
+ return "bar";
+ }
+
+ @Override
+ protected int getSimSlot() {
+ return 0;
+ }
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/imei/ImeiInfoDialogControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/imei/ImeiInfoDialogControllerTest.java
new file mode 100644
index 00000000000..bb4933bcddc
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/deviceinfo/imei/ImeiInfoDialogControllerTest.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.deviceinfo.imei;
+
+import static com.android.settings.deviceinfo.imei.ImeiInfoDialogController.ID_CDMA_SETTINGS;
+import static com.android.settings.deviceinfo.imei.ImeiInfoDialogController.ID_GSM_SETTINGS;
+import static com.android.settings.deviceinfo.imei.ImeiInfoDialogController.ID_ICC_ID_LABEL;
+import static com.android.settings.deviceinfo.imei.ImeiInfoDialogController.ID_ICC_ID_VALUE;
+import static com.android.settings.deviceinfo.imei.ImeiInfoDialogController.ID_IMEI_SV_VALUE;
+import static com.android.settings.deviceinfo.imei.ImeiInfoDialogController.ID_IMEI_VALUE;
+import static com.android.settings.deviceinfo.imei.ImeiInfoDialogController.ID_MEID_NUMBER_VALUE;
+import static com.android.settings.deviceinfo.imei.ImeiInfoDialogController.ID_MIN_NUMBER_VALUE;
+import static com.android.settings.deviceinfo.imei.ImeiInfoDialogController.ID_PRL_VERSION_VALUE;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.telephony.SubscriptionInfo;
+import android.telephony.TelephonyManager;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class ImeiInfoDialogControllerTest {
+
+ private static final String PRL_VERSION = "some_prl_version";
+ private static final String MEID_NUMBER = "12871234124";
+ private static final String IMEI_NUMBER = "2341982751254";
+ private static final String MIN_NUMBER = "123417851315";
+ private static final String ICCID_NUMBER = "3845672472";
+ private static final String IMEI_SV_NUMBER = "12";
+
+ @Mock
+ private ImeiInfoDialogFragment mDialog;
+ @Mock
+ private TelephonyManager mTelephonyManager;
+ @Mock
+ private SubscriptionInfo mSubscriptionInfo;
+
+ private Context mContext;
+ private ImeiInfoDialogController mController;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+ doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE);
+ when(mDialog.getContext()).thenReturn(mContext);
+ mController = spy(new ImeiInfoDialogController(mDialog, 0 /* phone id */));
+ ReflectionHelpers.setField(mController, "mSubscriptionInfo", mSubscriptionInfo);
+
+ doReturn(PRL_VERSION).when(mController).getCdmaPrlVersion();
+ doReturn(MEID_NUMBER).when(mController).getMeid();
+ when(mTelephonyManager.getCdmaMin(anyInt())).thenReturn(MIN_NUMBER);
+ when(mSubscriptionInfo.getIccId()).thenReturn(ICCID_NUMBER);
+ when(mTelephonyManager.getDeviceSoftwareVersion(anyInt())).thenReturn(IMEI_SV_NUMBER);
+ when(mTelephonyManager.getImei(anyInt())).thenReturn(IMEI_NUMBER);
+ }
+
+ @Test
+ public void populateImeiInfo_cdmaLteEnabled_shouldSetMeidAndImeiAndMin() {
+ doReturn(true).when(mController).isCdmaLteEnabled();
+ when(mTelephonyManager.getPhoneType()).thenReturn(TelephonyManager.PHONE_TYPE_CDMA);
+
+ mController.populateImeiInfo();
+
+ verify(mDialog).setText(ID_MEID_NUMBER_VALUE, MEID_NUMBER);
+ verify(mDialog).setText(ID_MIN_NUMBER_VALUE, MIN_NUMBER);
+ verify(mDialog).setText(ID_PRL_VERSION_VALUE, PRL_VERSION);
+ verify(mDialog).setText(ID_ICC_ID_VALUE, ICCID_NUMBER);
+ verify(mDialog).setText(eq(ID_IMEI_VALUE), any());
+ verify(mDialog).setText(eq(ID_IMEI_SV_VALUE), any());
+ }
+
+ @Test
+ public void populateImeiInfo_cdmaLteDisabled_shouldSetMeidAndMinAndRemoveGsmSettings() {
+ doReturn(false).when(mController).isCdmaLteEnabled();
+ when(mTelephonyManager.getPhoneType()).thenReturn(TelephonyManager.PHONE_TYPE_CDMA);
+
+ mController.populateImeiInfo();
+
+ verify(mDialog).setText(ID_MEID_NUMBER_VALUE, MEID_NUMBER);
+ verify(mDialog).setText(ID_MIN_NUMBER_VALUE, MIN_NUMBER);
+ verify(mDialog).setText(ID_PRL_VERSION_VALUE, PRL_VERSION);
+ verify(mDialog).removeViewFromScreen(ID_GSM_SETTINGS);
+ verify(mDialog).removeViewFromScreen(ID_ICC_ID_VALUE);
+ verify(mDialog).removeViewFromScreen(ID_ICC_ID_LABEL);
+ }
+
+ @Test
+ public void populateImeinfo_gsm_shouldSetImeiAndRemoveCdmaSettings() {
+ when(mTelephonyManager.getPhoneType()).thenReturn(TelephonyManager.PHONE_TYPE_GSM);
+
+ mController.populateImeiInfo();
+
+ verify(mDialog).setText(eq(ID_IMEI_VALUE), any());
+ verify(mDialog).setText(eq(ID_IMEI_SV_VALUE), any());
+ verify(mDialog).removeViewFromScreen(ID_CDMA_SETTINGS);
+ verify(mDialog).removeViewFromScreen(ID_ICC_ID_VALUE);
+ verify(mDialog).removeViewFromScreen(ID_ICC_ID_LABEL);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/imei/ImeiInfoDualSimPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/imei/ImeiInfoDualSimPreferenceControllerTest.java
new file mode 100644
index 00000000000..ce99ee4f718
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/deviceinfo/imei/ImeiInfoDualSimPreferenceControllerTest.java
@@ -0,0 +1,89 @@
+/*
+ * 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.deviceinfo.imei;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.app.Fragment;
+import android.content.Context;
+import android.os.UserManager;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.telephony.TelephonyManager;
+
+import com.android.settings.R;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class ImeiInfoDualSimPreferenceControllerTest {
+
+ @Mock
+ private Preference mPreference;
+ @Mock
+ private PreferenceScreen mScreen;
+ @Mock
+ private TelephonyManager mTelephonyManager;
+ @Mock
+ private UserManager mUserManager;
+ @Mock
+ private Fragment mFragment;
+
+ private Context mContext;
+ private ImeiInfoDualSimPreferenceController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+ doReturn(mUserManager).when(mContext).getSystemService(UserManager.class);
+ mController = new ImeiInfoDualSimPreferenceController(mContext, mFragment);
+ ReflectionHelpers.setField(mController, "mTelephonyManager", mTelephonyManager);
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
+ when(mPreference.getKey()).thenReturn(mController.getPreferenceKey());
+ }
+
+ @Test
+ public void getTitleForCdmaPhone_shouldReturnCdmaMultiSimString() {
+ ReflectionHelpers.setField(mController, "mIsMultiSim", true);
+
+ assertThat(mController.getTitleForCdmaPhone()).isEqualTo(mContext.getResources().getString(
+ R.string.meid_multi_sim_sim_slot_2));
+ }
+
+ @Test
+ public void getTitleForGsmPhone_shouldReturnGsmMultiSimString() {
+ ReflectionHelpers.setField(mController, "mIsMultiSim", true);
+
+ assertThat(mController.getTitleForGsmPhone()).isEqualTo(mContext.getResources().getString(
+ R.string.imei_multi_sim_slot_2));
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceControllerV2Test.java b/tests/robotests/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceControllerV2Test.java
new file mode 100644
index 00000000000..233e27e77a4
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceControllerV2Test.java
@@ -0,0 +1,105 @@
+/*
+ * 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.deviceinfo.imei;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.app.Fragment;
+import android.content.Context;
+import android.os.UserManager;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.telephony.TelephonyManager;
+
+import com.android.settings.R;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class ImeiInfoPreferenceControllerV2Test {
+
+ @Mock
+ private Preference mPreference;
+ @Mock
+ private PreferenceScreen mScreen;
+ @Mock
+ private TelephonyManager mTelephonyManager;
+ @Mock
+ private UserManager mUserManager;
+ @Mock
+ private Fragment mFragment;
+
+ private Context mContext;
+ private ImeiInfoPreferenceControllerV2 mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+ doReturn(mUserManager).when(mContext).getSystemService(UserManager.class);
+ mController = new ImeiInfoPreferenceControllerV2(mContext, mFragment);
+ ReflectionHelpers.setField(mController, "mTelephonyManager", mTelephonyManager);
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
+ when(mPreference.getKey()).thenReturn(mController.getPreferenceKey());
+ }
+
+ @Test
+ public void getTitleForCdmaPhone_noMultiSim_shouldReturnCdmaNoMultiSimString() {
+ ReflectionHelpers.setField(mController, "mIsMultiSim", false);
+
+ assertThat(mController.getTitleForCdmaPhone()).isEqualTo(mContext.getResources().getString(
+ R.string.status_meid_number));
+ }
+
+ @Test
+ public void getTitleForCdmaPhone_multiSim_shouldReturnCdmaMultiSimString() {
+ ReflectionHelpers.setField(mController, "mIsMultiSim", true);
+
+ assertThat(mController.getTitleForCdmaPhone()).isEqualTo(mContext.getResources().getString(
+ R.string.meid_multi_sim_sim_slot_1));
+ }
+
+ @Test
+ public void getTitleForGsmPhone_noMultiSim_shouldReturnGsmNoMultiSimString() {
+ ReflectionHelpers.setField(mController, "mIsMultiSim", false);
+
+ assertThat(mController.getTitleForGsmPhone()).isEqualTo(mContext.getResources().getString(
+ R.string.status_imei));
+ }
+
+ @Test
+ public void getTitleForGsmPhone_multiSim_shouldReturnGsmMultiSimString() {
+ ReflectionHelpers.setField(mController, "mIsMultiSim", true);
+
+ assertThat(mController.getTitleForGsmPhone()).isEqualTo(mContext.getResources().getString(
+ R.string.imei_multi_sim_slot_1));
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/simstatus/AbstractSimStatusPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/simstatus/AbstractSimStatusPreferenceControllerTest.java
new file mode 100644
index 00000000000..ee749d085d3
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/deviceinfo/simstatus/AbstractSimStatusPreferenceControllerTest.java
@@ -0,0 +1,113 @@
+/*
+ * 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.deviceinfo.simstatus;
+
+import static org.mockito.ArgumentMatchers.anyString;
+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.content.Context;
+import android.os.UserManager;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class AbstractSimStatusPreferenceControllerTest {
+
+ @Mock
+ private Preference mPreference;
+ @Mock
+ private PreferenceScreen mScreen;
+ @Mock
+ private UserManager mUserManager;
+ @Mock
+ private Fragment mFragment;
+
+ private Context mContext;
+ private AbstractSimStatusPreferenceControllerImpl mController;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+ doReturn(mUserManager).when(mContext).getSystemService(UserManager.class);
+ mController = new AbstractSimStatusPreferenceControllerImpl(mContext, mFragment);
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
+ when(mPreference.getKey()).thenReturn(mController.getPreferenceKey());
+ }
+
+ @Test
+ public void displayPreference_shouldSetTitleAndSummary() {
+ mController.displayPreference(mScreen);
+
+ verify(mPreference).setTitle(mController.getPreferenceTitle());
+ verify(mPreference).setSummary(anyString());
+ }
+
+ @Test
+ public void handlePreferenceTreeClick_shouldStartDialogFragment() {
+ when(mFragment.getChildFragmentManager()).thenReturn(
+ mock(FragmentManager.class, Answers.RETURNS_DEEP_STUBS));
+ when(mPreference.getTitle()).thenReturn("foo");
+ mController.displayPreference(mScreen);
+
+ mController.handlePreferenceTreeClick(mPreference);
+
+ verify(mFragment).getChildFragmentManager();
+ }
+
+ public class AbstractSimStatusPreferenceControllerImpl extends
+ AbstractSimStatusPreferenceController {
+
+ public AbstractSimStatusPreferenceControllerImpl(Context context, Fragment fragment) {
+ super(context, fragment);
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return "foo";
+ }
+
+ @Override
+ protected String getPreferenceTitle() {
+ return "bar";
+ }
+
+ @Override
+ protected int getSimSlot() {
+ return 0;
+ }
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogControllerTest.java
new file mode 100644
index 00000000000..73db81d9327
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogControllerTest.java
@@ -0,0 +1,202 @@
+/*
+ * 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.deviceinfo.simstatus;
+
+import static com.android.settings.deviceinfo.simstatus.SimStatusDialogController
+ .CELLULAR_NETWORK_TYPE_VALUE_ID;
+import static com.android.settings.deviceinfo.simstatus.SimStatusDialogController
+ .NETWORK_PROVIDER_VALUE_ID;
+import static com.android.settings.deviceinfo.simstatus.SimStatusDialogController
+ .OPERATOR_INFO_LABEL_ID;
+import static com.android.settings.deviceinfo.simstatus.SimStatusDialogController
+ .OPERATOR_INFO_VALUE_ID;
+import static com.android.settings.deviceinfo.simstatus.SimStatusDialogController
+ .PHONE_NUMBER_VALUE_ID;
+import static com.android.settings.deviceinfo.simstatus.SimStatusDialogController
+ .ROAMING_INFO_VALUE_ID;
+import static com.android.settings.deviceinfo.simstatus.SimStatusDialogController
+ .SERVICE_STATE_VALUE_ID;
+import static com.android.settings.deviceinfo.simstatus.SimStatusDialogController
+ .SIGNAL_STRENGTH_VALUE_ID;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.telephony.PhoneStateListener;
+import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
+import android.telephony.SubscriptionInfo;
+import android.telephony.TelephonyManager;
+
+import com.android.settings.R;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class SimStatusDialogControllerTest {
+
+ @Mock
+ private SimStatusDialogFragment mDialog;
+ @Mock
+ private TelephonyManager mTelephonyManager;
+ @Mock
+ private SubscriptionInfo mSubscriptionInfo;
+ @Mock
+ private ServiceState mServiceState;
+ @Mock
+ private PhoneStateListener mPhoneStateListener;
+ @Mock
+ private SignalStrength mSignalStrength;
+
+
+ private SimStatusDialogController mController;
+ private Context mContext;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ when(mDialog.getContext()).thenReturn(mContext);
+ mController = spy(
+ new SimStatusDialogController(mDialog, new Lifecycle(), 0 /* phone id */));
+ doReturn(mServiceState).when(mController).getCurrentServiceState();
+ doReturn(0).when(mController).getDbm(any());
+ doReturn(0).when(mController).getAsuLevel(any());
+ doReturn(mPhoneStateListener).when(mController).getPhoneStateListener();
+ doReturn("").when(mController).getPhoneNumber();
+ doReturn(mSignalStrength).when(mController).getSignalStrength();
+ ReflectionHelpers.setField(mController, "mTelephonyManager", mTelephonyManager);
+ ReflectionHelpers.setField(mController, "mSubscriptionInfo", mSubscriptionInfo);
+ }
+
+ @Test
+ public void initialize_updateNetworkProviderWithFoobarCarrier_shouldUpdateCarrierWithFoobar() {
+ final String carrierName = "foobar";
+ when(mServiceState.getOperatorAlphaLong()).thenReturn(carrierName);
+
+ mController.initialize();
+
+ verify(mDialog).setText(NETWORK_PROVIDER_VALUE_ID, carrierName);
+ }
+
+ @Test
+ public void initialize_updatePhoneNumberWith1111111111_shouldUpdatePhoneNumber() {
+ final String phoneNumber = "1111111111";
+ doReturn(phoneNumber).when(mController).getPhoneNumber();
+
+ mController.initialize();
+
+ verify(mDialog).setText(PHONE_NUMBER_VALUE_ID, phoneNumber);
+ }
+
+ @Test
+ public void initialize_updateLatestAreaInfoWithCdmaPhone_shouldRemoveOperatorInfoSetting() {
+ when(mTelephonyManager.getPhoneType()).thenReturn(TelephonyManager.PHONE_TYPE_CDMA);
+
+ mController.initialize();
+
+ verify(mDialog).removeSettingFromScreen(OPERATOR_INFO_LABEL_ID);
+ verify(mDialog).removeSettingFromScreen(OPERATOR_INFO_VALUE_ID);
+ }
+
+ @Test
+ public void initialize_updateServiceStateWithInService_shouldUpdateTextToBeCInService() {
+ when(mServiceState.getState()).thenReturn(ServiceState.STATE_IN_SERVICE);
+
+ mController.initialize();
+
+ final String inServiceText = mContext.getResources().getString(
+ R.string.radioInfo_service_in);
+ verify(mDialog).setText(SERVICE_STATE_VALUE_ID, inServiceText);
+ }
+
+ @Test
+ public void initialize_updateDataStateWithPowerOff_shouldUpdateSettingAndResetSignalStrength() {
+ when(mServiceState.getState()).thenReturn(ServiceState.STATE_POWER_OFF);
+
+ mController.initialize();
+
+ final String offServiceText = mContext.getResources().getString(
+ R.string.radioInfo_service_off);
+ verify(mDialog).setText(SERVICE_STATE_VALUE_ID, offServiceText);
+ verify(mDialog).setText(SIGNAL_STRENGTH_VALUE_ID, "0");
+ }
+
+ @Test
+ public void initialize_updateSignalStrengthWith50_shouldUpdateSignalStrengthTo50() {
+ final int signalDbm = 50;
+ final int signalAsu = 50;
+ doReturn(signalDbm).when(mController).getDbm(mSignalStrength);
+ doReturn(signalAsu).when(mController).getAsuLevel(mSignalStrength);
+
+ mController.initialize();
+
+ final String signalStrengthString = mContext.getResources().getString(
+ R.string.sim_signal_strength, signalDbm, signalAsu);
+ verify(mDialog).setText(SIGNAL_STRENGTH_VALUE_ID, signalStrengthString);
+ }
+
+ @Test
+ public void initialize_updateNetworkTypeWithEdge_shouldUpdateSettingToEdge() {
+ when(mTelephonyManager.getDataNetworkType(anyInt())).thenReturn(
+ TelephonyManager.NETWORK_TYPE_EDGE);
+
+ mController.initialize();
+
+ verify(mDialog).setText(CELLULAR_NETWORK_TYPE_VALUE_ID,
+ TelephonyManager.getNetworkTypeName(TelephonyManager.NETWORK_TYPE_EDGE));
+ }
+
+ @Test
+ public void initialize_updateRoamingStatusIsRoaming_shouldSetSettingToRoaming() {
+ when(mServiceState.getRoaming()).thenReturn(true);
+
+ mController.initialize();
+
+ final String roamingOnString = mContext.getResources().getString(
+ R.string.radioInfo_roaming_in);
+ verify(mDialog).setText(ROAMING_INFO_VALUE_ID, roamingOnString);
+ }
+
+ @Test
+ public void initialize_updateRoamingStatusNotRoaming_shouldSetSettingToRoamingOff() {
+ when(mServiceState.getRoaming()).thenReturn(false);
+
+ mController.initialize();
+
+ final String roamingOffString = mContext.getResources().getString(
+ R.string.radioInfo_roaming_not);
+ verify(mDialog).setText(ROAMING_INFO_VALUE_ID, roamingOffString);
+ }
+
+}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusDualSimPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusDualSimPreferenceControllerTest.java
new file mode 100644
index 00000000000..0845bfa95e9
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusDualSimPreferenceControllerTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.deviceinfo.simstatus;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.app.Fragment;
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.os.UserManager;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.telephony.TelephonyManager;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import com.google.common.truth.Truth;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class SimStatusDualSimPreferenceControllerTest {
+
+ @Mock
+ private Preference mPreference;
+ @Mock
+ private PreferenceScreen mScreen;
+ @Mock
+ private TelephonyManager mTelephonyManager;
+ @Mock
+ private UserManager mUserManager;
+ @Mock
+ private ConnectivityManager mConnectivityManager;
+ @Mock
+ private Fragment mFragment;
+
+ private Context mContext;
+ private SimStatusDualSimPreferenceController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+ doReturn(mUserManager).when(mContext).getSystemService(UserManager.class);
+ doReturn(mConnectivityManager).when(mContext).getSystemService(ConnectivityManager.class);
+ when(mUserManager.isAdminUser()).thenReturn(true);
+ when(mConnectivityManager.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)).thenReturn(
+ true);
+ mController = new SimStatusDualSimPreferenceController(mContext, mFragment);
+ ReflectionHelpers.setField(mController, "mTelephonyManager", mTelephonyManager);
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
+ when(mPreference.getKey()).thenReturn(mController.getPreferenceKey());
+ }
+
+ @Test
+ public void isAvailable_multiSim_shouldBeTrue() {
+ ReflectionHelpers.setField(mController, "mIsMultiSim", true);
+
+ Truth.assertThat(mController.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void isAvailable_notMultiSim_shouldBeFalse() {
+ ReflectionHelpers.setField(mController, "mIsMultiSim", false);
+
+ Truth.assertThat(mController.isAvailable()).isFalse();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceControllerV2Test.java b/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceControllerV2Test.java
new file mode 100644
index 00000000000..3282c3c85f7
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceControllerV2Test.java
@@ -0,0 +1,89 @@
+/*
+ * 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.deviceinfo.simstatus;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.app.Fragment;
+import android.content.Context;
+import android.os.UserManager;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+import android.telephony.TelephonyManager;
+
+import com.android.settings.R;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class SimStatusPreferenceControllerV2Test {
+
+ @Mock
+ private Preference mPreference;
+ @Mock
+ private PreferenceScreen mScreen;
+ @Mock
+ private TelephonyManager mTelephonyManager;
+ @Mock
+ private UserManager mUserManager;
+ @Mock
+ private Fragment mFragment;
+
+ private Context mContext;
+ private SimStatusPreferenceControllerV2 mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+ doReturn(mUserManager).when(mContext).getSystemService(UserManager.class);
+ mController = new SimStatusPreferenceControllerV2(mContext, mFragment);
+ ReflectionHelpers.setField(mController, "mTelephonyManager", mTelephonyManager);
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
+ when(mPreference.getKey()).thenReturn(mController.getPreferenceKey());
+ }
+
+ @Test
+ public void getPreferenceTitle_noMultiSim_shouldReturnSingleSimString() {
+ ReflectionHelpers.setField(mController, "mIsMultiSim", false);
+
+ assertThat(mController.getPreferenceTitle()).isEqualTo(mContext.getResources().getString(
+ R.string.sim_status_title));
+ }
+
+ @Test
+ public void getPreferenceTitle_multiSim_shouldReturnMultiSimString() {
+ ReflectionHelpers.setField(mController, "mIsMultiSim", true);
+
+ assertThat(mController.getPreferenceTitle()).isEqualTo(mContext.getResources().getString(
+ R.string.sim_status_title_sim_slot_1));
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/security/CredentialStoragePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/security/CredentialStoragePreferenceControllerTest.java
new file mode 100644
index 00000000000..71253d6a118
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/security/CredentialStoragePreferenceControllerTest.java
@@ -0,0 +1,72 @@
+/*
+ * 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.security;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.support.v7.preference.Preference;
+
+import com.android.settings.R;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowKeyStore;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION_O,
+ shadows = {
+ ShadowKeyStore.class
+ })
+public class CredentialStoragePreferenceControllerTest {
+
+ private Context mContext;
+ private CredentialStoragePreferenceController mController;
+ private Preference mPreference;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ mController = new CredentialStoragePreferenceController(mContext);
+ mPreference = new Preference(mContext);
+ }
+
+ @Test
+ public void updateState_hardwareBacked_showHardwareSummary() {
+ ShadowKeyStore.setHardwareBacked(true);
+
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.getSummary())
+ .isEqualTo(mContext.getText(R.string.credential_storage_type_hardware));
+ }
+
+ @Test
+ public void updateState_hardwareBacked_showSoftwareSummary() {
+ ShadowKeyStore.setHardwareBacked(false);
+
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.getSummary())
+ .isEqualTo(mContext.getText(R.string.credential_storage_type_software));
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/security/EncryptionAndCredentialTest.java b/tests/robotests/src/com/android/settings/security/EncryptionAndCredentialTest.java
index c87c96476ca..60e7dee6d21 100644
--- a/tests/robotests/src/com/android/settings/security/EncryptionAndCredentialTest.java
+++ b/tests/robotests/src/com/android/settings/security/EncryptionAndCredentialTest.java
@@ -16,8 +16,6 @@
package com.android.settings.security;
-import static android.app.admin.DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE;
-import static android.app.admin.DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE;
import static com.android.settings.security.EncryptionAndCredential.SEARCH_INDEX_DATA_PROVIDER;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
@@ -28,7 +26,6 @@ import android.os.UserManager;
import android.provider.SearchIndexableResource;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.settings.R;
import com.android.settings.TestConfig;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
@@ -71,16 +68,6 @@ public class EncryptionAndCredentialTest {
assertThat(fragment.getMetricsCategory()).isEqualTo(MetricsEvent.ENCRYPTION_AND_CREDENTIAL);
}
- // Search provider tests
- @Test
- public void getXmlResourcesToIndex_shouldReturnAllXmls() {
- final List index =
- SEARCH_INDEX_DATA_PROVIDER.getXmlResourcesToIndex(
- mContext, true /* enabled */);
-
- assertThat(index).hasSize(3);
- }
-
@Test
public void getNonIndexableKeys_pageIsDisabled_shouldReturnAllKeysAsNonIndexable() {
when(mUserManager.isAdminUser()).thenReturn(false);
@@ -96,32 +83,4 @@ public class EncryptionAndCredentialTest {
assertThat(keys).containsExactlyElementsIn(expectedKeys);
}
-
- @Test
- public void getNonIndexableKeys_deviceEncrypted_shouldReturnUnencryptedKeys() {
- when(mUserManager.isAdminUser()).thenReturn(true);
- when(mDevicePolicyManager.getStorageEncryptionStatus()).thenReturn(
- ENCRYPTION_STATUS_ACTIVE);
-
- final List expectedKeys = new ArrayList<>();
- expectedKeys.addAll(((BaseSearchIndexProvider) SEARCH_INDEX_DATA_PROVIDER)
- .getNonIndexableKeysFromXml(mContext, R.xml.security_settings_unencrypted));
- final List keys = SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext);
-
- assertThat(keys).containsExactlyElementsIn(expectedKeys);
- }
-
- @Test
- public void getNonIndexableKeys_deviceNotEncrypted_shouldReturnEncryptedKeys() {
- when(mUserManager.isAdminUser()).thenReturn(true);
- when(mDevicePolicyManager.getStorageEncryptionStatus())
- .thenReturn(ENCRYPTION_STATUS_INACTIVE);
-
- final List expectedKeys = new ArrayList<>();
- expectedKeys.addAll(((BaseSearchIndexProvider) SEARCH_INDEX_DATA_PROVIDER)
- .getNonIndexableKeysFromXml(mContext, R.xml.security_settings_encrypted));
- final List keys = SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext);
-
- assertThat(keys).containsExactlyElementsIn(expectedKeys);
- }
}
diff --git a/tests/robotests/src/com/android/settings/security/EncryptionStatusPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/security/EncryptionStatusPreferenceControllerTest.java
new file mode 100644
index 00000000000..d66d49538bd
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/security/EncryptionStatusPreferenceControllerTest.java
@@ -0,0 +1,90 @@
+/*
+ * 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.security;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.support.v7.preference.Preference;
+
+import com.android.settings.R;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
+import com.android.settings.testutils.shadow.ShadowUserManager;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION_O,
+ shadows = {
+ ShadowUserManager.class,
+ ShadowLockPatternUtils.class
+ })
+public class EncryptionStatusPreferenceControllerTest {
+
+ private Context mContext;
+ private EncryptionStatusPreferenceController mController;
+ private Preference mPreference;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ mController = new EncryptionStatusPreferenceController(mContext);
+ mPreference = new Preference(mContext);
+ }
+
+ @Test
+ public void isAvailable_admin_true() {
+ ShadowUserManager.getShadow().setIsAdminUser(true);
+
+ assertThat(mController.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void isAvailable_notAdmin_false() {
+ ShadowUserManager.getShadow().setIsAdminUser(false);
+
+ assertThat(mController.isAvailable()).isFalse();
+ }
+
+ @Test
+ public void updateSummary_encrypted_shouldSayEncrypted() {
+ ShadowLockPatternUtils.setDeviceEncryptionEnabled(true);
+
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.getFragment()).isNull();
+ assertThat(mPreference.getSummary())
+ .isEqualTo(mContext.getText(R.string.crypt_keeper_encrypted_summary));
+ }
+
+ @Test
+ public void updateSummary_unencrypted_shouldHasEncryptionFragment() {
+ ShadowLockPatternUtils.setDeviceEncryptionEnabled(false);
+
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.getSummary())
+ .isEqualTo(mContext.getText(R.string.summary_placeholder));
+ assertThat(mPreference.getFragment()).isEqualTo(CryptKeeperSettings.class.getName());
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/security/RestrictedEncryptionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/security/RestrictedEncryptionPreferenceControllerTest.java
new file mode 100644
index 00000000000..8db679542e7
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/security/RestrictedEncryptionPreferenceControllerTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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.security;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.os.UserManager;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowUserManager;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION_O,
+ shadows = {
+ ShadowUserManager.class
+ })
+public class RestrictedEncryptionPreferenceControllerTest {
+
+ private Context mContext;
+ private ShadowUserManager mUserManager;
+ private CredentialStoragePreferenceController mCredentialStoragePreferenceController;
+ private InstallCredentialsPreferenceController mInstallCredentialsPreferenceController;
+ private ResetCredentialsPreferenceController mResetCredentialsPreferenceController;
+ private UserCredentialsPreferenceController mUserCredentialsPreferenceController;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ mCredentialStoragePreferenceController =
+ new CredentialStoragePreferenceController(mContext);
+ mInstallCredentialsPreferenceController =
+ new InstallCredentialsPreferenceController(mContext);
+ mResetCredentialsPreferenceController =
+ new ResetCredentialsPreferenceController(mContext, new Lifecycle());
+ mUserCredentialsPreferenceController =
+ new UserCredentialsPreferenceController(mContext);
+ mUserManager = ShadowUserManager.getShadow();
+ }
+
+ @After
+ public void tearDown() {
+ mUserManager.reset();
+ }
+
+ @Test
+ public void isAvailable_noRestriction_shouldReturnTrue() {
+ assertThat(mCredentialStoragePreferenceController.isAvailable()).isTrue();
+ assertThat(mInstallCredentialsPreferenceController.isAvailable()).isTrue();
+ assertThat(mResetCredentialsPreferenceController.isAvailable()).isTrue();
+ assertThat(mUserCredentialsPreferenceController.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void isAvailable_hasRestriction_shouldReturnFalse() {
+ mUserManager.addBaseUserRestriction(UserManager.DISALLOW_CONFIG_CREDENTIALS);
+
+ assertThat(mCredentialStoragePreferenceController.isAvailable()).isFalse();
+ assertThat(mInstallCredentialsPreferenceController.isAvailable()).isFalse();
+ assertThat(mResetCredentialsPreferenceController.isAvailable()).isFalse();
+ assertThat(mUserCredentialsPreferenceController.isAvailable()).isFalse();
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/SecuritySettingsTest.java b/tests/robotests/src/com/android/settings/security/SecuritySettingsTest.java
similarity index 92%
rename from tests/robotests/src/com/android/settings/SecuritySettingsTest.java
rename to tests/robotests/src/com/android/settings/security/SecuritySettingsTest.java
index fc3478d25cc..827dd647761 100644
--- a/tests/robotests/src/com/android/settings/SecuritySettingsTest.java
+++ b/tests/robotests/src/com/android/settings/security/SecuritySettingsTest.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.settings;
+package com.android.settings.security;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.anyInt;
@@ -35,6 +35,8 @@ import android.support.v7.preference.PreferenceGroup;
import android.support.v7.preference.PreferenceScreen;
import com.android.internal.widget.LockPatternUtils;
+import com.android.settings.R;
+import com.android.settings.TestConfig;
import com.android.settings.dashboard.SummaryLoader;
import com.android.settings.notification.LockScreenNotificationPreferenceController;
import com.android.settings.testutils.FakeFeatureFactory;
@@ -56,11 +58,10 @@ import org.robolectric.util.ReflectionHelpers;
import java.util.List;
@RunWith(SettingsRobolectricTestRunner.class)
-@Config(
- manifest = TestConfig.MANIFEST_PATH,
- sdk = TestConfig.SDK_VERSION,
- shadows = {ShadowLockPatternUtils.class}
-)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION_O,
+ shadows = {
+ ShadowLockPatternUtils.class
+ })
public class SecuritySettingsTest {
@@ -104,7 +105,7 @@ public class SecuritySettingsTest {
public void testSummaryProvider_noFpFeature_shouldSetSummaryWithNoFingerprint() {
final FingerprintManager fpm = mock(FingerprintManager.class);
when(mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT))
- .thenReturn(false);
+ .thenReturn(false);
mSummaryProvider.setListening(true);
@@ -115,7 +116,7 @@ public class SecuritySettingsTest {
public void testSummaryProvider_noFpHardware_shouldSetSummaryWithNoFingerprint() {
final FingerprintManager fpm = mock(FingerprintManager.class);
when(mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT))
- .thenReturn(true);
+ .thenReturn(true);
// Cast to Object to workaround a robolectric casting bug
when((Object) mContext.getSystemService(FingerprintManager.class)).thenReturn(fpm);
@@ -147,7 +148,7 @@ public class SecuritySettingsTest {
securitySettings.initTrustAgentPreference(screen, 2);
verify(preference).setSummary(context.getResources().getQuantityString(
- R.plurals.manage_trust_agents_summary_on, 2, 2));
+ R.plurals.manage_trust_agents_summary_on, 2, 2));
}
@Test
@@ -155,13 +156,13 @@ public class SecuritySettingsTest {
final Preference preference = mock(Preference.class);
final PreferenceGroup group = mock(PreferenceGroup.class);
when(group.findPreference(SecuritySettings.KEY_LOCKSCREEN_PREFERENCES))
- .thenReturn(preference);
+ .thenReturn(preference);
final LockScreenNotificationPreferenceController controller =
- mock(LockScreenNotificationPreferenceController.class);
+ mock(LockScreenNotificationPreferenceController.class);
final SecuritySettings securitySettings = new SecuritySettings();
ReflectionHelpers.setField(securitySettings,
- "mLockScreenNotificationPreferenceController", controller);
+ "mLockScreenNotificationPreferenceController", controller);
when(controller.getSummaryResource()).thenReturn(1234);
securitySettings.setLockscreenPreferencesSummary(group);
diff --git a/tests/robotests/src/com/android/settings/trustagent/TrustAgentFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/security/trustagent/TrustAgentManagerTest.java
similarity index 77%
rename from tests/robotests/src/com/android/settings/trustagent/TrustAgentFeatureProviderImplTest.java
rename to tests/robotests/src/com/android/settings/security/trustagent/TrustAgentManagerTest.java
index b1812539794..ed616be22a0 100644
--- a/tests/robotests/src/com/android/settings/trustagent/TrustAgentFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/security/trustagent/TrustAgentManagerTest.java
@@ -14,14 +14,17 @@
* limitations under the License.
*/
-package com.android.settings.trustagent;
+package com.android.settings.security.trustagent;
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.when;
+
+import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
-import android.content.pm.PackageManager;
-import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
import org.junit.Before;
import org.junit.Test;
@@ -30,51 +33,48 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.annotation.Config;
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
@RunWith(SettingsRobolectricTestRunner.class)
-@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
-public class TrustAgentFeatureProviderImplTest {
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION_O)
+public class TrustAgentManagerTest {
private static final String CANNED_PACKAGE_NAME = "com.test.package";
@Mock
private PackageManager mPackageManager;
- private TrustAgentManagerImpl mImpl;
+ private TrustAgentManager mTrustAgentManager;
@Before
public void setUp() throws PackageManager.NameNotFoundException {
MockitoAnnotations.initMocks(this);
- mImpl = new TrustAgentManagerImpl();
+ mTrustAgentManager = new TrustAgentManager();
}
@Test
public void shouldProvideTrust_doesProvideTrustWithPermission() {
when(mPackageManager.checkPermission(TrustAgentManager.PERMISSION_PROVIDE_AGENT,
- CANNED_PACKAGE_NAME)).thenReturn(PackageManager.PERMISSION_GRANTED);
+ CANNED_PACKAGE_NAME)).thenReturn(PackageManager.PERMISSION_GRANTED);
ServiceInfo serviceInfo = new ServiceInfo();
serviceInfo.packageName = CANNED_PACKAGE_NAME;
ResolveInfo resolveInfo = new ResolveInfo();
resolveInfo.serviceInfo = serviceInfo;
- assertTrue(mImpl.shouldProvideTrust(resolveInfo, mPackageManager));
+ assertThat(mTrustAgentManager.shouldProvideTrust(resolveInfo, mPackageManager))
+ .isTrue();
}
@Test
public void shouldProvideTrust_doesNotProvideTrustWithoutPermission() {
when(mPackageManager.checkPermission(TrustAgentManager.PERMISSION_PROVIDE_AGENT,
- CANNED_PACKAGE_NAME)).thenReturn(PackageManager.PERMISSION_DENIED);
+ CANNED_PACKAGE_NAME)).thenReturn(PackageManager.PERMISSION_DENIED);
ServiceInfo serviceInfo = new ServiceInfo();
serviceInfo.packageName = CANNED_PACKAGE_NAME;
ResolveInfo resolveInfo = new ResolveInfo();
resolveInfo.serviceInfo = serviceInfo;
- assertFalse(mImpl.shouldProvideTrust(resolveInfo, mPackageManager));
+ assertThat(mTrustAgentManager.shouldProvideTrust(resolveInfo, mPackageManager))
+ .isFalse();
}
}
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowKeyStore.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowKeyStore.java
new file mode 100644
index 00000000000..c025a33a2f5
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowKeyStore.java
@@ -0,0 +1,43 @@
+/*
+ * 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.testutils.shadow;
+
+import android.security.KeyStore;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.annotation.Resetter;
+
+@Implements(KeyStore.class)
+public class ShadowKeyStore {
+
+ private static boolean sIsHardwareBacked;
+
+ @Resetter
+ public void reset() {
+ sIsHardwareBacked = false;
+ }
+
+ @Implementation
+ public boolean isHardwareBacked() {
+ return sIsHardwareBacked;
+ }
+
+ public static void setHardwareBacked(boolean hardwareBacked) {
+ sIsHardwareBacked = hardwareBacked;
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowLockPatternUtils.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowLockPatternUtils.java
index 3182a935d5d..e7f6be5f743 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowLockPatternUtils.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowLockPatternUtils.java
@@ -27,6 +27,8 @@ import org.robolectric.annotation.Implements;
public class ShadowLockPatternUtils {
private int mPasswordQuality = 1;
+ private static boolean sDeviceEncryptionEnabled;
+
@Implementation
public boolean isSecure(int id) {
return true;
@@ -42,6 +44,15 @@ public class ShadowLockPatternUtils {
return mPasswordQuality;
}
+ @Implementation
+ public static boolean isDeviceEncryptionEnabled() {
+ return sDeviceEncryptionEnabled;
+ }
+
+ public static void setDeviceEncryptionEnabled(boolean deviceEncryptionEnabled) {
+ sDeviceEncryptionEnabled = deviceEncryptionEnabled;
+ }
+
// Non-Android accessor.
public int getPasswordQuality() {
return mPasswordQuality;
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java
index 888fa366216..f24837dfa72 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java
@@ -19,30 +19,36 @@ package com.android.settings.testutils.shadow;
import android.annotation.UserIdInt;
import android.content.Context;
import android.content.pm.UserInfo;
+import android.os.UserHandle;
import android.os.UserManager;
import android.util.SparseArray;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
+import org.robolectric.annotation.Resetter;
import org.robolectric.shadow.api.Shadow;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-/**
- * This class provides the API 24 implementation of UserManager.get(Context).
- */
@Implements(UserManager.class)
public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager {
private SparseArray mUserInfos = new SparseArray<>();
private boolean mAdminUser;
+ private List mRestrictions = new ArrayList<>();
public void setIsAdminUser(boolean isAdminUser) {
mAdminUser = isAdminUser;
}
+ @Resetter
+ public void reset() {
+ mRestrictions.clear();
+ }
+
@Implementation
public boolean isAdminUser() {
return mAdminUser;
@@ -72,6 +78,15 @@ public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager
return (UserManager) context.getSystemService(Context.USER_SERVICE);
}
+ @Implementation
+ public boolean hasBaseUserRestriction(String restrictionKey, UserHandle userHandle) {
+ return mRestrictions.contains(restrictionKey);
+ }
+
+ public void addBaseUserRestriction(String restriction) {
+ mRestrictions.add(restriction);
+ }
+
public static ShadowUserManager getShadow() {
return (ShadowUserManager) Shadow.extract(
RuntimeEnvironment.application.getSystemService(UserManager.class));
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowWifiManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowWifiManager.java
new file mode 100644
index 00000000000..e5304daf1bf
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowWifiManager.java
@@ -0,0 +1,49 @@
+/*
+ * 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.testutils.shadow;
+
+import static org.robolectric.RuntimeEnvironment.application;
+
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
+
+import org.robolectric.annotation.HiddenApi;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.shadow.api.Shadow;
+
+@Implements(WifiManager.class)
+public class ShadowWifiManager extends org.robolectric.shadows.ShadowWifiManager {
+
+ public WifiConfiguration savedWifiConfig;
+
+ @HiddenApi // @SystemApi
+ @Implementation
+ public void connect(WifiConfiguration config, WifiManager.ActionListener listener) {
+ savedWifiConfig = config;
+ }
+
+ @HiddenApi
+ @Implementation
+ public void save(WifiConfiguration config, WifiManager.ActionListener listener) {
+ savedWifiConfig = config;
+ }
+
+ public static ShadowWifiManager get() {
+ return Shadow.extract(application.getSystemService(WifiManager.class));
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/widget/WorkOnlyCategoryPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/widget/PreferenceCategoryControllerTest.java
similarity index 91%
rename from tests/robotests/src/com/android/settings/widget/WorkOnlyCategoryPreferenceControllerTest.java
rename to tests/robotests/src/com/android/settings/widget/PreferenceCategoryControllerTest.java
index 9c7e8fc5ede..23aa378dad1 100644
--- a/tests/robotests/src/com/android/settings/widget/WorkOnlyCategoryPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/widget/PreferenceCategoryControllerTest.java
@@ -37,17 +37,17 @@ import java.util.List;
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
-public class WorkOnlyCategoryPreferenceControllerTest {
+public class PreferenceCategoryControllerTest {
private Context mContext;
- private WorkOnlyCategoryPreferenceController mController;
+ private PreferenceCategoryController mController;
private List mChildren;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mChildren = new ArrayList<>();
- mController = new WorkOnlyCategoryPreferenceController(mContext, "pref_key", mChildren);
+ mController = new PreferenceCategoryController(mContext, "pref_key", mChildren);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/wifi/WifiDialogActivityTest.java b/tests/robotests/src/com/android/settings/wifi/WifiDialogActivityTest.java
new file mode 100644
index 00000000000..40c147862c4
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/wifi/WifiDialogActivityTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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.wifi;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+
+import android.content.Intent;
+import android.net.wifi.WifiConfiguration;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.SettingsShadowResources;
+import com.android.settings.testutils.shadow.ShadowConnectivityManager;
+import com.android.settings.testutils.shadow.ShadowWifiManager;
+
+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.annotation.Config;
+import org.robolectric.shadows.ShadowAlertDialog;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(
+ manifest = TestConfig.MANIFEST_PATH,
+ sdk = TestConfig.SDK_VERSION_O,
+ shadows = {
+ SettingsShadowResources.class,
+ SettingsShadowResources.SettingsShadowTheme.class,
+ ShadowConnectivityManager.class,
+ ShadowWifiManager.class
+ }
+)
+public class WifiDialogActivityTest {
+
+ public static final String AP1_SSID = "\"ap1\"";
+ @Mock
+ private WifiConfigController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ WifiConfiguration wifiConfig = new WifiConfiguration();
+ wifiConfig.SSID = AP1_SSID;
+ doReturn(wifiConfig).when(mController).getConfig();
+ }
+
+ @Test
+ public void onSubmit_shouldConnectToNetwork() {
+ WifiDialogActivity activity = Robolectric.setupActivity(WifiDialogActivity.class);
+ WifiDialog dialog = (WifiDialog) ShadowAlertDialog.getLatestAlertDialog();
+ assertThat(dialog).isNotNull();
+
+ ReflectionHelpers.setField(dialog, "mController", mController);
+
+ activity.onSubmit(dialog);
+
+ assertThat(ShadowWifiManager.get().savedWifiConfig.SSID).isEqualTo(AP1_SSID);
+ }
+
+ @Test
+ public void onSubmit_shouldNotConnectToNetwork_whenConnectForCallerIsFalse() {
+ WifiDialogActivity activity =
+ Robolectric.buildActivity(
+ WifiDialogActivity.class,
+ new Intent().putExtra(WifiDialogActivity.KEY_CONNECT_FOR_CALLER, false))
+ .setup().get();
+ WifiDialog dialog = (WifiDialog) ShadowAlertDialog.getLatestAlertDialog();
+ assertThat(dialog).isNotNull();
+
+ ReflectionHelpers.setField(dialog, "mController", mController);
+
+ activity.onSubmit(dialog);
+
+ assertThat(ShadowWifiManager.get().savedWifiConfig).isNull();
+ }
+}