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 */ showDialog(Phone phone)77 public static void showDialog(Phone phone) { 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(), phone); 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 IccNetworkDepersonalizationPanel(Context context)134 public IccNetworkDepersonalizationPanel(Context context) { 135 super(context); 136 mPhone = PhoneGlobals.getPhone(); 137 } 138 139 //constructor IccNetworkDepersonalizationPanel(Context context, Phone phone)140 public IccNetworkDepersonalizationPanel(Context context, Phone phone) { 141 super(context); 142 mPhone = phone == null ? PhoneGlobals.getPhone() : phone; 143 } 144 145 @Override onCreate(Bundle icicle)146 protected void onCreate(Bundle icicle) { 147 super.onCreate(icicle); 148 setContentView(R.layout.sim_ndp); 149 150 // PIN entry text field 151 mPinEntry = (EditText) findViewById(R.id.pin_entry); 152 mPinEntry.setKeyListener(DialerKeyListener.getInstance()); 153 mPinEntry.setOnClickListener(mUnlockListener); 154 155 // Attach the textwatcher 156 CharSequence text = mPinEntry.getText(); 157 Spannable span = (Spannable) text; 158 span.setSpan(mPinEntryWatcher, 0, text.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE); 159 160 mEntryPanel = (LinearLayout) findViewById(R.id.entry_panel); 161 162 mUnlockButton = (Button) findViewById(R.id.ndp_unlock); 163 mUnlockButton.setOnClickListener(mUnlockListener); 164 165 // The "Dismiss" button is present in some (but not all) products, 166 // based on the "KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL" variable. 167 mDismissButton = (Button) findViewById(R.id.ndp_dismiss); 168 PersistableBundle carrierConfig = PhoneGlobals.getInstance().getCarrierConfig(); 169 if (carrierConfig.getBoolean( 170 CarrierConfigManager.KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL)) { 171 if (DBG) log("Enabling 'Dismiss' button..."); 172 mDismissButton.setVisibility(View.VISIBLE); 173 mDismissButton.setOnClickListener(mDismissListener); 174 } else { 175 if (DBG) log("Removing 'Dismiss' button..."); 176 mDismissButton.setVisibility(View.GONE); 177 } 178 179 //status panel is used since we're having problems with the alert dialog. 180 mStatusPanel = (LinearLayout) findViewById(R.id.status_panel); 181 mStatusText = (TextView) findViewById(R.id.status_text); 182 } 183 184 @Override onStart()185 protected void onStart() { 186 super.onStart(); 187 } 188 189 @Override onStop()190 public void onStop() { 191 super.onStop(); 192 Log.i(TAG, "[IccNetworkDepersonalizationPanel] - showDialog; hiding dialog."); 193 sShowingDialog = false; 194 } 195 196 //Mirrors IccPinUnlockPanel.onKeyDown(). onKeyDown(int keyCode, KeyEvent event)197 public boolean onKeyDown(int keyCode, KeyEvent event) { 198 if (keyCode == KeyEvent.KEYCODE_BACK) { 199 return true; 200 } 201 202 return super.onKeyDown(keyCode, event); 203 } 204 205 View.OnClickListener mUnlockListener = new View.OnClickListener() { 206 public void onClick(View v) { 207 String pin = mPinEntry.getText().toString(); 208 209 if (TextUtils.isEmpty(pin)) { 210 return; 211 } 212 213 if (DBG) log("requesting network depersonalization with code " + pin); 214 mPhone.getIccCard().supplyNetworkDepersonalization(pin, 215 Message.obtain(mHandler, EVENT_ICC_NTWRK_DEPERSONALIZATION_RESULT)); 216 indicateBusy(); 217 } 218 }; 219 indicateBusy()220 private void indicateBusy() { 221 mStatusText.setText(R.string.requesting_unlock); 222 mEntryPanel.setVisibility(View.GONE); 223 mStatusPanel.setVisibility(View.VISIBLE); 224 } 225 indicateError()226 private void indicateError() { 227 mStatusText.setText(R.string.unlock_failed); 228 mEntryPanel.setVisibility(View.GONE); 229 mStatusPanel.setVisibility(View.VISIBLE); 230 } 231 indicateSuccess()232 private void indicateSuccess() { 233 mStatusText.setText(R.string.unlock_success); 234 mEntryPanel.setVisibility(View.GONE); 235 mStatusPanel.setVisibility(View.VISIBLE); 236 } 237 hideAlert()238 private void hideAlert() { 239 mEntryPanel.setVisibility(View.VISIBLE); 240 mStatusPanel.setVisibility(View.GONE); 241 } 242 243 View.OnClickListener mDismissListener = new View.OnClickListener() { 244 public void onClick(View v) { 245 if (DBG) log("mDismissListener: skipping depersonalization..."); 246 dismiss(); 247 } 248 }; 249 log(String msg)250 private void log(String msg) { 251 Log.v(TAG, "[IccNetworkDepersonalizationPanel] " + msg); 252 } 253 } 254