Home | History | Annotate | Download | only in settings
      1 /*
      2  * Copyright (C) 2006 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.settings;
     18 
     19 import android.app.AlertDialog;
     20 import android.content.ContentUris;
     21 import android.content.ContentValues;
     22 import android.content.Intent;
     23 import android.content.SharedPreferences;
     24 import android.content.res.Resources;
     25 import android.database.Cursor;
     26 import android.net.Uri;
     27 import android.os.Bundle;
     28 import android.os.SystemProperties;
     29 import android.preference.EditTextPreference;
     30 import android.preference.ListPreference;
     31 import android.preference.Preference;
     32 import android.preference.PreferenceActivity;
     33 import android.provider.Telephony;
     34 import android.util.Log;
     35 import android.view.KeyEvent;
     36 import android.view.Menu;
     37 import android.view.MenuItem;
     38 
     39 import com.android.internal.telephony.TelephonyProperties;
     40 
     41 
     42 public class ApnEditor extends PreferenceActivity
     43         implements SharedPreferences.OnSharedPreferenceChangeListener,
     44                     Preference.OnPreferenceChangeListener {
     45 
     46     private final static String TAG = ApnEditor.class.getSimpleName();
     47 
     48     private final static String SAVED_POS = "pos";
     49     private final static String KEY_AUTH_TYPE = "auth_type";
     50 
     51     private static final int MENU_DELETE = Menu.FIRST;
     52     private static final int MENU_SAVE = Menu.FIRST + 1;
     53     private static final int MENU_CANCEL = Menu.FIRST + 2;
     54 
     55     private static String sNotSet;
     56     private EditTextPreference mName;
     57     private EditTextPreference mApn;
     58     private EditTextPreference mProxy;
     59     private EditTextPreference mPort;
     60     private EditTextPreference mUser;
     61     private EditTextPreference mServer;
     62     private EditTextPreference mPassword;
     63     private EditTextPreference mMmsc;
     64     private EditTextPreference mMcc;
     65     private EditTextPreference mMnc;
     66     private EditTextPreference mMmsProxy;
     67     private EditTextPreference mMmsPort;
     68     private ListPreference mAuthType;
     69     private EditTextPreference mApnType;
     70 
     71     private String mCurMnc;
     72     private String mCurMcc;
     73 
     74     private Uri mUri;
     75     private Cursor mCursor;
     76     private boolean mNewApn;
     77     private boolean mFirstTime;
     78     private Resources mRes;
     79 
     80     /**
     81      * Standard projection for the interesting columns of a normal note.
     82      */
     83     private static final String[] sProjection = new String[] {
     84             Telephony.Carriers._ID,     // 0
     85             Telephony.Carriers.NAME,    // 1
     86             Telephony.Carriers.APN,     // 2
     87             Telephony.Carriers.PROXY,   // 3
     88             Telephony.Carriers.PORT,    // 4
     89             Telephony.Carriers.USER,    // 5
     90             Telephony.Carriers.SERVER,  // 6
     91             Telephony.Carriers.PASSWORD, // 7
     92             Telephony.Carriers.MMSC, // 8
     93             Telephony.Carriers.MCC, // 9
     94             Telephony.Carriers.MNC, // 10
     95             Telephony.Carriers.NUMERIC, // 11
     96             Telephony.Carriers.MMSPROXY,// 12
     97             Telephony.Carriers.MMSPORT, // 13
     98             Telephony.Carriers.AUTH_TYPE, // 14
     99             Telephony.Carriers.TYPE, // 15
    100     };
    101 
    102     private static final int ID_INDEX = 0;
    103     private static final int NAME_INDEX = 1;
    104     private static final int APN_INDEX = 2;
    105     private static final int PROXY_INDEX = 3;
    106     private static final int PORT_INDEX = 4;
    107     private static final int USER_INDEX = 5;
    108     private static final int SERVER_INDEX = 6;
    109     private static final int PASSWORD_INDEX = 7;
    110     private static final int MMSC_INDEX = 8;
    111     private static final int MCC_INDEX = 9;
    112     private static final int MNC_INDEX = 10;
    113     private static final int MMSPROXY_INDEX = 12;
    114     private static final int MMSPORT_INDEX = 13;
    115     private static final int AUTH_TYPE_INDEX = 14;
    116     private static final int TYPE_INDEX = 15;
    117 
    118 
    119     @Override
    120     protected void onCreate(Bundle icicle) {
    121         super.onCreate(icicle);
    122 
    123         addPreferencesFromResource(R.xml.apn_editor);
    124 
    125         sNotSet = getResources().getString(R.string.apn_not_set);
    126         mName = (EditTextPreference) findPreference("apn_name");
    127         mApn = (EditTextPreference) findPreference("apn_apn");
    128         mProxy = (EditTextPreference) findPreference("apn_http_proxy");
    129         mPort = (EditTextPreference) findPreference("apn_http_port");
    130         mUser = (EditTextPreference) findPreference("apn_user");
    131         mServer = (EditTextPreference) findPreference("apn_server");
    132         mPassword = (EditTextPreference) findPreference("apn_password");
    133         mMmsProxy = (EditTextPreference) findPreference("apn_mms_proxy");
    134         mMmsPort = (EditTextPreference) findPreference("apn_mms_port");
    135         mMmsc = (EditTextPreference) findPreference("apn_mmsc");
    136         mMcc = (EditTextPreference) findPreference("apn_mcc");
    137         mMnc = (EditTextPreference) findPreference("apn_mnc");
    138         mApnType = (EditTextPreference) findPreference("apn_type");
    139 
    140         mAuthType = (ListPreference) findPreference("auth_type");
    141         mAuthType.setOnPreferenceChangeListener(this);
    142 
    143         mRes = getResources();
    144 
    145         final Intent intent = getIntent();
    146         final String action = intent.getAction();
    147 
    148         mFirstTime = icicle == null;
    149 
    150         if (action.equals(Intent.ACTION_EDIT)) {
    151             mUri = intent.getData();
    152         } else if (action.equals(Intent.ACTION_INSERT)) {
    153             if (mFirstTime || icicle.getInt(SAVED_POS) == 0) {
    154                 mUri = getContentResolver().insert(intent.getData(), new ContentValues());
    155             } else {
    156                 mUri = ContentUris.withAppendedId(Telephony.Carriers.CONTENT_URI,
    157                         icicle.getInt(SAVED_POS));
    158             }
    159             mNewApn = true;
    160             // If we were unable to create a new note, then just finish
    161             // this activity.  A RESULT_CANCELED will be sent back to the
    162             // original activity if they requested a result.
    163             if (mUri == null) {
    164                 Log.w(TAG, "Failed to insert new telephony provider into "
    165                         + getIntent().getData());
    166                 finish();
    167                 return;
    168             }
    169 
    170             // The new entry was created, so assume all will end well and
    171             // set the result to be returned.
    172             setResult(RESULT_OK, (new Intent()).setAction(mUri.toString()));
    173 
    174         } else {
    175             finish();
    176             return;
    177         }
    178 
    179         mCursor = managedQuery(mUri, sProjection, null, null);
    180         mCursor.moveToFirst();
    181 
    182         fillUi();
    183     }
    184 
    185     @Override
    186     public void onResume() {
    187         super.onResume();
    188         getPreferenceScreen().getSharedPreferences()
    189                 .registerOnSharedPreferenceChangeListener(this);
    190     }
    191 
    192     @Override
    193     public void onPause() {
    194         getPreferenceScreen().getSharedPreferences()
    195                 .unregisterOnSharedPreferenceChangeListener(this);
    196         super.onPause();
    197     }
    198 
    199     private void fillUi() {
    200         if (mFirstTime) {
    201             mFirstTime = false;
    202             // Fill in all the values from the db in both text editor and summary
    203             mName.setText(mCursor.getString(NAME_INDEX));
    204             mApn.setText(mCursor.getString(APN_INDEX));
    205             mProxy.setText(mCursor.getString(PROXY_INDEX));
    206             mPort.setText(mCursor.getString(PORT_INDEX));
    207             mUser.setText(mCursor.getString(USER_INDEX));
    208             mServer.setText(mCursor.getString(SERVER_INDEX));
    209             mPassword.setText(mCursor.getString(PASSWORD_INDEX));
    210             mMmsProxy.setText(mCursor.getString(MMSPROXY_INDEX));
    211             mMmsPort.setText(mCursor.getString(MMSPORT_INDEX));
    212             mMmsc.setText(mCursor.getString(MMSC_INDEX));
    213             mMcc.setText(mCursor.getString(MCC_INDEX));
    214             mMnc.setText(mCursor.getString(MNC_INDEX));
    215             mApnType.setText(mCursor.getString(TYPE_INDEX));
    216             if (mNewApn) {
    217                 String numeric =
    218                     SystemProperties.get(TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC);
    219                 // MCC is first 3 chars and then in 2 - 3 chars of MNC
    220                 if (numeric != null && numeric.length() > 4) {
    221                     // Country code
    222                     String mcc = numeric.substring(0, 3);
    223                     // Network code
    224                     String mnc = numeric.substring(3);
    225                     // Auto populate MNC and MCC for new entries, based on what SIM reports
    226                     mMcc.setText(mcc);
    227                     mMnc.setText(mnc);
    228                     mCurMnc = mnc;
    229                     mCurMcc = mcc;
    230                 }
    231             }
    232             int authVal = mCursor.getInt(AUTH_TYPE_INDEX);
    233             if (authVal != -1) {
    234                 mAuthType.setValueIndex(authVal);
    235             }
    236 
    237         }
    238 
    239         mName.setSummary(checkNull(mName.getText()));
    240         mApn.setSummary(checkNull(mApn.getText()));
    241         mProxy.setSummary(checkNull(mProxy.getText()));
    242         mPort.setSummary(checkNull(mPort.getText()));
    243         mUser.setSummary(checkNull(mUser.getText()));
    244         mServer.setSummary(checkNull(mServer.getText()));
    245         mPassword.setSummary(starify(mPassword.getText()));
    246         mMmsProxy.setSummary(checkNull(mMmsProxy.getText()));
    247         mMmsPort.setSummary(checkNull(mMmsPort.getText()));
    248         mMmsc.setSummary(checkNull(mMmsc.getText()));
    249         mMcc.setSummary(checkNull(mMcc.getText()));
    250         mMnc.setSummary(checkNull(mMnc.getText()));
    251         mApnType.setSummary(checkNull(mApnType.getText()));
    252 
    253         String authVal = mAuthType.getValue();
    254         if (authVal != null) {
    255             int authValIndex = Integer.parseInt(authVal);
    256             mAuthType.setValueIndex(authValIndex);
    257 
    258             String []values = mRes.getStringArray(R.array.apn_auth_entries);
    259             mAuthType.setSummary(values[authValIndex]);
    260         } else {
    261             mAuthType.setSummary(sNotSet);
    262         }
    263     }
    264 
    265     public boolean onPreferenceChange(Preference preference, Object newValue) {
    266         String key = preference.getKey();
    267         if (KEY_AUTH_TYPE.equals(key)) {
    268             try {
    269                 int index = Integer.parseInt((String) newValue);
    270                 mAuthType.setValueIndex(index);
    271 
    272                 String []values = mRes.getStringArray(R.array.apn_auth_entries);
    273                 mAuthType.setSummary(values[index]);
    274             } catch (NumberFormatException e) {
    275                 return false;
    276             }
    277         }
    278         return true;
    279     }
    280 
    281     @Override
    282     public boolean onCreateOptionsMenu(Menu menu) {
    283         super.onCreateOptionsMenu(menu);
    284         // If it's a new APN, then cancel will delete the new entry in onPause
    285         if (!mNewApn) {
    286             menu.add(0, MENU_DELETE, 0, R.string.menu_delete)
    287                 .setIcon(android.R.drawable.ic_menu_delete);
    288         }
    289         menu.add(0, MENU_SAVE, 0, R.string.menu_save)
    290             .setIcon(android.R.drawable.ic_menu_save);
    291         menu.add(0, MENU_CANCEL, 0, R.string.menu_cancel)
    292             .setIcon(android.R.drawable.ic_menu_close_clear_cancel);
    293         return true;
    294     }
    295 
    296     @Override
    297     public boolean onOptionsItemSelected(MenuItem item) {
    298         switch (item.getItemId()) {
    299         case MENU_DELETE:
    300             deleteApn();
    301             return true;
    302         case MENU_SAVE:
    303             if (validateAndSave(false)) {
    304                 finish();
    305             }
    306             return true;
    307         case MENU_CANCEL:
    308             if (mNewApn) {
    309                 getContentResolver().delete(mUri, null, null);
    310             }
    311             finish();
    312             return true;
    313         }
    314         return super.onOptionsItemSelected(item);
    315     }
    316 
    317     @Override
    318     public boolean onKeyDown(int keyCode, KeyEvent event) {
    319         switch (keyCode) {
    320             case KeyEvent.KEYCODE_BACK: {
    321                 if (validateAndSave(false)) {
    322                     finish();
    323                 }
    324                 return true;
    325             }
    326         }
    327         return super.onKeyDown(keyCode, event);
    328     }
    329 
    330     @Override
    331     protected void onSaveInstanceState(Bundle icicle) {
    332         super.onSaveInstanceState(icicle);
    333         if (validateAndSave(true)) {
    334             icicle.putInt(SAVED_POS, mCursor.getInt(ID_INDEX));
    335         }
    336     }
    337 
    338     /**
    339      * Check the key fields' validity and save if valid.
    340      * @param force save even if the fields are not valid, if the app is
    341      *        being suspended
    342      * @return true if the data was saved
    343      */
    344     private boolean validateAndSave(boolean force) {
    345         String name = checkNotSet(mName.getText());
    346         String apn = checkNotSet(mApn.getText());
    347         String mcc = checkNotSet(mMcc.getText());
    348         String mnc = checkNotSet(mMnc.getText());
    349 
    350         String errorMsg = null;
    351         if (name.length() < 1) {
    352             errorMsg = mRes.getString(R.string.error_name_empty);
    353         } else if (apn.length() < 1) {
    354             errorMsg = mRes.getString(R.string.error_apn_empty);
    355         } else if (mcc.length() != 3) {
    356             errorMsg = mRes.getString(R.string.error_mcc_not3);
    357         } else if ((mnc.length() & 0xFFFE) != 2) {
    358             errorMsg = mRes.getString(R.string.error_mnc_not23);
    359         }
    360 
    361         if (errorMsg != null && !force) {
    362             showErrorMessage(errorMsg);
    363             return false;
    364         }
    365 
    366         if (!mCursor.moveToFirst()) {
    367             Log.w(TAG,
    368                     "Could not go to the first row in the Cursor when saving data.");
    369             return false;
    370         }
    371 
    372         // If it's a new APN and a name or apn haven't been entered, then erase the entry
    373         if (force && mNewApn && name.length() < 1 && apn.length() < 1) {
    374             getContentResolver().delete(mUri, null, null);
    375             return false;
    376         }
    377 
    378         ContentValues values = new ContentValues();
    379 
    380         // Add a dummy name "Untitled", if the user exits the screen without adding a name but
    381         // entered other information worth keeping.
    382         values.put(Telephony.Carriers.NAME,
    383                 name.length() < 1 ? getResources().getString(R.string.untitled_apn) : name);
    384         values.put(Telephony.Carriers.APN, apn);
    385         values.put(Telephony.Carriers.PROXY, checkNotSet(mProxy.getText()));
    386         values.put(Telephony.Carriers.PORT, checkNotSet(mPort.getText()));
    387         values.put(Telephony.Carriers.MMSPROXY, checkNotSet(mMmsProxy.getText()));
    388         values.put(Telephony.Carriers.MMSPORT, checkNotSet(mMmsPort.getText()));
    389         values.put(Telephony.Carriers.USER, checkNotSet(mUser.getText()));
    390         values.put(Telephony.Carriers.SERVER, checkNotSet(mServer.getText()));
    391         values.put(Telephony.Carriers.PASSWORD, checkNotSet(mPassword.getText()));
    392         values.put(Telephony.Carriers.MMSC, checkNotSet(mMmsc.getText()));
    393 
    394         String authVal = mAuthType.getValue();
    395         if (authVal != null) {
    396             values.put(Telephony.Carriers.AUTH_TYPE, Integer.parseInt(authVal));
    397         }
    398 
    399         values.put(Telephony.Carriers.TYPE, checkNotSet(mApnType.getText()));
    400 
    401         values.put(Telephony.Carriers.MCC, mcc);
    402         values.put(Telephony.Carriers.MNC, mnc);
    403 
    404         values.put(Telephony.Carriers.NUMERIC, mcc + mnc);
    405 
    406         if (mCurMnc != null && mCurMcc != null) {
    407             if (mCurMnc.equals(mnc) && mCurMcc.equals(mcc)) {
    408                 values.put(Telephony.Carriers.CURRENT, 1);
    409             }
    410         }
    411 
    412         getContentResolver().update(mUri, values, null, null);
    413 
    414         return true;
    415     }
    416 
    417     private void showErrorMessage(String message) {
    418         new AlertDialog.Builder(this)
    419             .setTitle(R.string.error_title)
    420             .setMessage(message)
    421             .setPositiveButton(android.R.string.ok, null)
    422             .show();
    423     }
    424 
    425     private void deleteApn() {
    426         getContentResolver().delete(mUri, null, null);
    427         finish();
    428     }
    429 
    430     private String starify(String value) {
    431         if (value == null || value.length() == 0) {
    432             return sNotSet;
    433         } else {
    434             char[] password = new char[value.length()];
    435             for (int i = 0; i < password.length; i++) {
    436                 password[i] = '*';
    437             }
    438             return new String(password);
    439         }
    440     }
    441 
    442     private String checkNull(String value) {
    443         if (value == null || value.length() == 0) {
    444             return sNotSet;
    445         } else {
    446             return value;
    447         }
    448     }
    449 
    450     private String checkNotSet(String value) {
    451         if (value == null || value.equals(sNotSet)) {
    452             return "";
    453         } else {
    454             return value;
    455         }
    456     }
    457 
    458     public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
    459         Preference pref = findPreference(key);
    460         if (pref != null) {
    461             if (pref.equals(mPassword)){
    462                 pref.setSummary(starify(sharedPreferences.getString(key, "")));
    463             } else {
    464                 pref.setSummary(checkNull(sharedPreferences.getString(key, "")));
    465             }
    466         }
    467     }
    468 }
    469