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