/* * Copyright (C) 2008 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.phone; import android.content.Context; import android.os.AsyncResult; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.os.PersistableBundle; import android.telephony.CarrierConfigManager; import android.telephony.TelephonyManager; import android.text.Editable; import android.text.Spannable; import android.text.TextUtils; import android.text.TextWatcher; import android.text.method.DialerKeyListener; import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.TextView; import com.android.internal.telephony.Phone; import com.android.internal.telephony.uicc.IccCardApplicationStatus.PersoSubState; /** * "SIM network unlock" PIN entry screen. * * @see PhoneGlobals.EVENT_SIM_NETWORK_LOCKED * * TODO: This UI should be part of the lock screen, not the * phone app (see bug 1804111). */ public class IccNetworkDepersonalizationPanel extends IccPanel { /** * Tracks whether there is an instance of the network depersonalization dialog showing or not. * Ensures only a single instance of the dialog is visible. */ private static boolean [] sShowingDialog = new boolean[TelephonyManager.getDefault().getSupportedModemCount()]; //debug constants private static final boolean DBG = false; //events private static final int EVENT_ICC_NTWRK_DEPERSONALIZATION_RESULT = 100; private Phone mPhone; private int mPersoSubtype; private static IccNetworkDepersonalizationPanel [] sNdpPanel = new IccNetworkDepersonalizationPanel[ TelephonyManager.getDefault().getSupportedModemCount()]; //UI elements private EditText mPinEntry; private LinearLayout mEntryPanel; private LinearLayout mStatusPanel; private TextView mPersoSubtypeText; private PersoSubState mPersoSubState; private TextView mStatusText; private Button mUnlockButton; private Button mDismissButton; enum statusType { ENTRY, IN_PROGRESS, ERROR, SUCCESS } /** * Shows the network depersonalization dialog, but only if it is not already visible. */ public static void showDialog(Phone phone, int subType) { int phoneId = phone == null ? 0: phone.getPhoneId(); if (phoneId >= sShowingDialog.length) { Log.e(TAG, "[IccNetworkDepersonalizationPanel] showDialog; invalid phoneId" + phoneId); return; } if (sShowingDialog[phoneId]) { Log.i(TAG, "[IccNetworkDepersonalizationPanel] - showDialog; skipped already shown."); return; } Log.i(TAG, "[IccNetworkDepersonalizationPanel] - showDialog; showing dialog."); sShowingDialog[phoneId] = true; sNdpPanel[phoneId] = new IccNetworkDepersonalizationPanel(PhoneGlobals.getInstance(), phone, subType); sNdpPanel[phoneId].show(); } public static void dialogDismiss(int phoneId) { if (phoneId >= sShowingDialog.length) { Log.e(TAG, "[IccNetworkDepersonalizationPanel] - dismiss; invalid phoneId " + phoneId); return; } if (sNdpPanel[phoneId] != null && sShowingDialog[phoneId]) { sNdpPanel[phoneId].dismiss(); } } //private textwatcher to control text entry. private TextWatcher mPinEntryWatcher = new TextWatcher() { public void beforeTextChanged(CharSequence buffer, int start, int olen, int nlen) { } public void onTextChanged(CharSequence buffer, int start, int olen, int nlen) { } public void afterTextChanged(Editable buffer) { if (SpecialCharSequenceMgr.handleChars( getContext(), buffer.toString())) { mPinEntry.getText().clear(); } } }; //handler for unlock function results private Handler mHandler = new Handler() { public void handleMessage(Message msg) { if (msg.what == EVENT_ICC_NTWRK_DEPERSONALIZATION_RESULT) { AsyncResult res = (AsyncResult) msg.obj; if (res.exception != null) { if (DBG) log("network depersonalization request failure."); displayStatus(statusType.ERROR.name()); postDelayed(new Runnable() { public void run() { hideAlert(); mPinEntry.getText().clear(); mPinEntry.requestFocus(); } }, 3000); } else { if (DBG) log("network depersonalization success."); displayStatus(statusType.SUCCESS.name()); postDelayed(new Runnable() { public void run() { dismiss(); } }, 3000); } } } }; //constructor public IccNetworkDepersonalizationPanel(Context context) { super(context); mPhone = PhoneGlobals.getPhone(); mPersoSubtype = PersoSubState.PERSOSUBSTATE_SIM_NETWORK.ordinal(); } //constructor public IccNetworkDepersonalizationPanel(Context context, Phone phone, int subtype) { super(context); mPhone = phone == null ? PhoneGlobals.getPhone() : phone; mPersoSubtype = subtype; } @Override protected void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.sim_ndp); // PIN entry text field mPinEntry = (EditText) findViewById(R.id.pin_entry); mPinEntry.setKeyListener(DialerKeyListener.getInstance()); mPinEntry.setOnClickListener(mUnlockListener); // Attach the textwatcher CharSequence text = mPinEntry.getText(); Spannable span = (Spannable) text; span.setSpan(mPinEntryWatcher, 0, text.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE); mEntryPanel = (LinearLayout) findViewById(R.id.entry_panel); mPersoSubtypeText = (TextView) findViewById(R.id.perso_subtype_text); displayStatus(statusType.ENTRY.name()); mUnlockButton = (Button) findViewById(R.id.ndp_unlock); mUnlockButton.setOnClickListener(mUnlockListener); // The "Dismiss" button is present in some (but not all) products, // based on the "KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL" variable. mDismissButton = (Button) findViewById(R.id.ndp_dismiss); PersistableBundle carrierConfig = PhoneGlobals.getInstance().getCarrierConfig(); if (carrierConfig.getBoolean( CarrierConfigManager.KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL)) { if (DBG) log("Enabling 'Dismiss' button..."); mDismissButton.setVisibility(View.VISIBLE); mDismissButton.setOnClickListener(mDismissListener); } else { if (DBG) log("Removing 'Dismiss' button..."); mDismissButton.setVisibility(View.GONE); } //status panel is used since we're having problems with the alert dialog. mStatusPanel = (LinearLayout) findViewById(R.id.status_panel); mStatusText = (TextView) findViewById(R.id.status_text); } @Override protected void onStart() { super.onStart(); } @Override public void onStop() { super.onStop(); Log.i(TAG, "[IccNetworkDepersonalizationPanel] - showDialog; hiding dialog."); int phoneId = mPhone == null ? 0 : mPhone.getPhoneId(); if (phoneId >= sShowingDialog.length) { Log.e(TAG, "[IccNetworkDepersonalizationPanel] - onStop; invalid phoneId " + phoneId); return; } sShowingDialog[phoneId] = false; } //Mirrors IccPinUnlockPanel.onKeyDown(). public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { return true; } return super.onKeyDown(keyCode, event); } View.OnClickListener mUnlockListener = new View.OnClickListener() { public void onClick(View v) { String pin = mPinEntry.getText().toString(); if (TextUtils.isEmpty(pin)) { return; } log("Requesting De-Personalization for subtype " + mPersoSubtype); try { mPhone.getIccCard().supplySimDepersonalization(mPersoSubState,pin, Message.obtain(mHandler, EVENT_ICC_NTWRK_DEPERSONALIZATION_RESULT)); } catch (NullPointerException ex) { log("NullPointerException @supplySimDepersonalization" + ex); } displayStatus(statusType.IN_PROGRESS.name()); } }; private void displayStatus(String type) { int label = 0; mPersoSubState = PersoSubState.values()[mPersoSubtype]; log("displayStatus mPersoSubState: " +mPersoSubState.name() +"type: " +type); label = getContext().getResources().getIdentifier(mPersoSubState.name() + "_" + type, "string", "android"); if (label == 0) { log ("Unable to get the PersoSubType string"); return; } if(!PersoSubState.isPersoLocked(mPersoSubState)) { log ("Unsupported Perso Subtype :" + mPersoSubState.name()); return; } if (type == statusType.ENTRY.name()) { String displayText = getContext().getString(label); mPersoSubtypeText.setText(displayText); } else { mStatusText.setText(label); mEntryPanel.setVisibility(View.GONE); mStatusPanel.setVisibility(View.VISIBLE); } } private void hideAlert() { mEntryPanel.setVisibility(View.VISIBLE); mStatusPanel.setVisibility(View.GONE); } View.OnClickListener mDismissListener = new View.OnClickListener() { public void onClick(View v) { if (DBG) log("mDismissListener: skipping depersonalization..."); dismiss(); } }; private void log(String msg) { Log.d(TAG, "[IccNetworkDepersonalizationPanel] " + msg); } }