Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a09eb383 authored by Christine Franks's avatar Christine Franks
Browse files

Move logic for FR in demo mode out of Settings

Bug: 62712426
Test: make \
ROBOTEST_FILTER="(MasterClearTest|FactoryResetPreferenceControllerTest
|UtilsTest)" \
RunSettingsRoboTests -j100
Change-Id: I5e287c3d4a6a7050bda78187c52aec19e90b50bc
parent e4c9b716
Loading
Loading
Loading
Loading
+18 −18
Original line number Diff line number Diff line
@@ -22,7 +22,7 @@ import android.accounts.Account;
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.os.UserManager;
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 android.widget.TextView;
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 @@ import java.util.List;
 *
 * 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 @@ public class MasterClear extends OptionsMenuFragment
     * 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() {

        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 */);
    @VisibleForTesting
    protected final Button.OnClickListener mInitiateListener = new Button.OnClickListener() {

        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 @@ public class MasterClear extends OptionsMenuFragment
        }
    };

    @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 @@ public class MasterClear extends OptionsMenuFragment
        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);
+0 −1
Original line number Diff line number Diff line
@@ -24,7 +24,6 @@ import android.os.AsyncTask;
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;
+8 −8
Original line number Diff line number Diff line
@@ -74,6 +74,7 @@ import android.provider.ContactsContract.Data;
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;
@@ -1271,14 +1272,13 @@ public final class Utils extends com.android.settingslib.Utils {
        }
    }

    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);
    }

    /**
+1 −1
Original line number Diff line number Diff line
@@ -45,7 +45,7 @@ public class FactoryResetPreferenceController extends PreferenceController {
    /** 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
+0 −144
Original line number Diff line number Diff line
/*
 * 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();
    }
}
Loading