• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
16 
17 package com.android.settings.network.telephony;
18 
19 import android.app.Activity;
20 import android.app.settings.SettingsEnums;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.os.Bundle;
24 import android.os.Handler;
25 import android.os.Message;
26 import android.os.PersistableBundle;
27 import android.provider.Settings;
28 import android.telephony.AccessNetworkConstants;
29 import android.telephony.CarrierConfigManager;
30 import android.telephony.CellIdentity;
31 import android.telephony.CellInfo;
32 import android.telephony.NetworkRegistrationInfo;
33 import android.telephony.ServiceState;
34 import android.telephony.SignalStrength;
35 import android.telephony.SubscriptionManager;
36 import android.telephony.TelephonyManager;
37 import android.util.Log;
38 import android.view.View;
39 
40 import androidx.annotation.Keep;
41 import androidx.annotation.VisibleForTesting;
42 import androidx.preference.Preference;
43 import androidx.preference.PreferenceCategory;
44 
45 import com.android.internal.telephony.OperatorInfo;
46 import com.android.settings.R;
47 import com.android.settings.dashboard.DashboardFragment;
48 import com.android.settings.overlay.FeatureFactory;
49 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
50 import com.android.settingslib.utils.ThreadUtils;
51 
52 import java.util.ArrayList;
53 import java.util.Arrays;
54 import java.util.List;
55 import java.util.Optional;
56 import java.util.concurrent.ExecutorService;
57 import java.util.concurrent.Executors;
58 
59 /**
60  * "Choose network" settings UI for the Settings app.
61  */
62 @Keep
63 public class NetworkSelectSettings extends DashboardFragment {
64 
65     private static final String TAG = "NetworkSelectSettings";
66 
67     private static final int EVENT_SET_NETWORK_SELECTION_MANUALLY_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_NETWORK_OPERATORS = "network_operators_preference";
73     private static final int MIN_NUMBER_OF_SCAN_REQUIRED = 2;
74 
75     private PreferenceCategory mPreferenceCategory;
76     @VisibleForTesting
77     NetworkOperatorPreference mSelectedPreference;
78     private View mProgressHeader;
79     private Preference mStatusMessagePreference;
80     @VisibleForTesting
81     List<CellInfo> mCellInfoList;
82     private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
83     private TelephonyManager mTelephonyManager;
84     private List<String> mForbiddenPlmns;
85     private boolean mShow4GForLTE = false;
86     private NetworkScanHelper mNetworkScanHelper;
87     private final ExecutorService mNetworkScanExecutor = Executors.newFixedThreadPool(1);
88     private MetricsFeatureProvider mMetricsFeatureProvider;
89     private boolean mUseNewApi;
90     private long mRequestIdManualNetworkSelect;
91     private long mRequestIdManualNetworkScan;
92     private long mWaitingForNumberOfScanResults;
93     @VisibleForTesting
94     boolean mIsAggregationEnabled = false;
95 
96     @Override
onCreate(Bundle icicle)97     public void onCreate(Bundle icicle) {
98         super.onCreate(icicle);
99         onCreateInitialization();
100     }
101 
102     @Keep
103     @VisibleForTesting
onCreateInitialization()104     protected void onCreateInitialization() {
105         mUseNewApi = enableNewAutoSelectNetworkUI(getContext());
106         mSubId = getSubId();
107 
108         mPreferenceCategory = getPreferenceCategory(PREF_KEY_NETWORK_OPERATORS);
109         mStatusMessagePreference = new Preference(getContext());
110         mStatusMessagePreference.setSelectable(false);
111         mSelectedPreference = null;
112         mTelephonyManager = getTelephonyManager(getContext(), mSubId);
113         mNetworkScanHelper = new NetworkScanHelper(
114                 mTelephonyManager, mCallback, mNetworkScanExecutor);
115         PersistableBundle bundle = getCarrierConfigManager(getContext())
116                 .getConfigForSubId(mSubId);
117         if (bundle != null) {
118             mShow4GForLTE = bundle.getBoolean(
119                     CarrierConfigManager.KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL);
120         }
121 
122         mMetricsFeatureProvider = getMetricsFeatureProvider(getContext());
123         mIsAggregationEnabled = enableAggregation(getContext());
124         Log.d(TAG, "init: mUseNewApi:" + mUseNewApi
125                 + " ,mIsAggregationEnabled:" + mIsAggregationEnabled + " ,mSubId:" + mSubId);
126     }
127 
128     @Keep
129     @VisibleForTesting
enableNewAutoSelectNetworkUI(Context context)130     protected boolean enableNewAutoSelectNetworkUI(Context context) {
131         return context.getResources().getBoolean(
132                 com.android.internal.R.bool.config_enableNewAutoSelectNetworkUI);
133     }
134 
135     @Keep
136     @VisibleForTesting
enableAggregation(Context context)137     protected boolean enableAggregation(Context context) {
138         return context.getResources().getBoolean(
139                 R.bool.config_network_selection_list_aggregation_enabled);
140     }
141 
142     @Keep
143     @VisibleForTesting
getPreferenceCategory(String preferenceKey)144     protected PreferenceCategory getPreferenceCategory(String preferenceKey) {
145         return findPreference(preferenceKey);
146     }
147 
148     @Keep
149     @VisibleForTesting
getTelephonyManager(Context context, int subscriptionId)150     protected TelephonyManager getTelephonyManager(Context context, int subscriptionId) {
151         return context.getSystemService(TelephonyManager.class)
152                 .createForSubscriptionId(subscriptionId);
153     }
154 
155     @Keep
156     @VisibleForTesting
getCarrierConfigManager(Context context)157     protected CarrierConfigManager getCarrierConfigManager(Context context) {
158         return context.getSystemService(CarrierConfigManager.class);
159     }
160 
161     @Keep
162     @VisibleForTesting
getMetricsFeatureProvider(Context context)163     protected MetricsFeatureProvider getMetricsFeatureProvider(Context context) {
164         return FeatureFactory.getFactory(context).getMetricsFeatureProvider();
165     }
166 
167     @Keep
168     @VisibleForTesting
isPreferenceScreenEnabled()169     protected boolean isPreferenceScreenEnabled() {
170         return getPreferenceScreen().isEnabled();
171     }
172 
173     @Keep
174     @VisibleForTesting
enablePreferenceScreen(boolean enable)175     protected void enablePreferenceScreen(boolean enable) {
176         getPreferenceScreen().setEnabled(enable);
177     }
178 
179     @Keep
180     @VisibleForTesting
getSubId()181     protected int getSubId() {
182         int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
183         Intent intent = getActivity().getIntent();
184         if (intent != null) {
185             subId = intent.getIntExtra(Settings.EXTRA_SUB_ID,
186                     SubscriptionManager.INVALID_SUBSCRIPTION_ID);
187         }
188         return subId;
189     }
190 
191     @Override
onViewCreated(View view, Bundle savedInstanceState)192     public void onViewCreated(View view, Bundle savedInstanceState) {
193         super.onViewCreated(view, savedInstanceState);
194 
195         final Activity activity = getActivity();
196         if (activity != null) {
197             mProgressHeader = setPinnedHeaderView(R.layout.progress_header)
198                     .findViewById(R.id.progress_bar_animation);
199             setProgressBarVisible(false);
200         }
201         forceUpdateConnectedPreferenceCategory();
202     }
203 
204     @Override
onStart()205     public void onStart() {
206         super.onStart();
207 
208         updateForbiddenPlmns();
209         if (isProgressBarVisible()) {
210             return;
211         }
212         if (mWaitingForNumberOfScanResults <= 0) {
213             startNetworkQuery();
214         }
215     }
216 
217     /**
218      * Update forbidden PLMNs from the USIM App
219      */
220     @Keep
221     @VisibleForTesting
updateForbiddenPlmns()222     protected void updateForbiddenPlmns() {
223         final String[] forbiddenPlmns = mTelephonyManager.getForbiddenPlmns();
224         mForbiddenPlmns = forbiddenPlmns != null
225                 ? Arrays.asList(forbiddenPlmns)
226                 : new ArrayList<>();
227     }
228 
229     @Override
onStop()230     public void onStop() {
231         super.onStop();
232         if (mWaitingForNumberOfScanResults <= 0) {
233             stopNetworkQuery();
234         }
235     }
236 
237     @Override
onPreferenceTreeClick(Preference preference)238     public boolean onPreferenceTreeClick(Preference preference) {
239         if (preference != mSelectedPreference) {
240             stopNetworkQuery();
241 
242             // Refresh the last selected item in case users reselect network.
243             clearPreferenceSummary();
244             if (mSelectedPreference != null) {
245                 // Set summary as "Disconnected" to the previously connected network
246                 mSelectedPreference.setSummary(R.string.network_disconnected);
247             }
248 
249             mSelectedPreference = (NetworkOperatorPreference) preference;
250             mSelectedPreference.setSummary(R.string.network_connecting);
251 
252             mMetricsFeatureProvider.action(getContext(),
253                     SettingsEnums.ACTION_MOBILE_NETWORK_MANUAL_SELECT_NETWORK);
254 
255             setProgressBarVisible(true);
256             // Disable the screen until network is manually set
257             enablePreferenceScreen(false);
258 
259             mRequestIdManualNetworkSelect = getNewRequestId();
260             mWaitingForNumberOfScanResults = MIN_NUMBER_OF_SCAN_REQUIRED;
261             final OperatorInfo operator = mSelectedPreference.getOperatorInfo();
262             ThreadUtils.postOnBackgroundThread(() -> {
263                 final Message msg = mHandler.obtainMessage(
264                         EVENT_SET_NETWORK_SELECTION_MANUALLY_DONE);
265                 msg.obj = mTelephonyManager.setNetworkSelectionModeManual(
266                         operator, true /* persistSelection */);
267                 msg.sendToTarget();
268             });
269         }
270 
271         return true;
272     }
273 
274     @Override
getPreferenceScreenResId()275     protected int getPreferenceScreenResId() {
276         return R.xml.choose_network;
277     }
278 
279     @Override
getLogTag()280     protected String getLogTag() {
281         return TAG;
282     }
283 
284     @Override
getMetricsCategory()285     public int getMetricsCategory() {
286         return SettingsEnums.MOBILE_NETWORK_SELECT;
287     }
288 
289     private final Handler mHandler = new Handler() {
290         @Override
291         public void handleMessage(Message msg) {
292             switch (msg.what) {
293                 case EVENT_SET_NETWORK_SELECTION_MANUALLY_DONE:
294                     final boolean isSucceed = (boolean) msg.obj;
295                     stopNetworkQuery();
296                     setProgressBarVisible(false);
297                     enablePreferenceScreen(true);
298 
299                     if (mSelectedPreference != null) {
300                         mSelectedPreference.setSummary(isSucceed
301                                 ? R.string.network_connected
302                                 : R.string.network_could_not_connect);
303                     } else {
304                         Log.e(TAG, "No preference to update!");
305                     }
306                     break;
307                 case EVENT_NETWORK_SCAN_RESULTS:
308                     scanResultHandler((List<CellInfo>) msg.obj);
309                     break;
310 
311                 case EVENT_NETWORK_SCAN_ERROR:
312                     stopNetworkQuery();
313                     Log.i(TAG, "Network scan failure " + msg.arg1 + ":"
314                             + " scan request 0x" + Long.toHexString(mRequestIdManualNetworkScan)
315                             + ", waiting for scan results = " + mWaitingForNumberOfScanResults
316                             + ", select request 0x"
317                             + Long.toHexString(mRequestIdManualNetworkSelect));
318                     if (mRequestIdManualNetworkScan < mRequestIdManualNetworkSelect) {
319                         break;
320                     }
321                     if (!isPreferenceScreenEnabled()) {
322                         clearPreferenceSummary();
323                         enablePreferenceScreen(true);
324                     } else {
325                         addMessagePreference(R.string.network_query_error);
326                     }
327                     break;
328 
329                 case EVENT_NETWORK_SCAN_COMPLETED:
330                     stopNetworkQuery();
331                     Log.d(TAG, "Network scan complete:"
332                             + " scan request 0x" + Long.toHexString(mRequestIdManualNetworkScan)
333                             + ", waiting for scan results = " + mWaitingForNumberOfScanResults
334                             + ", select request 0x"
335                             + Long.toHexString(mRequestIdManualNetworkSelect));
336                     if (mRequestIdManualNetworkScan < mRequestIdManualNetworkSelect) {
337                         break;
338                     }
339                     if (!isPreferenceScreenEnabled()) {
340                         clearPreferenceSummary();
341                         enablePreferenceScreen(true);
342                     } else if (mCellInfoList == null) {
343                         // In case the scan timeout before getting any results
344                         addMessagePreference(R.string.empty_networks_list);
345                     }
346                     break;
347             }
348             return;
349         }
350     };
351 
352     @VisibleForTesting
doAggregation(List<CellInfo> cellInfoListInput)353     List<CellInfo> doAggregation(List<CellInfo> cellInfoListInput) {
354         if (!mIsAggregationEnabled) {
355             Log.d(TAG, "no aggregation");
356             return new ArrayList<>(cellInfoListInput);
357         }
358         ArrayList<CellInfo> aggregatedList = new ArrayList<>();
359         for (CellInfo cellInfo : cellInfoListInput) {
360             String plmn = CellInfoUtil.getNetworkTitle(cellInfo.getCellIdentity(),
361                     CellInfoUtil.getCellIdentityMccMnc(cellInfo.getCellIdentity()));
362             Class className = cellInfo.getClass();
363 
364             Optional<CellInfo> itemInTheList = aggregatedList.stream().filter(
365                     item -> {
366                         String itemPlmn = CellInfoUtil.getNetworkTitle(item.getCellIdentity(),
367                                 CellInfoUtil.getCellIdentityMccMnc(item.getCellIdentity()));
368                         return itemPlmn.equals(plmn) && item.getClass().equals(className);
369                     })
370                     .findFirst();
371             if (itemInTheList.isPresent()) {
372                 if (cellInfo.isRegistered() && !itemInTheList.get().isRegistered()) {
373                     // Adding the registered cellinfo item into list. If there are two registered
374                     // cellinfo items, then select first one from source list.
375                     aggregatedList.set(aggregatedList.indexOf(itemInTheList.get()), cellInfo);
376                 }
377                 continue;
378             }
379             aggregatedList.add(cellInfo);
380         }
381         return aggregatedList;
382     }
383 
384     private final NetworkScanHelper.NetworkScanCallback mCallback =
385             new NetworkScanHelper.NetworkScanCallback() {
386                 public void onResults(List<CellInfo> results) {
387                     final Message msg = mHandler.obtainMessage(EVENT_NETWORK_SCAN_RESULTS, results);
388                     msg.sendToTarget();
389                 }
390 
391                 public void onComplete() {
392                     final Message msg = mHandler.obtainMessage(EVENT_NETWORK_SCAN_COMPLETED);
393                     msg.sendToTarget();
394                 }
395 
396                 public void onError(int error) {
397                     final Message msg = mHandler.obtainMessage(EVENT_NETWORK_SCAN_ERROR, error,
398                             0 /* arg2 */);
399                     msg.sendToTarget();
400                 }
401             };
402 
403     @Keep
404     @VisibleForTesting
scanResultHandler(List<CellInfo> results)405     protected void scanResultHandler(List<CellInfo> results) {
406         if (mRequestIdManualNetworkScan < mRequestIdManualNetworkSelect) {
407             Log.d(TAG, "CellInfoList (drop): "
408                     + CellInfoUtil.cellInfoListToString(new ArrayList<>(results)));
409             return;
410         }
411         mWaitingForNumberOfScanResults--;
412         if ((mWaitingForNumberOfScanResults <= 0) && (!isResumed())) {
413             stopNetworkQuery();
414         }
415 
416         mCellInfoList = doAggregation(results);
417         Log.d(TAG, "CellInfoList: " + CellInfoUtil.cellInfoListToString(mCellInfoList));
418         if (mCellInfoList != null && mCellInfoList.size() != 0) {
419             final NetworkOperatorPreference connectedPref =
420                     updateAllPreferenceCategory();
421             if (connectedPref != null) {
422                 // update selected preference instance into connected preference
423                 if (mSelectedPreference != null) {
424                     mSelectedPreference = connectedPref;
425                 }
426             } else if (!isPreferenceScreenEnabled()) {
427                 if (connectedPref == null) {
428                     mSelectedPreference.setSummary(R.string.network_connecting);
429                 }
430             }
431             enablePreferenceScreen(true);
432         } else if (isPreferenceScreenEnabled()) {
433             addMessagePreference(R.string.empty_networks_list);
434             // keep showing progress bar, it will be stopped when error or completed
435             setProgressBarVisible(true);
436         }
437     }
438 
439     @Keep
440     @VisibleForTesting
createNetworkOperatorPreference(CellInfo cellInfo)441     protected NetworkOperatorPreference createNetworkOperatorPreference(CellInfo cellInfo) {
442         return new NetworkOperatorPreference(getPrefContext(),
443                 cellInfo, mForbiddenPlmns, mShow4GForLTE);
444     }
445 
446     /**
447      * Update the content of network operators list.
448      *
449      * @return preference which shows connected
450      */
updateAllPreferenceCategory()451     private NetworkOperatorPreference updateAllPreferenceCategory() {
452         int numberOfPreferences = mPreferenceCategory.getPreferenceCount();
453 
454         // remove unused preferences
455         while (numberOfPreferences > mCellInfoList.size()) {
456             numberOfPreferences--;
457             mPreferenceCategory.removePreference(
458                     mPreferenceCategory.getPreference(numberOfPreferences));
459         }
460 
461         // update the content of preference
462         NetworkOperatorPreference connectedPref = null;
463         for (int index = 0; index < mCellInfoList.size(); index++) {
464             final CellInfo cellInfo = mCellInfoList.get(index);
465 
466             NetworkOperatorPreference pref = null;
467             if (index < numberOfPreferences) {
468                 final Preference rawPref = mPreferenceCategory.getPreference(index);
469                 if (rawPref instanceof NetworkOperatorPreference) {
470                     // replace existing preference
471                     pref = (NetworkOperatorPreference) rawPref;
472                     pref.updateCell(cellInfo);
473                 } else {
474                     mPreferenceCategory.removePreference(rawPref);
475                 }
476             }
477             if (pref == null) {
478                 // add new preference
479                 pref = createNetworkOperatorPreference(cellInfo);
480                 pref.setOrder(index);
481                 mPreferenceCategory.addPreference(pref);
482             }
483             pref.setKey(pref.getOperatorName());
484 
485             if (mCellInfoList.get(index).isRegistered()) {
486                 pref.setSummary(R.string.network_connected);
487                 connectedPref = pref;
488             } else {
489                 pref.setSummary(null);
490             }
491         }
492 
493         // update selected preference instance by index
494         for (int index = 0; index < mCellInfoList.size(); index++) {
495             final CellInfo cellInfo = mCellInfoList.get(index);
496 
497             if ((mSelectedPreference != null) && mSelectedPreference.isSameCell(cellInfo)) {
498                 mSelectedPreference = (NetworkOperatorPreference)
499                         (mPreferenceCategory.getPreference(index));
500             }
501         }
502 
503         return connectedPref;
504     }
505 
506     /**
507      * Config the network operator list when the page was created. When user get
508      * into this page, the device might or might not have data connection.
509      * - If the device has data:
510      * 1. use {@code ServiceState#getNetworkRegistrationInfoList()} to get the currently
511      * registered cellIdentity, wrap it into a CellInfo;
512      * 2. set the signal strength level as strong;
513      * 3. get the title of the previously connected network operator, since the CellIdentity
514      * got from step 1 only has PLMN.
515      * - If the device has no data, we will remove the connected network operators list from the
516      * screen.
517      */
forceUpdateConnectedPreferenceCategory()518     private void forceUpdateConnectedPreferenceCategory() {
519         if (mTelephonyManager.getDataState() == mTelephonyManager.DATA_CONNECTED) {
520             // Try to get the network registration states
521             final ServiceState ss = mTelephonyManager.getServiceState();
522             if (ss == null) {
523                 return;
524             }
525             final List<NetworkRegistrationInfo> networkList =
526                     ss.getNetworkRegistrationInfoListForTransportType(
527                             AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
528             if (networkList == null || networkList.size() == 0) {
529                 return;
530             }
531             // Due to the aggregation of cell between carriers, it's possible to get CellIdentity
532             // containing forbidden PLMN.
533             // Getting current network from ServiceState is no longer a good idea.
534             // Add an additional rule to avoid from showing forbidden PLMN to the user.
535             if (mForbiddenPlmns == null) {
536                 updateForbiddenPlmns();
537             }
538             for (NetworkRegistrationInfo regInfo : networkList) {
539                 final CellIdentity cellIdentity = regInfo.getCellIdentity();
540                 if (cellIdentity == null) {
541                     continue;
542                 }
543                 final NetworkOperatorPreference pref = new NetworkOperatorPreference(
544                         getPrefContext(), cellIdentity, mForbiddenPlmns, mShow4GForLTE);
545                 if (pref.isForbiddenNetwork()) {
546                     continue;
547                 }
548                 pref.setSummary(R.string.network_connected);
549                 // Update the signal strength icon, since the default signalStrength value
550                 // would be zero
551                 // (it would be quite confusing why the connected network has no signal)
552                 pref.setIcon(SignalStrength.NUM_SIGNAL_STRENGTH_BINS - 1);
553                 mPreferenceCategory.addPreference(pref);
554                 break;
555             }
556         }
557     }
558 
559     /**
560      * Clear all of the preference summary
561      */
clearPreferenceSummary()562     private void clearPreferenceSummary() {
563         int idxPreference = mPreferenceCategory.getPreferenceCount();
564         while (idxPreference > 0) {
565             idxPreference--;
566             final NetworkOperatorPreference networkOperator = (NetworkOperatorPreference)
567                     (mPreferenceCategory.getPreference(idxPreference));
568             networkOperator.setSummary(null);
569         }
570     }
571 
getNewRequestId()572     private long getNewRequestId() {
573         return Math.max(mRequestIdManualNetworkSelect,
574                 mRequestIdManualNetworkScan) + 1;
575     }
576 
isProgressBarVisible()577     private boolean isProgressBarVisible() {
578         if (mProgressHeader == null) {
579             return false;
580         }
581         return (mProgressHeader.getVisibility() == View.VISIBLE);
582     }
583 
setProgressBarVisible(boolean visible)584     protected void setProgressBarVisible(boolean visible) {
585         if (mProgressHeader != null) {
586             mProgressHeader.setVisibility(visible ? View.VISIBLE : View.GONE);
587         }
588     }
589 
addMessagePreference(int messageId)590     private void addMessagePreference(int messageId) {
591         setProgressBarVisible(false);
592         mStatusMessagePreference.setTitle(messageId);
593         mPreferenceCategory.removeAll();
594         mPreferenceCategory.addPreference(mStatusMessagePreference);
595     }
596 
startNetworkQuery()597     private void startNetworkQuery() {
598         setProgressBarVisible(true);
599         if (mNetworkScanHelper != null) {
600             mRequestIdManualNetworkScan = getNewRequestId();
601             mWaitingForNumberOfScanResults = MIN_NUMBER_OF_SCAN_REQUIRED;
602             mNetworkScanHelper.startNetworkScan(
603                     mUseNewApi
604                             ? NetworkScanHelper.NETWORK_SCAN_TYPE_INCREMENTAL_RESULTS
605                             : NetworkScanHelper.NETWORK_SCAN_TYPE_WAIT_FOR_ALL_RESULTS);
606         }
607     }
608 
stopNetworkQuery()609     private void stopNetworkQuery() {
610         setProgressBarVisible(false);
611         if (mNetworkScanHelper != null) {
612             mWaitingForNumberOfScanResults = 0;
613             mNetworkScanHelper.stopNetworkQuery();
614         }
615     }
616 
617     @Override
onDestroy()618     public void onDestroy() {
619         stopNetworkQuery();
620         mNetworkScanExecutor.shutdown();
621         super.onDestroy();
622     }
623 }
624