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