OSDN Git Service

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