Home | History | Annotate | Download | only in widget
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.settings.widget;
     18 
     19 import android.app.AlertDialog;
     20 import android.app.Dialog;
     21 import android.app.Fragment;
     22 import android.content.Context;
     23 import android.content.DialogInterface;
     24 import android.content.res.TypedArray;
     25 import android.os.Bundle;
     26 import android.text.Editable;
     27 import android.text.InputType;
     28 import android.text.TextUtils;
     29 import android.text.TextWatcher;
     30 import android.util.Log;
     31 import android.view.inputmethod.InputMethodManager;
     32 import android.widget.Button;
     33 import android.widget.EditText;
     34 
     35 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
     36 import com.android.internal.util.HexDump;
     37 import com.android.settings.R;
     38 
     39 import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
     40 import java.security.MessageDigest;
     41 import java.security.NoSuchAlgorithmException;
     42 
     43 public class CarrierDemoPasswordDialogFragment extends InstrumentedDialogFragment {
     44 
     45     private static final String TAG = "CarrierDemoPasswordDF";
     46 
     47     private MessageDigest mMessageDigest;
     48 
     49     public CarrierDemoPasswordDialogFragment() {
     50         try {
     51             mMessageDigest = MessageDigest.getInstance("SHA-256");
     52         } catch (NoSuchAlgorithmException e) {
     53             Log.e(TAG, "Unable to verify demo mode password", e);
     54         }
     55     }
     56 
     57     @Override
     58     public Dialog onCreateDialog(Bundle savedInstanceState) {
     59         final AlertDialog dialog = new AlertDialog.Builder(getContext())
     60                 .setPositiveButton(R.string.retail_demo_reset_next,
     61                         new DialogInterface.OnClickListener() {
     62                     @Override
     63                     public void onClick(DialogInterface dialog, int which) {
     64                         final Fragment parentFragment = getParentFragment();
     65                         if (parentFragment instanceof Callback
     66                                 && which == DialogInterface.BUTTON_POSITIVE) {
     67                             ((Callback) parentFragment).onPasswordVerified();
     68                         }
     69                     }
     70                 })
     71                 .setNegativeButton(android.R.string.cancel, null)
     72                 .setMessage(R.string.retail_demo_reset_message)
     73                 .setTitle(R.string.retail_demo_reset_title)
     74                 .create();
     75 
     76         final Context context = dialog.getContext();
     77         final EditText passwordField = new EditText(context);
     78         passwordField.setSingleLine();
     79         passwordField.setInputType(InputType.TYPE_CLASS_TEXT
     80                 | InputType.TYPE_TEXT_VARIATION_PASSWORD);
     81         passwordField.addTextChangedListener(new TextWatcher() {
     82             @Override
     83             public void beforeTextChanged(CharSequence s, int start, int count, int after) {
     84                 // no-op
     85             }
     86 
     87             @Override
     88             public void onTextChanged(CharSequence s, int start, int before, int count) {
     89                 verifyPassword(dialog, passwordField.getText().toString());
     90             }
     91 
     92             @Override
     93             public void afterTextChanged(Editable s) {
     94                 // no-op
     95             }
     96         });
     97 
     98         dialog.setOnShowListener(new DialogInterface.OnShowListener() {
     99             @Override
    100             public void onShow(DialogInterface dialogInterface) {
    101                 verifyPassword(dialog, passwordField.getText().toString());
    102                 passwordField.requestFocus();
    103                 final InputMethodManager imm = (InputMethodManager) getContext().getSystemService(
    104                         Context.INPUT_METHOD_SERVICE);
    105                 imm.showSoftInput(passwordField, InputMethodManager.SHOW_IMPLICIT);
    106             }
    107         });
    108         dialog.setCanceledOnTouchOutside(false);
    109 
    110         final TypedArray a = context.obtainStyledAttributes(
    111                 new int[] { android.R.attr.dialogPreferredPadding });
    112         final int sidePadding = a.getDimensionPixelSize(0, 0);
    113         dialog.setView(passwordField, sidePadding, 0, sidePadding, 0);
    114         a.recycle();
    115 
    116         return dialog;
    117     }
    118 
    119     private void verifyPassword(AlertDialog dialog, String input) {
    120         final Button positiveButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
    121         if (mMessageDigest == null || TextUtils.isEmpty(input)) {
    122             positiveButton.setEnabled(false);
    123             return;
    124         }
    125         final String passwordHash = getContext().getString(
    126                 com.android.internal.R.string.config_carrierDemoModePassword);
    127         if (passwordHash == null || TextUtils.isEmpty(passwordHash)) {
    128             // This device does not support carrier demo mode.
    129             return;
    130         }
    131         final byte[] inputDigest = mMessageDigest.digest(input.getBytes());
    132         final String inputHash = HexDump.toHexString(inputDigest, 0, inputDigest.length, false);
    133         positiveButton.setEnabled(TextUtils.equals(passwordHash, inputHash));
    134     }
    135 
    136     @Override
    137     public int getMetricsCategory() {
    138         return MetricsEvent.CARRIER_DEMO_MODE_PASSWORD;
    139     }
    140 
    141     public interface Callback {
    142         void onPasswordVerified();
    143     }
    144 }
    145