Home | History | Annotate | Download | only in appsettings
      1 /*
      2  * Copyright (C) 2015 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.messaging.ui.appsettings;
     18 
     19 import android.app.Activity;
     20 import android.app.Dialog;
     21 import android.app.ProgressDialog;
     22 import android.content.ContentValues;
     23 import android.content.Context;
     24 import android.database.Cursor;
     25 import android.database.sqlite.SQLiteDatabase;
     26 import android.os.AsyncTask;
     27 import android.os.Bundle;
     28 import android.os.Handler;
     29 import android.os.HandlerThread;
     30 import android.os.Looper;
     31 import android.os.Message;
     32 import android.os.UserManager;
     33 import android.preference.Preference;
     34 import android.preference.PreferenceFragment;
     35 import android.preference.PreferenceGroup;
     36 import android.preference.PreferenceScreen;
     37 import android.provider.Telephony;
     38 import android.support.v4.app.NavUtils;
     39 import android.view.Menu;
     40 import android.view.MenuInflater;
     41 import android.view.MenuItem;
     42 import android.widget.ListView;
     43 import android.widget.TextView;
     44 import android.widget.Toast;
     45 
     46 import com.android.messaging.R;
     47 import com.android.messaging.datamodel.data.ParticipantData;
     48 import com.android.messaging.sms.ApnDatabase;
     49 import com.android.messaging.sms.BugleApnSettingsLoader;
     50 import com.android.messaging.ui.BugleActionBarActivity;
     51 import com.android.messaging.ui.UIIntents;
     52 import com.android.messaging.util.OsUtil;
     53 import com.android.messaging.util.PhoneUtils;
     54 
     55 public class ApnSettingsActivity extends BugleActionBarActivity {
     56     private static final int DIALOG_RESTORE_DEFAULTAPN = 1001;
     57 
     58     @Override
     59     protected void onCreate(Bundle savedInstanceState) {
     60         super.onCreate(savedInstanceState);
     61 
     62         getSupportActionBar().setDisplayHomeAsUpEnabled(true);
     63 
     64         // Display the fragment as the main content.
     65         final ApnSettingsFragment fragment = new ApnSettingsFragment();
     66         fragment.setSubId(getIntent().getIntExtra(UIIntents.UI_INTENT_EXTRA_SUB_ID,
     67                 ParticipantData.DEFAULT_SELF_SUB_ID));
     68         getFragmentManager().beginTransaction()
     69                 .replace(android.R.id.content, fragment)
     70                 .commit();
     71     }
     72 
     73     @Override
     74     public boolean onOptionsItemSelected(final MenuItem item) {
     75         switch (item.getItemId()) {
     76         case android.R.id.home:
     77             NavUtils.navigateUpFromSameTask(this);
     78             return true;
     79         }
     80         return super.onOptionsItemSelected(item);
     81     }
     82 
     83     @Override
     84     protected Dialog onCreateDialog(int id) {
     85         if (id == DIALOG_RESTORE_DEFAULTAPN) {
     86             ProgressDialog dialog = new ProgressDialog(this);
     87             dialog.setMessage(getResources().getString(R.string.restore_default_apn));
     88             dialog.setCancelable(false);
     89             return dialog;
     90         }
     91         return null;
     92     }
     93 
     94     public static class ApnSettingsFragment extends PreferenceFragment implements
     95             Preference.OnPreferenceChangeListener {
     96         public static final String EXTRA_POSITION = "position";
     97 
     98         public static final String APN_ID = "apn_id";
     99 
    100         private static final String[] APN_PROJECTION = {
    101             Telephony.Carriers._ID,         // 0
    102             Telephony.Carriers.NAME,        // 1
    103             Telephony.Carriers.APN,         // 2
    104             Telephony.Carriers.TYPE         // 3
    105         };
    106         private static final int ID_INDEX    = 0;
    107         private static final int NAME_INDEX  = 1;
    108         private static final int APN_INDEX   = 2;
    109         private static final int TYPES_INDEX = 3;
    110 
    111         private static final int MENU_NEW = Menu.FIRST;
    112         private static final int MENU_RESTORE = Menu.FIRST + 1;
    113 
    114         private static final int EVENT_RESTORE_DEFAULTAPN_START = 1;
    115         private static final int EVENT_RESTORE_DEFAULTAPN_COMPLETE = 2;
    116 
    117         private static boolean mRestoreDefaultApnMode;
    118 
    119         private RestoreApnUiHandler mRestoreApnUiHandler;
    120         private RestoreApnProcessHandler mRestoreApnProcessHandler;
    121         private HandlerThread mRestoreDefaultApnThread;
    122 
    123         private String mSelectedKey;
    124 
    125         private static final ContentValues sCurrentNullMap;
    126         private static final ContentValues sCurrentSetMap;
    127 
    128         private UserManager mUm;
    129 
    130         private boolean mUnavailable;
    131         private int mSubId;
    132 
    133         static {
    134             sCurrentNullMap = new ContentValues(1);
    135             sCurrentNullMap.putNull(Telephony.Carriers.CURRENT);
    136 
    137             sCurrentSetMap = new ContentValues(1);
    138             sCurrentSetMap.put(Telephony.Carriers.CURRENT, "2");    // 2 for user-selected APN,
    139             // 1 for Bugle-selected APN
    140         }
    141 
    142         private SQLiteDatabase mDatabase;
    143 
    144         public void setSubId(final int subId) {
    145             mSubId = subId;
    146         }
    147 
    148         @Override
    149         public void onCreate(Bundle icicle) {
    150             super.onCreate(icicle);
    151 
    152             mDatabase = ApnDatabase.getApnDatabase().getWritableDatabase();
    153 
    154             if (OsUtil.isAtLeastL()) {
    155                 mUm = (UserManager) getActivity().getSystemService(Context.USER_SERVICE);
    156                 if (!mUm.hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
    157                     setHasOptionsMenu(true);
    158                 }
    159             } else {
    160                 setHasOptionsMenu(true);
    161             }
    162         }
    163 
    164         @Override
    165         public void onActivityCreated(Bundle savedInstanceState) {
    166             super.onActivityCreated(savedInstanceState);
    167 
    168             final ListView lv = (ListView) getView().findViewById(android.R.id.list);
    169             TextView empty = (TextView) getView().findViewById(android.R.id.empty);
    170             if (empty != null) {
    171                 empty.setText(R.string.apn_settings_not_available);
    172                 lv.setEmptyView(empty);
    173             }
    174 
    175             if (OsUtil.isAtLeastL() &&
    176                     mUm.hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) {
    177                 mUnavailable = true;
    178                 setPreferenceScreen(getPreferenceManager().createPreferenceScreen(getActivity()));
    179                 return;
    180             }
    181 
    182             addPreferencesFromResource(R.xml.apn_settings);
    183 
    184             lv.setItemsCanFocus(true);
    185         }
    186 
    187         @Override
    188         public void onResume() {
    189             super.onResume();
    190 
    191             if (mUnavailable) {
    192                 return;
    193             }
    194 
    195             if (!mRestoreDefaultApnMode) {
    196                 fillList();
    197             }
    198         }
    199 
    200         @Override
    201         public void onPause() {
    202             super.onPause();
    203 
    204             if (mUnavailable) {
    205                 return;
    206             }
    207         }
    208 
    209         @Override
    210         public void onDestroy() {
    211             super.onDestroy();
    212 
    213             if (mRestoreDefaultApnThread != null) {
    214                 mRestoreDefaultApnThread.quit();
    215             }
    216         }
    217 
    218         private void fillList() {
    219             final String mccMnc = PhoneUtils.getMccMncString(PhoneUtils.get(mSubId).getMccMnc());
    220 
    221             new AsyncTask<Void, Void, Cursor>() {
    222                 @Override
    223                 protected Cursor doInBackground(Void... params) {
    224                     String selection = Telephony.Carriers.NUMERIC + " =?";
    225                     String[] selectionArgs = new String[]{ mccMnc };
    226                     final Cursor cursor = mDatabase.query(ApnDatabase.APN_TABLE, APN_PROJECTION,
    227                             selection, selectionArgs, null, null, null, null);
    228                     return cursor;
    229                 }
    230 
    231                 @Override
    232                 protected void onPostExecute(Cursor cursor) {
    233                     if (cursor != null) {
    234                         try {
    235                             PreferenceGroup apnList = (PreferenceGroup)
    236                                     findPreference(getString(R.string.apn_list_pref_key));
    237                             apnList.removeAll();
    238 
    239                             mSelectedKey = BugleApnSettingsLoader.getFirstTryApn(mDatabase, mccMnc);
    240                             while (cursor.moveToNext()) {
    241                                 String name = cursor.getString(NAME_INDEX);
    242                                 String apn = cursor.getString(APN_INDEX);
    243                                 String key = cursor.getString(ID_INDEX);
    244                                 String type = cursor.getString(TYPES_INDEX);
    245 
    246                                 if (BugleApnSettingsLoader.isValidApnType(type,
    247                                         BugleApnSettingsLoader.APN_TYPE_MMS)) {
    248                                     ApnPreference pref = new ApnPreference(getActivity());
    249                                     pref.setKey(key);
    250                                     pref.setTitle(name);
    251                                     pref.setSummary(apn);
    252                                     pref.setPersistent(false);
    253                                     pref.setOnPreferenceChangeListener(ApnSettingsFragment.this);
    254                                     pref.setSelectable(true);
    255 
    256                                     // Turn on the radio button for the currently selected APN. If
    257                                     // there is no selected APN, don't select an APN.
    258                                     if ((mSelectedKey != null && mSelectedKey.equals(key))) {
    259                                         pref.setChecked();
    260                                     }
    261                                     apnList.addPreference(pref);
    262                                 }
    263                             }
    264                         } finally {
    265                             cursor.close();
    266                         }
    267                     }
    268                 }
    269             }.execute((Void) null);
    270         }
    271 
    272         @Override
    273         public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    274             if (!mUnavailable) {
    275                 menu.add(0, MENU_NEW, 0,
    276                         getResources().getString(R.string.menu_new_apn))
    277                         .setIcon(R.drawable.ic_add_gray)
    278                         .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
    279                 menu.add(0, MENU_RESTORE, 0,
    280                         getResources().getString(R.string.menu_restore_default_apn))
    281                         .setIcon(android.R.drawable.ic_menu_upload);
    282             }
    283 
    284             super.onCreateOptionsMenu(menu, inflater);
    285         }
    286 
    287         @Override
    288         public boolean onOptionsItemSelected(MenuItem item) {
    289             switch (item.getItemId()) {
    290                 case MENU_NEW:
    291                     addNewApn();
    292                     return true;
    293 
    294                 case MENU_RESTORE:
    295                     restoreDefaultApn();
    296                     return true;
    297             }
    298             return super.onOptionsItemSelected(item);
    299         }
    300 
    301         private void addNewApn() {
    302             startActivity(UIIntents.get().getApnEditorIntent(getActivity(), null, mSubId));
    303         }
    304 
    305         @Override
    306         public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
    307                 Preference preference) {
    308             startActivity(
    309                     UIIntents.get().getApnEditorIntent(getActivity(), preference.getKey(), mSubId));
    310             return true;
    311         }
    312 
    313         @Override
    314         public boolean onPreferenceChange(Preference preference, Object newValue) {
    315             if (newValue instanceof String) {
    316                 setSelectedApnKey((String) newValue);
    317             }
    318 
    319             return true;
    320         }
    321 
    322         // current=2 means user selected APN
    323         private static final String UPDATE_SELECTION = Telephony.Carriers.CURRENT + " =?";
    324         private static final String[] UPDATE_SELECTION_ARGS = new String[] { "2" };
    325         private void setSelectedApnKey(final String key) {
    326             mSelectedKey = key;
    327 
    328             // Make database changes not on the UI thread
    329             new AsyncTask<Void, Void, Void>() {
    330                 @Override
    331                 protected Void doInBackground(Void... params) {
    332                     // null out the previous "current=2" APN
    333                     mDatabase.update(ApnDatabase.APN_TABLE, sCurrentNullMap,
    334                             UPDATE_SELECTION, UPDATE_SELECTION_ARGS);
    335 
    336                     // set the new "current" APN (2)
    337                     String selection = Telephony.Carriers._ID + " =?";
    338                     String[] selectionArgs = new String[]{ key };
    339 
    340                     mDatabase.update(ApnDatabase.APN_TABLE, sCurrentSetMap,
    341                             selection, selectionArgs);
    342                     return null;
    343                 }
    344             }.execute((Void) null);
    345         }
    346 
    347         private boolean restoreDefaultApn() {
    348             getActivity().showDialog(DIALOG_RESTORE_DEFAULTAPN);
    349             mRestoreDefaultApnMode = true;
    350 
    351             if (mRestoreApnUiHandler == null) {
    352                 mRestoreApnUiHandler = new RestoreApnUiHandler();
    353             }
    354 
    355             if (mRestoreApnProcessHandler == null ||
    356                     mRestoreDefaultApnThread == null) {
    357                 mRestoreDefaultApnThread = new HandlerThread(
    358                         "Restore default APN Handler: Process Thread");
    359                 mRestoreDefaultApnThread.start();
    360                 mRestoreApnProcessHandler = new RestoreApnProcessHandler(
    361                         mRestoreDefaultApnThread.getLooper(), mRestoreApnUiHandler);
    362             }
    363 
    364             mRestoreApnProcessHandler.sendEmptyMessage(EVENT_RESTORE_DEFAULTAPN_START);
    365             return true;
    366         }
    367 
    368         private class RestoreApnUiHandler extends Handler {
    369             @Override
    370             public void handleMessage(Message msg) {
    371                 switch (msg.what) {
    372                     case EVENT_RESTORE_DEFAULTAPN_COMPLETE:
    373                         fillList();
    374                         getPreferenceScreen().setEnabled(true);
    375                         mRestoreDefaultApnMode = false;
    376                         final Activity activity = getActivity();
    377                         activity.dismissDialog(DIALOG_RESTORE_DEFAULTAPN);
    378                         Toast.makeText(activity, getResources().getString(
    379                                         R.string.restore_default_apn_completed), Toast.LENGTH_LONG)
    380                                             .show();
    381                         break;
    382                 }
    383             }
    384         }
    385 
    386         private class RestoreApnProcessHandler extends Handler {
    387             private Handler mCachedRestoreApnUiHandler;
    388 
    389             public RestoreApnProcessHandler(Looper looper, Handler restoreApnUiHandler) {
    390                 super(looper);
    391                 this.mCachedRestoreApnUiHandler = restoreApnUiHandler;
    392             }
    393 
    394             @Override
    395             public void handleMessage(Message msg) {
    396                 switch (msg.what) {
    397                     case EVENT_RESTORE_DEFAULTAPN_START:
    398                         ApnDatabase.forceBuildAndLoadApnTables();
    399                         mCachedRestoreApnUiHandler.sendEmptyMessage(
    400                                 EVENT_RESTORE_DEFAULTAPN_COMPLETE);
    401                         break;
    402                 }
    403             }
    404         }
    405     }
    406 }
    407