1/* 2 * Copyright (C) 2018 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 */ 16package com.android.phone; 17 18import android.app.ActionBar; 19import android.app.Activity; 20import android.content.ComponentName; 21import android.content.Context; 22import android.content.Intent; 23import android.content.ServiceConnection; 24import android.os.AsyncResult; 25import android.os.AsyncTask; 26import android.os.Bundle; 27import android.os.Handler; 28import android.os.IBinder; 29import android.os.Message; 30import android.os.RemoteException; 31import android.preference.Preference; 32import android.preference.PreferenceCategory; 33import android.preference.PreferenceFragment; 34import android.preference.PreferenceScreen; 35import android.telephony.AccessNetworkConstants; 36import android.telephony.CellIdentity; 37import android.telephony.CellInfo; 38import android.telephony.NetworkRegistrationState; 39import android.telephony.ServiceState; 40import android.telephony.SubscriptionManager; 41import android.telephony.TelephonyManager; 42import android.util.Log; 43import android.view.LayoutInflater; 44import android.view.View; 45import android.view.ViewGroup; 46 47import com.android.internal.logging.MetricsLogger; 48import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 49import com.android.internal.telephony.OperatorInfo; 50import com.android.internal.telephony.Phone; 51import com.android.internal.telephony.PhoneFactory; 52 53import java.util.ArrayList; 54import java.util.Arrays; 55import java.util.HashMap; 56import java.util.List; 57import java.util.Map; 58 59/** 60 * "Choose network" settings UI for the Phone app. 61 */ 62public class NetworkSelectSetting extends PreferenceFragment { 63 64 private static final String TAG = "NetworkSelectSetting"; 65 private static final boolean DBG = true; 66 67 private static final int EVENT_NETWORK_SELECTION_DONE = 1; 68 private static final int EVENT_NETWORK_SCAN_RESULTS = 2; 69 private static final int EVENT_NETWORK_SCAN_ERROR = 3; 70 private static final int EVENT_NETWORK_SCAN_COMPLETED = 4; 71 72 private static final String PREF_KEY_CONNECTED_NETWORK_OPERATOR = 73 "connected_network_operator_preference"; 74 private static final String PREF_KEY_NETWORK_OPERATORS = "network_operators_preference"; 75 76 // used to add/remove NetworkOperatorsPreference. 77 private PreferenceCategory mNetworkOperatorsPreferences; 78 // used to add/remove connected NetworkOperatorPreference. 79 private PreferenceCategory mConnectedNetworkOperatorsPreference; 80 // manage the progress bar on the top of the page. 81 private View mProgressHeader; 82 private Preference mStatusMessagePreference; 83 private List<CellInfo> mCellInfoList; 84 private int mPhoneId = SubscriptionManager.INVALID_PHONE_INDEX; 85 private ViewGroup mFrameLayout; 86 private NetworkOperatorPreference mSelectedNetworkOperatorPreference; 87 private TelephonyManager mTelephonyManager; 88 private NetworkOperators mNetworkOperators; 89 private List<String> mForbiddenPlmns; 90 91 private final Runnable mUpdateNetworkOperatorsRunnable = () -> { 92 updateNetworkOperatorsPreferenceCategory(); 93 }; 94 95 /** 96 * Create a new instance of this fragment. 97 */ 98 public static NetworkSelectSetting newInstance(int phoneId) { 99 Bundle args = new Bundle(); 100 args.putInt(NetworkSelectSettingActivity.KEY_PHONE_ID, phoneId); 101 NetworkSelectSetting fragment = new NetworkSelectSetting(); 102 fragment.setArguments(args); 103 104 return fragment; 105 } 106 107 @Override 108 public void onCreate(Bundle icicle) { 109 if (DBG) logd("onCreate"); 110 super.onCreate(icicle); 111 112 mPhoneId = getArguments().getInt(NetworkSelectSettingActivity.KEY_PHONE_ID); 113 114 addPreferencesFromResource(R.xml.choose_network); 115 mConnectedNetworkOperatorsPreference = 116 (PreferenceCategory) findPreference(PREF_KEY_CONNECTED_NETWORK_OPERATOR); 117 mNetworkOperatorsPreferences = 118 (PreferenceCategory) findPreference(PREF_KEY_NETWORK_OPERATORS); 119 mStatusMessagePreference = new Preference(getContext()); 120 mSelectedNetworkOperatorPreference = null; 121 mTelephonyManager = (TelephonyManager) 122 getContext().getSystemService(Context.TELEPHONY_SERVICE); 123 mNetworkOperators = new NetworkOperators(getContext()); 124 setRetainInstance(true); 125 } 126 127 @Override 128 public void onViewCreated(View view, Bundle savedInstanceState) { 129 if (DBG) logd("onViewCreated"); 130 super.onViewCreated(view, savedInstanceState); 131 132 if (getListView() != null) { 133 getListView().setDivider(null); 134 } 135 // Inflate progress bar 136 final Activity activity = getActivity(); 137 if (activity != null) { 138 ActionBar actionBar = activity.getActionBar(); 139 if (actionBar != null) { 140 // android.R.id.home will be triggered in 141 // {@link NetworkSelectSettingAcitivity#onOptionsItemSelected()} 142 actionBar.setDisplayHomeAsUpEnabled(true); 143 } 144 mFrameLayout = activity.findViewById(R.id.choose_network_content); 145 final LayoutInflater inflater = activity.getLayoutInflater(); 146 final View pinnedHeader = 147 inflater.inflate(R.layout.choose_network_progress_header, mFrameLayout, false); 148 mFrameLayout.addView(pinnedHeader); 149 mFrameLayout.setVisibility(View.VISIBLE); 150 mProgressHeader = pinnedHeader.findViewById(R.id.progress_bar_animation); 151 setProgressBarVisible(false); 152 } 153 forceConfigConnectedNetworkOperatorsPreferenceCategory(); 154 } 155 156 @Override 157 public void onStart() { 158 if (DBG) logd("onStart"); 159 super.onStart(); 160 new AsyncTask<Void, Void, List<String>>() { 161 @Override 162 protected List<String> doInBackground(Void... voids) { 163 return Arrays.asList(mTelephonyManager.getForbiddenPlmns()); 164 } 165 166 @Override 167 protected void onPostExecute(List<String> result) { 168 mForbiddenPlmns = result; 169 bindNetworkQueryService(); 170 } 171 }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 172 } 173 174 /** 175 * Invoked on each preference click in this hierarchy, overrides 176 * PreferenceActivity's implementation. Used to make sure we track the 177 * preference click events. 178 * Since the connected network operator is either faked (when no data connection) or already 179 * connected, we do not allow user to click the connected network operator. 180 */ 181 @Override 182 public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, 183 Preference preference) { 184 if (DBG) logd("User clicked the screen"); 185 stopNetworkQuery(); 186 setProgressBarVisible(false); 187 if (preference instanceof NetworkOperatorPreference) { 188 // Refresh the last selected item in case users reselect network. 189 if (mSelectedNetworkOperatorPreference != null) { 190 mSelectedNetworkOperatorPreference.setSummary(""); 191 } 192 193 mSelectedNetworkOperatorPreference = (NetworkOperatorPreference) preference; 194 CellInfo cellInfo = mSelectedNetworkOperatorPreference.getCellInfo(); 195 if (DBG) logd("User click a NetworkOperatorPreference: " + cellInfo.toString()); 196 197 // Send metrics event 198 MetricsLogger.action(getContext(), 199 MetricsEvent.ACTION_MOBILE_NETWORK_MANUAL_SELECT_NETWORK); 200 201 // Connect to the network 202 Message msg = mHandler.obtainMessage(EVENT_NETWORK_SELECTION_DONE); 203 Phone phone = PhoneFactory.getPhone(mPhoneId); 204 if (phone != null) { 205 if (DBG) { 206 logd("Connect to the network: " + CellInfoUtil.getNetworkTitle(cellInfo)); 207 } 208 // Set summary as "Connecting" to the selected network. 209 mSelectedNetworkOperatorPreference.setSummary(R.string.network_connecting); 210 211 // Set summary as "Disconnected" to the previously connected network 212 if (mConnectedNetworkOperatorsPreference.getPreferenceCount() > 0) { 213 NetworkOperatorPreference connectedNetworkOperator = (NetworkOperatorPreference) 214 (mConnectedNetworkOperatorsPreference.getPreference(0)); 215 if (!CellInfoUtil.getNetworkTitle(cellInfo).equals( 216 CellInfoUtil.getNetworkTitle(connectedNetworkOperator.getCellInfo()))) { 217 connectedNetworkOperator.setSummary(R.string.network_disconnected); 218 } 219 } 220 221 // Select network manually via Phone 222 OperatorInfo operatorInfo = CellInfoUtil.getOperatorInfoFromCellInfo(cellInfo); 223 if (DBG) logd("manually selected network operator: " + operatorInfo.toString()); 224 phone.selectNetworkManually(operatorInfo, true, msg); 225 setProgressBarVisible(true); 226 return true; 227 } else { 228 loge("Error selecting network. phone is null."); 229 mSelectedNetworkOperatorPreference = null; 230 return false; 231 } 232 233 } else { 234 preferenceScreen.setEnabled(false); 235 return false; 236 } 237 } 238 239 @Override 240 public void onAttach(Activity activity) { 241 super.onAttach(activity); 242 if (!(getActivity() instanceof NetworkSelectSettingActivity)) { 243 throw new IllegalStateException("Parent activity is not NetworkSelectSettingActivity"); 244 } 245 } 246 247 @Override 248 public void onStop() { 249 super.onStop(); 250 if (DBG) logd("onStop"); 251 getView().removeCallbacks(mUpdateNetworkOperatorsRunnable); 252 stopNetworkQuery(); 253 // Unbind the NetworkQueryService 254 unbindNetworkQueryService(); 255 } 256 257 private final Handler mHandler = new Handler() { 258 @Override 259 public void handleMessage(Message msg) { 260 AsyncResult ar; 261 switch (msg.what) { 262 case EVENT_NETWORK_SELECTION_DONE: 263 if (DBG) logd("network selection done: hide the progress header"); 264 setProgressBarVisible(false); 265 266 ar = (AsyncResult) msg.obj; 267 if (ar.exception != null) { 268 if (DBG) logd("manual network selection: failed! "); 269 updateNetworkSelection(); 270 // Set summary as "Couldn't connect" to the selected network. 271 mSelectedNetworkOperatorPreference.setSummary( 272 R.string.network_could_not_connect); 273 } else { 274 if (DBG) logd("manual network selection: succeeded! "); 275 // Set summary as "Connected" to the selected network. 276 mSelectedNetworkOperatorPreference.setSummary(R.string.network_connected); 277 } 278 break; 279 280 case EVENT_NETWORK_SCAN_RESULTS: 281 List<CellInfo> results = aggregateCellInfoList((List<CellInfo>) msg.obj); 282 mCellInfoList = new ArrayList<>(results); 283 if (DBG) logd("after aggregate: " + mCellInfoList.toString()); 284 if (mCellInfoList != null && mCellInfoList.size() != 0) { 285 updateNetworkOperators(); 286 } else { 287 addMessagePreference(R.string.empty_networks_list); 288 } 289 290 break; 291 292 case EVENT_NETWORK_SCAN_ERROR: 293 int error = msg.arg1; 294 if (DBG) logd("error while querying available networks " + error); 295 stopNetworkQuery(); 296 addMessagePreference(R.string.network_query_error); 297 break; 298 299 case EVENT_NETWORK_SCAN_COMPLETED: 300 stopNetworkQuery(); 301 if (DBG) logd("scan complete"); 302 if (mCellInfoList == null) { 303 // In case the scan timeout before getting any results 304 addMessagePreference(R.string.empty_networks_list); 305 } 306 break; 307 } 308 return; 309 } 310 }; 311 312 private void loadNetworksList() { 313 if (DBG) logd("load networks list..."); 314 setProgressBarVisible(true); 315 try { 316 if (mNetworkQueryService != null) { 317 if (DBG) logd("start network query"); 318 mNetworkQueryService 319 .startNetworkQuery(mCallback, mPhoneId, true /* is incremental result */); 320 } else { 321 if (DBG) logd("unable to start network query, mNetworkQueryService is null"); 322 addMessagePreference(R.string.network_query_error); 323 } 324 } catch (RemoteException e) { 325 loge("loadNetworksList: exception from startNetworkQuery " + e); 326 addMessagePreference(R.string.network_query_error); 327 } 328 } 329 330 /** 331 * This implementation of INetworkQueryServiceCallback is used to receive 332 * callback notifications from the network query service. 333 */ 334 private final INetworkQueryServiceCallback mCallback = new INetworkQueryServiceCallback.Stub() { 335 336 /** Returns the scan results to the user, this callback will be called at lease one time. */ 337 public void onResults(List<CellInfo> results) { 338 if (DBG) logd("get scan results."); 339 Message msg = mHandler.obtainMessage(EVENT_NETWORK_SCAN_RESULTS, results); 340 msg.sendToTarget(); 341 } 342 343 /** 344 * Informs the user that the scan has stopped. 345 * 346 * This callback will be called when the scan is finished or cancelled by the user. 347 * The related NetworkScanRequest will be deleted after this callback. 348 */ 349 public void onComplete() { 350 if (DBG) logd("network scan completed."); 351 Message msg = mHandler.obtainMessage(EVENT_NETWORK_SCAN_COMPLETED); 352 msg.sendToTarget(); 353 } 354 355 /** 356 * Informs the user that there is some error about the scan. 357 * 358 * This callback will be called whenever there is any error about the scan, and the scan 359 * will be terminated. onComplete() will NOT be called. 360 */ 361 public void onError(int error) { 362 if (DBG) logd("get onError callback with error code: " + error); 363 Message msg = mHandler.obtainMessage(EVENT_NETWORK_SCAN_ERROR, error, 0 /* arg2 */); 364 msg.sendToTarget(); 365 } 366 }; 367 368 /** 369 * Updates network operators from {@link INetworkQueryServiceCallback#onResults()}. 370 */ 371 private void updateNetworkOperators() { 372 if (DBG) logd("updateNetworkOperators"); 373 if (getActivity() != null) { 374 final View view = getView(); 375 final Handler handler = view.getHandler(); 376 if (handler != null && handler.hasCallbacks(mUpdateNetworkOperatorsRunnable)) { 377 return; 378 } 379 view.post(mUpdateNetworkOperatorsRunnable); 380 } 381 } 382 383 /** 384 * Update the currently available network operators list, which only contains the unregistered 385 * network operators. So if the device has no data and the network operator in the connected 386 * network operator category shows "Disconnected", it will also exist in the available network 387 * operator category for user to select. On the other hand, if the device has data and the 388 * network operator in the connected network operator category shows "Connected", it will not 389 * exist in the available network category. 390 */ 391 private void updateNetworkOperatorsPreferenceCategory() { 392 mNetworkOperatorsPreferences.removeAll(); 393 394 configConnectedNetworkOperatorsPreferenceCategory(); 395 for (int index = 0; index < mCellInfoList.size(); index++) { 396 if (!mCellInfoList.get(index).isRegistered()) { 397 NetworkOperatorPreference pref = new NetworkOperatorPreference( 398 mCellInfoList.get(index), getContext(), mForbiddenPlmns); 399 pref.setKey(CellInfoUtil.getNetworkTitle(mCellInfoList.get(index))); 400 pref.setOrder(index); 401 mNetworkOperatorsPreferences.addPreference(pref); 402 } 403 } 404 } 405 406 /** 407 * Config the connected network operator preference when the page was created. When user get 408 * into this page, the device might or might not have data connection. 409 * - If the device has data: 410 * 1. use {@code ServiceState#getNetworkRegistrationStates()} to get the currently 411 * registered cellIdentity, wrap it into a CellInfo; 412 * 2. set the signal strength level as strong; 413 * 3. use {@link TelephonyManager#getNetworkOperatorName()} to get the title of the 414 * previously connected network operator, since the CellIdentity got from step 1 only has 415 * PLMN. 416 * - If the device has no data, we will remove the connected network operators list from the 417 * screen. 418 */ 419 private void forceConfigConnectedNetworkOperatorsPreferenceCategory() { 420 if (DBG) logd("Force config ConnectedNetworkOperatorsPreferenceCategory"); 421 if (mTelephonyManager.getDataState() == mTelephonyManager.DATA_CONNECTED) { 422 // Try to get the network registration states 423 ServiceState ss = mTelephonyManager.getServiceStateForSubscriber(mPhoneId); 424 List<NetworkRegistrationState> networkList = 425 ss.getNetworkRegistrationStates(AccessNetworkConstants.TransportType.WWAN); 426 if (networkList == null || networkList.size() == 0) { 427 loge("getNetworkRegistrationStates return null"); 428 // Remove the connected network operators category 429 removeConnectedNetworkOperatorPreference(); 430 return; 431 } 432 CellIdentity cellIdentity = networkList.get(0).getCellIdentity(); 433 CellInfo cellInfo = CellInfoUtil.wrapCellInfoWithCellIdentity(cellIdentity); 434 if (cellInfo != null) { 435 if (DBG) logd("Currently registered cell: " + cellInfo.toString()); 436 NetworkOperatorPreference pref = 437 new NetworkOperatorPreference(cellInfo, getContext(), mForbiddenPlmns); 438 pref.setTitle(mTelephonyManager.getNetworkOperatorName()); 439 pref.setSummary(R.string.network_connected); 440 // Update the signal strength icon, since the default signalStrength value would be 441 // zero (it would be quite confusing why the connected network has no signal) 442 pref.setIcon(NetworkOperatorPreference.NUMBER_OF_LEVELS - 1); 443 444 mConnectedNetworkOperatorsPreference.addPreference(pref); 445 } else { 446 loge("Invalid CellIfno: " + cellInfo.toString()); 447 // Remove the connected network operators category 448 removeConnectedNetworkOperatorPreference(); 449 } 450 } else { 451 if (DBG) logd("No currently registered cell"); 452 // Remove the connected network operators category 453 removeConnectedNetworkOperatorPreference(); 454 } 455 } 456 457 /** 458 * Configure the ConnectedNetworkOperatorsPreferenceCategory. The category only need to be 459 * configured if the category is currently empty or the operator network title of the previous 460 * connected network is different from the new one. 461 */ 462 private void configConnectedNetworkOperatorsPreferenceCategory() { 463 if (DBG) logd("config ConnectedNetworkOperatorsPreferenceCategory"); 464 // Remove the category if the CellInfo list is empty or does not have registered cell. 465 if (mCellInfoList.size() == 0) { 466 if (DBG) logd("empty cellinfo list"); 467 removeConnectedNetworkOperatorPreference(); 468 } 469 CellInfo connectedNetworkOperator = null; 470 for (CellInfo cellInfo: mCellInfoList) { 471 if (cellInfo.isRegistered()) { 472 connectedNetworkOperator = cellInfo; 473 break; 474 } 475 } 476 if (connectedNetworkOperator == null) { 477 if (DBG) logd("no registered network"); 478 removeConnectedNetworkOperatorPreference(); 479 return; 480 } 481 482 // config the category if it is empty. 483 if (mConnectedNetworkOperatorsPreference.getPreferenceCount() == 0) { 484 if (DBG) logd("ConnectedNetworkSelectList is empty, add one"); 485 addConnectedNetworkOperatorPreference(connectedNetworkOperator); 486 return; 487 } 488 NetworkOperatorPreference previousConnectedNetworkOperator = (NetworkOperatorPreference) 489 (mConnectedNetworkOperatorsPreference.getPreference(0)); 490 491 // config the category if the network title of the previous connected network is different 492 // from the new one. 493 String cTitle = CellInfoUtil.getNetworkTitle(connectedNetworkOperator); 494 String pTitle = CellInfoUtil.getNetworkTitle( 495 previousConnectedNetworkOperator.getCellInfo()); 496 if (!cTitle.equals(pTitle)) { 497 if (DBG) logd("reconfig the category: connected network changed"); 498 addConnectedNetworkOperatorPreference(connectedNetworkOperator); 499 return; 500 } 501 if (DBG) logd("same network operator is connected, only refresh the connected network"); 502 // Otherwise same network operator is connected, only refresh the connected network 503 // operator preference (first and the only one in this category). 504 ((NetworkOperatorPreference) mConnectedNetworkOperatorsPreference.getPreference(0)) 505 .refresh(); 506 return; 507 } 508 509 /** 510 * Creates a Preference for the given {@link CellInfo} and adds it to the 511 * {@link #mConnectedNetworkOperatorsPreference}. 512 */ 513 private void addConnectedNetworkOperatorPreference(CellInfo cellInfo) { 514 if (DBG) logd("addConnectedNetworkOperatorPreference"); 515 // Remove the current ConnectedNetworkOperatorsPreference 516 removeConnectedNetworkOperatorPreference(); 517 final NetworkOperatorPreference pref = 518 new NetworkOperatorPreference(cellInfo, getContext(), mForbiddenPlmns); 519 pref.setSummary(R.string.network_connected); 520 mConnectedNetworkOperatorsPreference.addPreference(pref); 521 PreferenceScreen preferenceScreen = getPreferenceScreen(); 522 preferenceScreen.addPreference(mConnectedNetworkOperatorsPreference); 523 } 524 525 /** Removes all preferences and hide the {@link #mConnectedNetworkOperatorsPreference}. */ 526 private void removeConnectedNetworkOperatorPreference() { 527 mConnectedNetworkOperatorsPreference.removeAll(); 528 PreferenceScreen preferenceScreen = getPreferenceScreen(); 529 preferenceScreen.removePreference(mConnectedNetworkOperatorsPreference); 530 } 531 532 protected void setProgressBarVisible(boolean visible) { 533 if (mProgressHeader != null) { 534 mProgressHeader.setVisibility(visible ? View.VISIBLE : View.GONE); 535 } 536 } 537 538 private void addMessagePreference(int messageId) { 539 if (DBG) logd("remove callback"); 540 getView().removeCallbacks(mUpdateNetworkOperatorsRunnable); 541 setProgressBarVisible(false); 542 if (DBG) logd("addMessagePreference"); 543 mStatusMessagePreference.setTitle(messageId); 544 removeConnectedNetworkOperatorPreference(); 545 mNetworkOperatorsPreferences.removeAll(); 546 mNetworkOperatorsPreferences.addPreference(mStatusMessagePreference); 547 } 548 549 /** 550 * The Scan results may contains several cell infos with different radio technologies and signal 551 * strength for one network operator. Aggregate the CellInfoList by retaining only the cell info 552 * with the strongest signal strength. 553 */ 554 private List<CellInfo> aggregateCellInfoList(List<CellInfo> cellInfoList) { 555 if (DBG) logd("before aggregate: " + cellInfoList.toString()); 556 Map<String, CellInfo> map = new HashMap<>(); 557 for (CellInfo cellInfo: cellInfoList) { 558 String networkTitle = CellInfoUtil.getNetworkTitle(cellInfo); 559 if (cellInfo.isRegistered() || !map.containsKey(networkTitle)) { 560 map.put(networkTitle, cellInfo); 561 } else { 562 if (map.get(networkTitle).isRegistered() 563 || CellInfoUtil.getLevel(map.get(networkTitle)) 564 > CellInfoUtil.getLevel(cellInfo)) { 565 // Skip if the stored cellInfo is registered or has higher signal strength level 566 continue; 567 } 568 // Otherwise replace it with the new CellInfo 569 map.put(networkTitle, cellInfo); 570 } 571 } 572 return new ArrayList<>(map.values()); 573 } 574 575 /** 576 * Service connection code for the NetworkQueryService. 577 * Handles the work of binding to a local object so that we can make 578 * the appropriate service calls. 579 */ 580 581 /** Local service interface */ 582 private INetworkQueryService mNetworkQueryService = null; 583 /** Flag indicating whether we have called bind on the service. */ 584 boolean mShouldUnbind; 585 586 /** Service connection */ 587 private final ServiceConnection mNetworkQueryServiceConnection = new ServiceConnection() { 588 589 /** Handle the task of binding the local object to the service */ 590 public void onServiceConnected(ComponentName className, IBinder service) { 591 if (DBG) logd("connection created, binding local service."); 592 mNetworkQueryService = ((NetworkQueryService.LocalBinder) service).getService(); 593 // Load the network list only when the service is well connected. 594 loadNetworksList(); 595 } 596 597 /** Handle the task of cleaning up the local binding */ 598 public void onServiceDisconnected(ComponentName className) { 599 if (DBG) logd("connection disconnected, cleaning local binding."); 600 mNetworkQueryService = null; 601 } 602 }; 603 604 private void bindNetworkQueryService() { 605 if (DBG) logd("bindNetworkQueryService"); 606 getContext().bindService(new Intent(getContext(), NetworkQueryService.class).setAction( 607 NetworkQueryService.ACTION_LOCAL_BINDER), 608 mNetworkQueryServiceConnection, Context.BIND_AUTO_CREATE); 609 mShouldUnbind = true; 610 } 611 612 private void unbindNetworkQueryService() { 613 if (DBG) logd("unbindNetworkQueryService"); 614 if (mShouldUnbind) { 615 if (DBG) logd("mShouldUnbind is true"); 616 // unbind the service. 617 getContext().unbindService(mNetworkQueryServiceConnection); 618 mShouldUnbind = false; 619 } 620 } 621 622 /** 623 * Call {@link NotificationMgr#updateNetworkSelection(int, int)} to send notification about 624 * no service of user selected operator 625 */ 626 private void updateNetworkSelection() { 627 if (DBG) logd("Update notification about no service of user selected operator"); 628 final PhoneGlobals app = PhoneGlobals.getInstance(); 629 Phone phone = PhoneFactory.getPhone(mPhoneId); 630 if (phone != null) { 631 ServiceState ss = mTelephonyManager.getServiceStateForSubscriber(phone.getSubId()); 632 if (ss != null) { 633 app.notificationMgr.updateNetworkSelection(ss.getState(), phone.getSubId()); 634 } 635 } 636 } 637 638 private void stopNetworkQuery() { 639 // Stop the network query process 640 try { 641 if (mNetworkQueryService != null) { 642 if (DBG) logd("Stop network query"); 643 mNetworkQueryService.stopNetworkQuery(); 644 mNetworkQueryService.unregisterCallback(mCallback); 645 } 646 } catch (RemoteException e) { 647 loge("Exception from stopNetworkQuery " + e); 648 } 649 } 650 651 private void logd(String msg) { 652 Log.d(TAG, msg); 653 } 654 655 private void loge(String msg) { 656 Log.e(TAG, msg); 657 } 658} 659