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

Commit 17f16f6b authored by Christine Franks's avatar Christine Franks Committed by Android (Google) Code Review
Browse files

Merge "Require password to FR in carrier demo mode"

parents d0de9e85 d7713c9d
Loading
Loading
Loading
Loading
+16 −2
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AuthenticatorDescription;
import android.app.Activity;
import android.app.FragmentManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -46,6 +47,7 @@ import android.widget.ScrollView;
import android.widget.TextView;

import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.widget.CarrierDemoPasswordDialogFragment;
import com.android.settingslib.RestrictedLockUtils;

import java.util.List;
@@ -62,7 +64,8 @@ import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
 *
 * This is the initial screen.
 */
public class MasterClear extends OptionsMenuFragment {
public class MasterClear extends OptionsMenuFragment
        implements CarrierDemoPasswordDialogFragment.Callback {
    private static final String TAG = "MasterClear";

    private static final int KEYGUARD_REQUEST = 55;
@@ -127,12 +130,23 @@ public class MasterClear extends OptionsMenuFragment {
    private final Button.OnClickListener mInitiateListener = new Button.OnClickListener() {

        public void onClick(View v) {
            if (!runKeyguardConfirmation(KEYGUARD_REQUEST)) {
            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 */);
                }
            } else if (!runKeyguardConfirmation(KEYGUARD_REQUEST)) {
                showFinalConfirmation();
            }
        }
    };

    @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
+144 −0
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();
    }
}