• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.telephony.SubscriptionInfo;
27 import android.telephony.SubscriptionManager;
28 import android.telephony.TelephonyManager;
29 import android.text.Editable;
30 import android.text.Spannable;
31 import android.text.TextUtils;
32 import android.text.TextWatcher;
33 import android.text.method.DialerKeyListener;
34 import android.util.Log;
35 import android.view.KeyEvent;
36 import android.view.View;
37 import android.widget.Button;
38 import android.widget.EditText;
39 import android.widget.LinearLayout;
40 import android.widget.TextView;
41 
42 import com.android.internal.telephony.Phone;
43 import com.android.internal.telephony.uicc.IccCardApplicationStatus.PersoSubState;
44 
45 /**
46  * "SIM network unlock" PIN entry screen.
47  *
48  * @see PhoneGlobals.EVENT_SIM_NETWORK_LOCKED
49  *
50  * TODO: This UI should be part of the lock screen, not the
51  * phone app (see bug 1804111).
52  */
53 public class IccNetworkDepersonalizationPanel extends IccPanel {
54 
55     /**
56      * Tracks whether there is an instance of the network depersonalization dialog showing or not.
57      * Ensures only a single instance of the dialog is visible.
58      */
59     private static boolean [] sShowingDialog =
60             new boolean[TelephonyManager.getDefault().getSupportedModemCount()];
61 
62     //debug constants
63     private static final boolean DBG = false;
64 
65     //events
66     private static final int EVENT_ICC_NTWRK_DEPERSONALIZATION_RESULT = 100;
67 
68     private Phone mPhone;
69     private int mPersoSubtype;
70     private static IccNetworkDepersonalizationPanel [] sNdpPanel =
71             new IccNetworkDepersonalizationPanel[
72                     TelephonyManager.getDefault().getSupportedModemCount()];
73     private SubscriptionInfo mSir;
74 
75     //UI elements
76     private EditText     mPinEntry;
77     private LinearLayout mEntryPanel;
78     private LinearLayout mStatusPanel;
79     private TextView     mPersoSubtypeText;
80     private PersoSubState mPersoSubState;
81     private TextView     mPhoneIdText;
82     private TextView     mStatusText;
83 
84     private Button       mUnlockButton;
85     private Button       mDismissButton;
86 
87     enum statusType {
88         ENTRY,
89         IN_PROGRESS,
90         ERROR,
91         SUCCESS
92     }
93 
94     /**
95      * Shows the network depersonalization dialog, but only if it is not already visible.
96      */
showDialog(Phone phone, int subType)97     public static void showDialog(Phone phone, int subType) {
98         int phoneId = phone == null ? 0: phone.getPhoneId();
99         if (phoneId >= sShowingDialog.length) {
100             Log.e(TAG, "[IccNetworkDepersonalizationPanel] showDialog; invalid phoneId" + phoneId);
101             return;
102         }
103         if (sShowingDialog[phoneId]) {
104             Log.i(TAG, "[IccNetworkDepersonalizationPanel] - showDialog; skipped already shown.");
105             return;
106         }
107         Log.i(TAG, "[IccNetworkDepersonalizationPanel] - showDialog; showing dialog.");
108         sShowingDialog[phoneId] = true;
109         sNdpPanel[phoneId] = new IccNetworkDepersonalizationPanel(PhoneGlobals.getInstance(),
110                 phone, subType);
111         sNdpPanel[phoneId].show();
112     }
113 
dialogDismiss(int phoneId)114     public static void dialogDismiss(int phoneId) {
115         if (phoneId >= sShowingDialog.length) {
116             Log.e(TAG, "[IccNetworkDepersonalizationPanel] - dismiss; invalid phoneId " + phoneId);
117             return;
118         }
119         if (sNdpPanel[phoneId] != null && sShowingDialog[phoneId]) {
120             sNdpPanel[phoneId].dismiss();
121         }
122     }
123 
124     //private textwatcher to control text entry.
125     private TextWatcher mPinEntryWatcher = new TextWatcher() {
126         public void beforeTextChanged(CharSequence buffer, int start, int olen, int nlen) {
127         }
128 
129         public void onTextChanged(CharSequence buffer, int start, int olen, int nlen) {
130         }
131 
132         public void afterTextChanged(Editable buffer) {
133             if (SpecialCharSequenceMgr.handleChars(
134                     getContext(), buffer.toString())) {
135                 mPinEntry.getText().clear();
136             }
137         }
138     };
139 
140     //handler for unlock function results
141     private Handler mHandler = new Handler() {
142         public void handleMessage(Message msg) {
143             if (msg.what == EVENT_ICC_NTWRK_DEPERSONALIZATION_RESULT) {
144                 AsyncResult res = (AsyncResult) msg.obj;
145                 if (res.exception != null) {
146                     if (DBG) log("network depersonalization request failure.");
147                     displayStatus(statusType.ERROR.name());
148                     postDelayed(new Runnable() {
149                         public void run() {
150                             hideAlert();
151                             mPinEntry.getText().clear();
152                             mPinEntry.requestFocus();
153                         }
154                     }, 3000);
155                 } else {
156                     if (DBG) log("network depersonalization success.");
157                     displayStatus(statusType.SUCCESS.name());
158                     postDelayed(new Runnable() {
159                         public void run() {
160                             dismiss();
161                         }
162                     }, 3000);
163                 }
164             }
165         }
166     };
167 
168 
169     //constructor
IccNetworkDepersonalizationPanel(Context context)170     public IccNetworkDepersonalizationPanel(Context context) {
171         super(context);
172         mPhone = PhoneGlobals.getPhone();
173         mPersoSubtype = PersoSubState.PERSOSUBSTATE_SIM_NETWORK.ordinal();
174         mSir = SubscriptionManager.from(context)
175                 .getActiveSubscriptionInfoForSimSlotIndex(mPhone.getPhoneId());
176     }
177 
178     //constructor
IccNetworkDepersonalizationPanel(Context context, Phone phone, int subtype)179     public IccNetworkDepersonalizationPanel(Context context, Phone phone,
180             int subtype) {
181         super(context);
182         mPhone = phone == null ? PhoneGlobals.getPhone() : phone;
183         mPersoSubtype = subtype;
184         mSir = SubscriptionManager.from(context)
185                 .getActiveSubscriptionInfoForSimSlotIndex(mPhone.getPhoneId());
186     }
187 
188     @Override
onCreate(Bundle icicle)189     protected void onCreate(Bundle icicle) {
190         super.onCreate(icicle);
191         setContentView(R.layout.sim_ndp);
192 
193         // PIN entry text field
194         mPinEntry = (EditText) findViewById(R.id.pin_entry);
195         mPinEntry.setKeyListener(DialerKeyListener.getInstance());
196         mPinEntry.setOnClickListener(mUnlockListener);
197 
198         // Attach the textwatcher
199         CharSequence text = mPinEntry.getText();
200         Spannable span = (Spannable) text;
201         span.setSpan(mPinEntryWatcher, 0, text.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
202 
203         mEntryPanel = (LinearLayout) findViewById(R.id.entry_panel);
204         mPersoSubtypeText = (TextView) findViewById(R.id.perso_subtype_text);
205         mPhoneIdText = (TextView) findViewById(R.id.perso_phoneid_text);
206         displayStatus(statusType.ENTRY.name());
207 
208         mUnlockButton = (Button) findViewById(R.id.ndp_unlock);
209         mUnlockButton.setOnClickListener(mUnlockListener);
210 
211         // The "Dismiss" button is present in some (but not all) products,
212         // based on the "KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL" variable.
213         mDismissButton = (Button) findViewById(R.id.ndp_dismiss);
214         PersistableBundle carrierConfig = PhoneGlobals.getInstance().getCarrierConfig();
215         if (carrierConfig.getBoolean(
216                 CarrierConfigManager.KEY_SIM_NETWORK_UNLOCK_ALLOW_DISMISS_BOOL)) {
217             if (DBG) log("Enabling 'Dismiss' button...");
218             mDismissButton.setVisibility(View.VISIBLE);
219             mDismissButton.setOnClickListener(mDismissListener);
220         } else {
221             if (DBG) log("Removing 'Dismiss' button...");
222             mDismissButton.setVisibility(View.GONE);
223         }
224 
225         //status panel is used since we're having problems with the alert dialog.
226         mStatusPanel = (LinearLayout) findViewById(R.id.status_panel);
227         mStatusText = (TextView) findViewById(R.id.status_text);
228     }
229 
230     @Override
onStart()231     protected void onStart() {
232         super.onStart();
233     }
234 
235     @Override
onStop()236     public void onStop() {
237         super.onStop();
238         Log.i(TAG, "[IccNetworkDepersonalizationPanel] - showDialog; hiding dialog.");
239         int phoneId = mPhone == null ? 0 : mPhone.getPhoneId();
240         if (phoneId >= sShowingDialog.length) {
241             Log.e(TAG, "[IccNetworkDepersonalizationPanel] - onStop; invalid phoneId " + phoneId);
242             return;
243         }
244         sShowingDialog[phoneId] = false;
245     }
246 
247     //Mirrors IccPinUnlockPanel.onKeyDown().
onKeyDown(int keyCode, KeyEvent event)248     public boolean onKeyDown(int keyCode, KeyEvent event) {
249         if (keyCode == KeyEvent.KEYCODE_BACK) {
250             return true;
251         }
252 
253         return super.onKeyDown(keyCode, event);
254     }
255 
256     View.OnClickListener mUnlockListener = new View.OnClickListener() {
257         public void onClick(View v) {
258             String pin = mPinEntry.getText().toString();
259 
260             if (TextUtils.isEmpty(pin)) {
261                 return;
262             }
263 
264             log("Requesting De-Personalization for subtype " + mPersoSubtype);
265 
266             try {
267                 mPhone.getIccCard().supplySimDepersonalization(mPersoSubState,pin,
268                         Message.obtain(mHandler, EVENT_ICC_NTWRK_DEPERSONALIZATION_RESULT));
269             } catch (NullPointerException ex) {
270                 log("NullPointerException @supplySimDepersonalization" + ex);
271             }
272             displayStatus(statusType.IN_PROGRESS.name());
273         }
274     };
275 
displayStatus(String type)276     private void displayStatus(String type) {
277         int label = 0;
278 
279         mPersoSubState = PersoSubState.values()[mPersoSubtype];
280         log("displayStatus mPersoSubState: " +mPersoSubState.name() +"type: " +type);
281 
282         label = getContext().getResources().getIdentifier(mPersoSubState.name()
283                 + "_" + type, "string", "android");
284 
285         if (label == 0) {
286             log ("Unable to get the PersoSubType string");
287             return;
288         }
289 
290         if(!PersoSubState.isPersoLocked(mPersoSubState)) {
291             log ("Unsupported Perso Subtype :" + mPersoSubState.name());
292             return;
293         }
294         if(mSir != null) {
295             CharSequence displayName = mSir.getDisplayName();
296             log("Operator displayName is: " + displayName + "phoneId: " + mPhone.getPhoneId());
297 
298             if(displayName != null && displayName != "") {
299                 // Displaying Operator displayName  on UI
300                 String phoneIdText = getContext().getString(R.string.label_phoneid)
301                         + ": " + displayName;
302                 mPhoneIdText.setText(phoneIdText);
303             }
304         }
305 
306         if (type == statusType.ENTRY.name()) {
307             String displayText = getContext().getString(label);
308             mPersoSubtypeText.setText(displayText);
309         } else {
310             mStatusText.setText(label);
311             mEntryPanel.setVisibility(View.GONE);
312             mStatusPanel.setVisibility(View.VISIBLE);
313         }
314     }
315 
hideAlert()316     private void hideAlert() {
317         mEntryPanel.setVisibility(View.VISIBLE);
318         mStatusPanel.setVisibility(View.GONE);
319     }
320 
321     View.OnClickListener mDismissListener = new View.OnClickListener() {
322         public void onClick(View v) {
323             if (DBG) log("mDismissListener: skipping depersonalization...");
324             dismiss();
325         }
326     };
327 
log(String msg)328     private void log(String msg) {
329         Log.d(TAG, "[IccNetworkDepersonalizationPanel] " + msg);
330     }
331 }
332