Home | History | Annotate | Download | only in settings
      1 /*
      2  * Copyright (C) 2006 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.settings;
     18 
     19 import android.app.AlertDialog;
     20 import android.app.Dialog;
     21 import android.content.ContentUris;
     22 import android.content.ContentValues;
     23 import android.content.Intent;
     24 import android.content.SharedPreferences;
     25 import android.content.res.Resources;
     26 import android.database.Cursor;
     27 import android.net.Uri;
     28 import android.os.Bundle;
     29 import android.os.SystemProperties;
     30 import android.preference.EditTextPreference;
     31 import android.preference.ListPreference;
     32 import android.preference.CheckBoxPreference;
     33 import android.preference.Preference;
     34 import android.preference.PreferenceActivity;
     35 import android.provider.Telephony;
     36 import android.telephony.TelephonyManager;
     37 import android.util.Log;
     38 import android.view.KeyEvent;
     39 import android.view.Menu;
     40 import android.view.MenuItem;
     41 
     42 import com.android.internal.telephony.Phone;
     43 import com.android.internal.telephony.PhoneConstants;
     44 import com.android.internal.telephony.RILConstants;
     45 import com.android.internal.telephony.TelephonyProperties;
     46 
     47 
     48 public class ApnEditor extends PreferenceActivity
     49         implements SharedPreferences.OnSharedPreferenceChangeListener,
     50                     Preference.OnPreferenceChangeListener {
     51 
     52     private final static String TAG = ApnEditor.class.getSimpleName();
     53 
     54     private final static String SAVED_POS = "pos";
     55     private final static String KEY_AUTH_TYPE = "auth_type";
     56     private final static String KEY_PROTOCOL = "apn_protocol";
     57     private final static String KEY_ROAMING_PROTOCOL = "apn_roaming_protocol";
     58     private final static String KEY_CARRIER_ENABLED = "carrier_enabled";
     59     private final static String KEY_BEARER = "bearer";
     60     private final static String KEY_MVNO_TYPE = "mvno_type";
     61 
     62     private static final int MENU_DELETE = Menu.FIRST;
     63     private static final int MENU_SAVE = Menu.FIRST + 1;
     64     private static final int MENU_CANCEL = Menu.FIRST + 2;
     65     private static final int ERROR_DIALOG_ID = 0;
     66 
     67     private static String sNotSet;
     68     private EditTextPreference mName;
     69     private EditTextPreference mApn;
     70     private EditTextPreference mProxy;
     71     private EditTextPreference mPort;
     72     private EditTextPreference mUser;
     73     private EditTextPreference mServer;
     74     private EditTextPreference mPassword;
     75     private EditTextPreference mMmsc;
     76     private EditTextPreference mMcc;
     77     private EditTextPreference mMnc;
     78     private EditTextPreference mMmsProxy;
     79     private EditTextPreference mMmsPort;
     80     private ListPreference mAuthType;
     81     private EditTextPreference mApnType;
     82     private ListPreference mProtocol;
     83     private ListPreference mRoamingProtocol;
     84     private CheckBoxPreference mCarrierEnabled;
     85     private ListPreference mBearer;
     86     private ListPreference mMvnoType;
     87     private EditTextPreference mMvnoMatchData;
     88 
     89     private String mCurMnc;
     90     private String mCurMcc;
     91 
     92     private Uri mUri;
     93     private Cursor mCursor;
     94     private boolean mNewApn;
     95     private boolean mFirstTime;
     96     private Resources mRes;
     97     private TelephonyManager mTelephonyManager;
     98 
     99     /**
    100      * Standard projection for the interesting columns of a normal note.
    101      */
    102     private static final String[] sProjection = new String[] {
    103             Telephony.Carriers._ID,     // 0
    104             Telephony.Carriers.NAME,    // 1
    105             Telephony.Carriers.APN,     // 2
    106             Telephony.Carriers.PROXY,   // 3
    107             Telephony.Carriers.PORT,    // 4
    108             Telephony.Carriers.USER,    // 5
    109             Telephony.Carriers.SERVER,  // 6
    110             Telephony.Carriers.PASSWORD, // 7
    111             Telephony.Carriers.MMSC, // 8
    112             Telephony.Carriers.MCC, // 9
    113             Telephony.Carriers.MNC, // 10
    114             Telephony.Carriers.NUMERIC, // 11
    115             Telephony.Carriers.MMSPROXY,// 12
    116             Telephony.Carriers.MMSPORT, // 13
    117             Telephony.Carriers.AUTH_TYPE, // 14
    118             Telephony.Carriers.TYPE, // 15
    119             Telephony.Carriers.PROTOCOL, // 16
    120             Telephony.Carriers.CARRIER_ENABLED, // 17
    121             Telephony.Carriers.BEARER, // 18
    122             Telephony.Carriers.ROAMING_PROTOCOL, // 19
    123             Telephony.Carriers.MVNO_TYPE,   // 20
    124             Telephony.Carriers.MVNO_MATCH_DATA  // 21
    125     };
    126 
    127     private static final int ID_INDEX = 0;
    128     private static final int NAME_INDEX = 1;
    129     private static final int APN_INDEX = 2;
    130     private static final int PROXY_INDEX = 3;
    131     private static final int PORT_INDEX = 4;
    132     private static final int USER_INDEX = 5;
    133     private static final int SERVER_INDEX = 6;
    134     private static final int PASSWORD_INDEX = 7;
    135     private static final int MMSC_INDEX = 8;
    136     private static final int MCC_INDEX = 9;
    137     private static final int MNC_INDEX = 10;
    138     private static final int MMSPROXY_INDEX = 12;
    139     private static final int MMSPORT_INDEX = 13;
    140     private static final int AUTH_TYPE_INDEX = 14;
    141     private static final int TYPE_INDEX = 15;
    142     private static final int PROTOCOL_INDEX = 16;
    143     private static final int CARRIER_ENABLED_INDEX = 17;
    144     private static final int BEARER_INDEX = 18;
    145     private static final int ROAMING_PROTOCOL_INDEX = 19;
    146     private static final int MVNO_TYPE_INDEX = 20;
    147     private static final int MVNO_MATCH_DATA_INDEX = 21;
    148 
    149 
    150     @Override
    151     protected void onCreate(Bundle icicle) {
    152         super.onCreate(icicle);
    153 
    154         addPreferencesFromResource(R.xml.apn_editor);
    155 
    156         sNotSet = getResources().getString(R.string.apn_not_set);
    157         mName = (EditTextPreference) findPreference("apn_name");
    158         mApn = (EditTextPreference) findPreference("apn_apn");
    159         mProxy = (EditTextPreference) findPreference("apn_http_proxy");
    160         mPort = (EditTextPreference) findPreference("apn_http_port");
    161         mUser = (EditTextPreference) findPreference("apn_user");
    162         mServer = (EditTextPreference) findPreference("apn_server");
    163         mPassword = (EditTextPreference) findPreference("apn_password");
    164         mMmsProxy = (EditTextPreference) findPreference("apn_mms_proxy");
    165         mMmsPort = (EditTextPreference) findPreference("apn_mms_port");
    166         mMmsc = (EditTextPreference) findPreference("apn_mmsc");
    167         mMcc = (EditTextPreference) findPreference("apn_mcc");
    168         mMnc = (EditTextPreference) findPreference("apn_mnc");
    169         mApnType = (EditTextPreference) findPreference("apn_type");
    170 
    171         mAuthType = (ListPreference) findPreference(KEY_AUTH_TYPE);
    172         mAuthType.setOnPreferenceChangeListener(this);
    173 
    174         mProtocol = (ListPreference) findPreference(KEY_PROTOCOL);
    175         mProtocol.setOnPreferenceChangeListener(this);
    176 
    177         mRoamingProtocol = (ListPreference) findPreference(KEY_ROAMING_PROTOCOL);
    178         mRoamingProtocol.setOnPreferenceChangeListener(this);
    179 
    180         mCarrierEnabled = (CheckBoxPreference) findPreference(KEY_CARRIER_ENABLED);
    181 
    182         mBearer = (ListPreference) findPreference(KEY_BEARER);
    183         mBearer.setOnPreferenceChangeListener(this);
    184 
    185         mMvnoType = (ListPreference) findPreference(KEY_MVNO_TYPE);
    186         mMvnoType.setOnPreferenceChangeListener(this);
    187         mMvnoMatchData = (EditTextPreference) findPreference("mvno_match_data");
    188 
    189         mRes = getResources();
    190 
    191         final Intent intent = getIntent();
    192         final String action = intent.getAction();
    193 
    194         mFirstTime = icicle == null;
    195 
    196         if (action.equals(Intent.ACTION_EDIT)) {
    197             mUri = intent.getData();
    198         } else if (action.equals(Intent.ACTION_INSERT)) {
    199             if (mFirstTime || icicle.getInt(SAVED_POS) == 0) {
    200                 mUri = getContentResolver().insert(intent.getData(), new ContentValues());
    201             } else {
    202                 mUri = ContentUris.withAppendedId(Telephony.Carriers.CONTENT_URI,
    203                         icicle.getInt(SAVED_POS));
    204             }
    205             mNewApn = true;
    206             // If we were unable to create a new note, then just finish
    207             // this activity.  A RESULT_CANCELED will be sent back to the
    208             // original activity if they requested a result.
    209             if (mUri == null) {
    210                 Log.w(TAG, "Failed to insert new telephony provider into "
    211                         + getIntent().getData());
    212                 finish();
    213                 return;
    214             }
    215 
    216             // The new entry was created, so assume all will end well and
    217             // set the result to be returned.
    218             setResult(RESULT_OK, (new Intent()).setAction(mUri.toString()));
    219 
    220         } else {
    221             finish();
    222             return;
    223         }
    224 
    225         mCursor = managedQuery(mUri, sProjection, null, null);
    226         mCursor.moveToFirst();
    227 
    228         mTelephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
    229 
    230         fillUi();
    231     }
    232 
    233     @Override
    234     public void onResume() {
    235         super.onResume();
    236         getPreferenceScreen().getSharedPreferences()
    237                 .registerOnSharedPreferenceChangeListener(this);
    238     }
    239 
    240     @Override
    241     public void onPause() {
    242         getPreferenceScreen().getSharedPreferences()
    243                 .unregisterOnSharedPreferenceChangeListener(this);
    244         super.onPause();
    245     }
    246 
    247     private void fillUi() {
    248         if (mFirstTime) {
    249             mFirstTime = false;
    250             // Fill in all the values from the db in both text editor and summary
    251             mName.setText(mCursor.getString(NAME_INDEX));
    252             mApn.setText(mCursor.getString(APN_INDEX));
    253             mProxy.setText(mCursor.getString(PROXY_INDEX));
    254             mPort.setText(mCursor.getString(PORT_INDEX));
    255             mUser.setText(mCursor.getString(USER_INDEX));
    256             mServer.setText(mCursor.getString(SERVER_INDEX));
    257             mPassword.setText(mCursor.getString(PASSWORD_INDEX));
    258             mMmsProxy.setText(mCursor.getString(MMSPROXY_INDEX));
    259             mMmsPort.setText(mCursor.getString(MMSPORT_INDEX));
    260             mMmsc.setText(mCursor.getString(MMSC_INDEX));
    261             mMcc.setText(mCursor.getString(MCC_INDEX));
    262             mMnc.setText(mCursor.getString(MNC_INDEX));
    263             mApnType.setText(mCursor.getString(TYPE_INDEX));
    264             if (mNewApn) {
    265                 String numeric =
    266                     SystemProperties.get(TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC);
    267                 // MCC is first 3 chars and then in 2 - 3 chars of MNC
    268                 if (numeric != null && numeric.length() > 4) {
    269                     // Country code
    270                     String mcc = numeric.substring(0, 3);
    271                     // Network code
    272                     String mnc = numeric.substring(3);
    273                     // Auto populate MNC and MCC for new entries, based on what SIM reports
    274                     mMcc.setText(mcc);
    275                     mMnc.setText(mnc);
    276                     mCurMnc = mnc;
    277                     mCurMcc = mcc;
    278                 }
    279             }
    280             int authVal = mCursor.getInt(AUTH_TYPE_INDEX);
    281             if (authVal != -1) {
    282                 mAuthType.setValueIndex(authVal);
    283             } else {
    284                 mAuthType.setValue(null);
    285             }
    286 
    287             mProtocol.setValue(mCursor.getString(PROTOCOL_INDEX));
    288             mRoamingProtocol.setValue(mCursor.getString(ROAMING_PROTOCOL_INDEX));
    289             mCarrierEnabled.setChecked(mCursor.getInt(CARRIER_ENABLED_INDEX)==1);
    290             mBearer.setValue(mCursor.getString(BEARER_INDEX));
    291             mMvnoType.setValue(mCursor.getString(MVNO_TYPE_INDEX));
    292             mMvnoMatchData.setEnabled(false);
    293             mMvnoMatchData.setText(mCursor.getString(MVNO_MATCH_DATA_INDEX));
    294         }
    295 
    296         mName.setSummary(checkNull(mName.getText()));
    297         mApn.setSummary(checkNull(mApn.getText()));
    298         mProxy.setSummary(checkNull(mProxy.getText()));
    299         mPort.setSummary(checkNull(mPort.getText()));
    300         mUser.setSummary(checkNull(mUser.getText()));
    301         mServer.setSummary(checkNull(mServer.getText()));
    302         mPassword.setSummary(starify(mPassword.getText()));
    303         mMmsProxy.setSummary(checkNull(mMmsProxy.getText()));
    304         mMmsPort.setSummary(checkNull(mMmsPort.getText()));
    305         mMmsc.setSummary(checkNull(mMmsc.getText()));
    306         mMcc.setSummary(checkNull(mMcc.getText()));
    307         mMnc.setSummary(checkNull(mMnc.getText()));
    308         mApnType.setSummary(checkNull(mApnType.getText()));
    309 
    310         String authVal = mAuthType.getValue();
    311         if (authVal != null) {
    312             int authValIndex = Integer.parseInt(authVal);
    313             mAuthType.setValueIndex(authValIndex);
    314 
    315             String []values = mRes.getStringArray(R.array.apn_auth_entries);
    316             mAuthType.setSummary(values[authValIndex]);
    317         } else {
    318             mAuthType.setSummary(sNotSet);
    319         }
    320 
    321         mProtocol.setSummary(
    322                 checkNull(protocolDescription(mProtocol.getValue(), mProtocol)));
    323         mRoamingProtocol.setSummary(
    324                 checkNull(protocolDescription(mRoamingProtocol.getValue(), mRoamingProtocol)));
    325         mBearer.setSummary(
    326                 checkNull(bearerDescription(mBearer.getValue())));
    327         mMvnoType.setSummary(
    328                 checkNull(mvnoDescription(mMvnoType.getValue())));
    329         mMvnoMatchData.setSummary(checkNull(mMvnoMatchData.getText()));
    330         // allow user to edit carrier_enabled for some APN
    331         boolean ceEditable = getResources().getBoolean(R.bool.config_allow_edit_carrier_enabled);
    332         if (ceEditable) {
    333             mCarrierEnabled.setEnabled(true);
    334         } else {
    335             mCarrierEnabled.setEnabled(false);
    336         }
    337     }
    338 
    339     /**
    340      * Returns the UI choice (e.g., "IPv4/IPv6") corresponding to the given
    341      * raw value of the protocol preference (e.g., "IPV4V6"). If unknown,
    342      * return null.
    343      */
    344     private String protocolDescription(String raw, ListPreference protocol) {
    345         int protocolIndex = protocol.findIndexOfValue(raw);
    346         if (protocolIndex == -1) {
    347             return null;
    348         } else {
    349             String[] values = mRes.getStringArray(R.array.apn_protocol_entries);
    350             try {
    351                 return values[protocolIndex];
    352             } catch (ArrayIndexOutOfBoundsException e) {
    353                 return null;
    354             }
    355         }
    356     }
    357 
    358     private String bearerDescription(String raw) {
    359         int mBearerIndex = mBearer.findIndexOfValue(raw);
    360         if (mBearerIndex == -1) {
    361             return null;
    362         } else {
    363             String[] values = mRes.getStringArray(R.array.bearer_entries);
    364             try {
    365                 return values[mBearerIndex];
    366             } catch (ArrayIndexOutOfBoundsException e) {
    367                 return null;
    368             }
    369         }
    370     }
    371 
    372     private String mvnoDescription(String newValue) {
    373         int mvnoIndex = mMvnoType.findIndexOfValue(newValue);
    374         String oldValue = mMvnoType.getValue();
    375 
    376         if (mvnoIndex == -1) {
    377             return null;
    378         } else {
    379             String[] values = mRes.getStringArray(R.array.mvno_type_entries);
    380             if (values[mvnoIndex].equals("None")) {
    381                 mMvnoMatchData.setEnabled(false);
    382             } else {
    383                 mMvnoMatchData.setEnabled(true);
    384             }
    385             if (newValue != null && newValue.equals(oldValue) == false) {
    386                 if (values[mvnoIndex].equals("SPN")) {
    387                     mMvnoMatchData.setText(mTelephonyManager.getSimOperatorName());
    388                 } else if (values[mvnoIndex].equals("IMSI")) {
    389                     String numeric =
    390                             SystemProperties.get(TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC);
    391                     mMvnoMatchData.setText(numeric + "x");
    392                 } else if (values[mvnoIndex].equals("GID")) {
    393                     mMvnoMatchData.setText(mTelephonyManager.getGroupIdLevel1());
    394                 }
    395             }
    396 
    397             try {
    398                 return values[mvnoIndex];
    399             } catch (ArrayIndexOutOfBoundsException e) {
    400                 return null;
    401             }
    402         }
    403     }
    404 
    405     public boolean onPreferenceChange(Preference preference, Object newValue) {
    406         String key = preference.getKey();
    407         if (KEY_AUTH_TYPE.equals(key)) {
    408             try {
    409                 int index = Integer.parseInt((String) newValue);
    410                 mAuthType.setValueIndex(index);
    411 
    412                 String []values = mRes.getStringArray(R.array.apn_auth_entries);
    413                 mAuthType.setSummary(values[index]);
    414             } catch (NumberFormatException e) {
    415                 return false;
    416             }
    417         } else if (KEY_PROTOCOL.equals(key)) {
    418             String protocol = protocolDescription((String) newValue, mProtocol);
    419             if (protocol == null) {
    420                 return false;
    421             }
    422             mProtocol.setSummary(protocol);
    423             mProtocol.setValue((String) newValue);
    424         } else if (KEY_ROAMING_PROTOCOL.equals(key)) {
    425             String protocol = protocolDescription((String) newValue, mRoamingProtocol);
    426             if (protocol == null) {
    427                 return false;
    428             }
    429             mRoamingProtocol.setSummary(protocol);
    430             mRoamingProtocol.setValue((String) newValue);
    431         } else if (KEY_BEARER.equals(key)) {
    432             String bearer = bearerDescription((String) newValue);
    433             if (bearer == null) {
    434                 return false;
    435             }
    436             mBearer.setValue((String) newValue);
    437             mBearer.setSummary(bearer);
    438         } else if (KEY_MVNO_TYPE.equals(key)) {
    439             String mvno = mvnoDescription((String) newValue);
    440             if (mvno == null) {
    441                 return false;
    442             }
    443             mMvnoType.setValue((String) newValue);
    444             mMvnoType.setSummary(mvno);
    445         }
    446 
    447         return true;
    448     }
    449 
    450     @Override
    451     public boolean onCreateOptionsMenu(Menu menu) {
    452         super.onCreateOptionsMenu(menu);
    453         // If it's a new APN, then cancel will delete the new entry in onPause
    454         if (!mNewApn) {
    455             menu.add(0, MENU_DELETE, 0, R.string.menu_delete)
    456                 .setIcon(R.drawable.ic_menu_delete);
    457         }
    458         menu.add(0, MENU_SAVE, 0, R.string.menu_save)
    459             .setIcon(android.R.drawable.ic_menu_save);
    460         menu.add(0, MENU_CANCEL, 0, R.string.menu_cancel)
    461             .setIcon(android.R.drawable.ic_menu_close_clear_cancel);
    462         return true;
    463     }
    464 
    465     @Override
    466     public boolean onOptionsItemSelected(MenuItem item) {
    467         switch (item.getItemId()) {
    468         case MENU_DELETE:
    469             deleteApn();
    470             return true;
    471         case MENU_SAVE:
    472             if (validateAndSave(false)) {
    473                 finish();
    474             }
    475             return true;
    476         case MENU_CANCEL:
    477             if (mNewApn) {
    478                 getContentResolver().delete(mUri, null, null);
    479             }
    480             finish();
    481             return true;
    482         }
    483         return super.onOptionsItemSelected(item);
    484     }
    485 
    486     @Override
    487     public boolean onKeyDown(int keyCode, KeyEvent event) {
    488         switch (keyCode) {
    489             case KeyEvent.KEYCODE_BACK: {
    490                 if (validateAndSave(false)) {
    491                     finish();
    492                 }
    493                 return true;
    494             }
    495         }
    496         return super.onKeyDown(keyCode, event);
    497     }
    498 
    499     @Override
    500     protected void onSaveInstanceState(Bundle icicle) {
    501         super.onSaveInstanceState(icicle);
    502         if (validateAndSave(true)) {
    503             icicle.putInt(SAVED_POS, mCursor.getInt(ID_INDEX));
    504         }
    505     }
    506 
    507     /**
    508      * Check the key fields' validity and save if valid.
    509      * @param force save even if the fields are not valid, if the app is
    510      *        being suspended
    511      * @return true if the data was saved
    512      */
    513     private boolean validateAndSave(boolean force) {
    514         String name = checkNotSet(mName.getText());
    515         String apn = checkNotSet(mApn.getText());
    516         String mcc = checkNotSet(mMcc.getText());
    517         String mnc = checkNotSet(mMnc.getText());
    518 
    519         if (getErrorMsg() != null && !force) {
    520             showDialog(ERROR_DIALOG_ID);
    521             return false;
    522         }
    523 
    524         if (!mCursor.moveToFirst()) {
    525             Log.w(TAG,
    526                     "Could not go to the first row in the Cursor when saving data.");
    527             return false;
    528         }
    529 
    530         // If it's a new APN and a name or apn haven't been entered, then erase the entry
    531         if (force && mNewApn && name.length() < 1 && apn.length() < 1) {
    532             getContentResolver().delete(mUri, null, null);
    533             return false;
    534         }
    535 
    536         ContentValues values = new ContentValues();
    537 
    538         // Add a dummy name "Untitled", if the user exits the screen without adding a name but
    539         // entered other information worth keeping.
    540         values.put(Telephony.Carriers.NAME,
    541                 name.length() < 1 ? getResources().getString(R.string.untitled_apn) : name);
    542         values.put(Telephony.Carriers.APN, apn);
    543         values.put(Telephony.Carriers.PROXY, checkNotSet(mProxy.getText()));
    544         values.put(Telephony.Carriers.PORT, checkNotSet(mPort.getText()));
    545         values.put(Telephony.Carriers.MMSPROXY, checkNotSet(mMmsProxy.getText()));
    546         values.put(Telephony.Carriers.MMSPORT, checkNotSet(mMmsPort.getText()));
    547         values.put(Telephony.Carriers.USER, checkNotSet(mUser.getText()));
    548         values.put(Telephony.Carriers.SERVER, checkNotSet(mServer.getText()));
    549         values.put(Telephony.Carriers.PASSWORD, checkNotSet(mPassword.getText()));
    550         values.put(Telephony.Carriers.MMSC, checkNotSet(mMmsc.getText()));
    551 
    552         String authVal = mAuthType.getValue();
    553         if (authVal != null) {
    554             values.put(Telephony.Carriers.AUTH_TYPE, Integer.parseInt(authVal));
    555         }
    556 
    557         values.put(Telephony.Carriers.PROTOCOL, checkNotSet(mProtocol.getValue()));
    558         values.put(Telephony.Carriers.ROAMING_PROTOCOL, checkNotSet(mRoamingProtocol.getValue()));
    559 
    560         values.put(Telephony.Carriers.TYPE, checkNotSet(mApnType.getText()));
    561 
    562         values.put(Telephony.Carriers.MCC, mcc);
    563         values.put(Telephony.Carriers.MNC, mnc);
    564 
    565         values.put(Telephony.Carriers.NUMERIC, mcc + mnc);
    566 
    567         if (mCurMnc != null && mCurMcc != null) {
    568             if (mCurMnc.equals(mnc) && mCurMcc.equals(mcc)) {
    569                 values.put(Telephony.Carriers.CURRENT, 1);
    570             }
    571         }
    572 
    573         String bearerVal = mBearer.getValue();
    574         if (bearerVal != null) {
    575             values.put(Telephony.Carriers.BEARER, Integer.parseInt(bearerVal));
    576         }
    577 
    578         values.put(Telephony.Carriers.MVNO_TYPE, checkNotSet(mMvnoType.getValue()));
    579         values.put(Telephony.Carriers.MVNO_MATCH_DATA, checkNotSet(mMvnoMatchData.getText()));
    580 
    581         values.put(Telephony.Carriers.CARRIER_ENABLED, mCarrierEnabled.isChecked() ? 1 : 0);
    582         getContentResolver().update(mUri, values, null, null);
    583 
    584         return true;
    585     }
    586 
    587     private String getErrorMsg() {
    588         String errorMsg = null;
    589 
    590         String name = checkNotSet(mName.getText());
    591         String apn = checkNotSet(mApn.getText());
    592         String mcc = checkNotSet(mMcc.getText());
    593         String mnc = checkNotSet(mMnc.getText());
    594 
    595         if (name.length() < 1) {
    596             errorMsg = mRes.getString(R.string.error_name_empty);
    597         } else if (apn.length() < 1) {
    598             errorMsg = mRes.getString(R.string.error_apn_empty);
    599         } else if (mcc.length() != 3) {
    600             errorMsg = mRes.getString(R.string.error_mcc_not3);
    601         } else if ((mnc.length() & 0xFFFE) != 2) {
    602             errorMsg = mRes.getString(R.string.error_mnc_not23);
    603         }
    604 
    605         return errorMsg;
    606     }
    607 
    608     @Override
    609     protected Dialog onCreateDialog(int id) {
    610 
    611         if (id == ERROR_DIALOG_ID) {
    612             String msg = getErrorMsg();
    613 
    614             return new AlertDialog.Builder(this)
    615                     .setTitle(R.string.error_title)
    616                     .setPositiveButton(android.R.string.ok, null)
    617                     .setMessage(msg)
    618                     .create();
    619         }
    620 
    621         return super.onCreateDialog(id);
    622     }
    623 
    624     @Override
    625     protected void onPrepareDialog(int id, Dialog dialog) {
    626         super.onPrepareDialog(id, dialog);
    627 
    628         if (id == ERROR_DIALOG_ID) {
    629             String msg = getErrorMsg();
    630 
    631             if (msg != null) {
    632                 ((AlertDialog)dialog).setMessage(msg);
    633             }
    634         }
    635     }
    636 
    637     private void deleteApn() {
    638         getContentResolver().delete(mUri, null, null);
    639         finish();
    640     }
    641 
    642     private String starify(String value) {
    643         if (value == null || value.length() == 0) {
    644             return sNotSet;
    645         } else {
    646             char[] password = new char[value.length()];
    647             for (int i = 0; i < password.length; i++) {
    648                 password[i] = '*';
    649             }
    650             return new String(password);
    651         }
    652     }
    653 
    654     private String checkNull(String value) {
    655         if (value == null || value.length() == 0) {
    656             return sNotSet;
    657         } else {
    658             return value;
    659         }
    660     }
    661 
    662     private String checkNotSet(String value) {
    663         if (value == null || value.equals(sNotSet)) {
    664             return "";
    665         } else {
    666             return value;
    667         }
    668     }
    669 
    670     public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
    671         Preference pref = findPreference(key);
    672         if (pref != null) {
    673             if (pref.equals(mPassword)){
    674                 pref.setSummary(starify(sharedPreferences.getString(key, "")));
    675             } else if (pref.equals(mCarrierEnabled)) {
    676                 // do nothing
    677             } else {
    678                 pref.setSummary(checkNull(sharedPreferences.getString(key, "")));
    679             }
    680         }
    681     }
    682 }
    683