Move logic for FR in demo mode out of Settings
Bug: 62712426
Test: make \
ROBOTEST_FILTER="(MasterClearTest|FactoryResetPreferenceControllerTest
|UtilsTest)" \
RunSettingsRoboTests -j100
Change-Id: I5e287c3d4a6a7050bda78187c52aec19e90b50bc
diff --git a/src/com/android/settings/MasterClear.java b/src/com/android/settings/MasterClear.java
index fe0111b..1bdd6f4 100644
--- a/src/com/android/settings/MasterClear.java
+++ b/src/com/android/settings/MasterClear.java
@@ -22,7 +22,7 @@
import android.accounts.AccountManager;
import android.accounts.AuthenticatorDescription;
import android.app.Activity;
-import android.app.FragmentManager;
+import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -38,6 +38,7 @@
import android.provider.Settings;
import android.support.annotation.VisibleForTesting;
import android.telephony.euicc.EuiccManager;
+import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -54,7 +55,6 @@
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.password.ConfirmLockPattern;
-import com.android.settings.widget.CarrierDemoPasswordDialogFragment;
import com.android.settingslib.RestrictedLockUtils;
import java.util.List;
@@ -69,8 +69,7 @@
*
* This is the initial screen.
*/
-public class MasterClear extends OptionsMenuFragment
- implements CarrierDemoPasswordDialogFragment.Callback {
+public class MasterClear extends OptionsMenuFragment {
private static final String TAG = "MasterClear";
private static final int KEYGUARD_REQUEST = 55;
@@ -137,15 +136,21 @@
* If the user clicks to begin the reset sequence, we next require a
* keyguard confirmation if the user has currently enabled one. If there
* is no keyguard available, we simply go to the final confirmation prompt.
+ *
+ * If the user is in demo mode, route to the demo mode app for confirmation.
*/
- private final Button.OnClickListener mInitiateListener = new Button.OnClickListener() {
+ @VisibleForTesting
+ protected final Button.OnClickListener mInitiateListener = new Button.OnClickListener() {
- public void onClick(View v) {
- if ( Utils.isCarrierDemoUser(v.getContext())) {
- // Require the carrier password before displaying the final confirmation.
- final FragmentManager fm = getChildFragmentManager();
- if (fm != null && !fm.isDestroyed()) {
- new CarrierDemoPasswordDialogFragment().show(fm, null /* tag */);
+ public void onClick(View view) {
+ final Context context = view.getContext();
+ if (Utils.isDemoUser(context)) {
+ final String packageName = Utils.getDemoModePackageName(context);
+ if (!TextUtils.isEmpty(packageName)) {
+ final Intent requestFactoryReset = new Intent()
+ .setPackage(packageName)
+ .setAction(Intent.ACTION_FACTORY_RESET);
+ context.startActivity(requestFactoryReset);
}
} else if (!runKeyguardConfirmation(KEYGUARD_REQUEST)) {
showFinalConfirmation();
@@ -153,11 +158,6 @@
}
};
- @Override
- public void onPasswordVerified() {
- showFinalConfirmation();
- }
-
/**
* In its initial state, the activity presents a button for the user to
* click in order to initiate a confirmation sequence. This method is
@@ -395,7 +395,7 @@
final UserManager um = UserManager.get(context);
final boolean disallow = !um.isAdminUser() || RestrictedLockUtils.hasBaseUserRestriction(
context, UserManager.DISALLOW_FACTORY_RESET, UserHandle.myUserId());
- if (disallow && !Utils.isCarrierDemoUser(context)) {
+ if (disallow && !Utils.isDemoUser(context)) {
return inflater.inflate(R.layout.master_clear_disallowed_screen, null);
} else if (admin != null) {
View view = inflater.inflate(R.layout.admin_support_details_empty_view, null);
diff --git a/src/com/android/settings/MasterClearConfirm.java b/src/com/android/settings/MasterClearConfirm.java
index 7a85dbe..39bf01a 100644
--- a/src/com/android/settings/MasterClearConfirm.java
+++ b/src/com/android/settings/MasterClearConfirm.java
@@ -24,7 +24,6 @@
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
-import android.provider.Settings;
import android.service.oemlock.OemLockManager;
import android.service.persistentdata.PersistentDataBlockManager;
import android.view.LayoutInflater;
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index 440debc..9b3414c 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -77,6 +77,7 @@
import android.provider.ContactsContract.Profile;
import android.provider.ContactsContract.RawContacts;
import android.provider.Settings;
+import android.provider.Settings.Secure;
import android.support.annotation.StringRes;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceGroup;
@@ -1240,14 +1241,13 @@
}
}
- public static boolean isCarrierDemoUser(Context context) {
- final String carrierDemoModeSetting =
- context.getString(com.android.internal.R.string.config_carrierDemoModeSetting);
- return UserManager.isDeviceInDemoMode(context)
- && getUserManager(context).isDemoUser()
- && !TextUtils.isEmpty(carrierDemoModeSetting)
- && (Settings.Secure.getInt(context.getContentResolver(),
- carrierDemoModeSetting, 0) == 1);
+ public static boolean isDemoUser(Context context) {
+ return UserManager.isDeviceInDemoMode(context) && getUserManager(context).isDemoUser();
+ }
+
+ public static String getDemoModePackageName(Context context) {
+ return context.getResources().getString(
+ com.android.internal.R.string.config_demoModePackage);
}
/**
diff --git a/src/com/android/settings/system/FactoryResetPreferenceController.java b/src/com/android/settings/system/FactoryResetPreferenceController.java
index 69eef2a..7e9773b 100644
--- a/src/com/android/settings/system/FactoryResetPreferenceController.java
+++ b/src/com/android/settings/system/FactoryResetPreferenceController.java
@@ -47,7 +47,7 @@
/** Hide "Factory reset" settings for secondary users, except demo users. */
@Override
public boolean isAvailable() {
- return mUm.isAdminUser() || Utils.isCarrierDemoUser(mContext);
+ return mUm.isAdminUser() || Utils.isDemoUser(mContext);
}
@Override
diff --git a/src/com/android/settings/widget/CarrierDemoPasswordDialogFragment.java b/src/com/android/settings/widget/CarrierDemoPasswordDialogFragment.java
deleted file mode 100644
index 8482b9f..0000000
--- a/src/com/android/settings/widget/CarrierDemoPasswordDialogFragment.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.widget;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.app.Fragment;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.res.TypedArray;
-import android.os.Bundle;
-import android.text.Editable;
-import android.text.InputType;
-import android.text.TextUtils;
-import android.text.TextWatcher;
-import android.util.Log;
-import android.view.inputmethod.InputMethodManager;
-import android.widget.Button;
-import android.widget.EditText;
-
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.internal.util.HexDump;
-import com.android.settings.R;
-
-import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-
-public class CarrierDemoPasswordDialogFragment extends InstrumentedDialogFragment {
-
- private static final String TAG = "CarrierDemoPasswordDF";
-
- private MessageDigest mMessageDigest;
-
- public CarrierDemoPasswordDialogFragment() {
- try {
- mMessageDigest = MessageDigest.getInstance("SHA-256");
- } catch (NoSuchAlgorithmException e) {
- Log.e(TAG, "Unable to verify demo mode password", e);
- }
- }
-
- @Override
- public Dialog onCreateDialog(Bundle savedInstanceState) {
- final AlertDialog dialog = new AlertDialog.Builder(getContext())
- .setPositiveButton(R.string.retail_demo_reset_next,
- new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- final Fragment parentFragment = getParentFragment();
- if (parentFragment instanceof Callback
- && which == DialogInterface.BUTTON_POSITIVE) {
- ((Callback) parentFragment).onPasswordVerified();
- }
- }
- })
- .setNegativeButton(android.R.string.cancel, null)
- .setMessage(R.string.retail_demo_reset_message)
- .setTitle(R.string.retail_demo_reset_title)
- .create();
-
- final Context context = dialog.getContext();
- final EditText passwordField = new EditText(context);
- passwordField.setSingleLine();
- passwordField.setInputType(InputType.TYPE_CLASS_TEXT
- | InputType.TYPE_TEXT_VARIATION_PASSWORD);
- passwordField.addTextChangedListener(new TextWatcher() {
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- // no-op
- }
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
- verifyPassword(dialog, passwordField.getText().toString());
- }
-
- @Override
- public void afterTextChanged(Editable s) {
- // no-op
- }
- });
-
- dialog.setOnShowListener(new DialogInterface.OnShowListener() {
- @Override
- public void onShow(DialogInterface dialogInterface) {
- verifyPassword(dialog, passwordField.getText().toString());
- passwordField.requestFocus();
- final InputMethodManager imm = (InputMethodManager) getContext().getSystemService(
- Context.INPUT_METHOD_SERVICE);
- imm.showSoftInput(passwordField, InputMethodManager.SHOW_IMPLICIT);
- }
- });
- dialog.setCanceledOnTouchOutside(false);
-
- final TypedArray a = context.obtainStyledAttributes(
- new int[] { android.R.attr.dialogPreferredPadding });
- final int sidePadding = a.getDimensionPixelSize(0, 0);
- dialog.setView(passwordField, sidePadding, 0, sidePadding, 0);
- a.recycle();
-
- return dialog;
- }
-
- private void verifyPassword(AlertDialog dialog, String input) {
- final Button positiveButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
- if (mMessageDigest == null || TextUtils.isEmpty(input)) {
- positiveButton.setEnabled(false);
- return;
- }
- final String passwordHash = getContext().getString(
- com.android.internal.R.string.config_carrierDemoModePassword);
- if (passwordHash == null || TextUtils.isEmpty(passwordHash)) {
- // This device does not support carrier demo mode.
- return;
- }
- final byte[] inputDigest = mMessageDigest.digest(input.getBytes());
- final String inputHash = HexDump.toHexString(inputDigest, 0, inputDigest.length, false);
- positiveButton.setEnabled(TextUtils.equals(passwordHash, inputHash));
- }
-
- @Override
- public int getMetricsCategory() {
- return MetricsEvent.CARRIER_DEMO_MODE_PASSWORD;
- }
-
- public interface Callback {
- void onPasswordVerified();
- }
-}
diff --git a/tests/robotests/src/com/android/settings/MasterClearTest.java b/tests/robotests/src/com/android/settings/MasterClearTest.java
index 8e8578f..edad391 100644
--- a/tests/robotests/src/com/android/settings/MasterClearTest.java
+++ b/tests/robotests/src/com/android/settings/MasterClearTest.java
@@ -27,6 +27,7 @@
import android.app.Activity;
import android.app.Fragment;
import android.content.ContentResolver;
+import android.content.Intent;
import android.os.Bundle;
import android.provider.Settings;
import android.view.LayoutInflater;
@@ -36,6 +37,8 @@
import android.widget.ScrollView;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.SettingsShadowResources;
+import com.android.settings.testutils.shadow.ShadowUtils;
import org.junit.Before;
import org.junit.Test;
@@ -43,11 +46,10 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
+import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowActivity;
-
-
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class MasterClearTest {
@@ -167,6 +169,22 @@
assertThat(mMasterClear.hasReachedBottom(mScrollView)).isTrue();
}
+ @Test
+ @Config(shadows = { ShadowUtils.class, SettingsShadowResources.class })
+ public void testInitiateMasterClear_inDemoMode_sendsIntent() {
+ SettingsShadowResources.overrideResource(
+ com.android.internal.R.string.config_demoModePackage, "package");
+
+ ShadowUtils.setIsDemoUser(true);
+
+ mMasterClear.mInitiateListener.onClick(
+ mContentView.findViewById(R.id.initiate_master_clear));
+ final Intent intent = mShadowActivity.getNextStartedActivity();
+ assertThat(Intent.ACTION_FACTORY_RESET).isEqualTo(intent.getAction());
+ final String packageName = Utils.getDemoModePackageName(RuntimeEnvironment.application);
+ assertThat(packageName).isEqualTo(intent.getPackage());
+ }
+
private void initScrollView(int height, int scrollY, int childBottom) {
when(mScrollView.getHeight()).thenReturn(height);
when(mScrollView.getScrollY()).thenReturn(scrollY);
diff --git a/tests/robotests/src/com/android/settings/UtilsTest.java b/tests/robotests/src/com/android/settings/UtilsTest.java
index d85464d..7531ce1 100644
--- a/tests/robotests/src/com/android/settings/UtilsTest.java
+++ b/tests/robotests/src/com/android/settings/UtilsTest.java
@@ -16,15 +16,18 @@
import android.net.Network;
import android.net.wifi.WifiManager;
import android.os.Bundle;
+import android.os.UserManager;
import android.os.storage.DiskInfo;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
+import android.provider.Settings;
import android.text.SpannableStringBuilder;
import android.text.format.DateUtils;
import android.text.style.TtsSpan;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settings.testutils.shadow.ShadowSecureSettings;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/tests/robotests/src/com/android/settings/system/FactoryResetPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/system/FactoryResetPreferenceControllerTest.java
index b9c34f3..7310ae0 100644
--- a/tests/robotests/src/com/android/settings/system/FactoryResetPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/system/FactoryResetPreferenceControllerTest.java
@@ -22,7 +22,6 @@
import android.accounts.AccountManager;
import android.content.Context;
import android.os.UserManager;
-import android.provider.Settings;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
@@ -76,21 +75,16 @@
@Config(shadows = { ShadowSecureSettings.class, ShadowUtils.class })
public void isAvailable_nonSystemUser() {
when(mUserManager.isAdminUser()).thenReturn(false);
- ShadowUtils.setIsCarrierDemoUser(false);
+ ShadowUtils.setIsDemoUser(false);
assertThat(mController.isAvailable()).isFalse();
}
@Test
@Config(shadows = { ShadowSecureSettings.class, ShadowUtils.class })
- public void isAvailable_carrierDemoUser() {
+ public void isAvailable_demoUser() {
when(mUserManager.isAdminUser()).thenReturn(false);
- ShadowUtils.setIsCarrierDemoUser(true);
-
- final String carrierDemoModeSetting = "carrier_demo_mode";
- when(mContext.getString(com.android.internal.R.string.config_carrierDemoModeSetting))
- .thenReturn(carrierDemoModeSetting);
- Settings.Secure.putInt(null, carrierDemoModeSetting, 1);
+ ShadowUtils.setIsDemoUser(true);
assertThat(mController.isAvailable()).isTrue();
}
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUtils.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUtils.java
index 854392f..82f53a2 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUtils.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUtils.java
@@ -16,6 +16,7 @@
package com.android.settings.testutils.shadow;
+import android.content.ComponentName;
import android.content.Context;
import com.android.settings.Utils;
@@ -28,8 +29,8 @@
public class ShadowUtils {
private static IFingerprintManager sFingerprintManager = null;
- private static boolean sIsCarrierDemoUser;
private static boolean sIsUserAMonkey;
+ private static boolean sIsDemoUser;
@Implementation
public static int enforceSameOwner(Context context, int userId) {
@@ -47,8 +48,8 @@
public static void reset() {
sFingerprintManager = null;
- sIsCarrierDemoUser = false;
sIsUserAMonkey = false;
+ sIsDemoUser = false;
}
@Implementation
@@ -56,8 +57,8 @@
return true;
}
- public static void setIsCarrierDemoUser(boolean isCarrierDemoUser) {
- sIsCarrierDemoUser = isCarrierDemoUser;
+ public static void setIsDemoUser(boolean isDemoUser) {
+ sIsDemoUser = isDemoUser;
}
public static void setIsUserAMonkey(boolean isUserAMonkey) {
@@ -66,8 +67,8 @@
@Implementation
- public static boolean isCarrierDemoUser(Context context) {
- return sIsCarrierDemoUser;
+ public static boolean isDemoUser(Context context) {
+ return sIsDemoUser;
}
/**