• 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.preference.EditTextPreference;
30 import android.preference.ListPreference;
31 import android.preference.MultiSelectListPreference;
32 import android.preference.Preference;
33 import android.preference.PreferenceActivity;
34 import android.preference.SwitchPreference;
35 import android.provider.Telephony;
36 import android.telephony.ServiceState;
37 import android.telephony.SubscriptionManager;
38 import android.telephony.TelephonyManager;
39 import android.text.TextUtils;
40 import android.util.Log;
41 import android.view.KeyEvent;
42 import android.view.Menu;
43 import android.view.MenuItem;
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
onCreate(Bundle icicle)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             mUri = intent.getData();
207         } else if (action.equals(Intent.ACTION_INSERT)) {
208             if (mFirstTime || icicle.getInt(SAVED_POS) == 0) {
209                 mUri = getContentResolver().insert(intent.getData(), new ContentValues());
210             } else {
211                 mUri = ContentUris.withAppendedId(Telephony.Carriers.CONTENT_URI,
212                         icicle.getInt(SAVED_POS));
213             }
214             mNewApn = true;
215             mMvnoTypeStr = intent.getStringExtra(ApnSettings.MVNO_TYPE);
216             mMvnoMatchDataStr = intent.getStringExtra(ApnSettings.MVNO_MATCH_DATA);
217             // If we were unable to create a new note, then just finish
218             // this activity.  A RESULT_CANCELED will be sent back to the
219             // original activity if they requested a result.
220             if (mUri == null) {
221                 Log.w(TAG, "Failed to insert new telephony provider into "
222                         + getIntent().getData());
223                 finish();
224                 return;
225             }
226 
227             // The new entry was created, so assume all will end well and
228             // set the result to be returned.
229             setResult(RESULT_OK, (new Intent()).setAction(mUri.toString()));
230 
231         } else {
232             finish();
233             return;
234         }
235 
236         mCursor = managedQuery(mUri, sProjection, null, null);
237         mCursor.moveToFirst();
238 
239         mTelephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
240 
241         fillUi();
242     }
243 
244     @Override
getMetricsCategory()245     protected int getMetricsCategory() {
246         return MetricsLogger.APN_EDITOR;
247     }
248 
249     @Override
onResume()250     public void onResume() {
251         super.onResume();
252         getPreferenceScreen().getSharedPreferences()
253                 .registerOnSharedPreferenceChangeListener(this);
254     }
255 
256     @Override
onPause()257     public void onPause() {
258         getPreferenceScreen().getSharedPreferences()
259                 .unregisterOnSharedPreferenceChangeListener(this);
260         super.onPause();
261     }
262 
fillUi()263     private void fillUi() {
264         if (mFirstTime) {
265             mFirstTime = false;
266             // Fill in all the values from the db in both text editor and summary
267             mName.setText(mCursor.getString(NAME_INDEX));
268             mApn.setText(mCursor.getString(APN_INDEX));
269             mProxy.setText(mCursor.getString(PROXY_INDEX));
270             mPort.setText(mCursor.getString(PORT_INDEX));
271             mUser.setText(mCursor.getString(USER_INDEX));
272             mServer.setText(mCursor.getString(SERVER_INDEX));
273             mPassword.setText(mCursor.getString(PASSWORD_INDEX));
274             mMmsProxy.setText(mCursor.getString(MMSPROXY_INDEX));
275             mMmsPort.setText(mCursor.getString(MMSPORT_INDEX));
276             mMmsc.setText(mCursor.getString(MMSC_INDEX));
277             mMcc.setText(mCursor.getString(MCC_INDEX));
278             mMnc.setText(mCursor.getString(MNC_INDEX));
279             mApnType.setText(mCursor.getString(TYPE_INDEX));
280             if (mNewApn) {
281                 String numeric = mTelephonyManager.getSimOperator(mSubId);
282                 // MCC is first 3 chars and then in 2 - 3 chars of MNC
283                 if (numeric != null && numeric.length() > 4) {
284                     // Country code
285                     String mcc = numeric.substring(0, 3);
286                     // Network code
287                     String mnc = numeric.substring(3);
288                     // Auto populate MNC and MCC for new entries, based on what SIM reports
289                     mMcc.setText(mcc);
290                     mMnc.setText(mnc);
291                     mCurMnc = mnc;
292                     mCurMcc = mcc;
293                 }
294             }
295             int authVal = mCursor.getInt(AUTH_TYPE_INDEX);
296             if (authVal != -1) {
297                 mAuthType.setValueIndex(authVal);
298             } else {
299                 mAuthType.setValue(null);
300             }
301 
302             mProtocol.setValue(mCursor.getString(PROTOCOL_INDEX));
303             mRoamingProtocol.setValue(mCursor.getString(ROAMING_PROTOCOL_INDEX));
304             mCarrierEnabled.setChecked(mCursor.getInt(CARRIER_ENABLED_INDEX)==1);
305             mBearerInitialVal = mCursor.getInt(BEARER_INDEX);
306 
307             HashSet<String> bearers = new HashSet<String>();
308             int bearerBitmask = mCursor.getInt(BEARER_BITMASK_INDEX);
309             if (bearerBitmask == 0) {
310                 if (mBearerInitialVal == 0) {
311                     bearers.add("" + 0);
312                 }
313             } else {
314                 int i = 1;
315                 while (bearerBitmask != 0) {
316                     if ((bearerBitmask & 1) == 1) {
317                         bearers.add("" + i);
318                     }
319                     bearerBitmask >>= 1;
320                     i++;
321                 }
322             }
323 
324             if (mBearerInitialVal != 0 && bearers.contains("" + mBearerInitialVal) == false) {
325                 // add mBearerInitialVal to bearers
326                 bearers.add("" + mBearerInitialVal);
327             }
328             mBearerMulti.setValues(bearers);
329 
330             mMvnoType.setValue(mCursor.getString(MVNO_TYPE_INDEX));
331             mMvnoMatchData.setEnabled(false);
332             mMvnoMatchData.setText(mCursor.getString(MVNO_MATCH_DATA_INDEX));
333             if (mNewApn && mMvnoTypeStr != null && mMvnoMatchDataStr != null) {
334                 mMvnoType.setValue(mMvnoTypeStr);
335                 mMvnoMatchData.setText(mMvnoMatchDataStr);
336             }
337         }
338 
339         mName.setSummary(checkNull(mName.getText()));
340         mApn.setSummary(checkNull(mApn.getText()));
341         mProxy.setSummary(checkNull(mProxy.getText()));
342         mPort.setSummary(checkNull(mPort.getText()));
343         mUser.setSummary(checkNull(mUser.getText()));
344         mServer.setSummary(checkNull(mServer.getText()));
345         mPassword.setSummary(starify(mPassword.getText()));
346         mMmsProxy.setSummary(checkNull(mMmsProxy.getText()));
347         mMmsPort.setSummary(checkNull(mMmsPort.getText()));
348         mMmsc.setSummary(checkNull(mMmsc.getText()));
349         mMcc.setSummary(checkNull(mMcc.getText()));
350         mMnc.setSummary(checkNull(mMnc.getText()));
351         mApnType.setSummary(checkNull(mApnType.getText()));
352 
353         String authVal = mAuthType.getValue();
354         if (authVal != null) {
355             int authValIndex = Integer.parseInt(authVal);
356             mAuthType.setValueIndex(authValIndex);
357 
358             String []values = mRes.getStringArray(R.array.apn_auth_entries);
359             mAuthType.setSummary(values[authValIndex]);
360         } else {
361             mAuthType.setSummary(sNotSet);
362         }
363 
364         mProtocol.setSummary(
365                 checkNull(protocolDescription(mProtocol.getValue(), mProtocol)));
366         mRoamingProtocol.setSummary(
367                 checkNull(protocolDescription(mRoamingProtocol.getValue(), mRoamingProtocol)));
368         mBearerMulti.setSummary(
369                 checkNull(bearerMultiDescription(mBearerMulti.getValues())));
370         mMvnoType.setSummary(
371                 checkNull(mvnoDescription(mMvnoType.getValue())));
372         mMvnoMatchData.setSummary(checkNull(mMvnoMatchData.getText()));
373         // allow user to edit carrier_enabled for some APN
374         boolean ceEditable = getResources().getBoolean(R.bool.config_allow_edit_carrier_enabled);
375         if (ceEditable) {
376             mCarrierEnabled.setEnabled(true);
377         } else {
378             mCarrierEnabled.setEnabled(false);
379         }
380     }
381 
382     /**
383      * Returns the UI choice (e.g., "IPv4/IPv6") corresponding to the given
384      * raw value of the protocol preference (e.g., "IPV4V6"). If unknown,
385      * return null.
386      */
protocolDescription(String raw, ListPreference protocol)387     private String protocolDescription(String raw, ListPreference protocol) {
388         int protocolIndex = protocol.findIndexOfValue(raw);
389         if (protocolIndex == -1) {
390             return null;
391         } else {
392             String[] values = mRes.getStringArray(R.array.apn_protocol_entries);
393             try {
394                 return values[protocolIndex];
395             } catch (ArrayIndexOutOfBoundsException e) {
396                 return null;
397             }
398         }
399     }
400 
bearerDescription(String raw)401     private String bearerDescription(String raw) {
402         int mBearerIndex = mBearerMulti.findIndexOfValue(raw);
403         if (mBearerIndex == -1) {
404             return null;
405         } else {
406             String[] values = mRes.getStringArray(R.array.bearer_entries);
407             try {
408                 return values[mBearerIndex];
409             } catch (ArrayIndexOutOfBoundsException e) {
410                 return null;
411             }
412         }
413     }
414 
bearerMultiDescription(Set<String> raw)415     private String bearerMultiDescription(Set<String> raw) {
416         String[] values = mRes.getStringArray(R.array.bearer_entries);
417         StringBuilder retVal = new StringBuilder();
418         boolean first = true;
419         for (String bearer : raw) {
420             int bearerIndex = mBearerMulti.findIndexOfValue(bearer);
421             try {
422                 if (first) {
423                     retVal.append(values[bearerIndex]);
424                     first = false;
425                 } else {
426                     retVal.append(", " + values[bearerIndex]);
427                 }
428             } catch (ArrayIndexOutOfBoundsException e) {
429                 // ignore
430             }
431         }
432         String val = retVal.toString();
433         if (!TextUtils.isEmpty(val)) {
434             return val;
435         }
436         return null;
437     }
438 
mvnoDescription(String newValue)439     private String mvnoDescription(String newValue) {
440         int mvnoIndex = mMvnoType.findIndexOfValue(newValue);
441         String oldValue = mMvnoType.getValue();
442 
443         if (mvnoIndex == -1) {
444             return null;
445         } else {
446             String[] values = mRes.getStringArray(R.array.mvno_type_entries);
447             if (values[mvnoIndex].equals("None")) {
448                 mMvnoMatchData.setEnabled(false);
449             } else {
450                 mMvnoMatchData.setEnabled(true);
451             }
452             if (newValue != null && newValue.equals(oldValue) == false) {
453                 if (values[mvnoIndex].equals("SPN")) {
454                     mMvnoMatchData.setText(mTelephonyManager.getSimOperatorName());
455                 } else if (values[mvnoIndex].equals("IMSI")) {
456                     String numeric = mTelephonyManager.getSimOperator(mSubId);
457                     mMvnoMatchData.setText(numeric + "x");
458                 } else if (values[mvnoIndex].equals("GID")) {
459                     mMvnoMatchData.setText(mTelephonyManager.getGroupIdLevel1());
460                 }
461             }
462 
463             try {
464                 return values[mvnoIndex];
465             } catch (ArrayIndexOutOfBoundsException e) {
466                 return null;
467             }
468         }
469     }
470 
onPreferenceChange(Preference preference, Object newValue)471     public boolean onPreferenceChange(Preference preference, Object newValue) {
472         String key = preference.getKey();
473         if (KEY_AUTH_TYPE.equals(key)) {
474             try {
475                 int index = Integer.parseInt((String) newValue);
476                 mAuthType.setValueIndex(index);
477 
478                 String []values = mRes.getStringArray(R.array.apn_auth_entries);
479                 mAuthType.setSummary(values[index]);
480             } catch (NumberFormatException e) {
481                 return false;
482             }
483         } else if (KEY_PROTOCOL.equals(key)) {
484             String protocol = protocolDescription((String) newValue, mProtocol);
485             if (protocol == null) {
486                 return false;
487             }
488             mProtocol.setSummary(protocol);
489             mProtocol.setValue((String) newValue);
490         } else if (KEY_ROAMING_PROTOCOL.equals(key)) {
491             String protocol = protocolDescription((String) newValue, mRoamingProtocol);
492             if (protocol == null) {
493                 return false;
494             }
495             mRoamingProtocol.setSummary(protocol);
496             mRoamingProtocol.setValue((String) newValue);
497         } else if (KEY_BEARER_MULTI.equals(key)) {
498             String bearer = bearerMultiDescription((Set<String>) newValue);
499             if (bearer == null) {
500                 return false;
501             }
502             mBearerMulti.setValues((Set<String>) newValue);
503             mBearerMulti.setSummary(bearer);
504         } else if (KEY_MVNO_TYPE.equals(key)) {
505             String mvno = mvnoDescription((String) newValue);
506             if (mvno == null) {
507                 return false;
508             }
509             mMvnoType.setValue((String) newValue);
510             mMvnoType.setSummary(mvno);
511         }
512 
513         return true;
514     }
515 
516     @Override
onCreateOptionsMenu(Menu menu)517     public boolean onCreateOptionsMenu(Menu menu) {
518         super.onCreateOptionsMenu(menu);
519         // If it's a new APN, then cancel will delete the new entry in onPause
520         if (!mNewApn) {
521             menu.add(0, MENU_DELETE, 0, R.string.menu_delete)
522                 .setIcon(R.drawable.ic_menu_delete);
523         }
524         menu.add(0, MENU_SAVE, 0, R.string.menu_save)
525             .setIcon(android.R.drawable.ic_menu_save);
526         menu.add(0, MENU_CANCEL, 0, R.string.menu_cancel)
527             .setIcon(android.R.drawable.ic_menu_close_clear_cancel);
528         return true;
529     }
530 
531     @Override
onOptionsItemSelected(MenuItem item)532     public boolean onOptionsItemSelected(MenuItem item) {
533         switch (item.getItemId()) {
534         case MENU_DELETE:
535             deleteApn();
536             return true;
537         case MENU_SAVE:
538             if (validateAndSave(false)) {
539                 finish();
540             }
541             return true;
542         case MENU_CANCEL:
543             if (mNewApn) {
544                 getContentResolver().delete(mUri, null, null);
545             }
546             finish();
547             return true;
548         }
549         return super.onOptionsItemSelected(item);
550     }
551 
552     @Override
onKeyDown(int keyCode, KeyEvent event)553     public boolean onKeyDown(int keyCode, KeyEvent event) {
554         switch (keyCode) {
555             case KeyEvent.KEYCODE_BACK: {
556                 if (validateAndSave(false)) {
557                     finish();
558                 }
559                 return true;
560             }
561         }
562         return super.onKeyDown(keyCode, event);
563     }
564 
565     @Override
onSaveInstanceState(Bundle icicle)566     protected void onSaveInstanceState(Bundle icicle) {
567         super.onSaveInstanceState(icicle);
568         if (validateAndSave(true)) {
569             icicle.putInt(SAVED_POS, mCursor.getInt(ID_INDEX));
570         }
571     }
572 
573     /**
574      * Check the key fields' validity and save if valid.
575      * @param force save even if the fields are not valid, if the app is
576      *        being suspended
577      * @return true if the data was saved
578      */
validateAndSave(boolean force)579     private boolean validateAndSave(boolean force) {
580         String name = checkNotSet(mName.getText());
581         String apn = checkNotSet(mApn.getText());
582         String mcc = checkNotSet(mMcc.getText());
583         String mnc = checkNotSet(mMnc.getText());
584 
585         if (getErrorMsg() != null && !force) {
586             showDialog(ERROR_DIALOG_ID);
587             return false;
588         }
589 
590         if (!mCursor.moveToFirst()) {
591             Log.w(TAG,
592                     "Could not go to the first row in the Cursor when saving data.");
593             return false;
594         }
595 
596         // If it's a new APN and a name or apn haven't been entered, then erase the entry
597         if (force && mNewApn && name.length() < 1 && apn.length() < 1) {
598             getContentResolver().delete(mUri, null, null);
599             return false;
600         }
601 
602         ContentValues values = new ContentValues();
603 
604         // Add a dummy name "Untitled", if the user exits the screen without adding a name but
605         // entered other information worth keeping.
606         values.put(Telephony.Carriers.NAME,
607                 name.length() < 1 ? getResources().getString(R.string.untitled_apn) : name);
608         values.put(Telephony.Carriers.APN, apn);
609         values.put(Telephony.Carriers.PROXY, checkNotSet(mProxy.getText()));
610         values.put(Telephony.Carriers.PORT, checkNotSet(mPort.getText()));
611         values.put(Telephony.Carriers.MMSPROXY, checkNotSet(mMmsProxy.getText()));
612         values.put(Telephony.Carriers.MMSPORT, checkNotSet(mMmsPort.getText()));
613         values.put(Telephony.Carriers.USER, checkNotSet(mUser.getText()));
614         values.put(Telephony.Carriers.SERVER, checkNotSet(mServer.getText()));
615         values.put(Telephony.Carriers.PASSWORD, checkNotSet(mPassword.getText()));
616         values.put(Telephony.Carriers.MMSC, checkNotSet(mMmsc.getText()));
617 
618         String authVal = mAuthType.getValue();
619         if (authVal != null) {
620             values.put(Telephony.Carriers.AUTH_TYPE, Integer.parseInt(authVal));
621         }
622 
623         values.put(Telephony.Carriers.PROTOCOL, checkNotSet(mProtocol.getValue()));
624         values.put(Telephony.Carriers.ROAMING_PROTOCOL, checkNotSet(mRoamingProtocol.getValue()));
625 
626         values.put(Telephony.Carriers.TYPE, checkNotSet(mApnType.getText()));
627 
628         values.put(Telephony.Carriers.MCC, mcc);
629         values.put(Telephony.Carriers.MNC, mnc);
630 
631         values.put(Telephony.Carriers.NUMERIC, mcc + mnc);
632 
633         if (mCurMnc != null && mCurMcc != null) {
634             if (mCurMnc.equals(mnc) && mCurMcc.equals(mcc)) {
635                 values.put(Telephony.Carriers.CURRENT, 1);
636             }
637         }
638 
639         Set<String> bearerSet = mBearerMulti.getValues();
640         int bearerBitmask = 0;
641         for (String bearer : bearerSet) {
642             if (Integer.parseInt(bearer) == 0) {
643                 bearerBitmask = 0;
644                 break;
645             } else {
646                 bearerBitmask |= ServiceState.getBitmaskForTech(Integer.parseInt(bearer));
647             }
648         }
649         values.put(Telephony.Carriers.BEARER_BITMASK, bearerBitmask);
650 
651         int bearerVal;
652         if (bearerBitmask == 0 || mBearerInitialVal == 0) {
653             bearerVal = 0;
654         } else if (ServiceState.bitmaskHasTech(bearerBitmask, mBearerInitialVal)) {
655             bearerVal = mBearerInitialVal;
656         } else {
657             // bearer field was being used but bitmask has changed now and does not include the
658             // initial bearer value -- setting bearer to 0 but maybe better behavior is to choose a
659             // random tech from the new bitmask??
660             bearerVal = 0;
661         }
662         values.put(Telephony.Carriers.BEARER, bearerVal);
663 
664         values.put(Telephony.Carriers.MVNO_TYPE, checkNotSet(mMvnoType.getValue()));
665         values.put(Telephony.Carriers.MVNO_MATCH_DATA, checkNotSet(mMvnoMatchData.getText()));
666 
667         values.put(Telephony.Carriers.CARRIER_ENABLED, mCarrierEnabled.isChecked() ? 1 : 0);
668         getContentResolver().update(mUri, values, null, null);
669 
670         return true;
671     }
672 
getErrorMsg()673     private String getErrorMsg() {
674         String errorMsg = null;
675 
676         String name = checkNotSet(mName.getText());
677         String apn = checkNotSet(mApn.getText());
678         String mcc = checkNotSet(mMcc.getText());
679         String mnc = checkNotSet(mMnc.getText());
680 
681         if (name.length() < 1) {
682             errorMsg = mRes.getString(R.string.error_name_empty);
683         } else if (apn.length() < 1) {
684             errorMsg = mRes.getString(R.string.error_apn_empty);
685         } else if (mcc.length() != 3) {
686             errorMsg = mRes.getString(R.string.error_mcc_not3);
687         } else if ((mnc.length() & 0xFFFE) != 2) {
688             errorMsg = mRes.getString(R.string.error_mnc_not23);
689         }
690 
691         return errorMsg;
692     }
693 
694     @Override
onCreateDialog(int id)695     protected Dialog onCreateDialog(int id) {
696 
697         if (id == ERROR_DIALOG_ID) {
698             String msg = getErrorMsg();
699 
700             return new AlertDialog.Builder(this)
701                     .setTitle(R.string.error_title)
702                     .setPositiveButton(android.R.string.ok, null)
703                     .setMessage(msg)
704                     .create();
705         }
706 
707         return super.onCreateDialog(id);
708     }
709 
710     @Override
onPrepareDialog(int id, Dialog dialog)711     protected void onPrepareDialog(int id, Dialog dialog) {
712         super.onPrepareDialog(id, dialog);
713 
714         if (id == ERROR_DIALOG_ID) {
715             String msg = getErrorMsg();
716 
717             if (msg != null) {
718                 ((AlertDialog)dialog).setMessage(msg);
719             }
720         }
721     }
722 
deleteApn()723     private void deleteApn() {
724         getContentResolver().delete(mUri, null, null);
725         finish();
726     }
727 
starify(String value)728     private String starify(String value) {
729         if (value == null || value.length() == 0) {
730             return sNotSet;
731         } else {
732             char[] password = new char[value.length()];
733             for (int i = 0; i < password.length; i++) {
734                 password[i] = '*';
735             }
736             return new String(password);
737         }
738     }
739 
checkNull(String value)740     private String checkNull(String value) {
741         if (value == null || value.length() == 0) {
742             return sNotSet;
743         } else {
744             return value;
745         }
746     }
747 
checkNotSet(String value)748     private String checkNotSet(String value) {
749         if (value == null || value.equals(sNotSet)) {
750             return "";
751         } else {
752             return value;
753         }
754     }
755 
onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)756     public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
757         Preference pref = findPreference(key);
758         if (pref != null) {
759             if (pref.equals(mPassword)){
760                 pref.setSummary(starify(sharedPreferences.getString(key, "")));
761             } else if (pref.equals(mCarrierEnabled) || pref.equals(mBearerMulti)) {
762                 // do nothing
763             } else {
764                 pref.setSummary(checkNull(sharedPreferences.getString(key, "")));
765             }
766         }
767     }
768 }
769