Home | History | Annotate | Download | only in settings
      1 /*
      2  * Copyright (C) 2008 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.Activity;
     20 import android.app.Dialog;
     21 import android.app.ProgressDialog;
     22 import android.content.BroadcastReceiver;
     23 import android.content.ContentResolver;
     24 import android.content.ContentUris;
     25 import android.content.ContentValues;
     26 import android.content.Context;
     27 import android.content.Intent;
     28 import android.content.IntentFilter;
     29 import android.database.Cursor;
     30 import android.net.Uri;
     31 import android.os.Bundle;
     32 import android.os.Handler;
     33 import android.os.HandlerThread;
     34 import android.os.Looper;
     35 import android.os.Message;
     36 import android.os.UserManager;
     37 import android.preference.Preference;
     38 import android.preference.PreferenceActivity;
     39 import android.preference.PreferenceGroup;
     40 import android.preference.PreferenceScreen;
     41 import android.provider.Telephony;
     42 import android.telephony.SubscriptionInfo;
     43 import android.telephony.SubscriptionManager;
     44 import android.util.Log;
     45 import android.view.LayoutInflater;
     46 import android.view.Menu;
     47 import android.view.MenuInflater;
     48 import android.view.MenuItem;
     49 import android.view.View;
     50 import android.widget.TextView;
     51 import android.widget.Toast;
     52 
     53 import com.android.internal.telephony.Phone;
     54 import com.android.internal.telephony.PhoneConstants;
     55 import com.android.internal.telephony.TelephonyIntents;
     56 import com.android.internal.telephony.TelephonyProperties;
     57 import android.telephony.TelephonyManager;
     58 
     59 import java.util.ArrayList;
     60 
     61 public class ApnSettings extends SettingsPreferenceFragment implements
     62         Preference.OnPreferenceChangeListener {
     63     static final String TAG = "ApnSettings";
     64 
     65     public static final String EXTRA_POSITION = "position";
     66     public static final String RESTORE_CARRIERS_URI =
     67         "content://telephony/carriers/restore";
     68     public static final String PREFERRED_APN_URI =
     69         "content://telephony/carriers/preferapn";
     70 
     71     public static final String APN_ID = "apn_id";
     72 
     73     private static final int ID_INDEX = 0;
     74     private static final int NAME_INDEX = 1;
     75     private static final int APN_INDEX = 2;
     76     private static final int TYPES_INDEX = 3;
     77 
     78     private static final int MENU_NEW = Menu.FIRST;
     79     private static final int MENU_RESTORE = Menu.FIRST + 1;
     80 
     81     private static final int EVENT_RESTORE_DEFAULTAPN_START = 1;
     82     private static final int EVENT_RESTORE_DEFAULTAPN_COMPLETE = 2;
     83 
     84     private static final int DIALOG_RESTORE_DEFAULTAPN = 1001;
     85 
     86     private static final Uri DEFAULTAPN_URI = Uri.parse(RESTORE_CARRIERS_URI);
     87     private static final Uri PREFERAPN_URI = Uri.parse(PREFERRED_APN_URI);
     88 
     89     private static boolean mRestoreDefaultApnMode;
     90 
     91     private RestoreApnUiHandler mRestoreApnUiHandler;
     92     private RestoreApnProcessHandler mRestoreApnProcessHandler;
     93     private HandlerThread mRestoreDefaultApnThread;
     94     private SubscriptionInfo mSubscriptionInfo;
     95 
     96     private UserManager mUm;
     97 
     98     private String mSelectedKey;
     99 
    100     private IntentFilter mMobileStateFilter;
    101 
    102     private boolean mUnavailable;
    103 
    104     private final BroadcastReceiver mMobileStateReceiver = new BroadcastReceiver() {
    105         @Override
    106         public void onReceive(Context context, Intent intent) {
    107             if (intent.getAction().equals(
    108                     TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) {
    109                 PhoneConstants.DataState state = getMobileDataState(intent);
    110                 switch (state) {
    111                 case CONNECTED:
    112                     if (!mRestoreDefaultApnMode) {
    113                         fillList();
    114                     } else {
    115                         showDialog(DIALOG_RESTORE_DEFAULTAPN);
    116                     }
    117                     break;
    118                 }
    119             }
    120         }
    121     };
    122 
    123     private static PhoneConstants.DataState getMobileDataState(Intent intent) {
    124         String str = intent.getStringExtra(PhoneConstants.STATE_KEY);
    125         if (str != null) {
    126             return Enum.valueOf(PhoneConstants.DataState.class, str);
    127         } else {
    128             return PhoneConstants.DataState.DISCONNECTED;
    129         }
    130     }
    131 
    132     @Override
    133     public void onCreate(Bundle icicle) {
    134         super.onCreate(icicle);
    135         final Activity activity = getActivity();
    136         final int subId = activity.getIntent().getIntExtra("sub_id",
    137                 SubscriptionManager.INVALID_SUBSCRIPTION_ID);
    138 
    139         mUm = (UserManager) getSystemService(Context.USER_SERVICE);
    140 
    141         mMobileStateFilter = new IntentFilter(
    142                 TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
    143 
    144         if (!mUm.hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
    145             setHasOptionsMenu(true);
    146         }
    147 
    148         mSubscriptionInfo = Utils.findRecordBySubId(activity, subId);
    149     }
    150 
    151     @Override
    152     public void onActivityCreated(Bundle savedInstanceState) {
    153         super.onActivityCreated(savedInstanceState);
    154 
    155         TextView empty = (TextView) getView().findViewById(android.R.id.empty);
    156         if (empty != null) {
    157             empty.setText(R.string.apn_settings_not_available);
    158             getListView().setEmptyView(empty);
    159         }
    160 
    161         if (mUm.hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
    162             mUnavailable = true;
    163             setPreferenceScreen(new PreferenceScreen(getActivity(), null));
    164             return;
    165         }
    166 
    167         addPreferencesFromResource(R.xml.apn_settings);
    168 
    169         getListView().setItemsCanFocus(true);
    170     }
    171 
    172     @Override
    173     public void onResume() {
    174         super.onResume();
    175 
    176         if (mUnavailable) {
    177             return;
    178         }
    179 
    180         getActivity().registerReceiver(mMobileStateReceiver, mMobileStateFilter);
    181 
    182         if (!mRestoreDefaultApnMode) {
    183             fillList();
    184         }
    185     }
    186 
    187     @Override
    188     public void onPause() {
    189         super.onPause();
    190 
    191         if (mUnavailable) {
    192             return;
    193         }
    194 
    195         getActivity().unregisterReceiver(mMobileStateReceiver);
    196     }
    197 
    198     @Override
    199     public void onDestroy() {
    200         super.onDestroy();
    201 
    202         if (mRestoreDefaultApnThread != null) {
    203             mRestoreDefaultApnThread.quit();
    204         }
    205     }
    206 
    207     private void fillList() {
    208         final TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
    209         final String mccmnc = mSubscriptionInfo == null ? ""
    210             : tm.getSimOperator(mSubscriptionInfo.getSubscriptionId());
    211         Log.d(TAG, "mccmnc = " + mccmnc);
    212         final String where = "numeric=\""
    213             + mccmnc
    214             + "\" AND NOT (type='ia' AND (apn=\"\" OR apn IS NULL))";
    215 
    216         Cursor cursor = getContentResolver().query(Telephony.Carriers.CONTENT_URI, new String[] {
    217                 "_id", "name", "apn", "type"}, where, null,
    218                 Telephony.Carriers.DEFAULT_SORT_ORDER);
    219 
    220         if (cursor != null) {
    221             PreferenceGroup apnList = (PreferenceGroup) findPreference("apn_list");
    222             apnList.removeAll();
    223 
    224             ArrayList<Preference> mmsApnList = new ArrayList<Preference>();
    225 
    226             mSelectedKey = getSelectedApnKey();
    227             cursor.moveToFirst();
    228             while (!cursor.isAfterLast()) {
    229                 String name = cursor.getString(NAME_INDEX);
    230                 String apn = cursor.getString(APN_INDEX);
    231                 String key = cursor.getString(ID_INDEX);
    232                 String type = cursor.getString(TYPES_INDEX);
    233 
    234                 ApnPreference pref = new ApnPreference(getActivity());
    235 
    236                 pref.setKey(key);
    237                 pref.setTitle(name);
    238                 pref.setSummary(apn);
    239                 pref.setPersistent(false);
    240                 pref.setOnPreferenceChangeListener(this);
    241 
    242                 boolean selectable = ((type == null) || !type.equals("mms"));
    243                 pref.setSelectable(selectable);
    244                 if (selectable) {
    245                     if ((mSelectedKey != null) && mSelectedKey.equals(key)) {
    246                         pref.setChecked();
    247                     }
    248                     apnList.addPreference(pref);
    249                 } else {
    250                     mmsApnList.add(pref);
    251                 }
    252                 cursor.moveToNext();
    253             }
    254             cursor.close();
    255 
    256             for (Preference preference : mmsApnList) {
    257                 apnList.addPreference(preference);
    258             }
    259         }
    260     }
    261 
    262     @Override
    263     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    264         if (!mUnavailable) {
    265             menu.add(0, MENU_NEW, 0,
    266                     getResources().getString(R.string.menu_new))
    267                     .setIcon(android.R.drawable.ic_menu_add)
    268                     .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
    269             menu.add(0, MENU_RESTORE, 0,
    270                     getResources().getString(R.string.menu_restore))
    271                     .setIcon(android.R.drawable.ic_menu_upload);
    272         }
    273 
    274         super.onCreateOptionsMenu(menu, inflater);
    275     }
    276 
    277     @Override
    278     public boolean onOptionsItemSelected(MenuItem item) {
    279         switch (item.getItemId()) {
    280         case MENU_NEW:
    281             addNewApn();
    282             return true;
    283 
    284         case MENU_RESTORE:
    285             restoreDefaultApn();
    286             return true;
    287         }
    288         return super.onOptionsItemSelected(item);
    289     }
    290 
    291     private void addNewApn() {
    292         Intent intent = new Intent(Intent.ACTION_INSERT, Telephony.Carriers.CONTENT_URI);
    293         int subId = mSubscriptionInfo != null ? mSubscriptionInfo.getSubscriptionId()
    294                 : SubscriptionManager.INVALID_SUBSCRIPTION_ID;
    295         intent.putExtra("sub_id", subId);
    296         startActivity(intent);
    297     }
    298 
    299     @Override
    300     public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
    301         int pos = Integer.parseInt(preference.getKey());
    302         Uri url = ContentUris.withAppendedId(Telephony.Carriers.CONTENT_URI, pos);
    303         startActivity(new Intent(Intent.ACTION_EDIT, url));
    304         return true;
    305     }
    306 
    307     public boolean onPreferenceChange(Preference preference, Object newValue) {
    308         Log.d(TAG, "onPreferenceChange(): Preference - " + preference
    309                 + ", newValue - " + newValue + ", newValue type - "
    310                 + newValue.getClass());
    311         if (newValue instanceof String) {
    312             setSelectedApnKey((String) newValue);
    313         }
    314 
    315         return true;
    316     }
    317 
    318     private void setSelectedApnKey(String key) {
    319         mSelectedKey = key;
    320         ContentResolver resolver = getContentResolver();
    321 
    322         ContentValues values = new ContentValues();
    323         values.put(APN_ID, mSelectedKey);
    324         resolver.update(PREFERAPN_URI, values, null, null);
    325     }
    326 
    327     private String getSelectedApnKey() {
    328         String key = null;
    329 
    330         Cursor cursor = getContentResolver().query(PREFERAPN_URI, new String[] {"_id"},
    331                 null, null, Telephony.Carriers.DEFAULT_SORT_ORDER);
    332         if (cursor.getCount() > 0) {
    333             cursor.moveToFirst();
    334             key = cursor.getString(ID_INDEX);
    335         }
    336         cursor.close();
    337         return key;
    338     }
    339 
    340     private boolean restoreDefaultApn() {
    341         showDialog(DIALOG_RESTORE_DEFAULTAPN);
    342         mRestoreDefaultApnMode = true;
    343 
    344         if (mRestoreApnUiHandler == null) {
    345             mRestoreApnUiHandler = new RestoreApnUiHandler();
    346         }
    347 
    348         if (mRestoreApnProcessHandler == null ||
    349             mRestoreDefaultApnThread == null) {
    350             mRestoreDefaultApnThread = new HandlerThread(
    351                     "Restore default APN Handler: Process Thread");
    352             mRestoreDefaultApnThread.start();
    353             mRestoreApnProcessHandler = new RestoreApnProcessHandler(
    354                     mRestoreDefaultApnThread.getLooper(), mRestoreApnUiHandler);
    355         }
    356 
    357         mRestoreApnProcessHandler
    358                 .sendEmptyMessage(EVENT_RESTORE_DEFAULTAPN_START);
    359         return true;
    360     }
    361 
    362     private class RestoreApnUiHandler extends Handler {
    363         @Override
    364         public void handleMessage(Message msg) {
    365             switch (msg.what) {
    366                 case EVENT_RESTORE_DEFAULTAPN_COMPLETE:
    367                     Activity activity = getActivity();
    368                     if (activity == null) {
    369                         mRestoreDefaultApnMode = false;
    370                         return;
    371                     }
    372                     fillList();
    373                     getPreferenceScreen().setEnabled(true);
    374                     mRestoreDefaultApnMode = false;
    375                     removeDialog(DIALOG_RESTORE_DEFAULTAPN);
    376                     Toast.makeText(
    377                         activity,
    378                         getResources().getString(
    379                                 R.string.restore_default_apn_completed),
    380                         Toast.LENGTH_LONG).show();
    381                     break;
    382             }
    383         }
    384     }
    385 
    386     private class RestoreApnProcessHandler extends Handler {
    387         private Handler mRestoreApnUiHandler;
    388 
    389         public RestoreApnProcessHandler(Looper looper, Handler restoreApnUiHandler) {
    390             super(looper);
    391             this.mRestoreApnUiHandler = restoreApnUiHandler;
    392         }
    393 
    394         @Override
    395         public void handleMessage(Message msg) {
    396             switch (msg.what) {
    397                 case EVENT_RESTORE_DEFAULTAPN_START:
    398                     ContentResolver resolver = getContentResolver();
    399                     resolver.delete(DEFAULTAPN_URI, null, null);
    400                     mRestoreApnUiHandler
    401                         .sendEmptyMessage(EVENT_RESTORE_DEFAULTAPN_COMPLETE);
    402                     break;
    403             }
    404         }
    405     }
    406 
    407     @Override
    408     public Dialog onCreateDialog(int id) {
    409         if (id == DIALOG_RESTORE_DEFAULTAPN) {
    410             ProgressDialog dialog = new ProgressDialog(getActivity());
    411             dialog.setMessage(getResources().getString(R.string.restore_default_apn));
    412             dialog.setCancelable(false);
    413             return dialog;
    414         }
    415         return null;
    416     }
    417 }
    418