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.Dialog; 20 import android.app.ProgressDialog; 21 import android.content.BroadcastReceiver; 22 import android.content.ContentResolver; 23 import android.content.ContentUris; 24 import android.content.ContentValues; 25 import android.content.Context; 26 import android.content.Intent; 27 import android.content.IntentFilter; 28 import android.database.Cursor; 29 import android.net.Uri; 30 import android.os.Bundle; 31 import android.os.Handler; 32 import android.os.HandlerThread; 33 import android.os.Looper; 34 import android.os.Message; 35 import android.preference.Preference; 36 import android.preference.PreferenceActivity; 37 import android.preference.PreferenceGroup; 38 import android.preference.PreferenceScreen; 39 import android.provider.Telephony; 40 import android.util.Log; 41 import android.view.Menu; 42 import android.view.MenuItem; 43 import android.widget.Toast; 44 45 import com.android.internal.telephony.Phone; 46 import com.android.internal.telephony.TelephonyIntents; 47 import com.android.internal.telephony.TelephonyProperties; 48 49 import java.util.ArrayList; 50 51 public class ApnSettings extends PreferenceActivity implements 52 Preference.OnPreferenceChangeListener { 53 static final String TAG = "ApnSettings"; 54 55 public static final String EXTRA_POSITION = "position"; 56 public static final String RESTORE_CARRIERS_URI = 57 "content://telephony/carriers/restore"; 58 public static final String PREFERRED_APN_URI = 59 "content://telephony/carriers/preferapn"; 60 61 public static final String APN_ID = "apn_id"; 62 63 private static final int ID_INDEX = 0; 64 private static final int NAME_INDEX = 1; 65 private static final int APN_INDEX = 2; 66 private static final int TYPES_INDEX = 3; 67 68 private static final int MENU_NEW = Menu.FIRST; 69 private static final int MENU_RESTORE = Menu.FIRST + 1; 70 71 private static final int EVENT_RESTORE_DEFAULTAPN_START = 1; 72 private static final int EVENT_RESTORE_DEFAULTAPN_COMPLETE = 2; 73 74 private static final int DIALOG_RESTORE_DEFAULTAPN = 1001; 75 76 private static final Uri DEFAULTAPN_URI = Uri.parse(RESTORE_CARRIERS_URI); 77 private static final Uri PREFERAPN_URI = Uri.parse(PREFERRED_APN_URI); 78 79 private static boolean mRestoreDefaultApnMode; 80 81 private RestoreApnUiHandler mRestoreApnUiHandler; 82 private RestoreApnProcessHandler mRestoreApnProcessHandler; 83 84 private String mSelectedKey; 85 86 private IntentFilter mMobileStateFilter; 87 88 private final BroadcastReceiver mMobileStateReceiver = new BroadcastReceiver() { 89 @Override 90 public void onReceive(Context context, Intent intent) { 91 if (intent.getAction().equals( 92 TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) { 93 Phone.DataState state = getMobileDataState(intent); 94 switch (state) { 95 case CONNECTED: 96 if (!mRestoreDefaultApnMode) { 97 fillList(); 98 } else { 99 showDialog(DIALOG_RESTORE_DEFAULTAPN); 100 } 101 break; 102 } 103 } 104 } 105 }; 106 107 private static Phone.DataState getMobileDataState(Intent intent) { 108 String str = intent.getStringExtra(Phone.STATE_KEY); 109 if (str != null) { 110 return Enum.valueOf(Phone.DataState.class, str); 111 } else { 112 return Phone.DataState.DISCONNECTED; 113 } 114 } 115 116 @Override 117 protected void onCreate(Bundle icicle) { 118 super.onCreate(icicle); 119 120 addPreferencesFromResource(R.xml.apn_settings); 121 getListView().setItemsCanFocus(true); 122 123 mMobileStateFilter = new IntentFilter( 124 TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED); 125 } 126 127 @Override 128 protected void onResume() { 129 super.onResume(); 130 131 registerReceiver(mMobileStateReceiver, mMobileStateFilter); 132 133 if (!mRestoreDefaultApnMode) { 134 fillList(); 135 } else { 136 showDialog(DIALOG_RESTORE_DEFAULTAPN); 137 } 138 } 139 140 @Override 141 protected void onPause() { 142 super.onPause(); 143 144 unregisterReceiver(mMobileStateReceiver); 145 } 146 147 private void fillList() { 148 String where = "numeric=\"" 149 + android.os.SystemProperties.get(TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC, "") 150 + "\""; 151 152 Cursor cursor = managedQuery(Telephony.Carriers.CONTENT_URI, new String[] { 153 "_id", "name", "apn", "type"}, where, 154 Telephony.Carriers.DEFAULT_SORT_ORDER); 155 156 PreferenceGroup apnList = (PreferenceGroup) findPreference("apn_list"); 157 apnList.removeAll(); 158 159 ArrayList<Preference> mmsApnList = new ArrayList<Preference>(); 160 161 mSelectedKey = getSelectedApnKey(); 162 cursor.moveToFirst(); 163 while (!cursor.isAfterLast()) { 164 String name = cursor.getString(NAME_INDEX); 165 String apn = cursor.getString(APN_INDEX); 166 String key = cursor.getString(ID_INDEX); 167 String type = cursor.getString(TYPES_INDEX); 168 169 ApnPreference pref = new ApnPreference(this); 170 171 pref.setKey(key); 172 pref.setTitle(name); 173 pref.setSummary(apn); 174 pref.setPersistent(false); 175 pref.setOnPreferenceChangeListener(this); 176 177 boolean selectable = ((type == null) || !type.equals("mms")); 178 pref.setSelectable(selectable); 179 if (selectable) { 180 if ((mSelectedKey != null) && mSelectedKey.equals(key)) { 181 pref.setChecked(); 182 } 183 apnList.addPreference(pref); 184 } else { 185 mmsApnList.add(pref); 186 } 187 cursor.moveToNext(); 188 } 189 cursor.close(); 190 191 for (Preference preference : mmsApnList) { 192 apnList.addPreference(preference); 193 } 194 } 195 196 @Override 197 public boolean onCreateOptionsMenu(Menu menu) { 198 super.onCreateOptionsMenu(menu); 199 menu.add(0, MENU_NEW, 0, 200 getResources().getString(R.string.menu_new)) 201 .setIcon(android.R.drawable.ic_menu_add); 202 menu.add(0, MENU_RESTORE, 0, 203 getResources().getString(R.string.menu_restore)) 204 .setIcon(android.R.drawable.ic_menu_upload); 205 return true; 206 } 207 208 @Override 209 public boolean onOptionsItemSelected(MenuItem item) { 210 switch (item.getItemId()) { 211 case MENU_NEW: 212 addNewApn(); 213 return true; 214 215 case MENU_RESTORE: 216 restoreDefaultApn(); 217 return true; 218 } 219 return super.onOptionsItemSelected(item); 220 } 221 222 private void addNewApn() { 223 startActivity(new Intent(Intent.ACTION_INSERT, Telephony.Carriers.CONTENT_URI)); 224 } 225 226 @Override 227 public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { 228 int pos = Integer.parseInt(preference.getKey()); 229 Uri url = ContentUris.withAppendedId(Telephony.Carriers.CONTENT_URI, pos); 230 startActivity(new Intent(Intent.ACTION_EDIT, url)); 231 return true; 232 } 233 234 public boolean onPreferenceChange(Preference preference, Object newValue) { 235 Log.d(TAG, "onPreferenceChange(): Preference - " + preference 236 + ", newValue - " + newValue + ", newValue type - " 237 + newValue.getClass()); 238 if (newValue instanceof String) { 239 setSelectedApnKey((String) newValue); 240 } 241 242 return true; 243 } 244 245 private void setSelectedApnKey(String key) { 246 mSelectedKey = key; 247 ContentResolver resolver = getContentResolver(); 248 249 ContentValues values = new ContentValues(); 250 values.put(APN_ID, mSelectedKey); 251 resolver.update(PREFERAPN_URI, values, null, null); 252 } 253 254 private String getSelectedApnKey() { 255 String key = null; 256 257 Cursor cursor = managedQuery(PREFERAPN_URI, new String[] {"_id"}, 258 null, Telephony.Carriers.DEFAULT_SORT_ORDER); 259 if (cursor.getCount() > 0) { 260 cursor.moveToFirst(); 261 key = cursor.getString(ID_INDEX); 262 } 263 cursor.close(); 264 return key; 265 } 266 267 private boolean restoreDefaultApn() { 268 showDialog(DIALOG_RESTORE_DEFAULTAPN); 269 mRestoreDefaultApnMode = true; 270 271 if (mRestoreApnUiHandler == null) { 272 mRestoreApnUiHandler = new RestoreApnUiHandler(); 273 } 274 275 if (mRestoreApnProcessHandler == null) { 276 HandlerThread restoreDefaultApnThread = new HandlerThread( 277 "Restore default APN Handler: Process Thread"); 278 restoreDefaultApnThread.start(); 279 mRestoreApnProcessHandler = new RestoreApnProcessHandler( 280 restoreDefaultApnThread.getLooper(), mRestoreApnUiHandler); 281 } 282 283 mRestoreApnProcessHandler 284 .sendEmptyMessage(EVENT_RESTORE_DEFAULTAPN_START); 285 return true; 286 } 287 288 private class RestoreApnUiHandler extends Handler { 289 @Override 290 public void handleMessage(Message msg) { 291 switch (msg.what) { 292 case EVENT_RESTORE_DEFAULTAPN_COMPLETE: 293 fillList(); 294 getPreferenceScreen().setEnabled(true); 295 mRestoreDefaultApnMode = false; 296 dismissDialog(DIALOG_RESTORE_DEFAULTAPN); 297 Toast.makeText( 298 ApnSettings.this, 299 getResources().getString( 300 R.string.restore_default_apn_completed), 301 Toast.LENGTH_LONG).show(); 302 break; 303 } 304 } 305 } 306 307 private class RestoreApnProcessHandler extends Handler { 308 private Handler mRestoreApnUiHandler; 309 310 public RestoreApnProcessHandler(Looper looper, Handler restoreApnUiHandler) { 311 super(looper); 312 this.mRestoreApnUiHandler = restoreApnUiHandler; 313 } 314 315 @Override 316 public void handleMessage(Message msg) { 317 switch (msg.what) { 318 case EVENT_RESTORE_DEFAULTAPN_START: 319 ContentResolver resolver = getContentResolver(); 320 resolver.delete(DEFAULTAPN_URI, null, null); 321 mRestoreApnUiHandler 322 .sendEmptyMessage(EVENT_RESTORE_DEFAULTAPN_COMPLETE); 323 break; 324 } 325 } 326 } 327 328 @Override 329 protected Dialog onCreateDialog(int id) { 330 if (id == DIALOG_RESTORE_DEFAULTAPN) { 331 ProgressDialog dialog = new ProgressDialog(this); 332 dialog.setMessage(getResources().getString(R.string.restore_default_apn)); 333 dialog.setCancelable(false); 334 return dialog; 335 } 336 return null; 337 } 338 339 @Override 340 protected void onPrepareDialog(int id, Dialog dialog) { 341 if (id == DIALOG_RESTORE_DEFAULTAPN) { 342 getPreferenceScreen().setEnabled(false); 343 } 344 } 345 } 346