SwitchPreference and SwitchPreferenceCompat are both TwoStatePreference. Using TwoStatePreference in Java will helps migration in the future. Bug: 306771414 Test: manual - check Settings pages Change-Id: I84e1d7b09451106797c2b23d127855c6976678ca
768 lines
28 KiB
Java
768 lines
28 KiB
Java
/*
|
|
* 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.settings;
|
|
|
|
import android.app.settings.SettingsEnums;
|
|
import android.content.BroadcastReceiver;
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.content.IntentFilter;
|
|
import android.content.res.Configuration;
|
|
import android.content.res.Resources;
|
|
import android.graphics.PixelFormat;
|
|
import android.os.AsyncTask;
|
|
import android.os.Bundle;
|
|
import android.os.Handler;
|
|
import android.os.Message;
|
|
import android.os.PersistableBundle;
|
|
import android.telephony.CarrierConfigManager;
|
|
import android.telephony.PinResult;
|
|
import android.telephony.SubscriptionInfo;
|
|
import android.telephony.SubscriptionManager;
|
|
import android.telephony.TelephonyManager;
|
|
import android.text.TextUtils;
|
|
import android.util.Log;
|
|
import android.view.Gravity;
|
|
import android.view.LayoutInflater;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
import android.view.WindowInsets.Type;
|
|
import android.view.WindowManager;
|
|
import android.widget.EditText;
|
|
import android.widget.ListView;
|
|
import android.widget.TabHost;
|
|
import android.widget.TabHost.OnTabChangeListener;
|
|
import android.widget.TabHost.TabContentFactory;
|
|
import android.widget.TabHost.TabSpec;
|
|
import android.widget.TabWidget;
|
|
import android.widget.TextView;
|
|
import android.widget.Toast;
|
|
|
|
import androidx.preference.Preference;
|
|
import androidx.preference.TwoStatePreference;
|
|
|
|
import com.android.settings.network.ProxySubscriptionManager;
|
|
import com.android.settings.network.SubscriptionUtil;
|
|
import com.android.settings.network.telephony.MobileNetworkUtils;
|
|
import com.android.settingslib.utils.StringUtil;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
/**
|
|
* Implements the preference screen to enable/disable ICC lock and
|
|
* also the dialogs to change the ICC PIN. In the former case, enabling/disabling
|
|
* the ICC lock will prompt the user for the current PIN.
|
|
* In the Change PIN case, it prompts the user for old pin, new pin and new pin
|
|
* again before attempting to change it. Calls the SimCard interface to execute
|
|
* these operations.
|
|
*
|
|
*/
|
|
public class IccLockSettings extends SettingsPreferenceFragment
|
|
implements EditPinPreference.OnPinEnteredListener {
|
|
private static final String TAG = "IccLockSettings";
|
|
private static final boolean DBG = false;
|
|
|
|
private static final int OFF_MODE = 0;
|
|
// State when enabling/disabling ICC lock
|
|
private static final int ICC_LOCK_MODE = 1;
|
|
// State when entering the old pin
|
|
private static final int ICC_OLD_MODE = 2;
|
|
// State when entering the new pin - first time
|
|
private static final int ICC_NEW_MODE = 3;
|
|
// State when entering the new pin - second time
|
|
private static final int ICC_REENTER_MODE = 4;
|
|
|
|
// Keys in xml file
|
|
private static final String PIN_DIALOG = "sim_pin";
|
|
private static final String PIN_TOGGLE = "sim_toggle";
|
|
// Keys in icicle
|
|
private static final String DIALOG_SUB_ID = "dialogSubId";
|
|
private static final String DIALOG_STATE = "dialogState";
|
|
private static final String DIALOG_PIN = "dialogPin";
|
|
private static final String DIALOG_ERROR = "dialogError";
|
|
private static final String ENABLE_TO_STATE = "enableState";
|
|
private static final String CURRENT_TAB = "currentTab";
|
|
|
|
// Save and restore inputted PIN code when configuration changed
|
|
// (ex. portrait<-->landscape) during change PIN code
|
|
private static final String OLD_PINCODE = "oldPinCode";
|
|
private static final String NEW_PINCODE = "newPinCode";
|
|
|
|
private static final int MIN_PIN_LENGTH = 4;
|
|
private static final int MAX_PIN_LENGTH = 8;
|
|
// Which dialog to show next when popped up
|
|
private int mDialogState = OFF_MODE;
|
|
|
|
private String mPin;
|
|
private String mOldPin;
|
|
private String mNewPin;
|
|
private String mError;
|
|
// Are we trying to enable or disable ICC lock?
|
|
private boolean mToState;
|
|
|
|
private TabHost mTabHost;
|
|
private TabWidget mTabWidget;
|
|
private ListView mListView;
|
|
|
|
private ProxySubscriptionManager mProxySubscriptionMgr;
|
|
|
|
private EditPinPreference mPinDialog;
|
|
private TwoStatePreference mPinToggle;
|
|
|
|
private Resources mRes;
|
|
|
|
// For async handler to identify request type
|
|
private static final int MSG_SIM_STATE_CHANGED = 102;
|
|
|
|
// @see android.widget.Toast$TN
|
|
private static final long LONG_DURATION_TIMEOUT = 7000;
|
|
|
|
private int mSlotId = -1;
|
|
private int mSubId;
|
|
private TelephonyManager mTelephonyManager;
|
|
|
|
// For replies from IccCard interface
|
|
private Handler mHandler = new Handler() {
|
|
public void handleMessage(Message msg) {
|
|
switch (msg.what) {
|
|
case MSG_SIM_STATE_CHANGED:
|
|
updatePreferences();
|
|
break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
};
|
|
|
|
private final BroadcastReceiver mSimStateReceiver = new BroadcastReceiver() {
|
|
public void onReceive(Context context, Intent intent) {
|
|
final String action = intent.getAction();
|
|
if (Intent.ACTION_SIM_STATE_CHANGED.equals(action)) {
|
|
mHandler.sendMessage(mHandler.obtainMessage(MSG_SIM_STATE_CHANGED));
|
|
}
|
|
}
|
|
};
|
|
|
|
// For top-level settings screen to query
|
|
private boolean isIccLockEnabled() {
|
|
mTelephonyManager = mTelephonyManager.createForSubscriptionId(mSubId);
|
|
return mTelephonyManager.isIccLockEnabled();
|
|
}
|
|
|
|
private String getSummary(Context context) {
|
|
final Resources res = context.getResources();
|
|
final String summary = isIccLockEnabled()
|
|
? res.getString(R.string.sim_lock_on)
|
|
: res.getString(R.string.sim_lock_off);
|
|
return summary;
|
|
}
|
|
|
|
@Override
|
|
public void onCreate(Bundle savedInstanceState) {
|
|
super.onCreate(savedInstanceState);
|
|
|
|
if (Utils.isMonkeyRunning() ||
|
|
!SubscriptionUtil.isSimHardwareVisible(getContext()) ||
|
|
MobileNetworkUtils.isMobileNetworkUserRestricted(getContext())) {
|
|
finish();
|
|
return;
|
|
}
|
|
|
|
// enable ProxySubscriptionMgr with Lifecycle support for all controllers
|
|
// live within this fragment
|
|
mProxySubscriptionMgr = ProxySubscriptionManager.getInstance(getContext());
|
|
mProxySubscriptionMgr.setLifecycle(getLifecycle());
|
|
|
|
mTelephonyManager = getContext().getSystemService(TelephonyManager.class);
|
|
|
|
addPreferencesFromResource(R.xml.sim_lock_settings);
|
|
|
|
mPinDialog = (EditPinPreference) findPreference(PIN_DIALOG);
|
|
mPinToggle = (TwoStatePreference) findPreference(PIN_TOGGLE);
|
|
if (savedInstanceState != null) {
|
|
if (savedInstanceState.containsKey(DIALOG_STATE)
|
|
&& restoreDialogStates(savedInstanceState)) {
|
|
Log.d(TAG, "onCreate: restore dialog for slotId=" + mSlotId + ", subId=" + mSubId);
|
|
} else if (savedInstanceState.containsKey(CURRENT_TAB)
|
|
&& restoreTabFocus(savedInstanceState)) {
|
|
Log.d(TAG, "onCreate: restore focus on slotId=" + mSlotId + ", subId=" + mSubId);
|
|
}
|
|
}
|
|
|
|
mPinDialog.setOnPinEnteredListener(this);
|
|
|
|
// Don't need any changes to be remembered
|
|
getPreferenceScreen().setPersistent(false);
|
|
|
|
mRes = getResources();
|
|
}
|
|
|
|
private boolean restoreDialogStates(Bundle savedInstanceState) {
|
|
final SubscriptionInfo subInfo = mProxySubscriptionMgr
|
|
.getActiveSubscriptionInfo(savedInstanceState.getInt(DIALOG_SUB_ID));
|
|
if (subInfo == null) {
|
|
return false;
|
|
}
|
|
|
|
final SubscriptionInfo visibleSubInfo = getVisibleSubscriptionInfoForSimSlotIndex(
|
|
subInfo.getSimSlotIndex());
|
|
if (visibleSubInfo == null) {
|
|
return false;
|
|
}
|
|
if (visibleSubInfo.getSubscriptionId() != subInfo.getSubscriptionId()) {
|
|
return false;
|
|
}
|
|
|
|
mSlotId = subInfo.getSimSlotIndex();
|
|
mSubId = subInfo.getSubscriptionId();
|
|
mDialogState = savedInstanceState.getInt(DIALOG_STATE);
|
|
mPin = savedInstanceState.getString(DIALOG_PIN);
|
|
mError = savedInstanceState.getString(DIALOG_ERROR);
|
|
mToState = savedInstanceState.getBoolean(ENABLE_TO_STATE);
|
|
|
|
// Restore inputted PIN code
|
|
switch (mDialogState) {
|
|
case ICC_NEW_MODE:
|
|
mOldPin = savedInstanceState.getString(OLD_PINCODE);
|
|
break;
|
|
|
|
case ICC_REENTER_MODE:
|
|
mOldPin = savedInstanceState.getString(OLD_PINCODE);
|
|
mNewPin = savedInstanceState.getString(NEW_PINCODE);
|
|
break;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private boolean restoreTabFocus(Bundle savedInstanceState) {
|
|
int slotId = 0;
|
|
try {
|
|
slotId = Integer.parseInt(savedInstanceState.getString(CURRENT_TAB));
|
|
} catch (NumberFormatException exception) {
|
|
return false;
|
|
}
|
|
|
|
final SubscriptionInfo subInfo = getVisibleSubscriptionInfoForSimSlotIndex(slotId);
|
|
if (subInfo == null) {
|
|
return false;
|
|
}
|
|
|
|
mSlotId = subInfo.getSimSlotIndex();
|
|
mSubId = subInfo.getSubscriptionId();
|
|
if (mTabHost != null) {
|
|
mTabHost.setCurrentTabByTag(getTagForSlotId(mSlotId));
|
|
}
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
|
Bundle savedInstanceState) {
|
|
|
|
final int numSims = mProxySubscriptionMgr.getActiveSubscriptionInfoCountMax();
|
|
final List<SubscriptionInfo> componenterList = new ArrayList<>();
|
|
|
|
for (int i = 0; i < numSims; ++i) {
|
|
final SubscriptionInfo subInfo = getVisibleSubscriptionInfoForSimSlotIndex(i);
|
|
if (subInfo != null) {
|
|
componenterList.add(subInfo);
|
|
}
|
|
}
|
|
|
|
if (componenterList.size() == 0) {
|
|
Log.e(TAG, "onCreateView: no sim info");
|
|
return super.onCreateView(inflater, container, savedInstanceState);
|
|
}
|
|
|
|
if (mSlotId < 0) {
|
|
mSlotId = componenterList.get(0).getSimSlotIndex();
|
|
mSubId = componenterList.get(0).getSubscriptionId();
|
|
Log.d(TAG, "onCreateView: default slotId=" + mSlotId + ", subId=" + mSubId);
|
|
}
|
|
|
|
if (componenterList.size() > 1) {
|
|
final View view = inflater.inflate(R.layout.icc_lock_tabs, container, false);
|
|
final ViewGroup prefs_container = (ViewGroup) view.findViewById(R.id.prefs_container);
|
|
Utils.prepareCustomPreferencesList(container, view, prefs_container, false);
|
|
final View prefs = super.onCreateView(inflater, prefs_container, savedInstanceState);
|
|
prefs_container.addView(prefs);
|
|
|
|
mTabHost = (TabHost) view.findViewById(android.R.id.tabhost);
|
|
mTabWidget = (TabWidget) view.findViewById(android.R.id.tabs);
|
|
mListView = (ListView) view.findViewById(android.R.id.list);
|
|
|
|
mTabHost.setup();
|
|
mTabHost.clearAllTabs();
|
|
|
|
for (SubscriptionInfo subInfo : componenterList) {
|
|
final int slot = subInfo.getSimSlotIndex();
|
|
final String tag = getTagForSlotId(slot);
|
|
mTabHost.addTab(buildTabSpec(tag,
|
|
String.valueOf(subInfo == null
|
|
? getContext().getString(R.string.sim_editor_title, slot + 1)
|
|
: SubscriptionUtil.getUniqueSubscriptionDisplayName(
|
|
subInfo, getContext()))));
|
|
}
|
|
|
|
mTabHost.setCurrentTabByTag(getTagForSlotId(mSlotId));
|
|
mTabHost.setOnTabChangedListener(mTabListener);
|
|
return view;
|
|
} else {
|
|
return super.onCreateView(inflater, container, savedInstanceState);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onViewCreated(View view, Bundle savedInstanceState) {
|
|
super.onViewCreated(view, savedInstanceState);
|
|
updatePreferences();
|
|
}
|
|
|
|
private void updatePreferences() {
|
|
|
|
final SubscriptionInfo sir = getVisibleSubscriptionInfoForSimSlotIndex(mSlotId);
|
|
final int subId = (sir != null) ? sir.getSubscriptionId()
|
|
: SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
|
|
|
if (mSubId != subId) {
|
|
mSubId = subId;
|
|
resetDialogState();
|
|
if ((mPinDialog != null) && mPinDialog.isDialogOpen()) {
|
|
mPinDialog.getDialog().dismiss();
|
|
}
|
|
}
|
|
|
|
if (mPinDialog != null) {
|
|
mPinDialog.setEnabled(sir != null);
|
|
}
|
|
if (mPinToggle != null) {
|
|
mPinToggle.setEnabled(sir != null);
|
|
|
|
if (sir != null) {
|
|
mPinToggle.setChecked(isIccLockEnabled());
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public int getMetricsCategory() {
|
|
return SettingsEnums.ICC_LOCK;
|
|
}
|
|
|
|
@Override
|
|
public void onResume() {
|
|
super.onResume();
|
|
|
|
// ACTION_SIM_STATE_CHANGED is sticky, so we'll receive current state after this call,
|
|
// which will call updatePreferences().
|
|
final IntentFilter filter = new IntentFilter(Intent.ACTION_SIM_STATE_CHANGED);
|
|
getContext().registerReceiver(mSimStateReceiver, filter);
|
|
|
|
if (mDialogState != OFF_MODE) {
|
|
showPinDialog();
|
|
} else {
|
|
// Prep for standard click on "Change PIN"
|
|
resetDialogState();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onPause() {
|
|
super.onPause();
|
|
getContext().unregisterReceiver(mSimStateReceiver);
|
|
}
|
|
|
|
@Override
|
|
public int getHelpResource() {
|
|
return R.string.help_url_icc_lock;
|
|
}
|
|
|
|
@Override
|
|
public void onSaveInstanceState(Bundle out) {
|
|
// Need to store this state for slider open/close
|
|
// There is one case where the dialog is popped up by the preference
|
|
// framework. In that case, let the preference framework store the
|
|
// dialog state. In other cases, where this activity manually launches
|
|
// the dialog, store the state of the dialog.
|
|
if (mPinDialog.isDialogOpen()) {
|
|
out.putInt(DIALOG_SUB_ID, mSubId);
|
|
out.putInt(DIALOG_STATE, mDialogState);
|
|
out.putString(DIALOG_PIN, mPinDialog.getEditText().getText().toString());
|
|
out.putString(DIALOG_ERROR, mError);
|
|
out.putBoolean(ENABLE_TO_STATE, mToState);
|
|
|
|
// Save inputted PIN code
|
|
switch (mDialogState) {
|
|
case ICC_NEW_MODE:
|
|
out.putString(OLD_PINCODE, mOldPin);
|
|
break;
|
|
|
|
case ICC_REENTER_MODE:
|
|
out.putString(OLD_PINCODE, mOldPin);
|
|
out.putString(NEW_PINCODE, mNewPin);
|
|
break;
|
|
}
|
|
} else {
|
|
super.onSaveInstanceState(out);
|
|
}
|
|
|
|
if (mTabHost != null) {
|
|
out.putString(CURRENT_TAB, mTabHost.getCurrentTabTag());
|
|
}
|
|
}
|
|
|
|
private void showPinDialog() {
|
|
if (mDialogState == OFF_MODE) {
|
|
return;
|
|
}
|
|
setDialogValues();
|
|
|
|
mPinDialog.showPinDialog();
|
|
|
|
final EditText editText = mPinDialog.getEditText();
|
|
if (!TextUtils.isEmpty(mPin) && editText != null) {
|
|
editText.setSelection(mPin.length());
|
|
}
|
|
}
|
|
|
|
private void setDialogValues() {
|
|
mPinDialog.setText(mPin);
|
|
String message = "";
|
|
switch (mDialogState) {
|
|
case ICC_LOCK_MODE:
|
|
message = mRes.getString(R.string.sim_enter_pin);
|
|
mPinDialog.setDialogTitle(mToState
|
|
? mRes.getString(R.string.sim_enable_sim_lock)
|
|
: mRes.getString(R.string.sim_disable_sim_lock));
|
|
break;
|
|
case ICC_OLD_MODE:
|
|
message = mRes.getString(R.string.sim_enter_old);
|
|
mPinDialog.setDialogTitle(mRes.getString(R.string.sim_change_pin));
|
|
break;
|
|
case ICC_NEW_MODE:
|
|
message = mRes.getString(R.string.sim_enter_new);
|
|
mPinDialog.setDialogTitle(mRes.getString(R.string.sim_change_pin));
|
|
break;
|
|
case ICC_REENTER_MODE:
|
|
message = mRes.getString(R.string.sim_reenter_new);
|
|
mPinDialog.setDialogTitle(mRes.getString(R.string.sim_change_pin));
|
|
break;
|
|
}
|
|
if (mError != null) {
|
|
message = mError + "\n" + message;
|
|
mError = null;
|
|
}
|
|
mPinDialog.setDialogMessage(message);
|
|
}
|
|
|
|
@Override
|
|
public void onPinEntered(EditPinPreference preference, boolean positiveResult) {
|
|
if (!positiveResult) {
|
|
resetDialogState();
|
|
return;
|
|
}
|
|
|
|
mPin = preference.getText();
|
|
if (!reasonablePin(mPin)) {
|
|
// inject error message and display dialog again
|
|
mError = mRes.getString(R.string.sim_invalid_pin_hint);
|
|
showPinDialog();
|
|
return;
|
|
}
|
|
switch (mDialogState) {
|
|
case ICC_LOCK_MODE:
|
|
tryChangeIccLockState();
|
|
break;
|
|
case ICC_OLD_MODE:
|
|
mOldPin = mPin;
|
|
mDialogState = ICC_NEW_MODE;
|
|
mError = null;
|
|
mPin = null;
|
|
showPinDialog();
|
|
break;
|
|
case ICC_NEW_MODE:
|
|
mNewPin = mPin;
|
|
mDialogState = ICC_REENTER_MODE;
|
|
mPin = null;
|
|
showPinDialog();
|
|
break;
|
|
case ICC_REENTER_MODE:
|
|
if (!mPin.equals(mNewPin)) {
|
|
mError = mRes.getString(R.string.sim_pins_dont_match);
|
|
mDialogState = ICC_NEW_MODE;
|
|
mPin = null;
|
|
showPinDialog();
|
|
} else {
|
|
mError = null;
|
|
tryChangePin();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean onPreferenceTreeClick(Preference preference) {
|
|
if (preference == mPinToggle) {
|
|
// Get the new, preferred state
|
|
mToState = mPinToggle.isChecked();
|
|
// Flip it back and pop up pin dialog
|
|
mPinToggle.setChecked(!mToState);
|
|
mDialogState = ICC_LOCK_MODE;
|
|
showPinDialog();
|
|
} else if (preference == mPinDialog) {
|
|
mDialogState = ICC_OLD_MODE;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private void tryChangeIccLockState() {
|
|
// Try to change icc lock. If it succeeds, toggle the lock state and
|
|
// reset dialog state. Else inject error message and show dialog again.
|
|
new SetIccLockEnabled(mToState, mPin).execute();
|
|
// Disable the setting till the response is received.
|
|
mPinToggle.setEnabled(false);
|
|
}
|
|
|
|
private class SetIccLockEnabled extends AsyncTask<Void, Void, PinResult> {
|
|
private final boolean mState;
|
|
private final String mPin;
|
|
|
|
private SetIccLockEnabled(boolean state, String pin) {
|
|
mState = state;
|
|
mPin = pin;
|
|
}
|
|
|
|
@Override
|
|
protected PinResult doInBackground(Void... params) {
|
|
mTelephonyManager = mTelephonyManager.createForSubscriptionId(mSubId);
|
|
return mTelephonyManager.setIccLockEnabled(mState, mPin);
|
|
}
|
|
|
|
@Override
|
|
protected void onPostExecute(PinResult pinResult) {
|
|
iccLockChanged(pinResult.getResult() == PinResult.PIN_RESULT_TYPE_SUCCESS /* success */,
|
|
pinResult.getAttemptsRemaining() /* attemptsRemaining */);
|
|
}
|
|
}
|
|
|
|
private void iccLockChanged(boolean success, int attemptsRemaining) {
|
|
Log.d(TAG, "iccLockChanged: success = " + success);
|
|
if (success) {
|
|
mPinToggle.setChecked(mToState);
|
|
} else {
|
|
if (attemptsRemaining >= 0) {
|
|
createCustomTextToast(getPinPasswordErrorMessage(attemptsRemaining));
|
|
} else {
|
|
if (mToState) {
|
|
Toast.makeText(getContext(), mRes.getString(
|
|
R.string.sim_pin_enable_failed), Toast.LENGTH_LONG).show();
|
|
} else {
|
|
Toast.makeText(getContext(), mRes.getString(
|
|
R.string.sim_pin_disable_failed), Toast.LENGTH_LONG).show();
|
|
}
|
|
}
|
|
}
|
|
mPinToggle.setEnabled(true);
|
|
resetDialogState();
|
|
}
|
|
|
|
private void createCustomTextToast(CharSequence errorMessage) {
|
|
// Cannot overlay Toast on PUK unlock screen.
|
|
// The window type of Toast is set by NotificationManagerService.
|
|
// It can't be overwritten by LayoutParams.type.
|
|
// Ovarlay a custom window with LayoutParams (TYPE_STATUS_BAR_PANEL) on PUK unlock screen.
|
|
final View v = ((LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE))
|
|
.inflate(com.android.internal.R.layout.transient_notification, null);
|
|
final TextView tv = (TextView) v.findViewById(com.android.internal.R.id.message);
|
|
tv.setText(errorMessage);
|
|
tv.setSingleLine(false);
|
|
|
|
final WindowManager.LayoutParams params = new WindowManager.LayoutParams();
|
|
final Configuration config = v.getContext().getResources().getConfiguration();
|
|
final int gravity = Gravity.getAbsoluteGravity(
|
|
getContext().getResources().getInteger(
|
|
com.android.internal.R.integer.config_toastDefaultGravity),
|
|
config.getLayoutDirection());
|
|
params.gravity = gravity;
|
|
if ((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.FILL_HORIZONTAL) {
|
|
params.horizontalWeight = 1.0f;
|
|
}
|
|
if ((gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.FILL_VERTICAL) {
|
|
params.verticalWeight = 1.0f;
|
|
}
|
|
params.y = getContext().getResources().getDimensionPixelSize(
|
|
com.android.internal.R.dimen.toast_y_offset);
|
|
|
|
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
|
|
params.width = WindowManager.LayoutParams.WRAP_CONTENT;
|
|
params.format = PixelFormat.TRANSLUCENT;
|
|
params.windowAnimations = com.android.internal.R.style.Animation_Toast;
|
|
params.type = WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
|
|
params.setFitInsetsTypes(params.getFitInsetsTypes() & ~Type.statusBars());
|
|
params.setTitle(errorMessage);
|
|
params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
|
|
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|
|
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
|
|
|
|
final WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
|
|
wm.addView(v, params);
|
|
|
|
mHandler.postDelayed(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
wm.removeViewImmediate(v);
|
|
}
|
|
}, LONG_DURATION_TIMEOUT);
|
|
}
|
|
|
|
private void iccPinChanged(boolean success, int attemptsRemaining) {
|
|
Log.d(TAG, "iccPinChanged: success = " + success);
|
|
if (!success) {
|
|
createCustomTextToast(getPinPasswordErrorMessage(attemptsRemaining));
|
|
} else {
|
|
Toast.makeText(getContext(), mRes.getString(R.string.sim_change_succeeded),
|
|
Toast.LENGTH_SHORT)
|
|
.show();
|
|
}
|
|
resetDialogState();
|
|
}
|
|
|
|
private void tryChangePin() {
|
|
new ChangeIccLockPin(mOldPin, mNewPin).execute();
|
|
}
|
|
|
|
private class ChangeIccLockPin extends AsyncTask<Void, Void, PinResult> {
|
|
private final String mOldPin;
|
|
private final String mNewPin;
|
|
|
|
private ChangeIccLockPin(String oldPin, String newPin) {
|
|
mOldPin = oldPin;
|
|
mNewPin = newPin;
|
|
}
|
|
|
|
@Override
|
|
protected PinResult doInBackground(Void... params) {
|
|
mTelephonyManager = mTelephonyManager.createForSubscriptionId(mSubId);
|
|
return mTelephonyManager.changeIccLockPin(mOldPin, mNewPin);
|
|
}
|
|
|
|
@Override
|
|
protected void onPostExecute(PinResult pinResult) {
|
|
iccPinChanged(pinResult.getResult() == PinResult.PIN_RESULT_TYPE_SUCCESS /* success */,
|
|
pinResult.getAttemptsRemaining() /* attemptsRemaining */);
|
|
}
|
|
}
|
|
|
|
private String getPinPasswordErrorMessage(int attemptsRemaining) {
|
|
String displayMessage;
|
|
|
|
if (attemptsRemaining == 0) {
|
|
displayMessage = mRes.getString(R.string.wrong_pin_code_pukked);
|
|
} else if (attemptsRemaining == 1) {
|
|
displayMessage = mRes.getString(R.string.wrong_pin_code_one, attemptsRemaining);
|
|
} else if (attemptsRemaining > 1) {
|
|
displayMessage = StringUtil.getIcuPluralsString(getPrefContext(), attemptsRemaining,
|
|
R.string.wrong_pin_code);
|
|
} else {
|
|
displayMessage = mRes.getString(R.string.pin_failed);
|
|
}
|
|
if (DBG) Log.d(TAG, "getPinPasswordErrorMessage:"
|
|
+ " attemptsRemaining=" + attemptsRemaining + " displayMessage=" + displayMessage);
|
|
return displayMessage;
|
|
}
|
|
|
|
private boolean reasonablePin(String pin) {
|
|
if (pin == null || pin.length() < MIN_PIN_LENGTH || pin.length() > MAX_PIN_LENGTH) {
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
private void resetDialogState() {
|
|
mError = null;
|
|
mDialogState = ICC_OLD_MODE; // Default for when Change PIN is clicked
|
|
mPin = "";
|
|
setDialogValues();
|
|
mDialogState = OFF_MODE;
|
|
}
|
|
|
|
private String getTagForSlotId(int slotId) {
|
|
return String.valueOf(slotId);
|
|
}
|
|
|
|
private int getSlotIndexFromTag(String tag) {
|
|
int slotId = -1;
|
|
try {
|
|
slotId = Integer.parseInt(tag);
|
|
} catch (NumberFormatException exception) {
|
|
}
|
|
return slotId;
|
|
}
|
|
|
|
private SubscriptionInfo getVisibleSubscriptionInfoForSimSlotIndex(int slotId) {
|
|
final List<SubscriptionInfo> subInfoList =
|
|
mProxySubscriptionMgr.getActiveSubscriptionsInfo();
|
|
if (subInfoList == null) {
|
|
return null;
|
|
}
|
|
final CarrierConfigManager carrierConfigManager = getContext().getSystemService(
|
|
CarrierConfigManager.class);
|
|
for (SubscriptionInfo subInfo : subInfoList) {
|
|
if ((isSubscriptionVisible(carrierConfigManager, subInfo)
|
|
&& (subInfo.getSimSlotIndex() == slotId))) {
|
|
return subInfo;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private boolean isSubscriptionVisible(CarrierConfigManager carrierConfigManager,
|
|
SubscriptionInfo subInfo) {
|
|
final PersistableBundle bundle = carrierConfigManager
|
|
.getConfigForSubId(subInfo.getSubscriptionId());
|
|
if (bundle == null) {
|
|
return false;
|
|
}
|
|
return !bundle.getBoolean(CarrierConfigManager.KEY_HIDE_SIM_LOCK_SETTINGS_BOOL);
|
|
}
|
|
|
|
private OnTabChangeListener mTabListener = new OnTabChangeListener() {
|
|
@Override
|
|
public void onTabChanged(String tabId) {
|
|
mSlotId = getSlotIndexFromTag(tabId);
|
|
|
|
// The User has changed tab; update the body.
|
|
updatePreferences();
|
|
}
|
|
};
|
|
|
|
private TabContentFactory mEmptyTabContent = new TabContentFactory() {
|
|
@Override
|
|
public View createTabContent(String tag) {
|
|
return new View(mTabHost.getContext());
|
|
}
|
|
};
|
|
|
|
private TabSpec buildTabSpec(String tag, String title) {
|
|
return mTabHost.newTabSpec(tag).setIndicator(title).setContent(
|
|
mEmptyTabContent);
|
|
}
|
|
}
|