Home | History | Annotate | Download | only in phone
      1 /*
      2  * Copyright (C) 2008 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.phone;
     18 
     19 import android.content.Context;
     20 import android.os.AsyncResult;
     21 import android.os.Bundle;
     22 import android.os.Handler;
     23 import android.os.Message;
     24 import android.os.PersistableBundle;
     25 import android.telephony.CarrierConfigManager;
     26 import android.text.Editable;
     27 import android.text.Spannable;
     28 import android.text.TextUtils;
     29 import android.text.TextWatcher;
     30 import android.text.method.DialerKeyListener;
     31 import android.util.Log;
     32 import android.view.KeyEvent;
     33 import android.view.View;
     34 import android.widget.Button;
     35 import android.widget.EditText;
     36 import android.widget.LinearLayout;
     37 import android.widget.TextView;
     38 
     39 import com.android.internal.telephony.Phone;
     40 
     41 /**
     42  * "SIM network unlock" PIN entry screen.
     43  *
     44  * @see PhoneGlobals.EVENT_SIM_NETWORK_LOCKED
     45  *
     46  * TODO: This UI should be part of the lock screen, not the
     47  * phone app (see bug 1804111).
     48  */
     49 public class IccNetworkDepersonalizationPanel extends IccPanel {
     50 
     51     /**
     52      * Tracks whether there is an instance of the network depersonalization dialog showing or not.
     53      * Ensures only a single instance of the dialog is visible.
     54      */
     55     private static boolean sShowingDialog = false;
     56 
     57     //debug constants
     58     private static final boolean DBG = false;
     59 
     60     //events
     61     private static final int EVENT_ICC_NTWRK_DEPERSONALIZATION_RESULT = 100;
     62 
     63     private Phone mPhone;
     64 
     65     //UI elements
     66     private EditText     mPinEntry;
     67     private LinearLayout mEntryPanel;
     68     private LinearLayout mStatusPanel;
     69     private TextView     mStatusText;
     70 
     71     private Button       mUnlockButton;
     72     private Button       mDismissButton;
     73 
     74     /**
     75      * Shows the network depersonalization dialog, but only if it is not already visible.
     76      */
     77     public static void showDialog() {
     78         if (sShowingDialog) {
     79             Log.i(TAG, "[IccNetworkDepersonalizationPanel] - showDialog; skipped already shown.");
     80             return;
     81         }
     82         Log.i(TAG, "[IccNetworkDepersonalizationPanel] - showDialog; showing dialog.");
     83         sShowingDialog = true;
     84         IccNetworkDepersonalizationPanel ndpPanel =
     85                 new IccNetworkDepersonalizationPanel(PhoneGlobals.getInstance());
     86         ndpPanel.show();
     87     }
     88 
     89     //private textwatcher to control text entry.
     90     private TextWatcher mPinEntryWatcher = new TextWatcher() {
     91         public void beforeTextChanged(CharSequence buffer, int start, int olen, int nlen) {
     92         }
     93 
     94         public void onTextChanged(CharSequence buffer, int start, int olen, int nlen) {
     95         }
     96 
     97         public void afterTextChanged(Editable buffer) {
     98             if (SpecialCharSequenceMgr.handleChars(
     99                     getContext(), buffer.toString())) {
    100                 mPinEntry.getText().clear();
    101             }
    102         }
    103     };
    104 
    105     //handler for unlock function results
    106     private Handler mHandler = new Handler() {
    107         public void handleMessage(Message msg) {
    108             if (msg.what == EVENT_ICC_NTWRK_DEPERSONALIZATION_RESULT) {
    109                 AsyncResult res = (AsyncResult) msg.obj;
    110                 if (res.exception != null) {
    111                     if (DBG) log("network depersonalization request failure.");
    112                     indicateError();
    113                     postDelayed(new Runnable() {
    114                                     public void run() {
    115                                         hideAlert();
    116                                         mPinEntry.getText().clear();
    117                                         mPinEntry.requestFocus();
    118                                     }
    119                                 }, 3000);
    120                 } else {
    121                     if (DBG) log("network depersonalization success.");
    122                     indicateSuccess();
    123                     postDelayed(new Runnable() {
    124                                     public void run() {
    125                                         dismiss();
    126                                     }
    127                                 }, 3000);
    128                 }
    129             }
    130         }
    131     };
    132 
    133     //constructor
    134     public IccNetworkDepersonalizationPanel(Context context) {
    135         super(context);
    136     }
    137 
    138     @Override
    139     protected void onCreate(Bundle icicle) {
    140         super.onCreate(icicle);
    141         setContentView(R.layout.sim_ndp);
    142 
    143         // PIN entry text field
    144         mPinEntry = (EditText) findViewById(R.id.pin_entry);
    145         mPinEntry.setKeyListener(DialerKeyListener.getInstance());
    146         mPinEntry.setOnClickListener(mUnlockListener);
    147 
    148         // Attach the textwatcher
    149         CharSequence text = mPinEntry.getText();
    150         Spannable span = (Spannable) text;
    151         span.setSpan(mPinEntryWatcher, 0, text.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
    152 
    153         mEntryPanel = (LinearLayout) findViewById(R.id.entry_panel);
    154 
    155         mUnlockButton = (Button) findViewById(R.id.ndp_unlock);
    156         mUnlockButton.setOnClickListener(mUnlockListener);
    157 
    158         // The "Dismiss" button is present in some (but not all) products,
    159         // based on the "KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL" variable.
    160         mDismissButton = (Button) findViewById(R.id.ndp_dismiss);
    161         PersistableBundle carrierConfig = PhoneGlobals.getInstance().getCarrierConfig();
    162         if (carrierConfig.getBoolean(
    163                 CarrierConfigManager.KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL)) {
    164             if (DBG) log("Enabling 'Dismiss' button...");
    165             mDismissButton.setVisibility(View.VISIBLE);
    166             mDismissButton.setOnClickListener(mDismissListener);
    167         } else {
    168             if (DBG) log("Removing 'Dismiss' button...");
    169             mDismissButton.setVisibility(View.GONE);
    170         }
    171 
    172         //status panel is used since we're having problems with the alert dialog.
    173         mStatusPanel = (LinearLayout) findViewById(R.id.status_panel);
    174         mStatusText = (TextView) findViewById(R.id.status_text);
    175 
    176         mPhone = PhoneGlobals.getPhone();
    177     }
    178 
    179     @Override
    180     protected void onStart() {
    181         super.onStart();
    182     }
    183 
    184     @Override
    185     public void onStop() {
    186         super.onStop();
    187         Log.i(TAG, "[IccNetworkDepersonalizationPanel] - showDialog; hiding dialog.");
    188         sShowingDialog = false;
    189     }
    190 
    191     //Mirrors IccPinUnlockPanel.onKeyDown().
    192     public boolean onKeyDown(int keyCode, KeyEvent event) {
    193         if (keyCode == KeyEvent.KEYCODE_BACK) {
    194             return true;
    195         }
    196 
    197         return super.onKeyDown(keyCode, event);
    198     }
    199 
    200     View.OnClickListener mUnlockListener = new View.OnClickListener() {
    201         public void onClick(View v) {
    202             String pin = mPinEntry.getText().toString();
    203 
    204             if (TextUtils.isEmpty(pin)) {
    205                 return;
    206             }
    207 
    208             if (DBG) log("requesting network depersonalization with code " + pin);
    209             mPhone.getIccCard().supplyNetworkDepersonalization(pin,
    210                     Message.obtain(mHandler, EVENT_ICC_NTWRK_DEPERSONALIZATION_RESULT));
    211             indicateBusy();
    212         }
    213     };
    214 
    215     private void indicateBusy() {
    216         mStatusText.setText(R.string.requesting_unlock);
    217         mEntryPanel.setVisibility(View.GONE);
    218         mStatusPanel.setVisibility(View.VISIBLE);
    219     }
    220 
    221     private void indicateError() {
    222         mStatusText.setText(R.string.unlock_failed);
    223         mEntryPanel.setVisibility(View.GONE);
    224         mStatusPanel.setVisibility(View.VISIBLE);
    225     }
    226 
    227     private void indicateSuccess() {
    228         mStatusText.setText(R.string.unlock_success);
    229         mEntryPanel.setVisibility(View.GONE);
    230         mStatusPanel.setVisibility(View.VISIBLE);
    231     }
    232 
    233     private void hideAlert() {
    234         mEntryPanel.setVisibility(View.VISIBLE);
    235         mStatusPanel.setVisibility(View.GONE);
    236     }
    237 
    238     View.OnClickListener mDismissListener = new View.OnClickListener() {
    239             public void onClick(View v) {
    240                 if (DBG) log("mDismissListener: skipping depersonalization...");
    241                 dismiss();
    242             }
    243         };
    244 
    245     private void log(String msg) {
    246         Log.v(TAG, "[IccNetworkDepersonalizationPanel] " + msg);
    247     }
    248 }
    249