RttService.java revision 435236f48f94a8373fa71251a3223e642f446e77
1package com.android.server.wifi; 2 3import android.Manifest; 4import android.content.BroadcastReceiver; 5import android.content.Context; 6import android.content.Intent; 7import android.content.IntentFilter; 8import android.content.pm.PackageManager; 9import android.net.wifi.IApInterface; 10import android.net.wifi.IClientInterface; 11import android.net.wifi.IInterfaceEventCallback; 12import android.net.wifi.IRttManager; 13import android.net.wifi.IWificond; 14import android.net.wifi.RttManager; 15import android.net.wifi.RttManager.ResponderConfig; 16import android.net.wifi.WifiManager; 17import android.os.Binder; 18import android.os.Bundle; 19import android.os.Handler; 20import android.os.HandlerThread; 21import android.os.IBinder; 22import android.os.Looper; 23import android.os.Message; 24import android.os.Messenger; 25import android.os.RemoteException; 26import android.util.ArrayMap; 27import android.util.Log; 28import android.util.Slog; 29 30import com.android.internal.annotations.GuardedBy; 31import com.android.internal.util.AsyncChannel; 32import com.android.internal.util.IState; 33import com.android.internal.util.Protocol; 34import com.android.internal.util.State; 35import com.android.internal.util.StateMachine; 36import com.android.server.SystemService; 37 38import java.io.FileDescriptor; 39import java.io.PrintWriter; 40import java.util.HashSet; 41import java.util.Iterator; 42import java.util.LinkedList; 43import java.util.List; 44import java.util.Queue; 45import java.util.Set; 46 47public final class RttService extends SystemService { 48 49 public static final boolean DBG = true; 50 private static final String WIFICOND_SERVICE_NAME = "wificond"; 51 52 static class RttServiceImpl extends IRttManager.Stub { 53 54 @Override 55 public Messenger getMessenger() { 56 return new Messenger(mClientHandler); 57 } 58 59 private class ClientHandler extends Handler { 60 61 ClientHandler(android.os.Looper looper) { 62 super(looper); 63 } 64 65 @Override 66 public void handleMessage(Message msg) { 67 68 if (DBG) { 69 Log.d(TAG, "ClientHandler got" + msg + " what = " + getDescription(msg.what)); 70 } 71 72 switch (msg.what) { 73 74 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: 75 if (msg.arg1 == AsyncChannel.STATUS_SEND_UNSUCCESSFUL) { 76 Slog.e(TAG, "Send failed, client connection lost"); 77 } else { 78 if (DBG) Slog.d(TAG, "Client connection lost with reason: " + msg.arg1); 79 } 80 if (DBG) Slog.d(TAG, "closing client " + msg.replyTo); 81 synchronized (mLock) { 82 ClientInfo ci = mClients.remove(msg.replyTo); 83 if (ci != null) ci.cleanup(); 84 } 85 return; 86 case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: 87 AsyncChannel ac = new AsyncChannel(); 88 ac.connected(mContext, this, msg.replyTo); 89 ClientInfo client = new ClientInfo(ac, msg.sendingUid); 90 synchronized (mLock) { 91 mClients.put(msg.replyTo, client); 92 } 93 ac.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED, 94 AsyncChannel.STATUS_SUCCESSFUL); 95 return; 96 } 97 98 ClientInfo ci; 99 synchronized (mLock) { 100 ci = mClients.get(msg.replyTo); 101 } 102 if (ci == null) { 103 Slog.e(TAG, "Could not find client info for message " + msg.replyTo); 104 replyFailed(msg, RttManager.REASON_INVALID_LISTENER, "Could not find listener"); 105 return; 106 } 107 if (!enforcePermissionCheck(msg)) { 108 replyFailed(msg, RttManager.REASON_PERMISSION_DENIED, 109 "Client doesn't have LOCATION_HARDWARE permission"); 110 return; 111 } 112 final int validCommands[] = { 113 RttManager.CMD_OP_START_RANGING, 114 RttManager.CMD_OP_STOP_RANGING, 115 RttManager.CMD_OP_ENABLE_RESPONDER, 116 RttManager.CMD_OP_DISABLE_RESPONDER, 117 }; 118 119 for (int cmd : validCommands) { 120 if (cmd == msg.what) { 121 mStateMachine.sendMessage(Message.obtain(msg)); 122 return; 123 } 124 } 125 126 replyFailed(msg, RttManager.REASON_INVALID_REQUEST, "Invalid request"); 127 } 128 129 private String getDescription(int what) { 130 switch(what) { 131 case RttManager.CMD_OP_ENABLE_RESPONDER: 132 return "CMD_OP_ENABLE_RESPONDER"; 133 case RttManager.CMD_OP_DISABLE_RESPONDER: 134 return "CMD_OP_DISABLE_RESPONDER"; 135 default: 136 return "CMD_UNKNOWN"; 137 } 138 } 139 } 140 141 private final WifiNative mWifiNative; 142 private final Context mContext; 143 private final Looper mLooper; 144 private RttStateMachine mStateMachine; 145 private ClientHandler mClientHandler; 146 private WifiInjector mWifiInjector; 147 148 RttServiceImpl(Context context, Looper looper, WifiInjector wifiInjector) { 149 mContext = context; 150 mWifiNative = WifiNative.getWlanNativeInterface(); 151 mLooper = looper; 152 mWifiInjector = wifiInjector; 153 } 154 155 public void startService() { 156 mClientHandler = new ClientHandler(mLooper); 157 mStateMachine = new RttStateMachine(mLooper); 158 mContext.registerReceiver( 159 new BroadcastReceiver() { 160 @Override 161 public void onReceive(Context context, Intent intent) { 162 int state = intent.getIntExtra( 163 WifiManager.EXTRA_SCAN_AVAILABLE, WifiManager.WIFI_STATE_DISABLED); 164 if (DBG) Log.d(TAG, "SCAN_AVAILABLE : " + state); 165 if (state == WifiManager.WIFI_STATE_ENABLED) { 166 mStateMachine.sendMessage(CMD_DRIVER_LOADED); 167 } else if (state == WifiManager.WIFI_STATE_DISABLED) { 168 mStateMachine.sendMessage(CMD_DRIVER_UNLOADED); 169 } 170 } 171 }, new IntentFilter(WifiManager.WIFI_SCAN_AVAILABLE)); 172 173 mStateMachine.start(); 174 } 175 176 private class RttRequest { 177 Integer key; 178 ClientInfo ci; 179 RttManager.RttParams[] params; 180 181 @Override 182 public String toString() { 183 String str = getClass().getName() + "@" + Integer.toHexString(hashCode()); 184 if(this.key != null) { 185 return str + " key: " + this.key; 186 } else { 187 return str + " key: " + " , null"; 188 } 189 } 190 } 191 192 private class ClientInfo { 193 private final AsyncChannel mChannel; 194 private final int mUid; 195 196 ArrayMap<Integer, RttRequest> mRequests = new ArrayMap<>(); 197 // Client keys of all outstanding responders. 198 Set<Integer> mResponderRequests = new HashSet<>(); 199 200 ClientInfo(AsyncChannel channel, int uid) { 201 mChannel = channel; 202 mUid = uid; 203 } 204 205 void addResponderRequest(int key) { 206 mResponderRequests.add(key); 207 } 208 209 void removeResponderRequest(int key) { 210 mResponderRequests.remove(key); 211 } 212 213 boolean addRttRequest(int key, RttManager.ParcelableRttParams parcelableParams) { 214 if (parcelableParams == null) { 215 return false; 216 } 217 218 RttManager.RttParams params[] = parcelableParams.mParams; 219 220 RttRequest request = new RttRequest(); 221 request.key = key; 222 request.ci = this; 223 request.params = params; 224 mRequests.put(key, request); 225 mRequestQueue.add(request); 226 return true; 227 } 228 229 void removeRttRequest(int key) { 230 mRequests.remove(key); 231 } 232 233 void reportResponderEnableSucceed(int key, ResponderConfig config) { 234 mChannel.sendMessage(RttManager.CMD_OP_ENALBE_RESPONDER_SUCCEEDED, 0, key, config); 235 } 236 237 void reportResponderEnableFailed(int key, int reason) { 238 mChannel.sendMessage(RttManager.CMD_OP_ENALBE_RESPONDER_FAILED, reason, key); 239 removeResponderRequest(key); 240 } 241 242 void reportResult(RttRequest request, RttManager.RttResult[] results) { 243 RttManager.ParcelableRttResults parcelableResults = 244 new RttManager.ParcelableRttResults(results); 245 246 mChannel.sendMessage(RttManager.CMD_OP_SUCCEEDED, 247 0, request.key, parcelableResults); 248 removeRttRequest(request.key); 249 } 250 251 void reportFailed(RttRequest request, int reason, String description) { 252 reportFailed(request.key, reason, description); 253 } 254 255 void reportFailed(int key, int reason, String description) { 256 Bundle bundle = new Bundle(); 257 bundle.putString(RttManager.DESCRIPTION_KEY, description); 258 mChannel.sendMessage(RttManager.CMD_OP_FAILED, key, reason, bundle); 259 removeRttRequest(key); 260 } 261 262 void reportAborted(int key) { 263 mChannel.sendMessage(RttManager.CMD_OP_ABORTED, 0, key); 264 //All Queued RTT request will be cleaned 265 cleanup(); 266 } 267 268 void cleanup() { 269 mRequests.clear(); 270 mRequestQueue.clear(); 271 // When client is lost, clean up responder requests and send disable responder 272 // message to RttStateMachine. 273 mResponderRequests.clear(); 274 mStateMachine.sendMessage(RttManager.CMD_OP_DISABLE_RESPONDER); 275 } 276 277 @Override 278 public String toString() { 279 return "ClientInfo [uid=" + mUid + ", channel=" + mChannel + "]"; 280 } 281 } 282 283 private Queue<RttRequest> mRequestQueue = new LinkedList<>(); 284 285 @GuardedBy("mLock") 286 private ArrayMap<Messenger, ClientInfo> mClients = new ArrayMap<>(); 287 // Lock for mClients. 288 private final Object mLock = new Object(); 289 290 private static final int BASE = Protocol.BASE_WIFI_RTT_SERVICE; 291 292 private static final int CMD_DRIVER_LOADED = BASE + 0; 293 private static final int CMD_DRIVER_UNLOADED = BASE + 1; 294 private static final int CMD_ISSUE_NEXT_REQUEST = BASE + 2; 295 private static final int CMD_RTT_RESPONSE = BASE + 3; 296 private static final int CMD_CLIENT_INTERFACE_READY = BASE + 4; 297 private static final int CMD_CLIENT_INTERFACE_DOWN = BASE + 5; 298 299 // Maximum duration for responder role. 300 private static final int MAX_RESPONDER_DURATION_SECONDS = 60 * 10; 301 302 private static class InterfaceEventHandler extends IInterfaceEventCallback.Stub { 303 InterfaceEventHandler(RttStateMachine rttStateMachine) { 304 mRttStateMachine = rttStateMachine; 305 } 306 @Override 307 public void OnClientTorndownEvent(IClientInterface networkInterface) { 308 mRttStateMachine.sendMessage(CMD_CLIENT_INTERFACE_DOWN, networkInterface); 309 } 310 @Override 311 public void OnClientInterfaceReady(IClientInterface networkInterface) { 312 mRttStateMachine.sendMessage(CMD_CLIENT_INTERFACE_READY, networkInterface); 313 } 314 @Override 315 public void OnApTorndownEvent(IApInterface networkInterface) { } 316 @Override 317 public void OnApInterfaceReady(IApInterface networkInterface) { } 318 319 private RttStateMachine mRttStateMachine; 320 } 321 322 class RttStateMachine extends StateMachine { 323 private IWificond mWificond; 324 private InterfaceEventHandler mInterfaceEventHandler; 325 private IClientInterface mClientInterface; 326 327 DefaultState mDefaultState = new DefaultState(); 328 EnabledState mEnabledState = new EnabledState(); 329 InitiatorEnabledState mInitiatorEnabledState = new InitiatorEnabledState(); 330 ResponderEnabledState mResponderEnabledState = new ResponderEnabledState(); 331 ResponderConfig mResponderConfig; 332 333 RttStateMachine(Looper looper) { 334 super("RttStateMachine", looper); 335 336 // CHECKSTYLE:OFF IndentationCheck 337 addState(mDefaultState); 338 addState(mEnabledState); 339 addState(mInitiatorEnabledState, mEnabledState); 340 addState(mResponderEnabledState, mEnabledState); 341 // CHECKSTYLE:ON IndentationCheck 342 343 setInitialState(mDefaultState); 344 } 345 346 class DefaultState extends State { 347 @Override 348 public boolean processMessage(Message msg) { 349 if (DBG) Log.d(TAG, "DefaultState got" + msg); 350 switch (msg.what) { 351 case CMD_DRIVER_LOADED: 352 transitionTo(mEnabledState); 353 break; 354 case CMD_ISSUE_NEXT_REQUEST: 355 deferMessage(msg); 356 break; 357 case RttManager.CMD_OP_START_RANGING: 358 replyFailed(msg, RttManager.REASON_NOT_AVAILABLE, "Try later"); 359 break; 360 case RttManager.CMD_OP_STOP_RANGING: 361 return HANDLED; 362 case RttManager.CMD_OP_ENABLE_RESPONDER: 363 364 ClientInfo client; 365 synchronized (mLock) { 366 client = mClients.get(msg.replyTo); 367 } 368 if (client == null) { 369 Log.e(TAG, "client not connected yet!"); 370 break; 371 } 372 int key = msg.arg2; 373 client.reportResponderEnableFailed(key, 374 RttManager.REASON_NOT_AVAILABLE); 375 break; 376 case RttManager.CMD_OP_DISABLE_RESPONDER: 377 return HANDLED; 378 default: 379 return NOT_HANDLED; 380 } 381 return HANDLED; 382 } 383 } 384 385 class EnabledState extends State { 386 @Override 387 public void enter() { 388 // This allows us to tolerate wificond restarts. 389 // When wificond restarts WifiStateMachine is supposed to go 390 // back to initial state and restart. 391 // 1) RttService watches for WIFI_STATE_ENABLED broadcasts 392 // 2) WifiStateMachine sends these broadcasts in the SupplicantStarted state 393 // 3) Since WSM will only be in SupplicantStarted for as long as wificond is 394 // alive, we refresh our wificond handler here and we don't subscribe to 395 // wificond's death explicitly. 396 mWificond = mWifiInjector.makeWificond(); 397 if (mWificond == null) { 398 Log.w(TAG, "Failed to get wificond binder handler"); 399 transitionTo(mDefaultState); 400 } 401 mInterfaceEventHandler = new InterfaceEventHandler(mStateMachine); 402 try { 403 mWificond.RegisterCallback(mInterfaceEventHandler); 404 // Get the current client interface, assuming there is at most 405 // one client interface for now. 406 List<IBinder> interfaces = mWificond.GetClientInterfaces(); 407 if (interfaces.size() > 0) { 408 mStateMachine.sendMessage( 409 CMD_CLIENT_INTERFACE_READY, 410 IClientInterface.Stub.asInterface(interfaces.get(0))); 411 } 412 } catch (RemoteException e1) { } 413 414 } 415 @Override 416 public void exit() { 417 try { 418 mWificond.UnregisterCallback(mInterfaceEventHandler); 419 } catch (RemoteException e1) { } 420 mInterfaceEventHandler = null; 421 } 422 @Override 423 public boolean processMessage(Message msg) { 424 if (DBG) Log.d(TAG, "EnabledState got" + msg); 425 ClientInfo ci; 426 synchronized (mLock) { 427 ci = mClients.get(msg.replyTo); 428 } 429 430 switch (msg.what) { 431 case CMD_DRIVER_UNLOADED: 432 transitionTo(mDefaultState); 433 break; 434 case CMD_ISSUE_NEXT_REQUEST: 435 deferMessage(msg); 436 transitionTo(mInitiatorEnabledState); 437 break; 438 case RttManager.CMD_OP_START_RANGING: { 439 RttManager.ParcelableRttParams params = 440 (RttManager.ParcelableRttParams)msg.obj; 441 if (params == null || params.mParams == null 442 || params.mParams.length == 0) { 443 replyFailed(msg, 444 RttManager.REASON_INVALID_REQUEST, "No params"); 445 } else if (ci.addRttRequest(msg.arg2, params) == false) { 446 replyFailed(msg, 447 RttManager.REASON_INVALID_REQUEST, "Unspecified"); 448 } else { 449 sendMessage(CMD_ISSUE_NEXT_REQUEST); 450 } 451 } 452 break; 453 case RttManager.CMD_OP_STOP_RANGING: 454 for (Iterator<RttRequest> it = mRequestQueue.iterator(); 455 it.hasNext(); ) { 456 RttRequest request = it.next(); 457 if (request.key == msg.arg2) { 458 if (DBG) Log.d(TAG, "Cancelling not-yet-scheduled RTT"); 459 mRequestQueue.remove(request); 460 request.ci.reportAborted(request.key); 461 break; 462 } 463 } 464 break; 465 case RttManager.CMD_OP_ENABLE_RESPONDER: 466 int key = msg.arg2; 467 mResponderConfig = 468 mWifiNative.enableRttResponder(MAX_RESPONDER_DURATION_SECONDS); 469 if (DBG) Log.d(TAG, "mWifiNative.enableRttResponder called"); 470 471 if (mResponderConfig != null) { 472 // TODO: remove once mac address is added when enabling responder. 473 mResponderConfig.macAddress = mWifiNative.getMacAddress(); 474 ci.addResponderRequest(key); 475 ci.reportResponderEnableSucceed(key, mResponderConfig); 476 transitionTo(mResponderEnabledState); 477 } else { 478 Log.e(TAG, "enable responder failed"); 479 ci.reportResponderEnableFailed(key, RttManager.REASON_UNSPECIFIED); 480 } 481 break; 482 case RttManager.CMD_OP_DISABLE_RESPONDER: 483 break; 484 case CMD_CLIENT_INTERFACE_DOWN: 485 if (mClientInterface == (IClientInterface) msg.obj) { 486 mClientInterface = null; 487 } 488 break; 489 case CMD_CLIENT_INTERFACE_READY: 490 mClientInterface = (IClientInterface) msg.obj; 491 break; 492 default: 493 return NOT_HANDLED; 494 } 495 return HANDLED; 496 } 497 } 498 499 class InitiatorEnabledState extends State { 500 RttRequest mOutstandingRequest; 501 @Override 502 public boolean processMessage(Message msg) { 503 if (DBG) Log.d(TAG, "RequestPendingState got" + msg); 504 switch (msg.what) { 505 case CMD_DRIVER_UNLOADED: 506 if (mOutstandingRequest != null) { 507 mWifiNative.cancelRtt(mOutstandingRequest.params); 508 if (DBG) Log.d(TAG, "abort key: " + mOutstandingRequest.key); 509 mOutstandingRequest.ci.reportAborted(mOutstandingRequest.key); 510 mOutstandingRequest = null; 511 } 512 transitionTo(mDefaultState); 513 break; 514 case CMD_ISSUE_NEXT_REQUEST: 515 if (mOutstandingRequest == null) { 516 mOutstandingRequest = issueNextRequest(); 517 if (mOutstandingRequest == null) { 518 transitionTo(mEnabledState); 519 } 520 if(mOutstandingRequest != null) { 521 if (DBG) Log.d(TAG, "new mOutstandingRequest.key is: " + 522 mOutstandingRequest.key); 523 } else { 524 if (DBG) Log.d(TAG, 525 "CMD_ISSUE_NEXT_REQUEST: mOutstandingRequest =null "); 526 } 527 } else { 528 /* just wait; we'll issue next request after 529 * current one is finished */ 530 if (DBG) Log.d(TAG, "Current mOutstandingRequest.key is: " + 531 mOutstandingRequest.key); 532 if (DBG) Log.d(TAG, "Ignoring CMD_ISSUE_NEXT_REQUEST"); 533 } 534 break; 535 case CMD_RTT_RESPONSE: 536 if (DBG) Log.d(TAG, "Received an RTT response from: " + msg.arg2); 537 mOutstandingRequest.ci.reportResult( 538 mOutstandingRequest, (RttManager.RttResult[])msg.obj); 539 mOutstandingRequest = null; 540 sendMessage(CMD_ISSUE_NEXT_REQUEST); 541 break; 542 case RttManager.CMD_OP_STOP_RANGING: 543 if (mOutstandingRequest != null 544 && msg.arg2 == mOutstandingRequest.key) { 545 if (DBG) Log.d(TAG, "Cancelling ongoing RTT of: " + msg.arg2); 546 mWifiNative.cancelRtt(mOutstandingRequest.params); 547 mOutstandingRequest.ci.reportAborted(mOutstandingRequest.key); 548 mOutstandingRequest = null; 549 sendMessage(CMD_ISSUE_NEXT_REQUEST); 550 } else { 551 /* Let EnabledState handle this */ 552 return NOT_HANDLED; 553 } 554 break; 555 default: 556 return NOT_HANDLED; 557 } 558 return HANDLED; 559 } 560 } 561 562 // Check if there are still outstanding responder requests from any client. 563 private boolean hasOutstandingReponderRequests() { 564 synchronized (mLock) { 565 for (ClientInfo client : mClients.values()) { 566 if (!client.mResponderRequests.isEmpty()) { 567 return true; 568 } 569 } 570 } 571 return false; 572 } 573 574 /** 575 * Representing an outstanding RTT responder state. 576 */ 577 class ResponderEnabledState extends State { 578 @Override 579 public boolean processMessage(Message msg) { 580 if (DBG) Log.d(TAG, "ResponderEnabledState got " + msg); 581 ClientInfo ci; 582 synchronized (mLock) { 583 ci = mClients.get(msg.replyTo); 584 } 585 int key = msg.arg2; 586 switch(msg.what) { 587 case RttManager.CMD_OP_ENABLE_RESPONDER: 588 // Responder already enabled, simply return the responder config. 589 ci.addResponderRequest(key); 590 ci.reportResponderEnableSucceed(key, mResponderConfig); 591 return HANDLED; 592 case RttManager.CMD_OP_DISABLE_RESPONDER: 593 if (ci != null) { 594 ci.removeResponderRequest(key); 595 } 596 // Only disable responder when there are no outstanding clients. 597 if (!hasOutstandingReponderRequests()) { 598 if (!mWifiNative.disableRttResponder()) { 599 Log.e(TAG, "disable responder failed"); 600 } 601 if (DBG) Log.d(TAG, "mWifiNative.disableRttResponder called"); 602 transitionTo(mEnabledState); 603 } 604 return HANDLED; 605 case RttManager.CMD_OP_START_RANGING: 606 case RttManager.CMD_OP_STOP_RANGING: // fall through 607 // Concurrent initiator and responder role is not supported. 608 replyFailed(msg, 609 RttManager.REASON_INITIATOR_NOT_ALLOWED_WHEN_RESPONDER_ON, 610 "Initiator not allowed when responder is turned on"); 611 return HANDLED; 612 default: 613 return NOT_HANDLED; 614 } 615 } 616 } 617 618 /** 619 * Returns name of current state. 620 */ 621 String currentState() { 622 IState state = getCurrentState(); 623 return state == null ? "null" : state.getName(); 624 } 625 } 626 627 void replySucceeded(Message msg, Object obj) { 628 if (msg.replyTo != null) { 629 Message reply = Message.obtain(); 630 reply.what = RttManager.CMD_OP_SUCCEEDED; 631 reply.arg2 = msg.arg2; 632 reply.obj = obj; 633 try { 634 msg.replyTo.send(reply); 635 } catch (RemoteException e) { 636 // There's not much we can do if reply can't be sent! 637 } 638 } else { 639 // locally generated message; doesn't need a reply! 640 } 641 } 642 643 void replyFailed(Message msg, int reason, String description) { 644 Message reply = Message.obtain(); 645 reply.what = RttManager.CMD_OP_FAILED; 646 reply.arg1 = reason; 647 reply.arg2 = msg.arg2; 648 649 Bundle bundle = new Bundle(); 650 bundle.putString(RttManager.DESCRIPTION_KEY, description); 651 reply.obj = bundle; 652 653 try { 654 if (msg.replyTo != null) { 655 msg.replyTo.send(reply); 656 } 657 } catch (RemoteException e) { 658 // There's not much we can do if reply can't be sent! 659 } 660 } 661 662 boolean enforcePermissionCheck(Message msg) { 663 try { 664 mContext.enforcePermission(Manifest.permission.LOCATION_HARDWARE, 665 -1, msg.sendingUid, "LocationRTT"); 666 } catch (SecurityException e) { 667 Log.e(TAG, "UID: " + msg.sendingUid + " has no LOCATION_HARDWARE Permission"); 668 return false; 669 } 670 return true; 671 } 672 673 @Override 674 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 675 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 676 != PackageManager.PERMISSION_GRANTED) { 677 pw.println("Permission Denial: can't dump RttService from from pid=" 678 + Binder.getCallingPid() 679 + ", uid=" + Binder.getCallingUid() 680 + " without permission " 681 + android.Manifest.permission.DUMP); 682 return; 683 } 684 pw.println("current state: " + mStateMachine.currentState()); 685 pw.println("clients:"); 686 synchronized (mLock) { 687 for (ClientInfo client : mClients.values()) { 688 pw.println(" " + client); 689 } 690 } 691 } 692 693 private WifiNative.RttEventHandler mEventHandler = new WifiNative.RttEventHandler() { 694 @Override 695 public void onRttResults(RttManager.RttResult[] result) { 696 mStateMachine.sendMessage(CMD_RTT_RESPONSE, result); 697 } 698 }; 699 700 RttRequest issueNextRequest() { 701 RttRequest request = null; 702 while (mRequestQueue.isEmpty() == false) { 703 request = mRequestQueue.remove(); 704 if(request != null) { 705 if (mWifiNative.requestRtt(request.params, mEventHandler)) { 706 if (DBG) Log.d(TAG, "Issued next RTT request with key: " + request.key); 707 return request; 708 } else { 709 Log.e(TAG, "Fail to issue key at native layer"); 710 request.ci.reportFailed(request, 711 RttManager.REASON_UNSPECIFIED, "Failed to start"); 712 } 713 } 714 } 715 716 /* all requests exhausted */ 717 if (DBG) Log.d(TAG, "No more requests left"); 718 return null; 719 } 720 @Override 721 public RttManager.RttCapabilities getRttCapabilities() { 722 return mWifiNative.getRttCapabilities(); 723 } 724 } 725 726 private static final String TAG = "RttService"; 727 RttServiceImpl mImpl; 728 private final HandlerThread mHandlerThread; 729 730 public RttService(Context context) { 731 super(context); 732 mHandlerThread = new HandlerThread("WifiRttService"); 733 mHandlerThread.start(); 734 Log.i(TAG, "Creating " + Context.WIFI_RTT_SERVICE); 735 } 736 737 @Override 738 public void onStart() { 739 mImpl = new RttServiceImpl(getContext(), 740 mHandlerThread.getLooper(), WifiInjector.getInstance()); 741 742 Log.i(TAG, "Starting " + Context.WIFI_RTT_SERVICE); 743 publishBinderService(Context.WIFI_RTT_SERVICE, mImpl); 744 } 745 746 @Override 747 public void onBootPhase(int phase) { 748 if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) { 749 Log.i(TAG, "Registering " + Context.WIFI_RTT_SERVICE); 750 if (mImpl == null) { 751 mImpl = new RttServiceImpl(getContext(), 752 mHandlerThread.getLooper(), WifiInjector.getInstance()); 753 } 754 mImpl.startService(); 755 } 756 } 757 758 759} 760