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