2 * Copyright (C) 2008 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.settings;
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.PersistableBundle;
37 import android.os.UserHandle;
38 import android.os.UserManager;
39 import android.preference.Preference;
40 import android.preference.PreferenceGroup;
41 import android.preference.PreferenceScreen;
42 import android.provider.Telephony;
43 import android.telephony.CarrierConfigManager;
44 import android.telephony.SubscriptionInfo;
45 import android.telephony.SubscriptionManager;
46 import android.text.TextUtils;
47 import android.util.Log;
48 import android.view.Menu;
49 import android.view.MenuInflater;
50 import android.view.MenuItem;
51 import android.widget.TextView;
52 import android.widget.Toast;
54 import com.android.internal.logging.MetricsLogger;
55 import com.android.internal.telephony.PhoneConstants;
56 import com.android.internal.telephony.TelephonyIntents;
57 import com.android.internal.telephony.dataconnection.ApnSetting;
58 import com.android.internal.telephony.uicc.IccRecords;
59 import com.android.internal.telephony.uicc.UiccController;
61 import android.telephony.TelephonyManager;
63 import java.util.ArrayList;
65 public class ApnSettings extends SettingsPreferenceFragment implements
66 Preference.OnPreferenceChangeListener {
67 static final String TAG = "ApnSettings";
69 public static final String EXTRA_POSITION = "position";
70 public static final String RESTORE_CARRIERS_URI =
71 "content://telephony/carriers/restore";
72 public static final String PREFERRED_APN_URI =
73 "content://telephony/carriers/preferapn";
75 public static final String APN_ID = "apn_id";
76 public static final String SUB_ID = "sub_id";
77 public static final String MVNO_TYPE = "mvno_type";
78 public static final String MVNO_MATCH_DATA = "mvno_match_data";
80 private static final int ID_INDEX = 0;
81 private static final int NAME_INDEX = 1;
82 private static final int APN_INDEX = 2;
83 private static final int TYPES_INDEX = 3;
84 private static final int MVNO_TYPE_INDEX = 4;
85 private static final int MVNO_MATCH_DATA_INDEX = 5;
87 private static final int MENU_NEW = Menu.FIRST;
88 private static final int MENU_RESTORE = Menu.FIRST + 1;
90 private static final int EVENT_RESTORE_DEFAULTAPN_START = 1;
91 private static final int EVENT_RESTORE_DEFAULTAPN_COMPLETE = 2;
93 private static final int DIALOG_RESTORE_DEFAULTAPN = 1001;
95 private static final Uri DEFAULTAPN_URI = Uri.parse(RESTORE_CARRIERS_URI);
96 private static final Uri PREFERAPN_URI = Uri.parse(PREFERRED_APN_URI);
98 private static boolean mRestoreDefaultApnMode;
100 private RestoreApnUiHandler mRestoreApnUiHandler;
101 private RestoreApnProcessHandler mRestoreApnProcessHandler;
102 private HandlerThread mRestoreDefaultApnThread;
103 private SubscriptionInfo mSubscriptionInfo;
104 private UiccController mUiccController;
105 private String mMvnoType;
106 private String mMvnoMatchData;
108 private UserManager mUm;
110 private String mSelectedKey;
112 private IntentFilter mMobileStateFilter;
114 private boolean mUnavailable;
116 private boolean mHideImsApn;
117 private boolean mAllowAddingApns;
119 private final BroadcastReceiver mMobileStateReceiver = new BroadcastReceiver() {
121 public void onReceive(Context context, Intent intent) {
122 if (intent.getAction().equals(
123 TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) {
124 PhoneConstants.DataState state = getMobileDataState(intent);
127 if (!mRestoreDefaultApnMode) {
130 showDialog(DIALOG_RESTORE_DEFAULTAPN);
138 private static PhoneConstants.DataState getMobileDataState(Intent intent) {
139 String str = intent.getStringExtra(PhoneConstants.STATE_KEY);
141 return Enum.valueOf(PhoneConstants.DataState.class, str);
143 return PhoneConstants.DataState.DISCONNECTED;
148 protected int getMetricsCategory() {
149 return MetricsLogger.APN;
153 public void onCreate(Bundle icicle) {
154 super.onCreate(icicle);
155 final Activity activity = getActivity();
156 final int subId = activity.getIntent().getIntExtra(SUB_ID,
157 SubscriptionManager.INVALID_SUBSCRIPTION_ID);
159 mUm = (UserManager) getSystemService(Context.USER_SERVICE);
161 mMobileStateFilter = new IntentFilter(
162 TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
164 if (!mUm.hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
165 setHasOptionsMenu(true);
168 mSubscriptionInfo = SubscriptionManager.from(activity).getActiveSubscriptionInfo(subId);
169 mUiccController = UiccController.getInstance();
171 CarrierConfigManager configManager = (CarrierConfigManager)
172 getSystemService(Context.CARRIER_CONFIG_SERVICE);
173 PersistableBundle b = configManager.getConfig();
174 mHideImsApn = b.getBoolean(CarrierConfigManager.KEY_HIDE_IMS_APN_BOOL);
175 mAllowAddingApns = b.getBoolean(CarrierConfigManager.KEY_ALLOW_ADDING_APNS_BOOL);
179 public void onActivityCreated(Bundle savedInstanceState) {
180 super.onActivityCreated(savedInstanceState);
182 TextView empty = (TextView) getView().findViewById(android.R.id.empty);
184 empty.setText(R.string.apn_settings_not_available);
185 getListView().setEmptyView(empty);
188 if (mUm.hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)
189 || UserHandle.myUserId()!= UserHandle.USER_OWNER) {
191 setPreferenceScreen(new PreferenceScreen(getActivity(), null));
195 addPreferencesFromResource(R.xml.apn_settings);
197 getListView().setItemsCanFocus(true);
201 public void onResume() {
208 getActivity().registerReceiver(mMobileStateReceiver, mMobileStateFilter);
210 if (!mRestoreDefaultApnMode) {
216 public void onPause() {
223 getActivity().unregisterReceiver(mMobileStateReceiver);
227 public void onDestroy() {
230 if (mRestoreDefaultApnThread != null) {
231 mRestoreDefaultApnThread.quit();
235 private void fillList() {
236 final TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
237 final String mccmnc = mSubscriptionInfo == null ? ""
238 : tm.getSimOperator(mSubscriptionInfo.getSubscriptionId());
239 Log.d(TAG, "mccmnc = " + mccmnc);
240 StringBuilder where = new StringBuilder("numeric=\"" + mccmnc +
241 "\" AND NOT (type='ia' AND (apn=\"\" OR apn IS NULL)) AND user_visible!=0");
244 where.append(" AND NOT (type='ims')");
247 Cursor cursor = getContentResolver().query(Telephony.Carriers.CONTENT_URI, new String[] {
248 "_id", "name", "apn", "type", "mvno_type", "mvno_match_data"}, where.toString(),
249 null, Telephony.Carriers.DEFAULT_SORT_ORDER);
251 if (cursor != null) {
253 if (mUiccController != null && mSubscriptionInfo != null) {
254 r = mUiccController.getIccRecords(SubscriptionManager.getPhoneId(
255 mSubscriptionInfo.getSubscriptionId()), UiccController.APP_FAM_3GPP);
257 PreferenceGroup apnList = (PreferenceGroup) findPreference("apn_list");
260 ArrayList<ApnPreference> mnoApnList = new ArrayList<ApnPreference>();
261 ArrayList<ApnPreference> mvnoApnList = new ArrayList<ApnPreference>();
262 ArrayList<ApnPreference> mnoMmsApnList = new ArrayList<ApnPreference>();
263 ArrayList<ApnPreference> mvnoMmsApnList = new ArrayList<ApnPreference>();
265 mSelectedKey = getSelectedApnKey();
266 cursor.moveToFirst();
267 while (!cursor.isAfterLast()) {
268 String name = cursor.getString(NAME_INDEX);
269 String apn = cursor.getString(APN_INDEX);
270 String key = cursor.getString(ID_INDEX);
271 String type = cursor.getString(TYPES_INDEX);
272 String mvnoType = cursor.getString(MVNO_TYPE_INDEX);
273 String mvnoMatchData = cursor.getString(MVNO_MATCH_DATA_INDEX);
275 ApnPreference pref = new ApnPreference(getActivity());
279 pref.setSummary(apn);
280 pref.setPersistent(false);
281 pref.setOnPreferenceChangeListener(this);
283 boolean selectable = ((type == null) || !type.equals("mms"));
284 pref.setSelectable(selectable);
286 if ((mSelectedKey != null) && mSelectedKey.equals(key)) {
289 addApnToList(pref, mnoApnList, mvnoApnList, r, mvnoType, mvnoMatchData);
291 addApnToList(pref, mnoMmsApnList, mvnoMmsApnList, r, mvnoType, mvnoMatchData);
297 if (!mvnoApnList.isEmpty()) {
298 mnoApnList = mvnoApnList;
299 mnoMmsApnList = mvnoMmsApnList;
301 // Also save the mvno info
304 for (Preference preference : mnoApnList) {
305 apnList.addPreference(preference);
307 for (Preference preference : mnoMmsApnList) {
308 apnList.addPreference(preference);
313 private void addApnToList(ApnPreference pref, ArrayList<ApnPreference> mnoList,
314 ArrayList<ApnPreference> mvnoList, IccRecords r, String mvnoType,
315 String mvnoMatchData) {
316 if (r != null && !TextUtils.isEmpty(mvnoType) && !TextUtils.isEmpty(mvnoMatchData)) {
317 if (ApnSetting.mvnoMatches(r, mvnoType, mvnoMatchData)) {
319 // Since adding to mvno list, save mvno info
320 mMvnoType = mvnoType;
321 mMvnoMatchData = mvnoMatchData;
329 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
331 if (mAllowAddingApns) {
332 menu.add(0, MENU_NEW, 0,
333 getResources().getString(R.string.menu_new))
334 .setIcon(android.R.drawable.ic_menu_add)
335 .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
337 menu.add(0, MENU_RESTORE, 0,
338 getResources().getString(R.string.menu_restore))
339 .setIcon(android.R.drawable.ic_menu_upload);
342 super.onCreateOptionsMenu(menu, inflater);
346 public boolean onOptionsItemSelected(MenuItem item) {
347 switch (item.getItemId()) {
356 return super.onOptionsItemSelected(item);
359 private void addNewApn() {
360 Intent intent = new Intent(Intent.ACTION_INSERT, Telephony.Carriers.CONTENT_URI);
361 int subId = mSubscriptionInfo != null ? mSubscriptionInfo.getSubscriptionId()
362 : SubscriptionManager.INVALID_SUBSCRIPTION_ID;
363 intent.putExtra(SUB_ID, subId);
364 if (!TextUtils.isEmpty(mMvnoType) && !TextUtils.isEmpty(mMvnoMatchData)) {
365 intent.putExtra(MVNO_TYPE, mMvnoType);
366 intent.putExtra(MVNO_MATCH_DATA, mMvnoMatchData);
368 startActivity(intent);
372 public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
373 int pos = Integer.parseInt(preference.getKey());
374 Uri url = ContentUris.withAppendedId(Telephony.Carriers.CONTENT_URI, pos);
375 startActivity(new Intent(Intent.ACTION_EDIT, url));
379 public boolean onPreferenceChange(Preference preference, Object newValue) {
380 Log.d(TAG, "onPreferenceChange(): Preference - " + preference
381 + ", newValue - " + newValue + ", newValue type - "
382 + newValue.getClass());
383 if (newValue instanceof String) {
384 setSelectedApnKey((String) newValue);
390 private void setSelectedApnKey(String key) {
392 ContentResolver resolver = getContentResolver();
394 ContentValues values = new ContentValues();
395 values.put(APN_ID, mSelectedKey);
396 resolver.update(PREFERAPN_URI, values, null, null);
399 private String getSelectedApnKey() {
402 Cursor cursor = getContentResolver().query(PREFERAPN_URI, new String[] {"_id"},
403 null, null, Telephony.Carriers.DEFAULT_SORT_ORDER);
404 if (cursor.getCount() > 0) {
405 cursor.moveToFirst();
406 key = cursor.getString(ID_INDEX);
412 private boolean restoreDefaultApn() {
413 showDialog(DIALOG_RESTORE_DEFAULTAPN);
414 mRestoreDefaultApnMode = true;
416 if (mRestoreApnUiHandler == null) {
417 mRestoreApnUiHandler = new RestoreApnUiHandler();
420 if (mRestoreApnProcessHandler == null ||
421 mRestoreDefaultApnThread == null) {
422 mRestoreDefaultApnThread = new HandlerThread(
423 "Restore default APN Handler: Process Thread");
424 mRestoreDefaultApnThread.start();
425 mRestoreApnProcessHandler = new RestoreApnProcessHandler(
426 mRestoreDefaultApnThread.getLooper(), mRestoreApnUiHandler);
429 mRestoreApnProcessHandler
430 .sendEmptyMessage(EVENT_RESTORE_DEFAULTAPN_START);
434 private class RestoreApnUiHandler extends Handler {
436 public void handleMessage(Message msg) {
438 case EVENT_RESTORE_DEFAULTAPN_COMPLETE:
439 Activity activity = getActivity();
440 if (activity == null) {
441 mRestoreDefaultApnMode = false;
445 getPreferenceScreen().setEnabled(true);
446 mRestoreDefaultApnMode = false;
447 removeDialog(DIALOG_RESTORE_DEFAULTAPN);
450 getResources().getString(
451 R.string.restore_default_apn_completed),
452 Toast.LENGTH_LONG).show();
458 private class RestoreApnProcessHandler extends Handler {
459 private Handler mRestoreApnUiHandler;
461 public RestoreApnProcessHandler(Looper looper, Handler restoreApnUiHandler) {
463 this.mRestoreApnUiHandler = restoreApnUiHandler;
467 public void handleMessage(Message msg) {
469 case EVENT_RESTORE_DEFAULTAPN_START:
470 ContentResolver resolver = getContentResolver();
471 resolver.delete(DEFAULTAPN_URI, null, null);
473 .sendEmptyMessage(EVENT_RESTORE_DEFAULTAPN_COMPLETE);
480 public Dialog onCreateDialog(int id) {
481 if (id == DIALOG_RESTORE_DEFAULTAPN) {
482 ProgressDialog dialog = new ProgressDialog(getActivity());
483 dialog.setMessage(getResources().getString(R.string.restore_default_apn));
484 dialog.setCancelable(false);