blob: 68cfb60f6a703a4f8c7d6e5eb15d6667c9022d58 [file] [log] [blame]
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -08001/*
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
17package com.android.settings;
18
Fabrice Di Meglio3e825fe2014-10-13 18:59:34 -070019import android.app.Activity;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080020import android.app.Dialog;
21import android.app.ProgressDialog;
John Huang68296882009-03-24 18:26:28 -070022import android.content.BroadcastReceiver;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080023import android.content.ContentResolver;
24import android.content.ContentUris;
John Huang68296882009-03-24 18:26:28 -070025import android.content.ContentValues;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080026import android.content.Context;
27import android.content.Intent;
John Huang68296882009-03-24 18:26:28 -070028import android.content.IntentFilter;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080029import android.database.Cursor;
30import android.net.Uri;
31import android.os.Bundle;
32import android.os.Handler;
33import android.os.HandlerThread;
34import android.os.Looper;
35import android.os.Message;
Julia Reynoldsee27b9d2014-05-09 13:36:20 -040036import android.os.UserManager;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080037import android.preference.Preference;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080038import android.preference.PreferenceGroup;
39import android.preference.PreferenceScreen;
40import android.provider.Telephony;
PauloftheWest6f341b22014-12-02 08:45:00 -080041import android.telephony.SubscriptionInfo;
Mick Lin09c9e5e2015-01-22 17:28:43 +080042import android.telephony.SubscriptionManager;
John Huang68296882009-03-24 18:26:28 -070043import android.util.Log;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080044import android.view.Menu;
Fabrice Di Meglio61a1fec2014-08-13 16:22:38 -070045import android.view.MenuInflater;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080046import android.view.MenuItem;
Fabrice Di Meglio61a1fec2014-08-13 16:22:38 -070047import android.widget.TextView;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080048import android.widget.Toast;
49
Chris Wren8a963ba2015-03-20 10:29:14 -040050import com.android.internal.logging.MetricsLogger;
Wink Saville9ad4a892012-06-14 12:33:43 -070051import com.android.internal.telephony.PhoneConstants;
John Huang68296882009-03-24 18:26:28 -070052import com.android.internal.telephony.TelephonyIntents;
Sanket Padawe19627ca2014-12-18 10:29:16 -080053import android.telephony.TelephonyManager;
John Huang68296882009-03-24 18:26:28 -070054
55import java.util.ArrayList;
56
Fabrice Di Meglio61a1fec2014-08-13 16:22:38 -070057public class ApnSettings extends SettingsPreferenceFragment implements
John Huang68296882009-03-24 18:26:28 -070058 Preference.OnPreferenceChangeListener {
59 static final String TAG = "ApnSettings";
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080060
61 public static final String EXTRA_POSITION = "position";
62 public static final String RESTORE_CARRIERS_URI =
63 "content://telephony/carriers/restore";
John Huang68296882009-03-24 18:26:28 -070064 public static final String PREFERRED_APN_URI =
65 "content://telephony/carriers/preferapn";
66
67 public static final String APN_ID = "apn_id";
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080068
69 private static final int ID_INDEX = 0;
70 private static final int NAME_INDEX = 1;
71 private static final int APN_INDEX = 2;
John Huang68296882009-03-24 18:26:28 -070072 private static final int TYPES_INDEX = 3;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080073
74 private static final int MENU_NEW = Menu.FIRST;
75 private static final int MENU_RESTORE = Menu.FIRST + 1;
76
77 private static final int EVENT_RESTORE_DEFAULTAPN_START = 1;
78 private static final int EVENT_RESTORE_DEFAULTAPN_COMPLETE = 2;
79
80 private static final int DIALOG_RESTORE_DEFAULTAPN = 1001;
81
82 private static final Uri DEFAULTAPN_URI = Uri.parse(RESTORE_CARRIERS_URI);
John Huang68296882009-03-24 18:26:28 -070083 private static final Uri PREFERAPN_URI = Uri.parse(PREFERRED_APN_URI);
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080084
85 private static boolean mRestoreDefaultApnMode;
86
87 private RestoreApnUiHandler mRestoreApnUiHandler;
88 private RestoreApnProcessHandler mRestoreApnProcessHandler;
Jack Wang481582f2011-01-27 14:25:22 +080089 private HandlerThread mRestoreDefaultApnThread;
PauloftheWest6f341b22014-12-02 08:45:00 -080090 private SubscriptionInfo mSubscriptionInfo;
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -080091
Julia Reynoldsee27b9d2014-05-09 13:36:20 -040092 private UserManager mUm;
93
John Huang68296882009-03-24 18:26:28 -070094 private String mSelectedKey;
95
96 private IntentFilter mMobileStateFilter;
97
Julia Reynoldsee27b9d2014-05-09 13:36:20 -040098 private boolean mUnavailable;
99
John Huang68296882009-03-24 18:26:28 -0700100 private final BroadcastReceiver mMobileStateReceiver = new BroadcastReceiver() {
101 @Override
102 public void onReceive(Context context, Intent intent) {
103 if (intent.getAction().equals(
104 TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) {
Wink Saville9ad4a892012-06-14 12:33:43 -0700105 PhoneConstants.DataState state = getMobileDataState(intent);
John Huang68296882009-03-24 18:26:28 -0700106 switch (state) {
107 case CONNECTED:
108 if (!mRestoreDefaultApnMode) {
109 fillList();
110 } else {
111 showDialog(DIALOG_RESTORE_DEFAULTAPN);
112 }
113 break;
114 }
115 }
116 }
117 };
118
Wink Saville9ad4a892012-06-14 12:33:43 -0700119 private static PhoneConstants.DataState getMobileDataState(Intent intent) {
120 String str = intent.getStringExtra(PhoneConstants.STATE_KEY);
John Huang68296882009-03-24 18:26:28 -0700121 if (str != null) {
Wink Saville9ad4a892012-06-14 12:33:43 -0700122 return Enum.valueOf(PhoneConstants.DataState.class, str);
John Huang68296882009-03-24 18:26:28 -0700123 } else {
Wink Saville9ad4a892012-06-14 12:33:43 -0700124 return PhoneConstants.DataState.DISCONNECTED;
John Huang68296882009-03-24 18:26:28 -0700125 }
126 }
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800127
128 @Override
Chris Wren8a963ba2015-03-20 10:29:14 -0400129 protected int getMetricsCategory() {
130 return MetricsLogger.APN;
131 }
132
133 @Override
Fabrice Di Meglio61a1fec2014-08-13 16:22:38 -0700134 public void onCreate(Bundle icicle) {
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800135 super.onCreate(icicle);
PauloftheWest6f341b22014-12-02 08:45:00 -0800136 final Activity activity = getActivity();
Mick Lin09c9e5e2015-01-22 17:28:43 +0800137 final int subId = activity.getIntent().getIntExtra("sub_id",
138 SubscriptionManager.INVALID_SUBSCRIPTION_ID);
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800139
Julia Reynoldsee27b9d2014-05-09 13:36:20 -0400140 mUm = (UserManager) getSystemService(Context.USER_SERVICE);
141
Fabrice Di Meglio61a1fec2014-08-13 16:22:38 -0700142 mMobileStateFilter = new IntentFilter(
143 TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
144
Julia Reynolds6cc7ccc2014-08-18 16:04:48 -0400145 if (!mUm.hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
146 setHasOptionsMenu(true);
147 }
PauloftheWest6f341b22014-12-02 08:45:00 -0800148
Sanket Padawe4be06d92014-12-18 06:24:36 +0000149 mSubscriptionInfo = Utils.findRecordBySubId(activity, subId);
Fabrice Di Meglio61a1fec2014-08-13 16:22:38 -0700150 }
151
152 @Override
153 public void onActivityCreated(Bundle savedInstanceState) {
154 super.onActivityCreated(savedInstanceState);
155
156 TextView empty = (TextView) getView().findViewById(android.R.id.empty);
157 if (empty != null) {
158 empty.setText(R.string.apn_settings_not_available);
159 getListView().setEmptyView(empty);
160 }
161
Julia Reynoldsee27b9d2014-05-09 13:36:20 -0400162 if (mUm.hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
163 mUnavailable = true;
Fabrice Di Meglio61a1fec2014-08-13 16:22:38 -0700164 setPreferenceScreen(new PreferenceScreen(getActivity(), null));
Julia Reynoldsee27b9d2014-05-09 13:36:20 -0400165 return;
166 }
167
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800168 addPreferencesFromResource(R.xml.apn_settings);
John Huang68296882009-03-24 18:26:28 -0700169
Fabrice Di Meglio61a1fec2014-08-13 16:22:38 -0700170 getListView().setItemsCanFocus(true);
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800171 }
172
173 @Override
Fabrice Di Meglio61a1fec2014-08-13 16:22:38 -0700174 public void onResume() {
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800175 super.onResume();
176
Julia Reynoldsee27b9d2014-05-09 13:36:20 -0400177 if (mUnavailable) {
178 return;
179 }
180
Fabrice Di Meglio61a1fec2014-08-13 16:22:38 -0700181 getActivity().registerReceiver(mMobileStateReceiver, mMobileStateFilter);
John Huang68296882009-03-24 18:26:28 -0700182
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800183 if (!mRestoreDefaultApnMode) {
184 fillList();
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800185 }
186 }
187
John Huang68296882009-03-24 18:26:28 -0700188 @Override
Fabrice Di Meglio61a1fec2014-08-13 16:22:38 -0700189 public void onPause() {
John Huang68296882009-03-24 18:26:28 -0700190 super.onPause();
Jack Wang481582f2011-01-27 14:25:22 +0800191
Julia Reynoldsee27b9d2014-05-09 13:36:20 -0400192 if (mUnavailable) {
193 return;
194 }
195
Fabrice Di Meglio61a1fec2014-08-13 16:22:38 -0700196 getActivity().unregisterReceiver(mMobileStateReceiver);
John Huang68296882009-03-24 18:26:28 -0700197 }
198
Jack Wang481582f2011-01-27 14:25:22 +0800199 @Override
Fabrice Di Meglio61a1fec2014-08-13 16:22:38 -0700200 public void onDestroy() {
Jack Wang481582f2011-01-27 14:25:22 +0800201 super.onDestroy();
202
203 if (mRestoreDefaultApnThread != null) {
204 mRestoreDefaultApnThread.quit();
205 }
206 }
207
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800208 private void fillList() {
Sanket Padawe19627ca2014-12-18 10:29:16 -0800209 final TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
PauloftheWest6f341b22014-12-02 08:45:00 -0800210 final String mccmnc = mSubscriptionInfo == null ? ""
Sanket Padawe19627ca2014-12-18 10:29:16 -0800211 : tm.getSimOperator(mSubscriptionInfo.getSubscriptionId());
212 Log.d(TAG, "mccmnc = " + mccmnc);
PauloftheWest6f341b22014-12-02 08:45:00 -0800213 final String where = "numeric=\""
214 + mccmnc
Sanket Padawea7f21a32015-01-23 09:53:48 -0800215 + "\" AND NOT (type='ia' AND (apn=\"\" OR apn IS NULL))";
John Huang68296882009-03-24 18:26:28 -0700216
Jeff Brownb4ea1e42011-09-12 14:59:51 -0700217 Cursor cursor = getContentResolver().query(Telephony.Carriers.CONTENT_URI, new String[] {
218 "_id", "name", "apn", "type"}, where, null,
John Huang68296882009-03-24 18:26:28 -0700219 Telephony.Carriers.DEFAULT_SORT_ORDER);
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800220
Hyejin Kim88c80b12013-02-14 15:49:19 +0900221 if (cursor != null) {
222 PreferenceGroup apnList = (PreferenceGroup) findPreference("apn_list");
223 apnList.removeAll();
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800224
Hyejin Kim88c80b12013-02-14 15:49:19 +0900225 ArrayList<Preference> mmsApnList = new ArrayList<Preference>();
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800226
Hyejin Kim88c80b12013-02-14 15:49:19 +0900227 mSelectedKey = getSelectedApnKey();
228 cursor.moveToFirst();
229 while (!cursor.isAfterLast()) {
230 String name = cursor.getString(NAME_INDEX);
231 String apn = cursor.getString(APN_INDEX);
232 String key = cursor.getString(ID_INDEX);
233 String type = cursor.getString(TYPES_INDEX);
John Huang68296882009-03-24 18:26:28 -0700234
Fabrice Di Meglio61a1fec2014-08-13 16:22:38 -0700235 ApnPreference pref = new ApnPreference(getActivity());
John Huang68296882009-03-24 18:26:28 -0700236
Hyejin Kim88c80b12013-02-14 15:49:19 +0900237 pref.setKey(key);
238 pref.setTitle(name);
239 pref.setSummary(apn);
240 pref.setPersistent(false);
241 pref.setOnPreferenceChangeListener(this);
John Huang68296882009-03-24 18:26:28 -0700242
Hyejin Kim88c80b12013-02-14 15:49:19 +0900243 boolean selectable = ((type == null) || !type.equals("mms"));
244 pref.setSelectable(selectable);
245 if (selectable) {
246 if ((mSelectedKey != null) && mSelectedKey.equals(key)) {
247 pref.setChecked();
248 }
249 apnList.addPreference(pref);
250 } else {
251 mmsApnList.add(pref);
John Huang68296882009-03-24 18:26:28 -0700252 }
Hyejin Kim88c80b12013-02-14 15:49:19 +0900253 cursor.moveToNext();
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800254 }
Hyejin Kim88c80b12013-02-14 15:49:19 +0900255 cursor.close();
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800256
Hyejin Kim88c80b12013-02-14 15:49:19 +0900257 for (Preference preference : mmsApnList) {
258 apnList.addPreference(preference);
259 }
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800260 }
261 }
262
263 @Override
Fabrice Di Meglio61a1fec2014-08-13 16:22:38 -0700264 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
265 if (!mUnavailable) {
266 menu.add(0, MENU_NEW, 0,
267 getResources().getString(R.string.menu_new))
268 .setIcon(android.R.drawable.ic_menu_add)
269 .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
270 menu.add(0, MENU_RESTORE, 0,
271 getResources().getString(R.string.menu_restore))
272 .setIcon(android.R.drawable.ic_menu_upload);
273 }
274
275 super.onCreateOptionsMenu(menu, inflater);
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800276 }
277
278 @Override
279 public boolean onOptionsItemSelected(MenuItem item) {
280 switch (item.getItemId()) {
281 case MENU_NEW:
282 addNewApn();
283 return true;
284
285 case MENU_RESTORE:
286 restoreDefaultApn();
287 return true;
288 }
289 return super.onOptionsItemSelected(item);
290 }
291
292 private void addNewApn() {
Mick Lin09c9e5e2015-01-22 17:28:43 +0800293 Intent intent = new Intent(Intent.ACTION_INSERT, Telephony.Carriers.CONTENT_URI);
294 int subId = mSubscriptionInfo != null ? mSubscriptionInfo.getSubscriptionId()
295 : SubscriptionManager.INVALID_SUBSCRIPTION_ID;
296 intent.putExtra("sub_id", subId);
297 startActivity(intent);
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800298 }
299
300 @Override
301 public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
302 int pos = Integer.parseInt(preference.getKey());
303 Uri url = ContentUris.withAppendedId(Telephony.Carriers.CONTENT_URI, pos);
304 startActivity(new Intent(Intent.ACTION_EDIT, url));
305 return true;
306 }
307
John Huang68296882009-03-24 18:26:28 -0700308 public boolean onPreferenceChange(Preference preference, Object newValue) {
309 Log.d(TAG, "onPreferenceChange(): Preference - " + preference
310 + ", newValue - " + newValue + ", newValue type - "
311 + newValue.getClass());
312 if (newValue instanceof String) {
313 setSelectedApnKey((String) newValue);
314 }
315
316 return true;
317 }
318
319 private void setSelectedApnKey(String key) {
320 mSelectedKey = key;
321 ContentResolver resolver = getContentResolver();
322
323 ContentValues values = new ContentValues();
324 values.put(APN_ID, mSelectedKey);
325 resolver.update(PREFERAPN_URI, values, null, null);
326 }
327
328 private String getSelectedApnKey() {
329 String key = null;
330
Jeff Brownb4ea1e42011-09-12 14:59:51 -0700331 Cursor cursor = getContentResolver().query(PREFERAPN_URI, new String[] {"_id"},
332 null, null, Telephony.Carriers.DEFAULT_SORT_ORDER);
John Huang68296882009-03-24 18:26:28 -0700333 if (cursor.getCount() > 0) {
334 cursor.moveToFirst();
335 key = cursor.getString(ID_INDEX);
336 }
337 cursor.close();
338 return key;
339 }
340
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800341 private boolean restoreDefaultApn() {
342 showDialog(DIALOG_RESTORE_DEFAULTAPN);
343 mRestoreDefaultApnMode = true;
344
345 if (mRestoreApnUiHandler == null) {
346 mRestoreApnUiHandler = new RestoreApnUiHandler();
347 }
348
Jack Wang481582f2011-01-27 14:25:22 +0800349 if (mRestoreApnProcessHandler == null ||
350 mRestoreDefaultApnThread == null) {
351 mRestoreDefaultApnThread = new HandlerThread(
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800352 "Restore default APN Handler: Process Thread");
Jack Wang481582f2011-01-27 14:25:22 +0800353 mRestoreDefaultApnThread.start();
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800354 mRestoreApnProcessHandler = new RestoreApnProcessHandler(
Jack Wang481582f2011-01-27 14:25:22 +0800355 mRestoreDefaultApnThread.getLooper(), mRestoreApnUiHandler);
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800356 }
357
358 mRestoreApnProcessHandler
359 .sendEmptyMessage(EVENT_RESTORE_DEFAULTAPN_START);
360 return true;
361 }
362
363 private class RestoreApnUiHandler extends Handler {
364 @Override
365 public void handleMessage(Message msg) {
366 switch (msg.what) {
367 case EVENT_RESTORE_DEFAULTAPN_COMPLETE:
Fabrice Di Meglio3e825fe2014-10-13 18:59:34 -0700368 Activity activity = getActivity();
369 if (activity == null) {
370 mRestoreDefaultApnMode = false;
371 return;
372 }
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800373 fillList();
374 getPreferenceScreen().setEnabled(true);
375 mRestoreDefaultApnMode = false;
Fabrice Di Meglio61a1fec2014-08-13 16:22:38 -0700376 removeDialog(DIALOG_RESTORE_DEFAULTAPN);
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800377 Toast.makeText(
Fabrice Di Meglio3e825fe2014-10-13 18:59:34 -0700378 activity,
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800379 getResources().getString(
380 R.string.restore_default_apn_completed),
381 Toast.LENGTH_LONG).show();
382 break;
383 }
384 }
385 }
386
387 private class RestoreApnProcessHandler extends Handler {
388 private Handler mRestoreApnUiHandler;
389
390 public RestoreApnProcessHandler(Looper looper, Handler restoreApnUiHandler) {
391 super(looper);
392 this.mRestoreApnUiHandler = restoreApnUiHandler;
393 }
394
395 @Override
396 public void handleMessage(Message msg) {
397 switch (msg.what) {
398 case EVENT_RESTORE_DEFAULTAPN_START:
399 ContentResolver resolver = getContentResolver();
Hyejin Kim88c80b12013-02-14 15:49:19 +0900400 resolver.delete(DEFAULTAPN_URI, null, null);
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800401 mRestoreApnUiHandler
402 .sendEmptyMessage(EVENT_RESTORE_DEFAULTAPN_COMPLETE);
403 break;
404 }
405 }
406 }
407
408 @Override
Fabrice Di Meglio61a1fec2014-08-13 16:22:38 -0700409 public Dialog onCreateDialog(int id) {
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800410 if (id == DIALOG_RESTORE_DEFAULTAPN) {
Fabrice Di Meglio61a1fec2014-08-13 16:22:38 -0700411 ProgressDialog dialog = new ProgressDialog(getActivity());
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800412 dialog.setMessage(getResources().getString(R.string.restore_default_apn));
413 dialog.setCancelable(false);
414 return dialog;
415 }
416 return null;
417 }
The Android Open Source Projectafc4ab22009-03-03 19:32:34 -0800418}