blob: 77cc03e92e73b442d31915a6a8eb1bf404afc0d2 [file] [log] [blame]
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -08001/*
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.settings;
18
Fan Zhang31b21002019-01-16 13:49:47 -080019import android.app.settings.SettingsEnums;
Jim Miller113ae022011-11-30 19:16:31 -080020import android.content.BroadcastReceiver;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080021import android.content.Context;
Jim Miller113ae022011-11-30 19:16:31 -080022import android.content.Intent;
23import android.content.IntentFilter;
Hao Zhao754930b2017-08-08 15:21:49 +080024import android.content.res.Configuration;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080025import android.content.res.Resources;
Hao Zhao754930b2017-08-08 15:21:49 +080026import android.graphics.PixelFormat;
zoey chen698e2ed2019-12-30 11:46:09 +080027import android.os.AsyncTask;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080028import android.os.Bundle;
29import android.os.Handler;
30import android.os.Message;
SongFerngWang3d545542020-02-26 17:17:49 +080031import android.os.PersistableBundle;
32import android.telephony.CarrierConfigManager;
PauloftheWest1d891b42014-11-11 06:42:54 -080033import android.telephony.SubscriptionInfo;
Treehugger Robot2b8bde12020-03-23 07:08:39 +000034import android.telephony.SubscriptionManager;
zoey chen698e2ed2019-12-30 11:46:09 +080035import android.telephony.TelephonyManager;
tiansiming64f48b52017-10-16 21:32:20 +080036import android.text.TextUtils;
Wink Saville82465792013-10-23 17:07:10 -070037import android.util.Log;
Hao Zhao754930b2017-08-08 15:21:49 +080038import android.view.Gravity;
Jason Monkb7e43802016-06-06 16:01:58 -040039import android.view.LayoutInflater;
PauloftheWest1d891b42014-11-11 06:42:54 -080040import android.view.View;
Jason Monkb7e43802016-06-06 16:01:58 -040041import android.view.ViewGroup;
Tiger Huangdf93c772019-11-20 22:29:50 +080042import android.view.WindowInsets.Type;
Hao Zhao754930b2017-08-08 15:21:49 +080043import android.view.WindowManager;
tiansiming64f48b52017-10-16 21:32:20 +080044import android.widget.EditText;
PauloftheWest1d891b42014-11-11 06:42:54 -080045import android.widget.ListView;
46import android.widget.TabHost;
47import android.widget.TabHost.OnTabChangeListener;
48import android.widget.TabHost.TabContentFactory;
49import android.widget.TabHost.TabSpec;
50import android.widget.TabWidget;
Hao Zhao754930b2017-08-08 15:21:49 +080051import android.widget.TextView;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080052import android.widget.Toast;
Fan Zhangc7162cd2018-06-18 15:21:41 -070053
Fan Zhang23f8d592018-08-28 15:11:40 -070054import androidx.preference.Preference;
55import androidx.preference.SwitchPreference;
56
Bonian Chen31367d72019-11-11 15:05:06 +080057import com.android.settings.network.ProxySubscriptionManager;
58
SongFerngWang3d545542020-02-26 17:17:49 +080059import java.util.ArrayList;
Bonian Chen31367d72019-11-11 15:05:06 +080060import java.util.List;
Wink Savillec3886682009-04-02 11:00:56 -070061
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080062/**
Wink Savillec3886682009-04-02 11:00:56 -070063 * Implements the preference screen to enable/disable ICC lock and
64 * also the dialogs to change the ICC PIN. In the former case, enabling/disabling
65 * the ICC lock will prompt the user for the current PIN.
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080066 * In the Change PIN case, it prompts the user for old pin, new pin and new pin
67 * again before attempting to change it. Calls the SimCard interface to execute
68 * these operations.
69 *
70 */
Jason Monkb7e43802016-06-06 16:01:58 -040071public class IccLockSettings extends SettingsPreferenceFragment
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080072 implements EditPinPreference.OnPinEnteredListener {
Wink Saville82465792013-10-23 17:07:10 -070073 private static final String TAG = "IccLockSettings";
Yanting Yang118e7ae2019-04-17 17:34:34 +080074 private static final boolean DBG = false;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080075
76 private static final int OFF_MODE = 0;
Wink Savillec3886682009-04-02 11:00:56 -070077 // State when enabling/disabling ICC lock
78 private static final int ICC_LOCK_MODE = 1;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080079 // State when entering the old pin
Wink Savillec3886682009-04-02 11:00:56 -070080 private static final int ICC_OLD_MODE = 2;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080081 // State when entering the new pin - first time
Wink Savillec3886682009-04-02 11:00:56 -070082 private static final int ICC_NEW_MODE = 3;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080083 // State when entering the new pin - second time
Wink Savillec3886682009-04-02 11:00:56 -070084 private static final int ICC_REENTER_MODE = 4;
Jim Miller113ae022011-11-30 19:16:31 -080085
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080086 // Keys in xml file
87 private static final String PIN_DIALOG = "sim_pin";
88 private static final String PIN_TOGGLE = "sim_toggle";
89 // Keys in icicle
Bonian Chenfb4a0c22020-05-29 14:53:43 +080090 private static final String DIALOG_SUB_ID = "dialogSubId";
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080091 private static final String DIALOG_STATE = "dialogState";
92 private static final String DIALOG_PIN = "dialogPin";
93 private static final String DIALOG_ERROR = "dialogError";
94 private static final String ENABLE_TO_STATE = "enableState";
Qi Ding4ca4bd32016-06-21 19:16:57 +080095 private static final String CURRENT_TAB = "currentTab";
Yongwei Cai22135ea2010-09-07 13:52:42 +020096
97 // Save and restore inputted PIN code when configuration changed
98 // (ex. portrait<-->landscape) during change PIN code
99 private static final String OLD_PINCODE = "oldPinCode";
100 private static final String NEW_PINCODE = "newPinCode";
Jim Miller113ae022011-11-30 19:16:31 -0800101
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800102 private static final int MIN_PIN_LENGTH = 4;
103 private static final int MAX_PIN_LENGTH = 8;
104 // Which dialog to show next when popped up
105 private int mDialogState = OFF_MODE;
Jim Miller113ae022011-11-30 19:16:31 -0800106
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800107 private String mPin;
108 private String mOldPin;
109 private String mNewPin;
110 private String mError;
Wink Savillec3886682009-04-02 11:00:56 -0700111 // Are we trying to enable or disable ICC lock?
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800112 private boolean mToState;
Jim Miller113ae022011-11-30 19:16:31 -0800113
PauloftheWest1d891b42014-11-11 06:42:54 -0800114 private TabHost mTabHost;
115 private TabWidget mTabWidget;
116 private ListView mListView;
117
Bonian Chen31367d72019-11-11 15:05:06 +0800118 private ProxySubscriptionManager mProxySubscriptionMgr;
Jim Miller113ae022011-11-30 19:16:31 -0800119
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800120 private EditPinPreference mPinDialog;
PauloftheWestac5c0812014-11-17 12:47:38 -0800121 private SwitchPreference mPinToggle;
Jim Miller113ae022011-11-30 19:16:31 -0800122
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800123 private Resources mRes;
124
125 // For async handler to identify request type
Jim Miller113ae022011-11-30 19:16:31 -0800126 private static final int MSG_SIM_STATE_CHANGED = 102;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800127
Hao Zhao754930b2017-08-08 15:21:49 +0800128 // @see android.widget.Toast$TN
129 private static final long LONG_DURATION_TIMEOUT = 7000;
130
Bonian Chenfb4a0c22020-05-29 14:53:43 +0800131 private int mSlotId = -1;
zoey chen698e2ed2019-12-30 11:46:09 +0800132 private int mSubId;
133 private TelephonyManager mTelephonyManager;
134
Wink Savillec3886682009-04-02 11:00:56 -0700135 // For replies from IccCard interface
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800136 private Handler mHandler = new Handler() {
137 public void handleMessage(Message msg) {
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800138 switch (msg.what) {
Jim Miller113ae022011-11-30 19:16:31 -0800139 case MSG_SIM_STATE_CHANGED:
140 updatePreferences();
141 break;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800142 }
143
144 return;
145 }
146 };
Jim Miller113ae022011-11-30 19:16:31 -0800147
148 private final BroadcastReceiver mSimStateReceiver = new BroadcastReceiver() {
149 public void onReceive(Context context, Intent intent) {
150 final String action = intent.getAction();
Daniel Bright721467c2020-01-22 12:49:24 -0800151 if (Intent.ACTION_SIM_STATE_CHANGED.equals(action)) {
Jim Miller113ae022011-11-30 19:16:31 -0800152 mHandler.sendMessage(mHandler.obtainMessage(MSG_SIM_STATE_CHANGED));
153 }
154 }
155 };
156
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800157 // For top-level settings screen to query
zoey chen698e2ed2019-12-30 11:46:09 +0800158 private boolean isIccLockEnabled() {
Bonian Chenfb4a0c22020-05-29 14:53:43 +0800159 mTelephonyManager = mTelephonyManager.createForSubscriptionId(mSubId);
zoey chen698e2ed2019-12-30 11:46:09 +0800160 return mTelephonyManager.isIccLockEnabled();
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800161 }
Jim Miller113ae022011-11-30 19:16:31 -0800162
zoey chen698e2ed2019-12-30 11:46:09 +0800163 private String getSummary(Context context) {
Bonian Chen31367d72019-11-11 15:05:06 +0800164 final Resources res = context.getResources();
165 final String summary = isIccLockEnabled()
Wink Savillec3886682009-04-02 11:00:56 -0700166 ? res.getString(R.string.sim_lock_on)
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800167 : res.getString(R.string.sim_lock_off);
168 return summary;
169 }
Wink Savillec3886682009-04-02 11:00:56 -0700170
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800171 @Override
Jason Monkb7e43802016-06-06 16:01:58 -0400172 public void onCreate(Bundle savedInstanceState) {
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800173 super.onCreate(savedInstanceState);
Wink Savillec3886682009-04-02 11:00:56 -0700174
Amith Yamasani2e180ef2010-01-07 19:05:07 -0800175 if (Utils.isMonkeyRunning()) {
176 finish();
177 return;
178 }
179
Bonian Chen31367d72019-11-11 15:05:06 +0800180 // enable ProxySubscriptionMgr with Lifecycle support for all controllers
181 // live within this fragment
182 mProxySubscriptionMgr = ProxySubscriptionManager.getInstance(getContext());
183 mProxySubscriptionMgr.setLifecycle(getLifecycle());
184
zoey chen698e2ed2019-12-30 11:46:09 +0800185 mTelephonyManager = getContext().getSystemService(TelephonyManager.class);
186
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800187 addPreferencesFromResource(R.xml.sim_lock_settings);
Wink Savillec3886682009-04-02 11:00:56 -0700188
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800189 mPinDialog = (EditPinPreference) findPreference(PIN_DIALOG);
PauloftheWestac5c0812014-11-17 12:47:38 -0800190 mPinToggle = (SwitchPreference) findPreference(PIN_TOGGLE);
Bonian Chenfb4a0c22020-05-29 14:53:43 +0800191 if (savedInstanceState != null) {
192 if (savedInstanceState.containsKey(DIALOG_STATE)
193 && restoreDialogStates(savedInstanceState)) {
194 Log.d(TAG, "onCreate: restore dialog for slotId=" + mSlotId + ", subId=" + mSubId);
195 } else if (savedInstanceState.containsKey(CURRENT_TAB)
196 && restoreTabFocus(savedInstanceState)) {
197 Log.d(TAG, "onCreate: restore focus on slotId=" + mSlotId + ", subId=" + mSubId);
Yongwei Cai22135ea2010-09-07 13:52:42 +0200198 }
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800199 }
200
201 mPinDialog.setOnPinEnteredListener(this);
Jim Miller113ae022011-11-30 19:16:31 -0800202
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800203 // Don't need any changes to be remembered
204 getPreferenceScreen().setPersistent(false);
Jim Miller113ae022011-11-30 19:16:31 -0800205
Jason Monkb7e43802016-06-06 16:01:58 -0400206 mRes = getResources();
207 }
PauloftheWest1d891b42014-11-11 06:42:54 -0800208
Bonian Chenfb4a0c22020-05-29 14:53:43 +0800209 private boolean restoreDialogStates(Bundle savedInstanceState) {
210 final SubscriptionInfo subInfo = mProxySubscriptionMgr
211 .getActiveSubscriptionInfo(savedInstanceState.getInt(DIALOG_SUB_ID));
212 if (subInfo == null) {
213 return false;
214 }
215
216 final SubscriptionInfo visibleSubInfo = getVisibleSubscriptionInfoForSimSlotIndex(
217 subInfo.getSimSlotIndex());
218 if (visibleSubInfo == null) {
219 return false;
220 }
221 if (visibleSubInfo.getSubscriptionId() != subInfo.getSubscriptionId()) {
222 return false;
223 }
224
225 mSlotId = subInfo.getSimSlotIndex();
226 mSubId = subInfo.getSubscriptionId();
227 mDialogState = savedInstanceState.getInt(DIALOG_STATE);
228 mPin = savedInstanceState.getString(DIALOG_PIN);
229 mError = savedInstanceState.getString(DIALOG_ERROR);
230 mToState = savedInstanceState.getBoolean(ENABLE_TO_STATE);
231
232 // Restore inputted PIN code
233 switch (mDialogState) {
234 case ICC_NEW_MODE:
235 mOldPin = savedInstanceState.getString(OLD_PINCODE);
236 break;
237
238 case ICC_REENTER_MODE:
239 mOldPin = savedInstanceState.getString(OLD_PINCODE);
240 mNewPin = savedInstanceState.getString(NEW_PINCODE);
241 break;
242 }
243 return true;
244 }
245
246 private boolean restoreTabFocus(Bundle savedInstanceState) {
247 int slotId = 0;
248 try {
249 slotId = Integer.parseInt(savedInstanceState.getString(CURRENT_TAB));
250 } catch (NumberFormatException exception) {
251 return false;
252 }
253
254 final SubscriptionInfo subInfo = getVisibleSubscriptionInfoForSimSlotIndex(slotId);
255 if (subInfo == null) {
256 return false;
257 }
258
259 mSlotId = subInfo.getSimSlotIndex();
260 mSubId = subInfo.getSubscriptionId();
261 if (mTabHost != null) {
262 mTabHost.setCurrentTabByTag(getTagForSlotId(mSlotId));
263 }
264 return true;
265 }
266
Jason Monkb7e43802016-06-06 16:01:58 -0400267 @Override
268 public View onCreateView(LayoutInflater inflater, ViewGroup container,
269 Bundle savedInstanceState) {
270
Bonian Chen31367d72019-11-11 15:05:06 +0800271 final int numSims = mProxySubscriptionMgr.getActiveSubscriptionInfoCountMax();
SongFerngWang3d545542020-02-26 17:17:49 +0800272 final List<SubscriptionInfo> componenterList = new ArrayList<>();
273
274 for (int i = 0; i < numSims; ++i) {
Bonian Chenfb4a0c22020-05-29 14:53:43 +0800275 final SubscriptionInfo subInfo = getVisibleSubscriptionInfoForSimSlotIndex(i);
Treehugger Robot2b8bde12020-03-23 07:08:39 +0000276 if (subInfo != null) {
Bonian Chenfb4a0c22020-05-29 14:53:43 +0800277 componenterList.add(subInfo);
SongFerngWang3d545542020-02-26 17:17:49 +0800278 }
279 }
280
281 if (componenterList.size() == 0) {
282 Log.e(TAG, "onCreateView: no sim info");
hoffcd6c805f2020-04-27 13:40:12 +0800283 return super.onCreateView(inflater, container, savedInstanceState);
SongFerngWang3d545542020-02-26 17:17:49 +0800284 }
285
Bonian Chenfb4a0c22020-05-29 14:53:43 +0800286 if (mSlotId < 0) {
287 mSlotId = componenterList.get(0).getSimSlotIndex();
288 mSubId = componenterList.get(0).getSubscriptionId();
289 Log.d(TAG, "onCreateView: default slotId=" + mSlotId + ", subId=" + mSubId);
290 }
291
SongFerngWang3d545542020-02-26 17:17:49 +0800292 if (componenterList.size() > 1) {
Bonian Chen31367d72019-11-11 15:05:06 +0800293 final View view = inflater.inflate(R.layout.icc_lock_tabs, container, false);
Jason Monkb7e43802016-06-06 16:01:58 -0400294 final ViewGroup prefs_container = (ViewGroup) view.findViewById(R.id.prefs_container);
295 Utils.prepareCustomPreferencesList(container, view, prefs_container, false);
Bonian Chen31367d72019-11-11 15:05:06 +0800296 final View prefs = super.onCreateView(inflater, prefs_container, savedInstanceState);
Jason Monkb7e43802016-06-06 16:01:58 -0400297 prefs_container.addView(prefs);
298
299 mTabHost = (TabHost) view.findViewById(android.R.id.tabhost);
300 mTabWidget = (TabWidget) view.findViewById(android.R.id.tabs);
301 mListView = (ListView) view.findViewById(android.R.id.list);
PauloftheWest1d891b42014-11-11 06:42:54 -0800302
303 mTabHost.setup();
PauloftheWest1d891b42014-11-11 06:42:54 -0800304 mTabHost.clearAllTabs();
305
SongFerngWang3d545542020-02-26 17:17:49 +0800306 for (SubscriptionInfo subInfo : componenterList) {
Bonian Chenfb4a0c22020-05-29 14:53:43 +0800307 final int slot = subInfo.getSimSlotIndex();
308 final String tag = getTagForSlotId(slot);
309 mTabHost.addTab(buildTabSpec(tag,
PauloftheWest1d891b42014-11-11 06:42:54 -0800310 String.valueOf(subInfo == null
SongFerngWang3d545542020-02-26 17:17:49 +0800311 ? getContext().getString(R.string.sim_editor_title, slot + 1)
312 : subInfo.getDisplayName())));
PauloftheWest1d891b42014-11-11 06:42:54 -0800313 }
SongFerngWang3d545542020-02-26 17:17:49 +0800314
Bonian Chenfb4a0c22020-05-29 14:53:43 +0800315 mTabHost.setCurrentTabByTag(getTagForSlotId(mSlotId));
316 mTabHost.setOnTabChangedListener(mTabListener);
Jason Monkb7e43802016-06-06 16:01:58 -0400317 return view;
PauloftheWest0b8788a2014-12-08 13:49:35 -0800318 } else {
Jason Monkb7e43802016-06-06 16:01:58 -0400319 return super.onCreateView(inflater, container, savedInstanceState);
PauloftheWest0b8788a2014-12-08 13:49:35 -0800320 }
Jason Monkb7e43802016-06-06 16:01:58 -0400321 }
322
323 @Override
324 public void onViewCreated(View view, Bundle savedInstanceState) {
325 super.onViewCreated(view, savedInstanceState);
Jim Miller113ae022011-11-30 19:16:31 -0800326 updatePreferences();
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800327 }
Jim Miller113ae022011-11-30 19:16:31 -0800328
329 private void updatePreferences() {
zoey chen698e2ed2019-12-30 11:46:09 +0800330
Bonian Chenfb4a0c22020-05-29 14:53:43 +0800331 final SubscriptionInfo sir = getVisibleSubscriptionInfoForSimSlotIndex(mSlotId);
332 final int subId = (sir != null) ? sir.getSubscriptionId()
333 : SubscriptionManager.INVALID_SUBSCRIPTION_ID;
334
335 if (mSubId != subId) {
336 mSubId = subId;
337 resetDialogState();
338 if ((mPinDialog != null) && mPinDialog.isDialogOpen()) {
339 mPinDialog.getDialog().dismiss();
340 }
341 }
zoey chen698e2ed2019-12-30 11:46:09 +0800342
xudiwen18615602017-05-09 17:30:57 +0800343 if (mPinDialog != null) {
zoey chen698e2ed2019-12-30 11:46:09 +0800344 mPinDialog.setEnabled(sir != null);
xudiwen18615602017-05-09 17:30:57 +0800345 }
346 if (mPinToggle != null) {
zoey chen698e2ed2019-12-30 11:46:09 +0800347 mPinToggle.setEnabled(sir != null);
PauloftheWest1d891b42014-11-11 06:42:54 -0800348
zoey chen698e2ed2019-12-30 11:46:09 +0800349 if (sir != null) {
350 mPinToggle.setChecked(isIccLockEnabled());
xudiwen18615602017-05-09 17:30:57 +0800351 }
PauloftheWest1d891b42014-11-11 06:42:54 -0800352 }
Jim Miller113ae022011-11-30 19:16:31 -0800353 }
354
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800355 @Override
Fan Zhang65076132016-08-08 10:25:13 -0700356 public int getMetricsCategory() {
Fan Zhang31b21002019-01-16 13:49:47 -0800357 return SettingsEnums.ICC_LOCK;
Chris Wren8a963ba2015-03-20 10:29:14 -0400358 }
359
360 @Override
Jason Monkb7e43802016-06-06 16:01:58 -0400361 public void onResume() {
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800362 super.onResume();
Jim Miller113ae022011-11-30 19:16:31 -0800363
364 // ACTION_SIM_STATE_CHANGED is sticky, so we'll receive current state after this call,
365 // which will call updatePreferences().
Daniel Bright721467c2020-01-22 12:49:24 -0800366 final IntentFilter filter = new IntentFilter(Intent.ACTION_SIM_STATE_CHANGED);
Jason Monkb7e43802016-06-06 16:01:58 -0400367 getContext().registerReceiver(mSimStateReceiver, filter);
Jim Miller113ae022011-11-30 19:16:31 -0800368
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800369 if (mDialogState != OFF_MODE) {
370 showPinDialog();
371 } else {
372 // Prep for standard click on "Change PIN"
373 resetDialogState();
374 }
375 }
Jim Miller113ae022011-11-30 19:16:31 -0800376
377 @Override
Jason Monkb7e43802016-06-06 16:01:58 -0400378 public void onPause() {
Jim Miller113ae022011-11-30 19:16:31 -0800379 super.onPause();
Jason Monkb7e43802016-06-06 16:01:58 -0400380 getContext().unregisterReceiver(mSimStateReceiver);
Jim Miller113ae022011-11-30 19:16:31 -0800381 }
382
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800383 @Override
Fan Zhange0b0e9f2017-11-29 14:55:59 -0800384 public int getHelpResource() {
Fan Zhangb91a26b2017-06-19 14:07:23 -0700385 return R.string.help_url_icc_lock;
386 }
387
388 @Override
Jason Monkb7e43802016-06-06 16:01:58 -0400389 public void onSaveInstanceState(Bundle out) {
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800390 // Need to store this state for slider open/close
391 // There is one case where the dialog is popped up by the preference
392 // framework. In that case, let the preference framework store the
393 // dialog state. In other cases, where this activity manually launches
394 // the dialog, store the state of the dialog.
395 if (mPinDialog.isDialogOpen()) {
Bonian Chenfb4a0c22020-05-29 14:53:43 +0800396 out.putInt(DIALOG_SUB_ID, mSubId);
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800397 out.putInt(DIALOG_STATE, mDialogState);
398 out.putString(DIALOG_PIN, mPinDialog.getEditText().getText().toString());
399 out.putString(DIALOG_ERROR, mError);
400 out.putBoolean(ENABLE_TO_STATE, mToState);
Yongwei Cai22135ea2010-09-07 13:52:42 +0200401
402 // Save inputted PIN code
403 switch (mDialogState) {
404 case ICC_NEW_MODE:
405 out.putString(OLD_PINCODE, mOldPin);
406 break;
407
408 case ICC_REENTER_MODE:
409 out.putString(OLD_PINCODE, mOldPin);
410 out.putString(NEW_PINCODE, mNewPin);
411 break;
Yongwei Cai22135ea2010-09-07 13:52:42 +0200412 }
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800413 } else {
414 super.onSaveInstanceState(out);
415 }
Qi Ding4ca4bd32016-06-21 19:16:57 +0800416
417 if (mTabHost != null) {
418 out.putString(CURRENT_TAB, mTabHost.getCurrentTabTag());
419 }
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800420 }
421
422 private void showPinDialog() {
423 if (mDialogState == OFF_MODE) {
424 return;
425 }
426 setDialogValues();
Jim Miller113ae022011-11-30 19:16:31 -0800427
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800428 mPinDialog.showPinDialog();
tiansiming64f48b52017-10-16 21:32:20 +0800429
430 final EditText editText = mPinDialog.getEditText();
431 if (!TextUtils.isEmpty(mPin) && editText != null) {
432 editText.setSelection(mPin.length());
433 }
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800434 }
Jim Miller113ae022011-11-30 19:16:31 -0800435
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800436 private void setDialogValues() {
437 mPinDialog.setText(mPin);
438 String message = "";
439 switch (mDialogState) {
Wink Savillec3886682009-04-02 11:00:56 -0700440 case ICC_LOCK_MODE:
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800441 message = mRes.getString(R.string.sim_enter_pin);
Jim Miller113ae022011-11-30 19:16:31 -0800442 mPinDialog.setDialogTitle(mToState
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800443 ? mRes.getString(R.string.sim_enable_sim_lock)
444 : mRes.getString(R.string.sim_disable_sim_lock));
445 break;
Wink Savillec3886682009-04-02 11:00:56 -0700446 case ICC_OLD_MODE:
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800447 message = mRes.getString(R.string.sim_enter_old);
448 mPinDialog.setDialogTitle(mRes.getString(R.string.sim_change_pin));
449 break;
Wink Savillec3886682009-04-02 11:00:56 -0700450 case ICC_NEW_MODE:
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800451 message = mRes.getString(R.string.sim_enter_new);
452 mPinDialog.setDialogTitle(mRes.getString(R.string.sim_change_pin));
453 break;
Wink Savillec3886682009-04-02 11:00:56 -0700454 case ICC_REENTER_MODE:
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800455 message = mRes.getString(R.string.sim_reenter_new);
456 mPinDialog.setDialogTitle(mRes.getString(R.string.sim_change_pin));
457 break;
458 }
459 if (mError != null) {
460 message = mError + "\n" + message;
461 mError = null;
462 }
463 mPinDialog.setDialogMessage(message);
464 }
465
Jason Monk5b397102016-03-30 11:41:45 -0400466 @Override
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800467 public void onPinEntered(EditPinPreference preference, boolean positiveResult) {
468 if (!positiveResult) {
469 resetDialogState();
470 return;
471 }
Jim Miller113ae022011-11-30 19:16:31 -0800472
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800473 mPin = preference.getText();
474 if (!reasonablePin(mPin)) {
475 // inject error message and display dialog again
476 mError = mRes.getString(R.string.sim_bad_pin);
477 showPinDialog();
478 return;
479 }
480 switch (mDialogState) {
Wink Savillec3886682009-04-02 11:00:56 -0700481 case ICC_LOCK_MODE:
482 tryChangeIccLockState();
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800483 break;
Wink Savillec3886682009-04-02 11:00:56 -0700484 case ICC_OLD_MODE:
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800485 mOldPin = mPin;
Wink Savillec3886682009-04-02 11:00:56 -0700486 mDialogState = ICC_NEW_MODE;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800487 mError = null;
488 mPin = null;
489 showPinDialog();
490 break;
Wink Savillec3886682009-04-02 11:00:56 -0700491 case ICC_NEW_MODE:
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800492 mNewPin = mPin;
Wink Savillec3886682009-04-02 11:00:56 -0700493 mDialogState = ICC_REENTER_MODE;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800494 mPin = null;
495 showPinDialog();
496 break;
Wink Savillec3886682009-04-02 11:00:56 -0700497 case ICC_REENTER_MODE:
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800498 if (!mPin.equals(mNewPin)) {
499 mError = mRes.getString(R.string.sim_pins_dont_match);
Wink Savillec3886682009-04-02 11:00:56 -0700500 mDialogState = ICC_NEW_MODE;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800501 mPin = null;
502 showPinDialog();
503 } else {
504 mError = null;
505 tryChangePin();
506 }
507 break;
508 }
509 }
Jim Miller113ae022011-11-30 19:16:31 -0800510
Jason Monk5b397102016-03-30 11:41:45 -0400511 @Override
512 public boolean onPreferenceTreeClick(Preference preference) {
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800513 if (preference == mPinToggle) {
514 // Get the new, preferred state
515 mToState = mPinToggle.isChecked();
Jim Miller113ae022011-11-30 19:16:31 -0800516 // Flip it back and pop up pin dialog
517 mPinToggle.setChecked(!mToState);
Wink Savillec3886682009-04-02 11:00:56 -0700518 mDialogState = ICC_LOCK_MODE;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800519 showPinDialog();
Amith Yamasani11cd8c52009-08-28 15:36:52 -0700520 } else if (preference == mPinDialog) {
521 mDialogState = ICC_OLD_MODE;
522 return false;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800523 }
524 return true;
525 }
Amith Yamasani11cd8c52009-08-28 15:36:52 -0700526
Wink Savillec3886682009-04-02 11:00:56 -0700527 private void tryChangeIccLockState() {
Jim Miller113ae022011-11-30 19:16:31 -0800528 // Try to change icc lock. If it succeeds, toggle the lock state and
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800529 // reset dialog state. Else inject error message and show dialog again.
zoey chen698e2ed2019-12-30 11:46:09 +0800530 new SetIccLockEnabled(mToState, mPin).execute();
Jeevaka Badrappan48c03832011-10-30 15:54:41 +0200531 // Disable the setting till the response is received.
532 mPinToggle.setEnabled(false);
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800533 }
Jim Miller113ae022011-11-30 19:16:31 -0800534
zoey chen698e2ed2019-12-30 11:46:09 +0800535 private class SetIccLockEnabled extends AsyncTask<Void, Void, Void> {
536 private final boolean mState;
537 private final String mPassword;
538 private int mAttemptsRemaining;
539
540 private SetIccLockEnabled(boolean state, String pin) {
541 mState = state;
542 mPassword = pin;
543 }
544
545 @Override
546 protected Void doInBackground(Void... params) {
547 mTelephonyManager = mTelephonyManager.createForSubscriptionId(mSubId);
548 mAttemptsRemaining = mTelephonyManager.setIccLockEnabled(mState, mPassword);
549 return null;
550 }
551
552 @Override
553 protected void onPostExecute(Void aVoid) {
554 if (mAttemptsRemaining == TelephonyManager.CHANGE_ICC_LOCK_SUCCESS) {
555 iccLockChanged(true, mAttemptsRemaining);
556 } else {
557 iccLockChanged(false, mAttemptsRemaining);
558 }
559 }
560 }
561
562 private void iccLockChanged(boolean success, int attemptsRemaining) {
563 Log.d(TAG, "iccLockChanged: success = " + success);
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800564 if (success) {
565 mPinToggle.setChecked(mToState);
566 } else {
zoey chen698e2ed2019-12-30 11:46:09 +0800567 if (attemptsRemaining >= 0) {
568 createCustomTextToast(getPinPasswordErrorMessage(attemptsRemaining));
569 } else {
570 if (mToState) {
571 Toast.makeText(getContext(), mRes.getString(
572 R.string.sim_pin_enable_failed), Toast.LENGTH_LONG).show();
Sandeep Guttafe6ddae2018-09-18 12:21:27 +0530573 } else {
zoey chen698e2ed2019-12-30 11:46:09 +0800574 Toast.makeText(getContext(), mRes.getString(
575 R.string.sim_pin_disable_failed), Toast.LENGTH_LONG).show();
Sandeep Guttafe6ddae2018-09-18 12:21:27 +0530576 }
577 }
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800578 }
Jeevaka Badrappan48c03832011-10-30 15:54:41 +0200579 mPinToggle.setEnabled(true);
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800580 resetDialogState();
581 }
582
Hao Zhao754930b2017-08-08 15:21:49 +0800583 private void createCustomTextToast(CharSequence errorMessage) {
584 // Cannot overlay Toast on PUK unlock screen.
585 // The window type of Toast is set by NotificationManagerService.
586 // It can't be overwritten by LayoutParams.type.
587 // Ovarlay a custom window with LayoutParams (TYPE_STATUS_BAR_PANEL) on PUK unlock screen.
Bonian Chen31367d72019-11-11 15:05:06 +0800588 final View v = ((LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE))
Hao Zhao754930b2017-08-08 15:21:49 +0800589 .inflate(com.android.internal.R.layout.transient_notification, null);
Bonian Chen31367d72019-11-11 15:05:06 +0800590 final TextView tv = (TextView) v.findViewById(com.android.internal.R.id.message);
Hao Zhao754930b2017-08-08 15:21:49 +0800591 tv.setText(errorMessage);
592
593 final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
594 final Configuration config = v.getContext().getResources().getConfiguration();
595 final int gravity = Gravity.getAbsoluteGravity(
596 getContext().getResources().getInteger(
597 com.android.internal.R.integer.config_toastDefaultGravity),
598 config.getLayoutDirection());
599 params.gravity = gravity;
600 if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.FILL_HORIZONTAL) {
601 params.horizontalWeight = 1.0f;
602 }
603 if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.FILL_VERTICAL) {
604 params.verticalWeight = 1.0f;
605 }
606 params.y = getContext().getResources().getDimensionPixelSize(
607 com.android.internal.R.dimen.toast_y_offset);
608
609 params.height = WindowManager.LayoutParams.WRAP_CONTENT;
610 params.width = WindowManager.LayoutParams.WRAP_CONTENT;
611 params.format = PixelFormat.TRANSLUCENT;
612 params.windowAnimations = com.android.internal.R.style.Animation_Toast;
Heemin Seog56e62ec2020-02-26 14:17:11 -0800613 params.type = WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
Jorim Jaggifd802bc2020-01-23 00:40:38 +0100614 params.setFitInsetsTypes(params.getFitInsetsTypes() & ~Type.statusBars());
Hao Zhao754930b2017-08-08 15:21:49 +0800615 params.setTitle(errorMessage);
616 params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
617 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
618 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
619
Bonian Chen31367d72019-11-11 15:05:06 +0800620 final WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
Hao Zhao754930b2017-08-08 15:21:49 +0800621 wm.addView(v, params);
622
623 mHandler.postDelayed(new Runnable() {
624 @Override
625 public void run() {
626 wm.removeViewImmediate(v);
627 }
628 }, LONG_DURATION_TIMEOUT);
629 }
630
Wink Saville82465792013-10-23 17:07:10 -0700631 private void iccPinChanged(boolean success, int attemptsRemaining) {
zoey chen698e2ed2019-12-30 11:46:09 +0800632 Log.d(TAG, "iccPinChanged: success = " + success);
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800633 if (!success) {
Hao Zhao754930b2017-08-08 15:21:49 +0800634 createCustomTextToast(getPinPasswordErrorMessage(attemptsRemaining));
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800635 } else {
Jason Monkb7e43802016-06-06 16:01:58 -0400636 Toast.makeText(getContext(), mRes.getString(R.string.sim_change_succeeded),
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800637 Toast.LENGTH_SHORT)
638 .show();
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800639 }
640 resetDialogState();
641 }
642
643 private void tryChangePin() {
zoey chen698e2ed2019-12-30 11:46:09 +0800644 new ChangeIccLockPassword(mOldPin, mNewPin).execute();
645 }
646
647 private class ChangeIccLockPassword extends AsyncTask<Void, Void, Void> {
648 private final String mOldPwd;
649 private final String mNewPwd;
650 private int mAttemptsRemaining;
651
652 private ChangeIccLockPassword(String oldPin, String newPin) {
653 mOldPwd = oldPin;
654 mNewPwd = newPin;
655 }
656
657 @Override
658 protected Void doInBackground(Void... params) {
659 mTelephonyManager = mTelephonyManager.createForSubscriptionId(mSubId);
660 mAttemptsRemaining = mTelephonyManager.changeIccLockPassword(mOldPwd, mNewPwd);
661 return null;
662 }
663
664 @Override
665 protected void onPostExecute(Void aVoid) {
666 if (mAttemptsRemaining == TelephonyManager.CHANGE_ICC_LOCK_SUCCESS) {
667 iccPinChanged(true, mAttemptsRemaining);
668 } else {
669 iccPinChanged(false, mAttemptsRemaining);
670 }
671 }
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800672 }
Amith Yamasani11cd8c52009-08-28 15:36:52 -0700673
Wink Saville82465792013-10-23 17:07:10 -0700674 private String getPinPasswordErrorMessage(int attemptsRemaining) {
675 String displayMessage;
676
677 if (attemptsRemaining == 0) {
678 displayMessage = mRes.getString(R.string.wrong_pin_code_pukked);
Tsung-Mao Fang9c69ded2020-04-07 15:40:02 +0800679 } else if (attemptsRemaining == 1) {
680 displayMessage = mRes.getString(R.string.wrong_pin_code_one, attemptsRemaining);
681 } else if (attemptsRemaining > 1) {
Wink Saville82465792013-10-23 17:07:10 -0700682 displayMessage = mRes
683 .getQuantityString(R.plurals.wrong_pin_code, attemptsRemaining,
684 attemptsRemaining);
685 } else {
686 displayMessage = mRes.getString(R.string.pin_failed);
687 }
688 if (DBG) Log.d(TAG, "getPinPasswordErrorMessage:"
689 + " attemptsRemaining=" + attemptsRemaining + " displayMessage=" + displayMessage);
690 return displayMessage;
691 }
692
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800693 private boolean reasonablePin(String pin) {
694 if (pin == null || pin.length() < MIN_PIN_LENGTH || pin.length() > MAX_PIN_LENGTH) {
695 return false;
696 } else {
697 return true;
698 }
699 }
Amith Yamasani11cd8c52009-08-28 15:36:52 -0700700
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800701 private void resetDialogState() {
702 mError = null;
Wink Savillec3886682009-04-02 11:00:56 -0700703 mDialogState = ICC_OLD_MODE; // Default for when Change PIN is clicked
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800704 mPin = "";
705 setDialogValues();
Amith Yamasani11cd8c52009-08-28 15:36:52 -0700706 mDialogState = OFF_MODE;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800707 }
PauloftheWest1d891b42014-11-11 06:42:54 -0800708
Bonian Chenfb4a0c22020-05-29 14:53:43 +0800709 private String getTagForSlotId(int slotId) {
710 return String.valueOf(slotId);
711 }
712
713 private int getSlotIndexFromTag(String tag) {
714 int slotId = -1;
715 try {
716 slotId = Integer.parseInt(tag);
717 } catch (NumberFormatException exception) {
718 }
719 return slotId;
720 }
721
722 private SubscriptionInfo getVisibleSubscriptionInfoForSimSlotIndex(int slotId) {
723 final List<SubscriptionInfo> subInfoList =
724 mProxySubscriptionMgr.getActiveSubscriptionsInfo();
Bonian Chen31367d72019-11-11 15:05:06 +0800725 if (subInfoList == null) {
726 return null;
727 }
Bonian Chenfb4a0c22020-05-29 14:53:43 +0800728 final CarrierConfigManager carrierConfigManager = getContext().getSystemService(
729 CarrierConfigManager.class);
Bonian Chen31367d72019-11-11 15:05:06 +0800730 for (SubscriptionInfo subInfo : subInfoList) {
Bonian Chenfb4a0c22020-05-29 14:53:43 +0800731 if ((isSubscriptionVisible(carrierConfigManager, subInfo)
732 && (subInfo.getSimSlotIndex() == slotId))) {
Bonian Chen31367d72019-11-11 15:05:06 +0800733 return subInfo;
734 }
735 }
736 return null;
737 }
738
Bonian Chenfb4a0c22020-05-29 14:53:43 +0800739 private boolean isSubscriptionVisible(CarrierConfigManager carrierConfigManager,
740 SubscriptionInfo subInfo) {
741 final PersistableBundle bundle = carrierConfigManager
742 .getConfigForSubId(subInfo.getSubscriptionId());
743 if (bundle == null) {
744 return false;
745 }
746 return !bundle.getBoolean(CarrierConfigManager.KEY_HIDE_SIM_LOCK_SETTINGS_BOOL);
747 }
748
PauloftheWest1d891b42014-11-11 06:42:54 -0800749 private OnTabChangeListener mTabListener = new OnTabChangeListener() {
750 @Override
751 public void onTabChanged(String tabId) {
Bonian Chenfb4a0c22020-05-29 14:53:43 +0800752 mSlotId = getSlotIndexFromTag(tabId);
PauloftheWest1d891b42014-11-11 06:42:54 -0800753
PauloftheWest1d891b42014-11-11 06:42:54 -0800754 // The User has changed tab; update the body.
755 updatePreferences();
756 }
757 };
758
759 private TabContentFactory mEmptyTabContent = new TabContentFactory() {
760 @Override
761 public View createTabContent(String tag) {
762 return new View(mTabHost.getContext());
763 }
764 };
765
766 private TabSpec buildTabSpec(String tag, String title) {
767 return mTabHost.newTabSpec(tag).setIndicator(title).setContent(
768 mEmptyTabContent);
769 }
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800770}