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.server.wifi; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.hardware.wifi.V1_0.IWifi; 22 import android.hardware.wifi.V1_0.IWifiApIface; 23 import android.hardware.wifi.V1_0.IWifiChip; 24 import android.hardware.wifi.V1_0.IWifiChipEventCallback; 25 import android.hardware.wifi.V1_0.IWifiEventCallback; 26 import android.hardware.wifi.V1_0.IWifiIface; 27 import android.hardware.wifi.V1_0.IWifiNanIface; 28 import android.hardware.wifi.V1_0.IWifiP2pIface; 29 import android.hardware.wifi.V1_0.IWifiRttController; 30 import android.hardware.wifi.V1_0.IWifiStaIface; 31 import android.hardware.wifi.V1_0.IfaceType; 32 import android.hardware.wifi.V1_0.WifiDebugRingBufferStatus; 33 import android.hardware.wifi.V1_0.WifiStatus; 34 import android.hardware.wifi.V1_0.WifiStatusCode; 35 import android.hidl.manager.V1_0.IServiceNotification; 36 import android.hidl.manager.V1_2.IServiceManager; 37 import android.os.Handler; 38 import android.os.HidlSupport.Mutable; 39 import android.os.HwRemoteBinder; 40 import android.os.RemoteException; 41 import android.util.Log; 42 import android.util.LongSparseArray; 43 import android.util.MutableBoolean; 44 import android.util.MutableInt; 45 import android.util.Pair; 46 import android.util.SparseArray; 47 48 import com.android.internal.annotations.VisibleForTesting; 49 50 import java.io.FileDescriptor; 51 import java.io.PrintWriter; 52 import java.util.ArrayList; 53 import java.util.Arrays; 54 import java.util.HashMap; 55 import java.util.HashSet; 56 import java.util.Iterator; 57 import java.util.List; 58 import java.util.Map; 59 import java.util.Set; 60 61 /** 62 * Handles device management through the HAL (HIDL) interface. 63 */ 64 public class HalDeviceManager { 65 private static final String TAG = "HalDevMgr"; 66 private static final boolean VDBG = false; 67 private boolean mDbg = false; 68 69 private static final int START_HAL_RETRY_INTERVAL_MS = 20; 70 // Number of attempts a start() is re-tried. A value of 0 means no retries after a single 71 // attempt. 72 @VisibleForTesting 73 public static final int START_HAL_RETRY_TIMES = 3; 74 75 private final Clock mClock; 76 77 // cache the value for supporting vendor HAL or not 78 private boolean mIsVendorHalSupported = false; 79 80 // public API HalDeviceManager(Clock clock)81 public HalDeviceManager(Clock clock) { 82 mClock = clock; 83 84 mInterfaceAvailableForRequestListeners.put(IfaceType.STA, new HashMap<>()); 85 mInterfaceAvailableForRequestListeners.put(IfaceType.AP, new HashMap<>()); 86 mInterfaceAvailableForRequestListeners.put(IfaceType.P2P, new HashMap<>()); 87 mInterfaceAvailableForRequestListeners.put(IfaceType.NAN, new HashMap<>()); 88 } 89 enableVerboseLogging(int verbose)90 /* package */ void enableVerboseLogging(int verbose) { 91 if (verbose > 0) { 92 mDbg = true; 93 } else { 94 mDbg = false; 95 } 96 if (VDBG) { 97 mDbg = true; // just override 98 } 99 } 100 101 /** 102 * Actually starts the HalDeviceManager: separate from constructor since may want to phase 103 * at a later time. 104 * 105 * TODO: if decide that no need for separating construction from initialization (e.g. both are 106 * done at injector) then move to constructor. 107 */ initialize()108 public void initialize() { 109 initializeInternal(); 110 } 111 112 /** 113 * Register a ManagerStatusListener to get information about the status of the manager. Use the 114 * isReady() and isStarted() methods to check status immediately after registration and when 115 * triggered. 116 * 117 * It is safe to re-register the same callback object - duplicates are detected and only a 118 * single copy kept. 119 * 120 * @param listener ManagerStatusListener listener object. 121 * @param handler Handler on which to dispatch listener. Null implies the listener will be 122 * invoked synchronously from the context of the client which triggered the 123 * state change. 124 */ registerStatusListener(@onNull ManagerStatusListener listener, @Nullable Handler handler)125 public void registerStatusListener(@NonNull ManagerStatusListener listener, 126 @Nullable Handler handler) { 127 synchronized (mLock) { 128 if (!mManagerStatusListeners.add(new ManagerStatusListenerProxy(listener, handler))) { 129 Log.w(TAG, "registerStatusListener: duplicate registration ignored"); 130 } 131 } 132 } 133 134 /** 135 * Returns whether the vendor HAL is supported on this device or not. 136 */ isSupported()137 public boolean isSupported() { 138 return mIsVendorHalSupported; 139 } 140 141 /** 142 * Returns the current status of the HalDeviceManager: whether or not it is ready to execute 143 * commands. A return of 'false' indicates that the HAL service (IWifi) is not available. Use 144 * the registerStatusListener() to listener for status changes. 145 */ isReady()146 public boolean isReady() { 147 return mIsReady; 148 } 149 150 /** 151 * Returns the current status of Wi-Fi: started (true) or stopped (false). 152 * 153 * Note: direct call to HIDL. 154 */ isStarted()155 public boolean isStarted() { 156 return isWifiStarted(); 157 } 158 159 /** 160 * Attempts to start Wi-Fi (using HIDL). Returns the success (true) or failure (false) or 161 * the start operation. Will also dispatch any registered ManagerStatusCallback.onStart() on 162 * success. 163 * 164 * Note: direct call to HIDL. 165 */ start()166 public boolean start() { 167 return startWifi(); 168 } 169 170 /** 171 * Stops Wi-Fi. Will also dispatch any registeredManagerStatusCallback.onStop(). 172 * 173 * Note: direct call to HIDL - failure is not-expected. 174 */ stop()175 public void stop() { 176 stopWifi(); 177 mWifi = null; 178 } 179 180 /** 181 * HAL device manager status change listener. 182 */ 183 public interface ManagerStatusListener { 184 /** 185 * Indicates that the status of the HalDeviceManager has changed. Use isReady() and 186 * isStarted() to obtain status information. 187 */ onStatusChanged()188 void onStatusChanged(); 189 } 190 191 /** 192 * Return the set of supported interface types across all Wi-Fi chips on the device. 193 * 194 * @return A set of IfaceTypes constants (possibly empty, e.g. on error). 195 */ getSupportedIfaceTypes()196 public Set<Integer> getSupportedIfaceTypes() { 197 return getSupportedIfaceTypesInternal(null); 198 } 199 200 /** 201 * Return the set of supported interface types for the specified Wi-Fi chip. 202 * 203 * @return A set of IfaceTypes constants (possibly empty, e.g. on error). 204 */ getSupportedIfaceTypes(IWifiChip chip)205 public Set<Integer> getSupportedIfaceTypes(IWifiChip chip) { 206 return getSupportedIfaceTypesInternal(chip); 207 } 208 209 // interface-specific behavior 210 211 /** 212 * Create a STA interface if possible. Changes chip mode and removes conflicting interfaces if 213 * needed and permitted by priority. 214 * 215 * @param lowPrioritySta Indicates whether the requested STA is a low priority STA. The priority 216 * and preemption rules for low priority STA are: 217 * - Do not destroy any interface for it (even another low priority STA) 218 * - Destroy it for any other request 219 * @param destroyedListener Optional (nullable) listener to call when the allocated interface 220 * is removed. Will only be registered and used if an interface is 221 * created successfully. 222 * @param handler Handler on which to dispatch listener. Null implies the listener will be 223 * invoked synchronously from the context of the client which triggered the 224 * iface destruction. 225 * @return A newly created interface - or null if the interface could not be created. 226 */ createStaIface(boolean lowPrioritySta, @Nullable InterfaceDestroyedListener destroyedListener, @Nullable Handler handler)227 public IWifiStaIface createStaIface(boolean lowPrioritySta, 228 @Nullable InterfaceDestroyedListener destroyedListener, @Nullable Handler handler) { 229 return (IWifiStaIface) createIface(IfaceType.STA, lowPrioritySta, destroyedListener, 230 handler); 231 } 232 233 /** 234 * Create AP interface if possible (see createStaIface doc). 235 */ createApIface(@ullable InterfaceDestroyedListener destroyedListener, @Nullable Handler handler)236 public IWifiApIface createApIface(@Nullable InterfaceDestroyedListener destroyedListener, 237 @Nullable Handler handler) { 238 return (IWifiApIface) createIface(IfaceType.AP, false, destroyedListener, handler); 239 } 240 241 /** 242 * Create P2P interface if possible (see createStaIface doc). 243 */ createP2pIface(@ullable InterfaceDestroyedListener destroyedListener, @Nullable Handler handler)244 public IWifiP2pIface createP2pIface(@Nullable InterfaceDestroyedListener destroyedListener, 245 @Nullable Handler handler) { 246 return (IWifiP2pIface) createIface(IfaceType.P2P, false, destroyedListener, handler); 247 } 248 249 /** 250 * Create NAN interface if possible (see createStaIface doc). 251 */ createNanIface(@ullable InterfaceDestroyedListener destroyedListener, @Nullable Handler handler)252 public IWifiNanIface createNanIface(@Nullable InterfaceDestroyedListener destroyedListener, 253 @Nullable Handler handler) { 254 return (IWifiNanIface) createIface(IfaceType.NAN, false, destroyedListener, handler); 255 } 256 257 /** 258 * Removes (releases/destroys) the given interface. Will trigger any registered 259 * InterfaceDestroyedListeners and possibly some InterfaceAvailableForRequestListeners if we 260 * can potentially create some other interfaces as a result of removing this interface. 261 */ removeIface(IWifiIface iface)262 public boolean removeIface(IWifiIface iface) { 263 boolean success = removeIfaceInternal(iface); 264 dispatchAvailableForRequestListeners(); 265 return success; 266 } 267 268 /** 269 * Returns the IWifiChip corresponding to the specified interface (or null on error). 270 * 271 * Note: clients must not perform chip mode changes or interface management (create/delete) 272 * operations on IWifiChip directly. However, they can use the IWifiChip interface to perform 273 * other functions - e.g. calling the debug/trace methods. 274 */ getChip(IWifiIface iface)275 public IWifiChip getChip(IWifiIface iface) { 276 String name = getName(iface); 277 int type = getType(iface); 278 if (VDBG) Log.d(TAG, "getChip: iface(name)=" + name); 279 280 synchronized (mLock) { 281 InterfaceCacheEntry cacheEntry = mInterfaceInfoCache.get(Pair.create(name, type)); 282 if (cacheEntry == null) { 283 Log.e(TAG, "getChip: no entry for iface(name)=" + name); 284 return null; 285 } 286 287 return cacheEntry.chip; 288 } 289 } 290 291 /** 292 * Register an InterfaceDestroyedListener to the specified iface - returns true on success 293 * and false on failure. This listener is in addition to the one registered when the interface 294 * was created - allowing non-creators to monitor interface status. 295 * 296 * @param destroyedListener Listener to call when the allocated interface is removed. 297 * Will only be registered and used if an interface is created 298 * successfully. 299 * @param handler Handler on which to dispatch listener. Null implies the listener will be 300 * invoked synchronously from the context of the client which triggered the 301 * iface destruction. 302 */ registerDestroyedListener(IWifiIface iface, @NonNull InterfaceDestroyedListener destroyedListener, @Nullable Handler handler)303 public boolean registerDestroyedListener(IWifiIface iface, 304 @NonNull InterfaceDestroyedListener destroyedListener, 305 @Nullable Handler handler) { 306 String name = getName(iface); 307 int type = getType(iface); 308 if (VDBG) Log.d(TAG, "registerDestroyedListener: iface(name)=" + name); 309 310 synchronized (mLock) { 311 InterfaceCacheEntry cacheEntry = mInterfaceInfoCache.get(Pair.create(name, type)); 312 if (cacheEntry == null) { 313 Log.e(TAG, "registerDestroyedListener: no entry for iface(name)=" + name); 314 return false; 315 } 316 317 return cacheEntry.destroyedListeners.add( 318 new InterfaceDestroyedListenerProxy(name, destroyedListener, handler)); 319 } 320 } 321 322 /** 323 * Register a listener to be called when an interface of the specified type could be requested. 324 * No guarantees are provided (some other entity could request it first). The listener is 325 * active from registration until unregistration - using 326 * unregisterInterfaceAvailableForRequestListener(). 327 * 328 * Only a single instance of a listener will be registered (even if the specified looper is 329 * different). 330 * 331 * Note that if it is possible to create the specified interface type at registration time 332 * then the callback will be triggered immediately. 333 * 334 * @param ifaceType The interface type (IfaceType) to be monitored. 335 * @param listener Listener to call when an interface of the requested 336 * type could be created 337 * @param handler Handler on which to dispatch listener. Null implies the listener will be 338 * invoked synchronously from the context of the client which triggered the 339 * mode change. 340 */ registerInterfaceAvailableForRequestListener(int ifaceType, @NonNull InterfaceAvailableForRequestListener listener, @Nullable Handler handler)341 public void registerInterfaceAvailableForRequestListener(int ifaceType, 342 @NonNull InterfaceAvailableForRequestListener listener, @Nullable Handler handler) { 343 if (VDBG) { 344 Log.d(TAG, "registerInterfaceAvailableForRequestListener: ifaceType=" + ifaceType 345 + ", listener=" + listener + ", handler=" + handler); 346 } 347 348 synchronized (mLock) { 349 InterfaceAvailableForRequestListenerProxy proxy = 350 new InterfaceAvailableForRequestListenerProxy(listener, handler); 351 if (mInterfaceAvailableForRequestListeners.get(ifaceType).containsKey(proxy)) { 352 if (VDBG) { 353 Log.d(TAG, 354 "registerInterfaceAvailableForRequestListener: dup listener skipped: " 355 + listener); 356 } 357 return; 358 } 359 mInterfaceAvailableForRequestListeners.get(ifaceType).put(proxy, null); 360 } 361 362 WifiChipInfo[] chipInfos = getAllChipInfo(); 363 if (chipInfos == null) { 364 Log.e(TAG, 365 "registerInterfaceAvailableForRequestListener: no chip info found - but " 366 + "possibly registered pre-started - ignoring"); 367 return; 368 } 369 dispatchAvailableForRequestListenersForType(ifaceType, chipInfos); 370 } 371 372 /** 373 * Unregisters a listener registered with registerInterfaceAvailableForRequestListener(). 374 */ unregisterInterfaceAvailableForRequestListener( int ifaceType, InterfaceAvailableForRequestListener listener)375 public void unregisterInterfaceAvailableForRequestListener( 376 int ifaceType, 377 InterfaceAvailableForRequestListener listener) { 378 if (VDBG) { 379 Log.d(TAG, "unregisterInterfaceAvailableForRequestListener: ifaceType=" + ifaceType); 380 } 381 382 synchronized (mLock) { 383 mInterfaceAvailableForRequestListeners.get(ifaceType).remove( 384 new InterfaceAvailableForRequestListenerProxy(listener, null)); 385 } 386 } 387 388 /** 389 * Register a callback object for RTT life-cycle events. The callback object registration 390 * indicates that an RTT controller should be created whenever possible. The callback object 391 * will be called with a new RTT controller whenever it is created (or at registration time 392 * if an RTT controller already exists). The callback object will also be triggered whenever 393 * an existing RTT controller is destroyed (the previous copies must be discarded by the 394 * recipient). 395 * 396 * @param callback InterfaceRttControllerLifecycleCallback object. 397 * @param handler Handler on which to dispatch callback 398 */ registerRttControllerLifecycleCallback( @onNull InterfaceRttControllerLifecycleCallback callback, @NonNull Handler handler)399 public void registerRttControllerLifecycleCallback( 400 @NonNull InterfaceRttControllerLifecycleCallback callback, @NonNull Handler handler) { 401 if (VDBG) { 402 Log.d(TAG, "registerRttControllerLifecycleCallback: callback=" + callback + ", handler=" 403 + handler); 404 } 405 406 if (callback == null || handler == null) { 407 Log.wtf(TAG, "registerRttControllerLifecycleCallback with nulls!? callback=" + callback 408 + ", handler=" + handler); 409 return; 410 } 411 412 synchronized (mLock) { 413 InterfaceRttControllerLifecycleCallbackProxy proxy = 414 new InterfaceRttControllerLifecycleCallbackProxy(callback, handler); 415 if (!mRttControllerLifecycleCallbacks.add(proxy)) { 416 Log.d(TAG, 417 "registerRttControllerLifecycleCallback: registering an existing callback=" 418 + callback); 419 return; 420 } 421 422 if (mIWifiRttController == null) { 423 mIWifiRttController = createRttControllerIfPossible(); 424 } 425 if (mIWifiRttController != null) { 426 proxy.onNewRttController(mIWifiRttController); 427 } 428 } 429 } 430 431 /** 432 * Return the name of the input interface or null on error. 433 */ getName(IWifiIface iface)434 public static String getName(IWifiIface iface) { 435 if (iface == null) { 436 return "<null>"; 437 } 438 439 Mutable<String> nameResp = new Mutable<>(); 440 try { 441 iface.getName((WifiStatus status, String name) -> { 442 if (status.code == WifiStatusCode.SUCCESS) { 443 nameResp.value = name; 444 } else { 445 Log.e(TAG, "Error on getName: " + statusString(status)); 446 } 447 }); 448 } catch (RemoteException e) { 449 Log.e(TAG, "Exception on getName: " + e); 450 } 451 452 return nameResp.value; 453 } 454 455 /** 456 * Called when interface is destroyed. 457 */ 458 public interface InterfaceDestroyedListener { 459 /** 460 * Called for every interface on which registered when destroyed - whether 461 * destroyed by releaseIface() or through chip mode change or through Wi-Fi 462 * going down. 463 * 464 * Can be registered when the interface is requested with createXxxIface() - will 465 * only be valid if the interface creation was successful - i.e. a non-null was returned. 466 * 467 * @param ifaceName Name of the interface that was destroyed. 468 */ onDestroyed(@onNull String ifaceName)469 void onDestroyed(@NonNull String ifaceName); 470 } 471 472 /** 473 * Called when an interface type availability for creation is changed. 474 */ 475 public interface InterfaceAvailableForRequestListener { 476 /** 477 * Called when an interface type availability for creation is updated. Registered with 478 * registerInterfaceAvailableForRequestListener() and unregistered with 479 * unregisterInterfaceAvailableForRequestListener(). 480 */ onAvailabilityChanged(boolean isAvailable)481 void onAvailabilityChanged(boolean isAvailable); 482 } 483 484 /** 485 * Called on RTT controller lifecycle events. RTT controller is a singleton which will be 486 * created when possible (after first lifecycle registration) and destroyed if necessary. 487 * 488 * Determination of availability is determined by the HAL. Creation attempts (if requested 489 * by registration of interface) will be done on any mode changes. 490 */ 491 public interface InterfaceRttControllerLifecycleCallback { 492 /** 493 * Called when an RTT controller was created (or for newly registered listeners - if it 494 * was already available). The controller provided by this callback may be destroyed by 495 * the HAL at which point the {@link #onRttControllerDestroyed()} will be called. 496 * 497 * Note: this callback can be triggered to replace an existing controller (instead of 498 * calling the Destroyed callback in between). 499 * 500 * @param controller The RTT controller object. 501 */ onNewRttController(@onNull IWifiRttController controller)502 void onNewRttController(@NonNull IWifiRttController controller); 503 504 /** 505 * Called when the previously provided RTT controller is destroyed. Clients must discard 506 * their copy. A new copy may be provided later by 507 * {@link #onNewRttController(IWifiRttController)}. 508 */ onRttControllerDestroyed()509 void onRttControllerDestroyed(); 510 } 511 512 // internal state 513 514 /* This "PRIORITY" is not for deciding interface elimination (that is controlled by 515 * allowedToDeleteIfaceTypeForRequestedType. This priority is used for: 516 * - Comparing 2 configuration options 517 * - Order of dispatch of available for request listeners 518 */ 519 private static final int[] IFACE_TYPES_BY_PRIORITY = 520 {IfaceType.AP, IfaceType.STA, IfaceType.P2P, IfaceType.NAN}; 521 522 private final Object mLock = new Object(); 523 524 private IServiceManager mServiceManager; 525 private IWifi mWifi; 526 private IWifiRttController mIWifiRttController; 527 private final WifiEventCallback mWifiEventCallback = new WifiEventCallback(); 528 private final Set<ManagerStatusListenerProxy> mManagerStatusListeners = new HashSet<>(); 529 private final Set<InterfaceRttControllerLifecycleCallbackProxy> 530 mRttControllerLifecycleCallbacks = new HashSet<>(); 531 private final SparseArray<Map<InterfaceAvailableForRequestListenerProxy, Boolean>> 532 mInterfaceAvailableForRequestListeners = new SparseArray<>(); 533 private final SparseArray<IWifiChipEventCallback.Stub> mDebugCallbacks = new SparseArray<>(); 534 private boolean mIsReady; 535 536 /* 537 * This is the only place where we cache HIDL information in this manager. Necessary since 538 * we need to keep a list of registered destroyed listeners. Will be validated regularly 539 * in getAllChipInfoAndValidateCache(). 540 */ 541 private final Map<Pair<String, Integer>, InterfaceCacheEntry> mInterfaceInfoCache = 542 new HashMap<>(); 543 544 private class InterfaceCacheEntry { 545 public IWifiChip chip; 546 public int chipId; 547 public String name; 548 public int type; 549 public Set<InterfaceDestroyedListenerProxy> destroyedListeners = new HashSet<>(); 550 public long creationTime; 551 public boolean isLowPriority; 552 553 @Override toString()554 public String toString() { 555 StringBuilder sb = new StringBuilder(); 556 sb.append("{name=").append(name).append(", type=").append(type) 557 .append(", destroyedListeners.size()=").append(destroyedListeners.size()) 558 .append(", creationTime=").append(creationTime).append( 559 ", isLowPriority=").append(isLowPriority).append("}"); 560 return sb.toString(); 561 } 562 } 563 564 private class WifiIfaceInfo { 565 public String name; 566 public IWifiIface iface; 567 } 568 569 private class WifiChipInfo { 570 public IWifiChip chip; 571 public int chipId; 572 public ArrayList<IWifiChip.ChipMode> availableModes; 573 public boolean currentModeIdValid; 574 public int currentModeId; 575 public WifiIfaceInfo[][] ifaces = new WifiIfaceInfo[IFACE_TYPES_BY_PRIORITY.length][]; 576 577 @Override toString()578 public String toString() { 579 StringBuilder sb = new StringBuilder(); 580 sb.append("{chipId=").append(chipId).append(", availableModes=").append(availableModes) 581 .append(", currentModeIdValid=").append(currentModeIdValid) 582 .append(", currentModeId=").append(currentModeId); 583 for (int type: IFACE_TYPES_BY_PRIORITY) { 584 sb.append(", ifaces[" + type + "].length=").append(ifaces[type].length); 585 } 586 sb.append(")"); 587 return sb.toString(); 588 } 589 } 590 591 /** 592 * Wrapper function to access the HIDL services. Created to be mockable in unit-tests. 593 */ getWifiServiceMockable()594 protected IWifi getWifiServiceMockable() { 595 try { 596 return IWifi.getService(true /* retry */); 597 } catch (RemoteException e) { 598 Log.e(TAG, "Exception getting IWifi service: " + e); 599 return null; 600 } 601 } 602 getServiceManagerMockable()603 protected IServiceManager getServiceManagerMockable() { 604 try { 605 return IServiceManager.getService(); 606 } catch (RemoteException e) { 607 Log.e(TAG, "Exception getting IServiceManager: " + e); 608 return null; 609 } 610 } 611 612 // internal implementation 613 initializeInternal()614 private void initializeInternal() { 615 initIServiceManagerIfNecessary(); 616 if (mIsVendorHalSupported) { 617 initIWifiIfNecessary(); 618 } 619 } 620 teardownInternal()621 private void teardownInternal() { 622 managerStatusListenerDispatch(); 623 dispatchAllDestroyedListeners(); 624 mInterfaceAvailableForRequestListeners.get(IfaceType.STA).clear(); 625 mInterfaceAvailableForRequestListeners.get(IfaceType.AP).clear(); 626 mInterfaceAvailableForRequestListeners.get(IfaceType.P2P).clear(); 627 mInterfaceAvailableForRequestListeners.get(IfaceType.NAN).clear(); 628 629 mIWifiRttController = null; 630 dispatchRttControllerLifecycleOnDestroyed(); 631 mRttControllerLifecycleCallbacks.clear(); 632 } 633 634 private final HwRemoteBinder.DeathRecipient mServiceManagerDeathRecipient = 635 cookie -> { 636 Log.wtf(TAG, "IServiceManager died: cookie=" + cookie); 637 synchronized (mLock) { 638 mServiceManager = null; 639 // theoretically can call initServiceManager again here - but 640 // there's no point since most likely system is going to reboot 641 } 642 }; 643 644 private final IServiceNotification mServiceNotificationCallback = 645 new IServiceNotification.Stub() { 646 @Override 647 public void onRegistration(String fqName, String name, 648 boolean preexisting) { 649 Log.d(TAG, "IWifi registration notification: fqName=" + fqName 650 + ", name=" + name + ", preexisting=" + preexisting); 651 synchronized (mLock) { 652 initIWifiIfNecessary(); 653 } 654 } 655 }; 656 657 /** 658 * Failures of IServiceManager are most likely system breaking in any case. Behavior here 659 * will be to WTF and continue. 660 */ initIServiceManagerIfNecessary()661 private void initIServiceManagerIfNecessary() { 662 if (mDbg) Log.d(TAG, "initIServiceManagerIfNecessary"); 663 664 synchronized (mLock) { 665 if (mServiceManager != null) { 666 return; 667 } 668 669 mServiceManager = getServiceManagerMockable(); 670 if (mServiceManager == null) { 671 Log.wtf(TAG, "Failed to get IServiceManager instance"); 672 } else { 673 try { 674 if (!mServiceManager.linkToDeath( 675 mServiceManagerDeathRecipient, /* don't care */ 0)) { 676 Log.wtf(TAG, "Error on linkToDeath on IServiceManager"); 677 mServiceManager = null; 678 return; 679 } 680 681 if (!mServiceManager.registerForNotifications(IWifi.kInterfaceName, "", 682 mServiceNotificationCallback)) { 683 Log.wtf(TAG, "Failed to register a listener for IWifi service"); 684 mServiceManager = null; 685 } 686 } catch (RemoteException e) { 687 Log.wtf(TAG, "Exception while operating on IServiceManager: " + e); 688 mServiceManager = null; 689 } 690 691 // Cache the result for the supporting vendor hal or not 692 mIsVendorHalSupported = isSupportedInternal(); 693 } 694 } 695 } 696 697 /** 698 * Uses the IServiceManager to query if the vendor HAL is present in the VINTF for the device 699 * or not. 700 * @return true if supported, false otherwise. 701 */ isSupportedInternal()702 private boolean isSupportedInternal() { 703 if (VDBG) Log.d(TAG, "isSupportedInternal"); 704 705 synchronized (mLock) { 706 if (mServiceManager == null) { 707 Log.e(TAG, "isSupported: called but mServiceManager is null!?"); 708 return false; 709 } 710 try { 711 List<String> wifiServices = 712 mServiceManager.listManifestByInterface(IWifi.kInterfaceName); 713 return !wifiServices.isEmpty(); 714 } catch (RemoteException e) { 715 Log.wtf(TAG, "Exception while operating on IServiceManager: " + e); 716 return false; 717 } 718 } 719 } 720 721 private final HwRemoteBinder.DeathRecipient mIWifiDeathRecipient = 722 cookie -> { 723 Log.e(TAG, "IWifi HAL service died! Have a listener for it ... cookie=" + cookie); 724 synchronized (mLock) { // prevents race condition with surrounding method 725 mWifi = null; 726 mIsReady = false; 727 teardownInternal(); 728 // don't restart: wait for registration notification 729 } 730 }; 731 732 /** 733 * Initialize IWifi and register death listener and event callback. 734 * 735 * - It is possible that IWifi is not ready - we have a listener on IServiceManager for it. 736 * - It is not expected that any of the registrations will fail. Possible indication that 737 * service died after we obtained a handle to it. 738 * 739 * Here and elsewhere we assume that death listener will do the right thing! 740 */ initIWifiIfNecessary()741 private void initIWifiIfNecessary() { 742 if (mDbg) Log.d(TAG, "initIWifiIfNecessary"); 743 744 synchronized (mLock) { 745 if (mWifi != null) { 746 return; 747 } 748 749 try { 750 mWifi = getWifiServiceMockable(); 751 if (mWifi == null) { 752 Log.e(TAG, "IWifi not (yet) available - but have a listener for it ..."); 753 return; 754 } 755 756 if (!mWifi.linkToDeath(mIWifiDeathRecipient, /* don't care */ 0)) { 757 Log.e(TAG, "Error on linkToDeath on IWifi - will retry later"); 758 return; 759 } 760 761 WifiStatus status = mWifi.registerEventCallback(mWifiEventCallback); 762 if (status.code != WifiStatusCode.SUCCESS) { 763 Log.e(TAG, "IWifi.registerEventCallback failed: " + statusString(status)); 764 mWifi = null; 765 return; 766 } 767 // Stopping wifi just in case. This would also trigger the status callback. 768 stopWifi(); 769 mIsReady = true; 770 } catch (RemoteException e) { 771 Log.e(TAG, "Exception while operating on IWifi: " + e); 772 } 773 } 774 } 775 776 /** 777 * Registers event listeners on all IWifiChips after a successful start: DEBUG only! 778 * 779 * We don't need the listeners since any callbacks are just confirmation of status codes we 780 * obtain directly from mode changes or interface creation/deletion. 781 * 782 * Relies (to the degree we care) on the service removing all listeners when Wi-Fi is stopped. 783 */ initIWifiChipDebugListeners()784 private void initIWifiChipDebugListeners() { 785 if (VDBG) Log.d(TAG, "initIWifiChipDebugListeners"); 786 787 if (!VDBG) { 788 return; 789 } 790 791 synchronized (mLock) { 792 try { 793 MutableBoolean statusOk = new MutableBoolean(false); 794 Mutable<ArrayList<Integer>> chipIdsResp = new Mutable<>(); 795 796 // get all chip IDs 797 mWifi.getChipIds((WifiStatus status, ArrayList<Integer> chipIds) -> { 798 statusOk.value = status.code == WifiStatusCode.SUCCESS; 799 if (statusOk.value) { 800 chipIdsResp.value = chipIds; 801 } else { 802 Log.e(TAG, "getChipIds failed: " + statusString(status)); 803 } 804 }); 805 if (!statusOk.value) { 806 return; 807 } 808 809 Log.d(TAG, "getChipIds=" + chipIdsResp.value); 810 if (chipIdsResp.value.size() == 0) { 811 Log.e(TAG, "Should have at least 1 chip!"); 812 return; 813 } 814 815 // register a callback for each chip 816 Mutable<IWifiChip> chipResp = new Mutable<>(); 817 for (Integer chipId: chipIdsResp.value) { 818 mWifi.getChip(chipId, (WifiStatus status, IWifiChip chip) -> { 819 statusOk.value = status.code == WifiStatusCode.SUCCESS; 820 if (statusOk.value) { 821 chipResp.value = chip; 822 } else { 823 Log.e(TAG, "getChip failed: " + statusString(status)); 824 } 825 }); 826 if (!statusOk.value) { 827 continue; // still try next one? 828 } 829 830 IWifiChipEventCallback.Stub callback = 831 new IWifiChipEventCallback.Stub() { 832 @Override 833 public void onChipReconfigured(int modeId) throws RemoteException { 834 Log.d(TAG, "onChipReconfigured: modeId=" + modeId); 835 } 836 837 @Override 838 public void onChipReconfigureFailure(WifiStatus status) 839 throws RemoteException { 840 Log.d(TAG, "onChipReconfigureFailure: status=" + statusString( 841 status)); 842 } 843 844 @Override 845 public void onIfaceAdded(int type, String name) 846 throws RemoteException { 847 Log.d(TAG, "onIfaceAdded: type=" + type + ", name=" + name); 848 } 849 850 @Override 851 public void onIfaceRemoved(int type, String name) 852 throws RemoteException { 853 Log.d(TAG, "onIfaceRemoved: type=" + type + ", name=" + name); 854 } 855 856 @Override 857 public void onDebugRingBufferDataAvailable( 858 WifiDebugRingBufferStatus status, 859 ArrayList<Byte> data) throws RemoteException { 860 Log.d(TAG, "onDebugRingBufferDataAvailable"); 861 } 862 863 @Override 864 public void onDebugErrorAlert(int errorCode, 865 ArrayList<Byte> debugData) 866 throws RemoteException { 867 Log.d(TAG, "onDebugErrorAlert"); 868 } 869 }; 870 mDebugCallbacks.put(chipId, callback); // store to prevent GC: needed by HIDL 871 WifiStatus status = chipResp.value.registerEventCallback(callback); 872 if (status.code != WifiStatusCode.SUCCESS) { 873 Log.e(TAG, "registerEventCallback failed: " + statusString(status)); 874 continue; // still try next one? 875 } 876 } 877 } catch (RemoteException e) { 878 Log.e(TAG, "initIWifiChipDebugListeners: exception: " + e); 879 return; 880 } 881 } 882 } 883 884 /** 885 * Get current information about all the chips in the system: modes, current mode (if any), and 886 * any existing interfaces. 887 * 888 * Intended to be called whenever we need to configure the chips - information is NOT cached (to 889 * reduce the likelihood that we get out-of-sync). 890 */ getAllChipInfo()891 private WifiChipInfo[] getAllChipInfo() { 892 if (VDBG) Log.d(TAG, "getAllChipInfo"); 893 894 synchronized (mLock) { 895 if (mWifi == null) { 896 Log.e(TAG, "getAllChipInfo: called but mWifi is null!?"); 897 return null; 898 } 899 900 try { 901 MutableBoolean statusOk = new MutableBoolean(false); 902 Mutable<ArrayList<Integer>> chipIdsResp = new Mutable<>(); 903 904 // get all chip IDs 905 mWifi.getChipIds((WifiStatus status, ArrayList<Integer> chipIds) -> { 906 statusOk.value = status.code == WifiStatusCode.SUCCESS; 907 if (statusOk.value) { 908 chipIdsResp.value = chipIds; 909 } else { 910 Log.e(TAG, "getChipIds failed: " + statusString(status)); 911 } 912 }); 913 if (!statusOk.value) { 914 return null; 915 } 916 917 if (VDBG) Log.d(TAG, "getChipIds=" + chipIdsResp.value); 918 if (chipIdsResp.value.size() == 0) { 919 Log.e(TAG, "Should have at least 1 chip!"); 920 return null; 921 } 922 923 int chipInfoIndex = 0; 924 WifiChipInfo[] chipsInfo = new WifiChipInfo[chipIdsResp.value.size()]; 925 926 Mutable<IWifiChip> chipResp = new Mutable<>(); 927 for (Integer chipId: chipIdsResp.value) { 928 mWifi.getChip(chipId, (WifiStatus status, IWifiChip chip) -> { 929 statusOk.value = status.code == WifiStatusCode.SUCCESS; 930 if (statusOk.value) { 931 chipResp.value = chip; 932 } else { 933 Log.e(TAG, "getChip failed: " + statusString(status)); 934 } 935 }); 936 if (!statusOk.value) { 937 return null; 938 } 939 940 Mutable<ArrayList<IWifiChip.ChipMode>> availableModesResp = new Mutable<>(); 941 chipResp.value.getAvailableModes( 942 (WifiStatus status, ArrayList<IWifiChip.ChipMode> modes) -> { 943 statusOk.value = status.code == WifiStatusCode.SUCCESS; 944 if (statusOk.value) { 945 availableModesResp.value = modes; 946 } else { 947 Log.e(TAG, "getAvailableModes failed: " + statusString(status)); 948 } 949 }); 950 if (!statusOk.value) { 951 return null; 952 } 953 954 MutableBoolean currentModeValidResp = new MutableBoolean(false); 955 MutableInt currentModeResp = new MutableInt(0); 956 chipResp.value.getMode((WifiStatus status, int modeId) -> { 957 statusOk.value = status.code == WifiStatusCode.SUCCESS; 958 if (statusOk.value) { 959 currentModeValidResp.value = true; 960 currentModeResp.value = modeId; 961 } else if (status.code == WifiStatusCode.ERROR_NOT_AVAILABLE) { 962 statusOk.value = true; // valid response 963 } else { 964 Log.e(TAG, "getMode failed: " + statusString(status)); 965 } 966 }); 967 if (!statusOk.value) { 968 return null; 969 } 970 971 Mutable<ArrayList<String>> ifaceNamesResp = new Mutable<>(); 972 MutableInt ifaceIndex = new MutableInt(0); 973 974 chipResp.value.getStaIfaceNames( 975 (WifiStatus status, ArrayList<String> ifnames) -> { 976 statusOk.value = status.code == WifiStatusCode.SUCCESS; 977 if (statusOk.value) { 978 ifaceNamesResp.value = ifnames; 979 } else { 980 Log.e(TAG, "getStaIfaceNames failed: " + statusString(status)); 981 } 982 }); 983 if (!statusOk.value) { 984 return null; 985 } 986 987 WifiIfaceInfo[] staIfaces = new WifiIfaceInfo[ifaceNamesResp.value.size()]; 988 for (String ifaceName: ifaceNamesResp.value) { 989 chipResp.value.getStaIface(ifaceName, 990 (WifiStatus status, IWifiStaIface iface) -> { 991 statusOk.value = status.code == WifiStatusCode.SUCCESS; 992 if (statusOk.value) { 993 WifiIfaceInfo ifaceInfo = new WifiIfaceInfo(); 994 ifaceInfo.name = ifaceName; 995 ifaceInfo.iface = iface; 996 staIfaces[ifaceIndex.value++] = ifaceInfo; 997 } else { 998 Log.e(TAG, "getStaIface failed: " + statusString(status)); 999 } 1000 }); 1001 if (!statusOk.value) { 1002 return null; 1003 } 1004 } 1005 1006 ifaceIndex.value = 0; 1007 chipResp.value.getApIfaceNames( 1008 (WifiStatus status, ArrayList<String> ifnames) -> { 1009 statusOk.value = status.code == WifiStatusCode.SUCCESS; 1010 if (statusOk.value) { 1011 ifaceNamesResp.value = ifnames; 1012 } else { 1013 Log.e(TAG, "getApIfaceNames failed: " + statusString(status)); 1014 } 1015 }); 1016 if (!statusOk.value) { 1017 return null; 1018 } 1019 1020 WifiIfaceInfo[] apIfaces = new WifiIfaceInfo[ifaceNamesResp.value.size()]; 1021 for (String ifaceName: ifaceNamesResp.value) { 1022 chipResp.value.getApIface(ifaceName, 1023 (WifiStatus status, IWifiApIface iface) -> { 1024 statusOk.value = status.code == WifiStatusCode.SUCCESS; 1025 if (statusOk.value) { 1026 WifiIfaceInfo ifaceInfo = new WifiIfaceInfo(); 1027 ifaceInfo.name = ifaceName; 1028 ifaceInfo.iface = iface; 1029 apIfaces[ifaceIndex.value++] = ifaceInfo; 1030 } else { 1031 Log.e(TAG, "getApIface failed: " + statusString(status)); 1032 } 1033 }); 1034 if (!statusOk.value) { 1035 return null; 1036 } 1037 } 1038 1039 ifaceIndex.value = 0; 1040 chipResp.value.getP2pIfaceNames( 1041 (WifiStatus status, ArrayList<String> ifnames) -> { 1042 statusOk.value = status.code == WifiStatusCode.SUCCESS; 1043 if (statusOk.value) { 1044 ifaceNamesResp.value = ifnames; 1045 } else { 1046 Log.e(TAG, "getP2pIfaceNames failed: " + statusString(status)); 1047 } 1048 }); 1049 if (!statusOk.value) { 1050 return null; 1051 } 1052 1053 WifiIfaceInfo[] p2pIfaces = new WifiIfaceInfo[ifaceNamesResp.value.size()]; 1054 for (String ifaceName: ifaceNamesResp.value) { 1055 chipResp.value.getP2pIface(ifaceName, 1056 (WifiStatus status, IWifiP2pIface iface) -> { 1057 statusOk.value = status.code == WifiStatusCode.SUCCESS; 1058 if (statusOk.value) { 1059 WifiIfaceInfo ifaceInfo = new WifiIfaceInfo(); 1060 ifaceInfo.name = ifaceName; 1061 ifaceInfo.iface = iface; 1062 p2pIfaces[ifaceIndex.value++] = ifaceInfo; 1063 } else { 1064 Log.e(TAG, "getP2pIface failed: " + statusString(status)); 1065 } 1066 }); 1067 if (!statusOk.value) { 1068 return null; 1069 } 1070 } 1071 1072 ifaceIndex.value = 0; 1073 chipResp.value.getNanIfaceNames( 1074 (WifiStatus status, ArrayList<String> ifnames) -> { 1075 statusOk.value = status.code == WifiStatusCode.SUCCESS; 1076 if (statusOk.value) { 1077 ifaceNamesResp.value = ifnames; 1078 } else { 1079 Log.e(TAG, "getNanIfaceNames failed: " + statusString(status)); 1080 } 1081 }); 1082 if (!statusOk.value) { 1083 return null; 1084 } 1085 1086 WifiIfaceInfo[] nanIfaces = new WifiIfaceInfo[ifaceNamesResp.value.size()]; 1087 for (String ifaceName: ifaceNamesResp.value) { 1088 chipResp.value.getNanIface(ifaceName, 1089 (WifiStatus status, IWifiNanIface iface) -> { 1090 statusOk.value = status.code == WifiStatusCode.SUCCESS; 1091 if (statusOk.value) { 1092 WifiIfaceInfo ifaceInfo = new WifiIfaceInfo(); 1093 ifaceInfo.name = ifaceName; 1094 ifaceInfo.iface = iface; 1095 nanIfaces[ifaceIndex.value++] = ifaceInfo; 1096 } else { 1097 Log.e(TAG, "getNanIface failed: " + statusString(status)); 1098 } 1099 }); 1100 if (!statusOk.value) { 1101 return null; 1102 } 1103 } 1104 1105 WifiChipInfo chipInfo = new WifiChipInfo(); 1106 chipsInfo[chipInfoIndex++] = chipInfo; 1107 1108 chipInfo.chip = chipResp.value; 1109 chipInfo.chipId = chipId; 1110 chipInfo.availableModes = availableModesResp.value; 1111 chipInfo.currentModeIdValid = currentModeValidResp.value; 1112 chipInfo.currentModeId = currentModeResp.value; 1113 chipInfo.ifaces[IfaceType.STA] = staIfaces; 1114 chipInfo.ifaces[IfaceType.AP] = apIfaces; 1115 chipInfo.ifaces[IfaceType.P2P] = p2pIfaces; 1116 chipInfo.ifaces[IfaceType.NAN] = nanIfaces; 1117 } 1118 1119 return chipsInfo; 1120 } catch (RemoteException e) { 1121 Log.e(TAG, "getAllChipInfoAndValidateCache exception: " + e); 1122 } 1123 } 1124 1125 return null; 1126 } 1127 1128 /** 1129 * Checks the local state of this object (the cached state) against the input 'chipInfos' 1130 * state (which is a live representation of the Wi-Fi firmware status - read through the HAL). 1131 * Returns 'true' if there are no discrepancies - 'false' otherwise. 1132 * 1133 * A discrepancy is if any local state contains references to a chip or interface which are not 1134 * found on the information read from the chip. 1135 */ validateInterfaceCache(WifiChipInfo[] chipInfos)1136 private boolean validateInterfaceCache(WifiChipInfo[] chipInfos) { 1137 if (VDBG) Log.d(TAG, "validateInterfaceCache"); 1138 1139 synchronized (mLock) { 1140 for (InterfaceCacheEntry entry: mInterfaceInfoCache.values()) { 1141 // search for chip 1142 WifiChipInfo matchingChipInfo = null; 1143 for (WifiChipInfo ci: chipInfos) { 1144 if (ci.chipId == entry.chipId) { 1145 matchingChipInfo = ci; 1146 break; 1147 } 1148 } 1149 if (matchingChipInfo == null) { 1150 Log.e(TAG, "validateInterfaceCache: no chip found for " + entry); 1151 return false; 1152 } 1153 1154 // search for interface 1155 WifiIfaceInfo[] ifaceInfoList = matchingChipInfo.ifaces[entry.type]; 1156 if (ifaceInfoList == null) { 1157 Log.e(TAG, "validateInterfaceCache: invalid type on entry " + entry); 1158 return false; 1159 } 1160 1161 boolean matchFound = false; 1162 for (WifiIfaceInfo ifaceInfo: ifaceInfoList) { 1163 if (ifaceInfo.name.equals(entry.name)) { 1164 matchFound = true; 1165 break; 1166 } 1167 } 1168 if (!matchFound) { 1169 Log.e(TAG, "validateInterfaceCache: no interface found for " + entry); 1170 return false; 1171 } 1172 } 1173 } 1174 1175 return true; 1176 } 1177 isWifiStarted()1178 private boolean isWifiStarted() { 1179 if (VDBG) Log.d(TAG, "isWifiStart"); 1180 1181 synchronized (mLock) { 1182 try { 1183 if (mWifi == null) { 1184 Log.w(TAG, "isWifiStarted called but mWifi is null!?"); 1185 return false; 1186 } else { 1187 return mWifi.isStarted(); 1188 } 1189 } catch (RemoteException e) { 1190 Log.e(TAG, "isWifiStarted exception: " + e); 1191 return false; 1192 } 1193 } 1194 } 1195 startWifi()1196 private boolean startWifi() { 1197 if (VDBG) Log.d(TAG, "startWifi"); 1198 initIWifiIfNecessary(); 1199 synchronized (mLock) { 1200 try { 1201 if (mWifi == null) { 1202 Log.w(TAG, "startWifi called but mWifi is null!?"); 1203 return false; 1204 } else { 1205 int triedCount = 0; 1206 while (triedCount <= START_HAL_RETRY_TIMES) { 1207 WifiStatus status = mWifi.start(); 1208 if (status.code == WifiStatusCode.SUCCESS) { 1209 initIWifiChipDebugListeners(); 1210 managerStatusListenerDispatch(); 1211 if (triedCount != 0) { 1212 Log.d(TAG, "start IWifi succeeded after trying " 1213 + triedCount + " times"); 1214 } 1215 return true; 1216 } else if (status.code == WifiStatusCode.ERROR_NOT_AVAILABLE) { 1217 // Should retry. Hal might still be stopping. 1218 Log.e(TAG, "Cannot start IWifi: " + statusString(status) 1219 + ", Retrying..."); 1220 try { 1221 Thread.sleep(START_HAL_RETRY_INTERVAL_MS); 1222 } catch (InterruptedException ignore) { 1223 // no-op 1224 } 1225 triedCount++; 1226 } else { 1227 // Should not retry on other failures. 1228 Log.e(TAG, "Cannot start IWifi: " + statusString(status)); 1229 return false; 1230 } 1231 } 1232 Log.e(TAG, "Cannot start IWifi after trying " + triedCount + " times"); 1233 return false; 1234 } 1235 } catch (RemoteException e) { 1236 Log.e(TAG, "startWifi exception: " + e); 1237 return false; 1238 } 1239 } 1240 } 1241 stopWifi()1242 private void stopWifi() { 1243 if (VDBG) Log.d(TAG, "stopWifi"); 1244 1245 synchronized (mLock) { 1246 try { 1247 if (mWifi == null) { 1248 Log.w(TAG, "stopWifi called but mWifi is null!?"); 1249 } else { 1250 WifiStatus status = mWifi.stop(); 1251 if (status.code != WifiStatusCode.SUCCESS) { 1252 Log.e(TAG, "Cannot stop IWifi: " + statusString(status)); 1253 } 1254 1255 // even on failure since WTF?? 1256 teardownInternal(); 1257 } 1258 } catch (RemoteException e) { 1259 Log.e(TAG, "stopWifi exception: " + e); 1260 } 1261 } 1262 } 1263 1264 private class WifiEventCallback extends IWifiEventCallback.Stub { 1265 @Override onStart()1266 public void onStart() throws RemoteException { 1267 if (VDBG) Log.d(TAG, "IWifiEventCallback.onStart"); 1268 // NOP: only happens in reaction to my calls - will handle directly 1269 } 1270 1271 @Override onStop()1272 public void onStop() throws RemoteException { 1273 if (VDBG) Log.d(TAG, "IWifiEventCallback.onStop"); 1274 // NOP: only happens in reaction to my calls - will handle directly 1275 } 1276 1277 @Override onFailure(WifiStatus status)1278 public void onFailure(WifiStatus status) throws RemoteException { 1279 Log.e(TAG, "IWifiEventCallback.onFailure: " + statusString(status)); 1280 teardownInternal(); 1281 1282 // No need to do anything else: listeners may (will) re-start Wi-Fi 1283 } 1284 } 1285 managerStatusListenerDispatch()1286 private void managerStatusListenerDispatch() { 1287 synchronized (mLock) { 1288 for (ManagerStatusListenerProxy cb : mManagerStatusListeners) { 1289 cb.trigger(); 1290 } 1291 } 1292 } 1293 1294 private class ManagerStatusListenerProxy extends 1295 ListenerProxy<ManagerStatusListener> { ManagerStatusListenerProxy(ManagerStatusListener statusListener, Handler handler)1296 ManagerStatusListenerProxy(ManagerStatusListener statusListener, Handler handler) { 1297 super(statusListener, handler, "ManagerStatusListenerProxy"); 1298 } 1299 1300 @Override action()1301 protected void action() { 1302 mListener.onStatusChanged(); 1303 } 1304 } 1305 getSupportedIfaceTypesInternal(IWifiChip chip)1306 Set<Integer> getSupportedIfaceTypesInternal(IWifiChip chip) { 1307 Set<Integer> results = new HashSet<>(); 1308 1309 WifiChipInfo[] chipInfos = getAllChipInfo(); 1310 if (chipInfos == null) { 1311 Log.e(TAG, "getSupportedIfaceTypesInternal: no chip info found"); 1312 return results; 1313 } 1314 1315 MutableInt chipIdIfProvided = new MutableInt(0); // NOT using 0 as a magic value 1316 if (chip != null) { 1317 MutableBoolean statusOk = new MutableBoolean(false); 1318 try { 1319 chip.getId((WifiStatus status, int id) -> { 1320 if (status.code == WifiStatusCode.SUCCESS) { 1321 chipIdIfProvided.value = id; 1322 statusOk.value = true; 1323 } else { 1324 Log.e(TAG, "getSupportedIfaceTypesInternal: IWifiChip.getId() error: " 1325 + statusString(status)); 1326 statusOk.value = false; 1327 } 1328 }); 1329 } catch (RemoteException e) { 1330 Log.e(TAG, "getSupportedIfaceTypesInternal IWifiChip.getId() exception: " + e); 1331 return results; 1332 } 1333 if (!statusOk.value) { 1334 return results; 1335 } 1336 } 1337 1338 for (WifiChipInfo wci: chipInfos) { 1339 if (chip != null && wci.chipId != chipIdIfProvided.value) { 1340 continue; 1341 } 1342 1343 for (IWifiChip.ChipMode cm: wci.availableModes) { 1344 for (IWifiChip.ChipIfaceCombination cic: cm.availableCombinations) { 1345 for (IWifiChip.ChipIfaceCombinationLimit cicl: cic.limits) { 1346 for (int type: cicl.types) { 1347 results.add(type); 1348 } 1349 } 1350 } 1351 } 1352 } 1353 1354 return results; 1355 } 1356 createIface(int ifaceType, boolean lowPriority, InterfaceDestroyedListener destroyedListener, Handler handler)1357 private IWifiIface createIface(int ifaceType, boolean lowPriority, 1358 InterfaceDestroyedListener destroyedListener, Handler handler) { 1359 if (mDbg) { 1360 Log.d(TAG, "createIface: ifaceType=" + ifaceType + ", lowPriority=" + lowPriority); 1361 } 1362 1363 synchronized (mLock) { 1364 WifiChipInfo[] chipInfos = getAllChipInfo(); 1365 if (chipInfos == null) { 1366 Log.e(TAG, "createIface: no chip info found"); 1367 stopWifi(); // major error: shutting down 1368 return null; 1369 } 1370 1371 if (!validateInterfaceCache(chipInfos)) { 1372 Log.e(TAG, "createIface: local cache is invalid!"); 1373 stopWifi(); // major error: shutting down 1374 return null; 1375 } 1376 1377 IWifiIface iface = createIfaceIfPossible(chipInfos, ifaceType, lowPriority, 1378 destroyedListener, handler); 1379 if (iface != null) { // means that some configuration has changed 1380 if (!dispatchAvailableForRequestListeners()) { 1381 return null; // catastrophic failure - shut down 1382 } 1383 } 1384 1385 return iface; 1386 } 1387 } 1388 createIfaceIfPossible(WifiChipInfo[] chipInfos, int ifaceType, boolean lowPriority, InterfaceDestroyedListener destroyedListener, Handler handler)1389 private IWifiIface createIfaceIfPossible(WifiChipInfo[] chipInfos, int ifaceType, 1390 boolean lowPriority, InterfaceDestroyedListener destroyedListener, Handler handler) { 1391 if (VDBG) { 1392 Log.d(TAG, "createIfaceIfPossible: chipInfos=" + Arrays.deepToString(chipInfos) 1393 + ", ifaceType=" + ifaceType + ", lowPriority=" + lowPriority); 1394 } 1395 synchronized (mLock) { 1396 IfaceCreationData bestIfaceCreationProposal = null; 1397 for (WifiChipInfo chipInfo: chipInfos) { 1398 for (IWifiChip.ChipMode chipMode: chipInfo.availableModes) { 1399 for (IWifiChip.ChipIfaceCombination chipIfaceCombo : chipMode 1400 .availableCombinations) { 1401 int[][] expandedIfaceCombos = expandIfaceCombos(chipIfaceCombo); 1402 if (VDBG) { 1403 Log.d(TAG, chipIfaceCombo + " expands to " 1404 + Arrays.deepToString(expandedIfaceCombos)); 1405 } 1406 1407 for (int[] expandedIfaceCombo: expandedIfaceCombos) { 1408 IfaceCreationData currentProposal = canIfaceComboSupportRequest( 1409 chipInfo, chipMode, expandedIfaceCombo, ifaceType, lowPriority); 1410 if (compareIfaceCreationData(currentProposal, 1411 bestIfaceCreationProposal)) { 1412 if (VDBG) Log.d(TAG, "new proposal accepted"); 1413 bestIfaceCreationProposal = currentProposal; 1414 } 1415 } 1416 } 1417 } 1418 } 1419 1420 if (bestIfaceCreationProposal != null) { 1421 IWifiIface iface = executeChipReconfiguration(bestIfaceCreationProposal, ifaceType); 1422 if (iface != null) { 1423 InterfaceCacheEntry cacheEntry = new InterfaceCacheEntry(); 1424 1425 cacheEntry.chip = bestIfaceCreationProposal.chipInfo.chip; 1426 cacheEntry.chipId = bestIfaceCreationProposal.chipInfo.chipId; 1427 cacheEntry.name = getName(iface); 1428 cacheEntry.type = ifaceType; 1429 if (destroyedListener != null) { 1430 cacheEntry.destroyedListeners.add( 1431 new InterfaceDestroyedListenerProxy( 1432 cacheEntry.name, destroyedListener, handler)); 1433 } 1434 cacheEntry.creationTime = mClock.getUptimeSinceBootMillis(); 1435 cacheEntry.isLowPriority = lowPriority; 1436 1437 if (mDbg) Log.d(TAG, "createIfaceIfPossible: added cacheEntry=" + cacheEntry); 1438 mInterfaceInfoCache.put( 1439 Pair.create(cacheEntry.name, cacheEntry.type), cacheEntry); 1440 return iface; 1441 } 1442 } 1443 } 1444 1445 return null; 1446 } 1447 1448 // similar to createIfaceIfPossible - but simpler code: not looking for best option just 1449 // for any option (so terminates on first one). isItPossibleToCreateIface(WifiChipInfo[] chipInfos, int ifaceType)1450 private boolean isItPossibleToCreateIface(WifiChipInfo[] chipInfos, int ifaceType) { 1451 if (VDBG) { 1452 Log.d(TAG, "isItPossibleToCreateIface: chipInfos=" + Arrays.deepToString(chipInfos) 1453 + ", ifaceType=" + ifaceType); 1454 } 1455 1456 for (WifiChipInfo chipInfo: chipInfos) { 1457 for (IWifiChip.ChipMode chipMode: chipInfo.availableModes) { 1458 for (IWifiChip.ChipIfaceCombination chipIfaceCombo : chipMode 1459 .availableCombinations) { 1460 int[][] expandedIfaceCombos = expandIfaceCombos(chipIfaceCombo); 1461 if (VDBG) { 1462 Log.d(TAG, chipIfaceCombo + " expands to " 1463 + Arrays.deepToString(expandedIfaceCombos)); 1464 } 1465 1466 for (int[] expandedIfaceCombo: expandedIfaceCombos) { 1467 if (canIfaceComboSupportRequest(chipInfo, chipMode, expandedIfaceCombo, 1468 ifaceType, false) != null) { 1469 return true; 1470 } 1471 } 1472 } 1473 } 1474 } 1475 1476 return false; 1477 } 1478 1479 /** 1480 * Expands (or provides an alternative representation) of the ChipIfaceCombination as all 1481 * possible combinations of interface. 1482 * 1483 * Returns [# of combinations][4 (IfaceType)] 1484 * 1485 * Note: there could be duplicates - allow (inefficient but ...). 1486 * TODO: optimize by using a Set as opposed to a []: will remove duplicates. Will need to 1487 * provide correct hashes. 1488 */ expandIfaceCombos(IWifiChip.ChipIfaceCombination chipIfaceCombo)1489 private int[][] expandIfaceCombos(IWifiChip.ChipIfaceCombination chipIfaceCombo) { 1490 int numOfCombos = 1; 1491 for (IWifiChip.ChipIfaceCombinationLimit limit: chipIfaceCombo.limits) { 1492 for (int i = 0; i < limit.maxIfaces; ++i) { 1493 numOfCombos *= limit.types.size(); 1494 } 1495 } 1496 1497 int[][] expandedIfaceCombos = new int[numOfCombos][IFACE_TYPES_BY_PRIORITY.length]; 1498 1499 int span = numOfCombos; // span of an individual type (or sub-tree size) 1500 for (IWifiChip.ChipIfaceCombinationLimit limit: chipIfaceCombo.limits) { 1501 for (int i = 0; i < limit.maxIfaces; ++i) { 1502 span /= limit.types.size(); 1503 for (int k = 0; k < numOfCombos; ++k) { 1504 expandedIfaceCombos[k][limit.types.get((k / span) % limit.types.size())]++; 1505 } 1506 } 1507 } 1508 1509 return expandedIfaceCombos; 1510 } 1511 1512 private class IfaceCreationData { 1513 public WifiChipInfo chipInfo; 1514 public int chipModeId; 1515 public List<WifiIfaceInfo> interfacesToBeRemovedFirst; 1516 1517 @Override toString()1518 public String toString() { 1519 StringBuilder sb = new StringBuilder(); 1520 sb.append("{chipInfo=").append(chipInfo).append(", chipModeId=").append(chipModeId) 1521 .append(", interfacesToBeRemovedFirst=").append(interfacesToBeRemovedFirst) 1522 .append(")"); 1523 return sb.toString(); 1524 } 1525 } 1526 1527 /** 1528 * Checks whether the input chip-iface-combo can support the requested interface type: if not 1529 * then returns null, if yes then returns information containing the list of interfaces which 1530 * would have to be removed first before the requested interface can be created. 1531 * 1532 * Note: the list of interfaces to be removed is EMPTY if a chip mode change is required - in 1533 * that case ALL the interfaces on the current chip have to be removed first. 1534 * 1535 * Response determined based on: 1536 * - Mode configuration: i.e. could the mode support the interface type in principle 1537 * - Priority information: i.e. are we 'allowed' to remove interfaces in order to create the 1538 * requested interface 1539 */ canIfaceComboSupportRequest(WifiChipInfo chipInfo, IWifiChip.ChipMode chipMode, int[] chipIfaceCombo, int ifaceType, boolean lowPriority)1540 private IfaceCreationData canIfaceComboSupportRequest(WifiChipInfo chipInfo, 1541 IWifiChip.ChipMode chipMode, int[] chipIfaceCombo, int ifaceType, boolean lowPriority) { 1542 if (VDBG) { 1543 Log.d(TAG, "canIfaceComboSupportRequest: chipInfo=" + chipInfo + ", chipMode=" 1544 + chipMode + ", chipIfaceCombo=" + chipIfaceCombo + ", ifaceType=" + ifaceType 1545 + ", lowPriority=" + lowPriority); 1546 } 1547 1548 // short-circuit: does the chipIfaceCombo even support the requested type? 1549 if (chipIfaceCombo[ifaceType] == 0) { 1550 if (VDBG) Log.d(TAG, "Requested type not supported by combo"); 1551 return null; 1552 } 1553 1554 boolean isChipModeChangeProposed = 1555 chipInfo.currentModeIdValid && chipInfo.currentModeId != chipMode.id; 1556 1557 // short-circuit: can't change chip-mode if an existing interface on this chip has a higher 1558 // priority than the requested interface 1559 if (isChipModeChangeProposed) { 1560 for (int type: IFACE_TYPES_BY_PRIORITY) { 1561 if (chipInfo.ifaces[type].length != 0) { 1562 if (lowPriority) { 1563 if (VDBG) { 1564 Log.d(TAG, "Couldn't delete existing type " + type 1565 + " interfaces for a low priority request"); 1566 } 1567 return null; 1568 } 1569 if (!allowedToDeleteIfaceTypeForRequestedType(type, ifaceType, 1570 chipInfo.ifaces, chipInfo.ifaces[type].length)) { 1571 if (VDBG) { 1572 Log.d(TAG, "Couldn't delete existing type " + type 1573 + " interfaces for requested type"); 1574 } 1575 return null; 1576 } 1577 } 1578 } 1579 1580 // but if priority allows the mode change then we're good to go 1581 IfaceCreationData ifaceCreationData = new IfaceCreationData(); 1582 ifaceCreationData.chipInfo = chipInfo; 1583 ifaceCreationData.chipModeId = chipMode.id; 1584 1585 return ifaceCreationData; 1586 } 1587 1588 // possibly supported 1589 List<WifiIfaceInfo> interfacesToBeRemovedFirst = new ArrayList<>(); 1590 1591 for (int type: IFACE_TYPES_BY_PRIORITY) { 1592 int tooManyInterfaces = chipInfo.ifaces[type].length - chipIfaceCombo[type]; 1593 1594 // need to count the requested interface as well 1595 if (type == ifaceType) { 1596 tooManyInterfaces += 1; 1597 } 1598 1599 if (tooManyInterfaces > 0) { // may need to delete some 1600 if (lowPriority) { 1601 if (VDBG) { 1602 Log.d(TAG, "Couldn't delete existing type " + type 1603 + " interfaces for a low priority request"); 1604 } 1605 return null; 1606 } 1607 1608 if (!allowedToDeleteIfaceTypeForRequestedType(type, ifaceType, chipInfo.ifaces, 1609 tooManyInterfaces)) { 1610 if (VDBG) { 1611 Log.d(TAG, "Would need to delete some higher priority interfaces"); 1612 } 1613 return null; 1614 } 1615 1616 // delete the most recently created interfaces or LOW priority interfaces 1617 interfacesToBeRemovedFirst = selectInterfacesToDelete(tooManyInterfaces, 1618 chipInfo.ifaces[type]); 1619 } 1620 } 1621 1622 IfaceCreationData ifaceCreationData = new IfaceCreationData(); 1623 ifaceCreationData.chipInfo = chipInfo; 1624 ifaceCreationData.chipModeId = chipMode.id; 1625 ifaceCreationData.interfacesToBeRemovedFirst = interfacesToBeRemovedFirst; 1626 1627 return ifaceCreationData; 1628 } 1629 1630 /** 1631 * Compares two options to create an interface and determines which is the 'best'. Returns 1632 * true if proposal 1 (val1) is better, other false. 1633 * 1634 * Note: both proposals are 'acceptable' bases on priority criteria. 1635 * 1636 * Criteria: 1637 * - Proposal is better if it means removing fewer high priority interfaces 1638 */ compareIfaceCreationData(IfaceCreationData val1, IfaceCreationData val2)1639 private boolean compareIfaceCreationData(IfaceCreationData val1, IfaceCreationData val2) { 1640 if (VDBG) Log.d(TAG, "compareIfaceCreationData: val1=" + val1 + ", val2=" + val2); 1641 1642 // deal with trivial case of one or the other being null 1643 if (val1 == null) { 1644 return false; 1645 } else if (val2 == null) { 1646 return true; 1647 } 1648 1649 for (int type: IFACE_TYPES_BY_PRIORITY) { 1650 // # of interfaces to be deleted: the list or all interfaces of the type if mode change 1651 int numIfacesToDelete1 = 0; 1652 if (val1.chipInfo.currentModeIdValid 1653 && val1.chipInfo.currentModeId != val1.chipModeId) { 1654 numIfacesToDelete1 = val1.chipInfo.ifaces[type].length; 1655 } else { 1656 numIfacesToDelete1 = val1.interfacesToBeRemovedFirst.size(); 1657 } 1658 1659 int numIfacesToDelete2 = 0; 1660 if (val2.chipInfo.currentModeIdValid 1661 && val2.chipInfo.currentModeId != val2.chipModeId) { 1662 numIfacesToDelete2 = val2.chipInfo.ifaces[type].length; 1663 } else { 1664 numIfacesToDelete2 = val2.interfacesToBeRemovedFirst.size(); 1665 } 1666 1667 if (numIfacesToDelete1 < numIfacesToDelete2) { 1668 if (VDBG) { 1669 Log.d(TAG, "decision based on type=" + type + ": " + numIfacesToDelete1 1670 + " < " + numIfacesToDelete2); 1671 } 1672 return true; 1673 } 1674 } 1675 1676 // arbitrary - flip a coin 1677 if (VDBG) Log.d(TAG, "proposals identical - flip a coin"); 1678 return false; 1679 } 1680 1681 /** 1682 * Returns true if we're allowed to delete the existing interface type for the requested 1683 * interface type. 1684 * 1685 * Rules - applies in order: 1686 * 1687 * General rules: 1688 * 1. No interface will be destroyed for a requested interface of the same type 1689 * 2. No interface will be destroyed if one of the requested interfaces already exists 1690 * 3. If there are >1 interface of an existing type, then it is ok to destroy that type 1691 * interface 1692 * 1693 * Type-specific rules (but note that the general rules are appied first): 1694 * 4. Request for AP or STA will destroy any other interface 1695 * 5. Request for P2P will destroy NAN-only (but will destroy a second STA per #3) 1696 * 6. Request for NAN will not destroy any interface (but will destroy a second STA per #3) 1697 * 1698 * Note: the 'numNecessaryInterfaces' is used to specify how many interfaces would be needed to 1699 * be deleted. This is used to determine whether there are that many low priority interfaces 1700 * of the requested type to delete. 1701 */ allowedToDeleteIfaceTypeForRequestedType(int existingIfaceType, int requestedIfaceType, WifiIfaceInfo[][] currentIfaces, int numNecessaryInterfaces)1702 private boolean allowedToDeleteIfaceTypeForRequestedType(int existingIfaceType, 1703 int requestedIfaceType, WifiIfaceInfo[][] currentIfaces, int numNecessaryInterfaces) { 1704 // rule 0: check for any low priority interfaces 1705 int numAvailableLowPriorityInterfaces = 0; 1706 for (InterfaceCacheEntry entry : mInterfaceInfoCache.values()) { 1707 if (entry.type == existingIfaceType && entry.isLowPriority) { 1708 numAvailableLowPriorityInterfaces++; 1709 } 1710 } 1711 if (numAvailableLowPriorityInterfaces >= numNecessaryInterfaces) { 1712 return true; 1713 } 1714 1715 // rule 1 1716 if (existingIfaceType == requestedIfaceType) { 1717 return false; 1718 } 1719 1720 // rule 2 1721 if (currentIfaces[requestedIfaceType].length != 0) { 1722 return false; 1723 } 1724 1725 // rule 3 1726 if (currentIfaces[existingIfaceType].length > 1) { 1727 return true; 1728 } 1729 1730 // rule 6 1731 if (requestedIfaceType == IfaceType.NAN) { 1732 return false; 1733 } 1734 1735 // rule 5 1736 if (requestedIfaceType == IfaceType.P2P) { 1737 return existingIfaceType == IfaceType.NAN; 1738 } 1739 1740 // rule 4, the requestIfaceType is either AP or STA 1741 return true; 1742 } 1743 1744 /** 1745 * Selects the interfaces to delete. 1746 * 1747 * Rule: select low priority interfaces and then other interfaces in order of creation time. 1748 * 1749 * @param excessInterfaces Number of interfaces which need to be selected. 1750 * @param interfaces Array of interfaces. 1751 */ selectInterfacesToDelete(int excessInterfaces, WifiIfaceInfo[] interfaces)1752 private List<WifiIfaceInfo> selectInterfacesToDelete(int excessInterfaces, 1753 WifiIfaceInfo[] interfaces) { 1754 if (VDBG) { 1755 Log.d(TAG, "selectInterfacesToDelete: excessInterfaces=" + excessInterfaces 1756 + ", interfaces=" + Arrays.toString(interfaces)); 1757 } 1758 1759 boolean lookupError = false; 1760 LongSparseArray<WifiIfaceInfo> orderedListLowPriority = new LongSparseArray<>(); 1761 LongSparseArray<WifiIfaceInfo> orderedList = new LongSparseArray<>(); 1762 for (WifiIfaceInfo info : interfaces) { 1763 InterfaceCacheEntry cacheEntry = mInterfaceInfoCache.get( 1764 Pair.create(info.name, getType(info.iface))); 1765 if (cacheEntry == null) { 1766 Log.e(TAG, 1767 "selectInterfacesToDelete: can't find cache entry with name=" + info.name); 1768 lookupError = true; 1769 break; 1770 } 1771 if (cacheEntry.isLowPriority) { 1772 orderedListLowPriority.append(cacheEntry.creationTime, info); 1773 } else { 1774 orderedList.append(cacheEntry.creationTime, info); 1775 } 1776 } 1777 1778 if (lookupError) { 1779 Log.e(TAG, "selectInterfacesToDelete: falling back to arbitrary selection"); 1780 return Arrays.asList(Arrays.copyOf(interfaces, excessInterfaces)); 1781 } else { 1782 List<WifiIfaceInfo> result = new ArrayList<>(excessInterfaces); 1783 for (int i = 0; i < excessInterfaces; ++i) { 1784 int lowPriorityNextIndex = orderedListLowPriority.size() - i - 1; 1785 if (lowPriorityNextIndex >= 0) { 1786 result.add(orderedListLowPriority.valueAt(lowPriorityNextIndex)); 1787 } else { 1788 result.add(orderedList.valueAt( 1789 orderedList.size() - i + orderedListLowPriority.size() - 1)); 1790 } 1791 } 1792 return result; 1793 } 1794 } 1795 1796 /** 1797 * Performs chip reconfiguration per the input: 1798 * - Removes the specified interfaces 1799 * - Reconfigures the chip to the new chip mode (if necessary) 1800 * - Creates the new interface 1801 * 1802 * Returns the newly created interface or a null on any error. 1803 */ executeChipReconfiguration(IfaceCreationData ifaceCreationData, int ifaceType)1804 private IWifiIface executeChipReconfiguration(IfaceCreationData ifaceCreationData, 1805 int ifaceType) { 1806 if (mDbg) { 1807 Log.d(TAG, "executeChipReconfiguration: ifaceCreationData=" + ifaceCreationData 1808 + ", ifaceType=" + ifaceType); 1809 } 1810 synchronized (mLock) { 1811 try { 1812 // is this a mode change? 1813 boolean isModeConfigNeeded = !ifaceCreationData.chipInfo.currentModeIdValid 1814 || ifaceCreationData.chipInfo.currentModeId != ifaceCreationData.chipModeId; 1815 if (mDbg) Log.d(TAG, "isModeConfigNeeded=" + isModeConfigNeeded); 1816 1817 // first delete interfaces/change modes 1818 if (isModeConfigNeeded) { 1819 // remove all interfaces pre mode-change 1820 // TODO: is this necessary? note that even if we don't want to explicitly 1821 // remove the interfaces we do need to call the onDeleted callbacks - which 1822 // this does 1823 for (WifiIfaceInfo[] ifaceInfos: ifaceCreationData.chipInfo.ifaces) { 1824 for (WifiIfaceInfo ifaceInfo: ifaceInfos) { 1825 removeIfaceInternal(ifaceInfo.iface); // ignore return value 1826 } 1827 } 1828 1829 WifiStatus status = ifaceCreationData.chipInfo.chip.configureChip( 1830 ifaceCreationData.chipModeId); 1831 updateRttControllerOnModeChange(); 1832 if (status.code != WifiStatusCode.SUCCESS) { 1833 Log.e(TAG, "executeChipReconfiguration: configureChip error: " 1834 + statusString(status)); 1835 return null; 1836 } 1837 } else { 1838 // remove all interfaces on the delete list 1839 for (WifiIfaceInfo ifaceInfo: ifaceCreationData.interfacesToBeRemovedFirst) { 1840 removeIfaceInternal(ifaceInfo.iface); // ignore return value 1841 } 1842 } 1843 1844 // create new interface 1845 Mutable<WifiStatus> statusResp = new Mutable<>(); 1846 Mutable<IWifiIface> ifaceResp = new Mutable<>(); 1847 switch (ifaceType) { 1848 case IfaceType.STA: 1849 ifaceCreationData.chipInfo.chip.createStaIface( 1850 (WifiStatus status, IWifiStaIface iface) -> { 1851 statusResp.value = status; 1852 ifaceResp.value = iface; 1853 }); 1854 break; 1855 case IfaceType.AP: 1856 ifaceCreationData.chipInfo.chip.createApIface( 1857 (WifiStatus status, IWifiApIface iface) -> { 1858 statusResp.value = status; 1859 ifaceResp.value = iface; 1860 }); 1861 break; 1862 case IfaceType.P2P: 1863 ifaceCreationData.chipInfo.chip.createP2pIface( 1864 (WifiStatus status, IWifiP2pIface iface) -> { 1865 statusResp.value = status; 1866 ifaceResp.value = iface; 1867 }); 1868 break; 1869 case IfaceType.NAN: 1870 ifaceCreationData.chipInfo.chip.createNanIface( 1871 (WifiStatus status, IWifiNanIface iface) -> { 1872 statusResp.value = status; 1873 ifaceResp.value = iface; 1874 }); 1875 break; 1876 } 1877 1878 if (statusResp.value.code != WifiStatusCode.SUCCESS) { 1879 Log.e(TAG, "executeChipReconfiguration: failed to create interface ifaceType=" 1880 + ifaceType + ": " + statusString(statusResp.value)); 1881 return null; 1882 } 1883 1884 return ifaceResp.value; 1885 } catch (RemoteException e) { 1886 Log.e(TAG, "executeChipReconfiguration exception: " + e); 1887 return null; 1888 } 1889 } 1890 } 1891 removeIfaceInternal(IWifiIface iface)1892 private boolean removeIfaceInternal(IWifiIface iface) { 1893 String name = getName(iface); 1894 int type = getType(iface); 1895 if (mDbg) Log.d(TAG, "removeIfaceInternal: iface(name)=" + name + ", type=" + type); 1896 1897 if (type == -1) { 1898 Log.e(TAG, "removeIfaceInternal: can't get type -- iface(name)=" + name); 1899 return false; 1900 } 1901 1902 synchronized (mLock) { 1903 if (mWifi == null) { 1904 Log.e(TAG, "removeIfaceInternal: null IWifi -- iface(name)=" + name); 1905 return false; 1906 } 1907 1908 IWifiChip chip = getChip(iface); 1909 if (chip == null) { 1910 Log.e(TAG, "removeIfaceInternal: null IWifiChip -- iface(name)=" + name); 1911 return false; 1912 } 1913 1914 if (name == null) { 1915 Log.e(TAG, "removeIfaceInternal: can't get name"); 1916 return false; 1917 } 1918 1919 WifiStatus status = null; 1920 try { 1921 switch (type) { 1922 case IfaceType.STA: 1923 status = chip.removeStaIface(name); 1924 break; 1925 case IfaceType.AP: 1926 status = chip.removeApIface(name); 1927 break; 1928 case IfaceType.P2P: 1929 status = chip.removeP2pIface(name); 1930 break; 1931 case IfaceType.NAN: 1932 status = chip.removeNanIface(name); 1933 break; 1934 default: 1935 Log.wtf(TAG, "removeIfaceInternal: invalid type=" + type); 1936 return false; 1937 } 1938 } catch (RemoteException e) { 1939 Log.e(TAG, "IWifiChip.removeXxxIface exception: " + e); 1940 } 1941 1942 // dispatch listeners no matter what status 1943 dispatchDestroyedListeners(name, type); 1944 1945 if (status != null && status.code == WifiStatusCode.SUCCESS) { 1946 return true; 1947 } else { 1948 Log.e(TAG, "IWifiChip.removeXxxIface failed: " + statusString(status)); 1949 return false; 1950 } 1951 } 1952 } 1953 1954 // dispatch all available for request listeners of the specified type AND clean-out the list: 1955 // listeners are called once at most! dispatchAvailableForRequestListeners()1956 private boolean dispatchAvailableForRequestListeners() { 1957 if (VDBG) Log.d(TAG, "dispatchAvailableForRequestListeners"); 1958 1959 synchronized (mLock) { 1960 WifiChipInfo[] chipInfos = getAllChipInfo(); 1961 if (chipInfos == null) { 1962 Log.e(TAG, "dispatchAvailableForRequestListeners: no chip info found"); 1963 stopWifi(); // major error: shutting down 1964 return false; 1965 } 1966 if (VDBG) { 1967 Log.d(TAG, "dispatchAvailableForRequestListeners: chipInfos=" 1968 + Arrays.deepToString(chipInfos)); 1969 } 1970 1971 for (int ifaceType : IFACE_TYPES_BY_PRIORITY) { 1972 dispatchAvailableForRequestListenersForType(ifaceType, chipInfos); 1973 } 1974 } 1975 1976 return true; 1977 } 1978 dispatchAvailableForRequestListenersForType(int ifaceType, WifiChipInfo[] chipInfos)1979 private void dispatchAvailableForRequestListenersForType(int ifaceType, 1980 WifiChipInfo[] chipInfos) { 1981 if (VDBG) Log.d(TAG, "dispatchAvailableForRequestListenersForType: ifaceType=" + ifaceType); 1982 1983 synchronized (mLock) { 1984 Map<InterfaceAvailableForRequestListenerProxy, Boolean> listeners = 1985 mInterfaceAvailableForRequestListeners.get(ifaceType); 1986 1987 if (listeners.size() == 0) { 1988 return; 1989 } 1990 1991 boolean isAvailable = isItPossibleToCreateIface(chipInfos, ifaceType); 1992 1993 if (VDBG) { 1994 Log.d(TAG, "Interface available for: ifaceType=" + ifaceType + " = " + isAvailable); 1995 } 1996 for (Map.Entry<InterfaceAvailableForRequestListenerProxy, Boolean> listenerEntry : 1997 listeners.entrySet()) { 1998 if (listenerEntry.getValue() == null || listenerEntry.getValue() != isAvailable) { 1999 if (VDBG) { 2000 Log.d(TAG, "Interface available listener dispatched: ifaceType=" + ifaceType 2001 + ", listener=" + listenerEntry.getKey()); 2002 } 2003 listenerEntry.getKey().triggerWithArg(isAvailable); 2004 } 2005 listenerEntry.setValue(isAvailable); 2006 } 2007 } 2008 } 2009 2010 // dispatch all destroyed listeners registered for the specified interface AND remove the 2011 // cache entry dispatchDestroyedListeners(String name, int type)2012 private void dispatchDestroyedListeners(String name, int type) { 2013 if (VDBG) Log.d(TAG, "dispatchDestroyedListeners: iface(name)=" + name); 2014 2015 synchronized (mLock) { 2016 InterfaceCacheEntry entry = mInterfaceInfoCache.get(Pair.create(name, type)); 2017 if (entry == null) { 2018 Log.e(TAG, "dispatchDestroyedListeners: no cache entry for iface(name)=" + name); 2019 return; 2020 } 2021 2022 for (InterfaceDestroyedListenerProxy listener : entry.destroyedListeners) { 2023 listener.trigger(); 2024 } 2025 entry.destroyedListeners.clear(); // for insurance (though cache entry is removed) 2026 mInterfaceInfoCache.remove(Pair.create(name, type)); 2027 } 2028 } 2029 2030 // dispatch all destroyed listeners registered to all interfaces dispatchAllDestroyedListeners()2031 private void dispatchAllDestroyedListeners() { 2032 if (VDBG) Log.d(TAG, "dispatchAllDestroyedListeners"); 2033 2034 synchronized (mLock) { 2035 Iterator<Map.Entry<Pair<String, Integer>, InterfaceCacheEntry>> it = 2036 mInterfaceInfoCache.entrySet().iterator(); 2037 while (it.hasNext()) { 2038 InterfaceCacheEntry entry = it.next().getValue(); 2039 for (InterfaceDestroyedListenerProxy listener : entry.destroyedListeners) { 2040 listener.trigger(); 2041 } 2042 entry.destroyedListeners.clear(); // for insurance (though cache entry is removed) 2043 it.remove(); 2044 } 2045 } 2046 } 2047 2048 private abstract class ListenerProxy<LISTENER> { 2049 protected LISTENER mListener; 2050 private Handler mHandler; 2051 2052 // override equals & hash to make sure that the container HashSet is unique with respect to 2053 // the contained listener 2054 @Override equals(Object obj)2055 public boolean equals(Object obj) { 2056 return mListener == ((ListenerProxy<LISTENER>) obj).mListener; 2057 } 2058 2059 @Override hashCode()2060 public int hashCode() { 2061 return mListener.hashCode(); 2062 } 2063 trigger()2064 void trigger() { 2065 if (mHandler != null) { 2066 mHandler.post(() -> { 2067 action(); 2068 }); 2069 } else { 2070 action(); 2071 } 2072 } 2073 triggerWithArg(boolean arg)2074 void triggerWithArg(boolean arg) { 2075 if (mHandler != null) { 2076 mHandler.post(() -> { 2077 actionWithArg(arg); 2078 }); 2079 } else { 2080 actionWithArg(arg); 2081 } 2082 } 2083 action()2084 protected void action() {} actionWithArg(boolean arg)2085 protected void actionWithArg(boolean arg) {} 2086 ListenerProxy(LISTENER listener, Handler handler, String tag)2087 ListenerProxy(LISTENER listener, Handler handler, String tag) { 2088 mListener = listener; 2089 mHandler = handler; 2090 } 2091 } 2092 2093 private class InterfaceDestroyedListenerProxy extends 2094 ListenerProxy<InterfaceDestroyedListener> { 2095 private final String mIfaceName; InterfaceDestroyedListenerProxy(@onNull String ifaceName, InterfaceDestroyedListener destroyedListener, Handler handler)2096 InterfaceDestroyedListenerProxy(@NonNull String ifaceName, 2097 InterfaceDestroyedListener destroyedListener, 2098 Handler handler) { 2099 super(destroyedListener, handler, "InterfaceDestroyedListenerProxy"); 2100 mIfaceName = ifaceName; 2101 } 2102 2103 @Override action()2104 protected void action() { 2105 mListener.onDestroyed(mIfaceName); 2106 } 2107 } 2108 2109 private class InterfaceAvailableForRequestListenerProxy extends 2110 ListenerProxy<InterfaceAvailableForRequestListener> { InterfaceAvailableForRequestListenerProxy( InterfaceAvailableForRequestListener destroyedListener, Handler handler)2111 InterfaceAvailableForRequestListenerProxy( 2112 InterfaceAvailableForRequestListener destroyedListener, Handler handler) { 2113 super(destroyedListener, handler, "InterfaceAvailableForRequestListenerProxy"); 2114 } 2115 2116 @Override actionWithArg(boolean isAvailable)2117 protected void actionWithArg(boolean isAvailable) { 2118 mListener.onAvailabilityChanged(isAvailable); 2119 } 2120 } 2121 2122 private class InterfaceRttControllerLifecycleCallbackProxy implements 2123 InterfaceRttControllerLifecycleCallback { 2124 private InterfaceRttControllerLifecycleCallback mCallback; 2125 private Handler mHandler; 2126 InterfaceRttControllerLifecycleCallbackProxy( InterfaceRttControllerLifecycleCallback callback, Handler handler)2127 InterfaceRttControllerLifecycleCallbackProxy( 2128 InterfaceRttControllerLifecycleCallback callback, Handler handler) { 2129 mCallback = callback; 2130 mHandler = handler; 2131 } 2132 2133 // override equals & hash to make sure that the container HashSet is unique with respect to 2134 // the contained listener 2135 @Override equals(Object obj)2136 public boolean equals(Object obj) { 2137 return mCallback == ((InterfaceRttControllerLifecycleCallbackProxy) obj).mCallback; 2138 } 2139 2140 @Override hashCode()2141 public int hashCode() { 2142 return mCallback.hashCode(); 2143 } 2144 2145 @Override onNewRttController(IWifiRttController controller)2146 public void onNewRttController(IWifiRttController controller) { 2147 mHandler.post(() -> mCallback.onNewRttController(controller)); 2148 } 2149 2150 @Override onRttControllerDestroyed()2151 public void onRttControllerDestroyed() { 2152 mHandler.post(() -> mCallback.onRttControllerDestroyed()); 2153 } 2154 } 2155 dispatchRttControllerLifecycleOnNew()2156 private void dispatchRttControllerLifecycleOnNew() { 2157 if (VDBG) { 2158 Log.v(TAG, "dispatchRttControllerLifecycleOnNew: # cbs=" 2159 + mRttControllerLifecycleCallbacks.size()); 2160 } 2161 for (InterfaceRttControllerLifecycleCallbackProxy cbp : mRttControllerLifecycleCallbacks) { 2162 cbp.onNewRttController(mIWifiRttController); 2163 } 2164 } 2165 dispatchRttControllerLifecycleOnDestroyed()2166 private void dispatchRttControllerLifecycleOnDestroyed() { 2167 for (InterfaceRttControllerLifecycleCallbackProxy cbp : mRttControllerLifecycleCallbacks) { 2168 cbp.onRttControllerDestroyed(); 2169 } 2170 } 2171 2172 2173 /** 2174 * Updates the RttController when the chip mode is changed: 2175 * - Handles callbacks to registered listeners 2176 * - Handles creation of new RttController 2177 */ updateRttControllerOnModeChange()2178 private void updateRttControllerOnModeChange() { 2179 synchronized (mLock) { 2180 boolean controllerDestroyed = mIWifiRttController != null; 2181 mIWifiRttController = null; 2182 if (mRttControllerLifecycleCallbacks.size() == 0) { 2183 Log.d(TAG, "updateRttController: no one is interested in RTT controllers"); 2184 return; 2185 } 2186 2187 IWifiRttController newRttController = createRttControllerIfPossible(); 2188 if (newRttController == null) { 2189 if (controllerDestroyed) { 2190 dispatchRttControllerLifecycleOnDestroyed(); 2191 } 2192 } else { 2193 mIWifiRttController = newRttController; 2194 dispatchRttControllerLifecycleOnNew(); 2195 } 2196 } 2197 } 2198 2199 /** 2200 * Try to create a new RttController. 2201 * 2202 * @return The new RttController - or null on failure. 2203 */ createRttControllerIfPossible()2204 private IWifiRttController createRttControllerIfPossible() { 2205 synchronized (mLock) { 2206 if (!isWifiStarted()) { 2207 Log.d(TAG, "createRttControllerIfPossible: Wifi is not started"); 2208 return null; 2209 } 2210 2211 WifiChipInfo[] chipInfos = getAllChipInfo(); 2212 if (chipInfos == null) { 2213 Log.d(TAG, "createRttControllerIfPossible: no chip info found - most likely chip " 2214 + "not up yet"); 2215 return null; 2216 } 2217 2218 for (WifiChipInfo chipInfo : chipInfos) { 2219 if (!chipInfo.currentModeIdValid) { 2220 if (VDBG) { 2221 Log.d(TAG, "createRttControllerIfPossible: chip not configured yet: " 2222 + chipInfo); 2223 } 2224 continue; 2225 } 2226 2227 Mutable<IWifiRttController> rttResp = new Mutable<>(); 2228 try { 2229 chipInfo.chip.createRttController(null, 2230 (WifiStatus status, IWifiRttController rtt) -> { 2231 if (status.code == WifiStatusCode.SUCCESS) { 2232 rttResp.value = rtt; 2233 } else { 2234 Log.e(TAG, "IWifiChip.createRttController failed: " 2235 + statusString(status)); 2236 } 2237 }); 2238 } catch (RemoteException e) { 2239 Log.e(TAG, "IWifiChip.createRttController exception: " + e); 2240 } 2241 if (rttResp.value != null) { 2242 return rttResp.value; 2243 } 2244 } 2245 } 2246 2247 Log.w(TAG, "createRttControllerIfPossible: not available from any of the chips"); 2248 return null; 2249 } 2250 2251 // general utilities 2252 statusString(WifiStatus status)2253 private static String statusString(WifiStatus status) { 2254 if (status == null) { 2255 return "status=null"; 2256 } 2257 StringBuilder sb = new StringBuilder(); 2258 sb.append(status.code).append(" (").append(status.description).append(")"); 2259 return sb.toString(); 2260 } 2261 2262 // Will return -1 for invalid results! Otherwise will return one of the 4 valid values. getType(IWifiIface iface)2263 private static int getType(IWifiIface iface) { 2264 MutableInt typeResp = new MutableInt(-1); 2265 try { 2266 iface.getType((WifiStatus status, int type) -> { 2267 if (status.code == WifiStatusCode.SUCCESS) { 2268 typeResp.value = type; 2269 } else { 2270 Log.e(TAG, "Error on getType: " + statusString(status)); 2271 } 2272 }); 2273 } catch (RemoteException e) { 2274 Log.e(TAG, "Exception on getType: " + e); 2275 } 2276 2277 return typeResp.value; 2278 } 2279 2280 /** 2281 * Dump the internal state of the class. 2282 */ dump(FileDescriptor fd, PrintWriter pw, String[] args)2283 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2284 pw.println("HalDeviceManager:"); 2285 pw.println(" mServiceManager: " + mServiceManager); 2286 pw.println(" mWifi: " + mWifi); 2287 pw.println(" mManagerStatusListeners: " + mManagerStatusListeners); 2288 pw.println(" mInterfaceAvailableForRequestListeners: " 2289 + mInterfaceAvailableForRequestListeners); 2290 pw.println(" mInterfaceInfoCache: " + mInterfaceInfoCache); 2291 } 2292 } 2293