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