1 /* 2 * Copyright (C) 2017 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.internal.telephony; 18 19 import static android.telephony.AccessNetworkConstants.AccessNetworkType.EUTRAN; 20 import static android.telephony.AccessNetworkConstants.AccessNetworkType.GERAN; 21 import static android.telephony.AccessNetworkConstants.AccessNetworkType.UTRAN; 22 23 import android.hardware.radio.V1_0.RadioError; 24 import android.os.AsyncResult; 25 import android.os.Binder; 26 import android.os.Bundle; 27 import android.os.Handler; 28 import android.os.IBinder; 29 import android.os.Message; 30 import android.os.Messenger; 31 import android.os.Process; 32 import android.os.RemoteException; 33 import android.telephony.CellInfo; 34 import android.telephony.NetworkScan; 35 import android.telephony.NetworkScanRequest; 36 import android.telephony.RadioAccessSpecifier; 37 import android.telephony.TelephonyScanManager; 38 import android.util.Log; 39 40 import java.util.List; 41 import java.util.concurrent.atomic.AtomicInteger; 42 43 /** 44 * Manages radio access network scan requests. 45 * 46 * Provides methods to start and stop network scan requests, and keeps track of all the live scans. 47 * 48 * {@hide} 49 */ 50 public final class NetworkScanRequestTracker { 51 52 private static final String TAG = "ScanRequestTracker"; 53 54 private static final int CMD_START_NETWORK_SCAN = 1; 55 private static final int EVENT_START_NETWORK_SCAN_DONE = 2; 56 private static final int EVENT_RECEIVE_NETWORK_SCAN_RESULT = 3; 57 private static final int CMD_STOP_NETWORK_SCAN = 4; 58 private static final int EVENT_STOP_NETWORK_SCAN_DONE = 5; 59 private static final int CMD_INTERRUPT_NETWORK_SCAN = 6; 60 private static final int EVENT_INTERRUPT_NETWORK_SCAN_DONE = 7; 61 62 private final Handler mHandler = new Handler() { 63 @Override 64 public void handleMessage(Message msg) { 65 switch (msg.what) { 66 case CMD_START_NETWORK_SCAN: 67 mScheduler.doStartScan((NetworkScanRequestInfo) msg.obj); 68 break; 69 70 case EVENT_START_NETWORK_SCAN_DONE: 71 mScheduler.startScanDone((AsyncResult) msg.obj); 72 break; 73 74 case EVENT_RECEIVE_NETWORK_SCAN_RESULT: 75 mScheduler.receiveResult((AsyncResult) msg.obj); 76 break; 77 78 case CMD_STOP_NETWORK_SCAN: 79 mScheduler.doStopScan(msg.arg1); 80 break; 81 82 case EVENT_STOP_NETWORK_SCAN_DONE: 83 mScheduler.stopScanDone((AsyncResult) msg.obj); 84 break; 85 86 case CMD_INTERRUPT_NETWORK_SCAN: 87 mScheduler.doInterruptScan(msg.arg1); 88 break; 89 90 case EVENT_INTERRUPT_NETWORK_SCAN_DONE: 91 mScheduler.interruptScanDone((AsyncResult) msg.obj); 92 break; 93 } 94 } 95 }; 96 97 // The sequence number of NetworkScanRequests 98 private final AtomicInteger mNextNetworkScanRequestId = new AtomicInteger(1); 99 private final NetworkScanRequestScheduler mScheduler = new NetworkScanRequestScheduler(); 100 101 private void logEmptyResultOrException(AsyncResult ar) { 102 if (ar.result == null) { 103 Log.e(TAG, "NetworkScanResult: Empty result"); 104 } else { 105 Log.e(TAG, "NetworkScanResult: Exception: " + ar.exception); 106 } 107 } 108 109 private boolean isValidScan(NetworkScanRequestInfo nsri) { 110 if (nsri.mRequest == null || nsri.mRequest.getSpecifiers() == null) { 111 return false; 112 } 113 if (nsri.mRequest.getSpecifiers().length > NetworkScanRequest.MAX_RADIO_ACCESS_NETWORKS) { 114 return false; 115 } 116 for (RadioAccessSpecifier ras : nsri.mRequest.getSpecifiers()) { 117 if (ras.getRadioAccessNetwork() != GERAN && ras.getRadioAccessNetwork() != UTRAN 118 && ras.getRadioAccessNetwork() != EUTRAN) { 119 return false; 120 } 121 if (ras.getBands() != null && ras.getBands().length > NetworkScanRequest.MAX_BANDS) { 122 return false; 123 } 124 if (ras.getChannels() != null 125 && ras.getChannels().length > NetworkScanRequest.MAX_CHANNELS) { 126 return false; 127 } 128 } 129 130 if ((nsri.mRequest.getSearchPeriodicity() < NetworkScanRequest.MIN_SEARCH_PERIODICITY_SEC) 131 || (nsri.mRequest.getSearchPeriodicity() 132 > NetworkScanRequest.MAX_SEARCH_PERIODICITY_SEC)) { 133 return false; 134 } 135 136 if ((nsri.mRequest.getMaxSearchTime() < NetworkScanRequest.MIN_SEARCH_MAX_SEC) 137 || (nsri.mRequest.getMaxSearchTime() > NetworkScanRequest.MAX_SEARCH_MAX_SEC)) { 138 return false; 139 } 140 141 if ((nsri.mRequest.getIncrementalResultsPeriodicity() 142 < NetworkScanRequest.MIN_INCREMENTAL_PERIODICITY_SEC) 143 || (nsri.mRequest.getIncrementalResultsPeriodicity() 144 > NetworkScanRequest.MAX_INCREMENTAL_PERIODICITY_SEC)) { 145 return false; 146 } 147 148 if ((nsri.mRequest.getSearchPeriodicity() > nsri.mRequest.getMaxSearchTime()) 149 || (nsri.mRequest.getIncrementalResultsPeriodicity() 150 > nsri.mRequest.getMaxSearchTime())) { 151 return false; 152 } 153 154 if ((nsri.mRequest.getPlmns() != null) 155 && (nsri.mRequest.getPlmns().size() > NetworkScanRequest.MAX_MCC_MNC_LIST_SIZE)) { 156 return false; 157 } 158 return true; 159 } 160 161 /** Sends a message back to the application via its callback. */ 162 private void notifyMessenger(NetworkScanRequestInfo nsri, int what, int err, 163 List<CellInfo> result) { 164 Messenger messenger = nsri.mMessenger; 165 Message message = Message.obtain(); 166 message.what = what; 167 message.arg1 = err; 168 message.arg2 = nsri.mScanId; 169 if (result != null) { 170 CellInfo[] ci = result.toArray(new CellInfo[result.size()]); 171 Bundle b = new Bundle(); 172 b.putParcelableArray(TelephonyScanManager.SCAN_RESULT_KEY, ci); 173 message.setData(b); 174 } else { 175 message.obj = null; 176 } 177 try { 178 messenger.send(message); 179 } catch (RemoteException e) { 180 Log.e(TAG, "Exception in notifyMessenger: " + e); 181 } 182 } 183 184 /** 185 * Tracks info about the radio network scan. 186 * 187 * Also used to notice when the calling process dies so we can self-expire. 188 */ 189 class NetworkScanRequestInfo implements IBinder.DeathRecipient { 190 private final NetworkScanRequest mRequest; 191 private final Messenger mMessenger; 192 private final IBinder mBinder; 193 private final Phone mPhone; 194 private final int mScanId; 195 private final int mUid; 196 private final int mPid; 197 private boolean mIsBinderDead; 198 199 NetworkScanRequestInfo(NetworkScanRequest r, Messenger m, IBinder b, int id, Phone phone) { 200 super(); 201 mRequest = r; 202 mMessenger = m; 203 mBinder = b; 204 mScanId = id; 205 mPhone = phone; 206 mUid = Binder.getCallingUid(); 207 mPid = Binder.getCallingPid(); 208 mIsBinderDead = false; 209 210 try { 211 mBinder.linkToDeath(this, 0); 212 } catch (RemoteException e) { 213 binderDied(); 214 } 215 } 216 217 synchronized void setIsBinderDead(boolean val) { 218 mIsBinderDead = val; 219 } 220 221 synchronized boolean getIsBinderDead() { 222 return mIsBinderDead; 223 } 224 225 NetworkScanRequest getRequest() { 226 return mRequest; 227 } 228 229 void unlinkDeathRecipient() { 230 if (mBinder != null) { 231 mBinder.unlinkToDeath(this, 0); 232 } 233 } 234 235 @Override 236 public void binderDied() { 237 Log.e(TAG, "PhoneInterfaceManager NetworkScanRequestInfo binderDied(" 238 + mRequest + ", " + mBinder + ")"); 239 setIsBinderDead(true); 240 interruptNetworkScan(mScanId); 241 } 242 } 243 244 /** 245 * Handles multiplexing and scheduling for multiple requests. 246 */ 247 private class NetworkScanRequestScheduler { 248 249 private NetworkScanRequestInfo mLiveRequestInfo; 250 private NetworkScanRequestInfo mPendingRequestInfo; 251 252 private int rilErrorToScanError(int rilError) { 253 switch (rilError) { 254 case RadioError.NONE: 255 return NetworkScan.SUCCESS; 256 case RadioError.RADIO_NOT_AVAILABLE: 257 Log.e(TAG, "rilErrorToScanError: RADIO_NOT_AVAILABLE"); 258 return NetworkScan.ERROR_MODEM_ERROR; 259 case RadioError.REQUEST_NOT_SUPPORTED: 260 Log.e(TAG, "rilErrorToScanError: REQUEST_NOT_SUPPORTED"); 261 return NetworkScan.ERROR_UNSUPPORTED; 262 case RadioError.NO_MEMORY: 263 Log.e(TAG, "rilErrorToScanError: NO_MEMORY"); 264 return NetworkScan.ERROR_MODEM_ERROR; 265 case RadioError.INTERNAL_ERR: 266 Log.e(TAG, "rilErrorToScanError: INTERNAL_ERR"); 267 return NetworkScan.ERROR_MODEM_ERROR; 268 case RadioError.MODEM_ERR: 269 Log.e(TAG, "rilErrorToScanError: MODEM_ERR"); 270 return NetworkScan.ERROR_MODEM_ERROR; 271 case RadioError.OPERATION_NOT_ALLOWED: 272 Log.e(TAG, "rilErrorToScanError: OPERATION_NOT_ALLOWED"); 273 return NetworkScan.ERROR_MODEM_ERROR; 274 case RadioError.INVALID_ARGUMENTS: 275 Log.e(TAG, "rilErrorToScanError: INVALID_ARGUMENTS"); 276 return NetworkScan.ERROR_INVALID_SCAN; 277 case RadioError.DEVICE_IN_USE: 278 Log.e(TAG, "rilErrorToScanError: DEVICE_IN_USE"); 279 return NetworkScan.ERROR_MODEM_UNAVAILABLE; 280 default: 281 Log.e(TAG, "rilErrorToScanError: Unexpected RadioError " + rilError); 282 return NetworkScan.ERROR_RADIO_INTERFACE_ERROR; 283 } 284 } 285 286 private int commandExceptionErrorToScanError(CommandException.Error error) { 287 switch (error) { 288 case RADIO_NOT_AVAILABLE: 289 Log.e(TAG, "commandExceptionErrorToScanError: RADIO_NOT_AVAILABLE"); 290 return NetworkScan.ERROR_MODEM_ERROR; 291 case REQUEST_NOT_SUPPORTED: 292 Log.e(TAG, "commandExceptionErrorToScanError: REQUEST_NOT_SUPPORTED"); 293 return NetworkScan.ERROR_UNSUPPORTED; 294 case NO_MEMORY: 295 Log.e(TAG, "commandExceptionErrorToScanError: NO_MEMORY"); 296 return NetworkScan.ERROR_MODEM_ERROR; 297 case INTERNAL_ERR: 298 Log.e(TAG, "commandExceptionErrorToScanError: INTERNAL_ERR"); 299 return NetworkScan.ERROR_MODEM_ERROR; 300 case MODEM_ERR: 301 Log.e(TAG, "commandExceptionErrorToScanError: MODEM_ERR"); 302 return NetworkScan.ERROR_MODEM_ERROR; 303 case OPERATION_NOT_ALLOWED: 304 Log.e(TAG, "commandExceptionErrorToScanError: OPERATION_NOT_ALLOWED"); 305 return NetworkScan.ERROR_MODEM_ERROR; 306 case INVALID_ARGUMENTS: 307 Log.e(TAG, "commandExceptionErrorToScanError: INVALID_ARGUMENTS"); 308 return NetworkScan.ERROR_INVALID_SCAN; 309 case DEVICE_IN_USE: 310 Log.e(TAG, "commandExceptionErrorToScanError: DEVICE_IN_USE"); 311 return NetworkScan.ERROR_MODEM_UNAVAILABLE; 312 default: 313 Log.e(TAG, "commandExceptionErrorToScanError: Unexpected CommandExceptionError " 314 + error); 315 return NetworkScan.ERROR_RADIO_INTERFACE_ERROR; 316 } 317 } 318 319 private void doStartScan(NetworkScanRequestInfo nsri) { 320 if (nsri == null) { 321 Log.e(TAG, "CMD_START_NETWORK_SCAN: nsri is null"); 322 return; 323 } 324 if (!isValidScan(nsri)) { 325 notifyMessenger(nsri, TelephonyScanManager.CALLBACK_SCAN_ERROR, 326 NetworkScan.ERROR_INVALID_SCAN, null); 327 return; 328 } 329 if (nsri.getIsBinderDead()) { 330 Log.e(TAG, "CMD_START_NETWORK_SCAN: Binder has died"); 331 return; 332 } 333 if (!startNewScan(nsri)) { 334 if (!interruptLiveScan(nsri)) { 335 if (!cacheScan(nsri)) { 336 notifyMessenger(nsri, TelephonyScanManager.CALLBACK_SCAN_ERROR, 337 NetworkScan.ERROR_MODEM_UNAVAILABLE, null); 338 } 339 } 340 } 341 } 342 343 private synchronized void startScanDone(AsyncResult ar) { 344 NetworkScanRequestInfo nsri = (NetworkScanRequestInfo) ar.userObj; 345 if (nsri == null) { 346 Log.e(TAG, "EVENT_START_NETWORK_SCAN_DONE: nsri is null"); 347 return; 348 } 349 if (mLiveRequestInfo == null || nsri.mScanId != mLiveRequestInfo.mScanId) { 350 Log.e(TAG, "EVENT_START_NETWORK_SCAN_DONE: nsri does not match mLiveRequestInfo"); 351 return; 352 } 353 if (ar.exception == null && ar.result != null) { 354 // Register for the scan results if the scan started successfully. 355 nsri.mPhone.mCi.registerForNetworkScanResult(mHandler, 356 EVENT_RECEIVE_NETWORK_SCAN_RESULT, nsri); 357 } else { 358 logEmptyResultOrException(ar); 359 if (ar.exception != null) { 360 CommandException.Error error = 361 ((CommandException) (ar.exception)).getCommandError(); 362 deleteScanAndMayNotify(nsri, commandExceptionErrorToScanError(error), true); 363 } else { 364 Log.wtf(TAG, "EVENT_START_NETWORK_SCAN_DONE: ar.exception can not be null!"); 365 } 366 } 367 } 368 369 private void receiveResult(AsyncResult ar) { 370 NetworkScanRequestInfo nsri = (NetworkScanRequestInfo) ar.userObj; 371 if (nsri == null) { 372 Log.e(TAG, "EVENT_RECEIVE_NETWORK_SCAN_RESULT: nsri is null"); 373 return; 374 } 375 if (ar.exception == null && ar.result != null) { 376 NetworkScanResult nsr = (NetworkScanResult) ar.result; 377 if (nsr.scanError == NetworkScan.SUCCESS) { 378 notifyMessenger(nsri, TelephonyScanManager.CALLBACK_SCAN_RESULTS, 379 rilErrorToScanError(nsr.scanError), nsr.networkInfos); 380 if (nsr.scanStatus == NetworkScanResult.SCAN_STATUS_COMPLETE) { 381 deleteScanAndMayNotify(nsri, NetworkScan.SUCCESS, true); 382 nsri.mPhone.mCi.unregisterForNetworkScanResult(mHandler); 383 } 384 } else { 385 if (nsr.networkInfos != null) { 386 notifyMessenger(nsri, TelephonyScanManager.CALLBACK_SCAN_RESULTS, 387 NetworkScan.SUCCESS, nsr.networkInfos); 388 } 389 deleteScanAndMayNotify(nsri, rilErrorToScanError(nsr.scanError), true); 390 nsri.mPhone.mCi.unregisterForNetworkScanResult(mHandler); 391 } 392 } else { 393 logEmptyResultOrException(ar); 394 deleteScanAndMayNotify(nsri, NetworkScan.ERROR_RADIO_INTERFACE_ERROR, true); 395 nsri.mPhone.mCi.unregisterForNetworkScanResult(mHandler); 396 } 397 } 398 399 400 // Stops the scan if the scanId and uid match the mScanId and mUid. 401 // If the scan to be stopped is the live scan, we only send the request to RIL, while the 402 // mLiveRequestInfo will not be cleared and the user will not be notified either. 403 // If the scan to be stopped is the pending scan, we will clear mPendingRequestInfo and 404 // notify the user. 405 private synchronized void doStopScan(int scanId) { 406 if (mLiveRequestInfo != null && scanId == mLiveRequestInfo.mScanId) { 407 mLiveRequestInfo.mPhone.stopNetworkScan( 408 mHandler.obtainMessage(EVENT_STOP_NETWORK_SCAN_DONE, mLiveRequestInfo)); 409 } else if (mPendingRequestInfo != null && scanId == mPendingRequestInfo.mScanId) { 410 notifyMessenger(mPendingRequestInfo, 411 TelephonyScanManager.CALLBACK_SCAN_COMPLETE, NetworkScan.SUCCESS, null); 412 mPendingRequestInfo = null; 413 } else { 414 Log.e(TAG, "stopScan: scan " + scanId + " does not exist!"); 415 } 416 } 417 418 private void stopScanDone(AsyncResult ar) { 419 NetworkScanRequestInfo nsri = (NetworkScanRequestInfo) ar.userObj; 420 if (nsri == null) { 421 Log.e(TAG, "EVENT_STOP_NETWORK_SCAN_DONE: nsri is null"); 422 return; 423 } 424 if (ar.exception == null && ar.result != null) { 425 deleteScanAndMayNotify(nsri, NetworkScan.SUCCESS, true); 426 } else { 427 logEmptyResultOrException(ar); 428 if (ar.exception != null) { 429 CommandException.Error error = 430 ((CommandException) (ar.exception)).getCommandError(); 431 deleteScanAndMayNotify(nsri, commandExceptionErrorToScanError(error), true); 432 } else { 433 Log.wtf(TAG, "EVENT_STOP_NETWORK_SCAN_DONE: ar.exception can not be null!"); 434 } 435 } 436 nsri.mPhone.mCi.unregisterForNetworkScanResult(mHandler); 437 } 438 439 // Interrupts the live scan is the scanId matches the mScanId of the mLiveRequestInfo. 440 private synchronized void doInterruptScan(int scanId) { 441 if (mLiveRequestInfo != null && scanId == mLiveRequestInfo.mScanId) { 442 mLiveRequestInfo.mPhone.stopNetworkScan(mHandler.obtainMessage( 443 EVENT_INTERRUPT_NETWORK_SCAN_DONE, mLiveRequestInfo)); 444 } else { 445 Log.e(TAG, "doInterruptScan: scan " + scanId + " does not exist!"); 446 } 447 } 448 449 private void interruptScanDone(AsyncResult ar) { 450 NetworkScanRequestInfo nsri = (NetworkScanRequestInfo) ar.userObj; 451 if (nsri == null) { 452 Log.e(TAG, "EVENT_INTERRUPT_NETWORK_SCAN_DONE: nsri is null"); 453 return; 454 } 455 nsri.mPhone.mCi.unregisterForNetworkScanResult(mHandler); 456 deleteScanAndMayNotify(nsri, 0, false); 457 } 458 459 // Interrupts the live scan and caches nsri in mPendingRequestInfo. Once the live scan is 460 // stopped, a new scan will automatically start with nsri. 461 // The new scan can interrupt the live scan only when all the below requirements are met: 462 // 1. There is 1 live scan and no other pending scan 463 // 2. The new scan is requested by mobile network setting menu (owned by PHONE process) 464 // 3. The live scan is not requested by mobile network setting menu 465 private synchronized boolean interruptLiveScan(NetworkScanRequestInfo nsri) { 466 if (mLiveRequestInfo != null && mPendingRequestInfo == null 467 && nsri.mUid == Process.PHONE_UID 468 && mLiveRequestInfo.mUid != Process.PHONE_UID) { 469 doInterruptScan(mLiveRequestInfo.mScanId); 470 mPendingRequestInfo = nsri; 471 notifyMessenger(mLiveRequestInfo, TelephonyScanManager.CALLBACK_SCAN_ERROR, 472 NetworkScan.ERROR_INTERRUPTED, null); 473 return true; 474 } 475 return false; 476 } 477 478 private boolean cacheScan(NetworkScanRequestInfo nsri) { 479 // TODO(30954762): Cache periodic scan for OC-MR1. 480 return false; 481 } 482 483 // Starts a new scan with nsri if there is no live scan running. 484 private synchronized boolean startNewScan(NetworkScanRequestInfo nsri) { 485 if (mLiveRequestInfo == null) { 486 mLiveRequestInfo = nsri; 487 nsri.mPhone.startNetworkScan(nsri.getRequest(), 488 mHandler.obtainMessage(EVENT_START_NETWORK_SCAN_DONE, nsri)); 489 return true; 490 } 491 return false; 492 } 493 494 495 // Deletes the mLiveRequestInfo and notify the user if it matches nsri. 496 private synchronized void deleteScanAndMayNotify(NetworkScanRequestInfo nsri, int error, 497 boolean notify) { 498 if (mLiveRequestInfo != null && nsri.mScanId == mLiveRequestInfo.mScanId) { 499 if (notify) { 500 if (error == NetworkScan.SUCCESS) { 501 notifyMessenger(nsri, TelephonyScanManager.CALLBACK_SCAN_COMPLETE, error, 502 null); 503 } else { 504 notifyMessenger(nsri, TelephonyScanManager.CALLBACK_SCAN_ERROR, error, 505 null); 506 } 507 } 508 mLiveRequestInfo = null; 509 if (mPendingRequestInfo != null) { 510 startNewScan(mPendingRequestInfo); 511 mPendingRequestInfo = null; 512 } 513 } 514 } 515 } 516 517 /** 518 * Interrupts an ongoing network scan 519 * 520 * This method is similar to stopNetworkScan, since they both stops an ongoing scan. The 521 * difference is that stopNetworkScan is only used by the callers to stop their own scans, so 522 * sanity check will be done to make sure the request is valid; while this method is only 523 * internally used by NetworkScanRequestTracker so sanity check is not needed. 524 */ 525 private void interruptNetworkScan(int scanId) { 526 // scanId will be stored at Message.arg1 527 mHandler.obtainMessage(CMD_INTERRUPT_NETWORK_SCAN, scanId, 0).sendToTarget(); 528 } 529 530 /** 531 * Starts a new network scan 532 * 533 * This function only wraps all the incoming information and delegate then to the handler thread 534 * which will actually handles the scan request. So a new scanId will always be generated and 535 * returned to the user, no matter how this scan will be actually handled. 536 */ 537 public int startNetworkScan( 538 NetworkScanRequest request, Messenger messenger, IBinder binder, Phone phone) { 539 int scanId = mNextNetworkScanRequestId.getAndIncrement(); 540 NetworkScanRequestInfo nsri = 541 new NetworkScanRequestInfo(request, messenger, binder, scanId, phone); 542 // nsri will be stored as Message.obj 543 mHandler.obtainMessage(CMD_START_NETWORK_SCAN, nsri).sendToTarget(); 544 return scanId; 545 } 546 547 /** 548 * Stops an ongoing network scan 549 * 550 * The ongoing scan will be stopped only when the input scanId and caller's uid matches the 551 * corresponding information associated with it. 552 */ 553 public void stopNetworkScan(int scanId) { 554 synchronized (mScheduler) { 555 if ((mScheduler.mLiveRequestInfo != null 556 && scanId == mScheduler.mLiveRequestInfo.mScanId 557 && Binder.getCallingUid() == mScheduler.mLiveRequestInfo.mUid) 558 || (mScheduler.mPendingRequestInfo != null 559 && scanId == mScheduler.mPendingRequestInfo.mScanId 560 && Binder.getCallingUid() == mScheduler.mPendingRequestInfo.mUid)) { 561 // scanId will be stored at Message.arg1 562 mHandler.obtainMessage(CMD_STOP_NETWORK_SCAN, scanId, 0).sendToTarget(); 563 } else { 564 throw new IllegalArgumentException("Scan with id: " + scanId + " does not exist!"); 565 } 566 } 567 } 568 } 569