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 Log.i(TAG, "onSubsystemRestart"); 1526 mEventHandler.post(() -> { 1527 Log.i(TAG, "IWifiEventCallback.onSubsystemRestart: " + statusString(status)); 1528 synchronized (mLock) { 1529 Log.i(TAG, "Attempting to invoke mSubsystemRestartListener"); 1530 for (SubsystemRestartListenerProxy cb : mSubsystemRestartListener) { 1531 Log.i(TAG, "Invoking mSubsystemRestartListener"); 1532 cb.action(); 1533 } 1534 } 1535 }); 1536 } 1537 } 1538 managerStatusListenerDispatch()1539 private void managerStatusListenerDispatch() { 1540 synchronized (mLock) { 1541 for (ManagerStatusListenerProxy cb : mManagerStatusListeners) { 1542 cb.trigger(); 1543 } 1544 } 1545 } 1546 1547 private class ManagerStatusListenerProxy extends 1548 ListenerProxy<ManagerStatusListener> { ManagerStatusListenerProxy(ManagerStatusListener statusListener, Handler handler)1549 ManagerStatusListenerProxy(ManagerStatusListener statusListener, Handler handler) { 1550 super(statusListener, handler, "ManagerStatusListenerProxy"); 1551 } 1552 1553 @Override action()1554 protected void action() { 1555 mListener.onStatusChanged(); 1556 } 1557 } 1558 getSupportedIfaceTypesInternal(IWifiChip chip)1559 private Set<Integer> getSupportedIfaceTypesInternal(IWifiChip chip) { 1560 Set<Integer> results = new HashSet<>(); 1561 1562 WifiChipInfo[] chipInfos = getAllChipInfoCached(); 1563 if (chipInfos == null) { 1564 Log.e(TAG, "getSupportedIfaceTypesInternal: no chip info found"); 1565 return results; 1566 } 1567 1568 Mutable<Integer> chipIdIfProvided = new Mutable<>(0); // NOT using 0 as a magic value 1569 if (chip != null) { 1570 Mutable<Boolean> statusOk = new Mutable<>(false); 1571 try { 1572 chip.getId((WifiStatus status, int id) -> { 1573 if (status.code == WifiStatusCode.SUCCESS) { 1574 chipIdIfProvided.value = id; 1575 statusOk.value = true; 1576 } else { 1577 Log.e(TAG, "getSupportedIfaceTypesInternal: IWifiChip.getId() error: " 1578 + statusString(status)); 1579 statusOk.value = false; 1580 } 1581 }); 1582 } catch (RemoteException e) { 1583 Log.e(TAG, "getSupportedIfaceTypesInternal IWifiChip.getId() exception: " + e); 1584 return results; 1585 } 1586 if (!statusOk.value) { 1587 return results; 1588 } 1589 } 1590 1591 for (WifiChipInfo wci: chipInfos) { 1592 if (chip != null && wci.chipId != chipIdIfProvided.value) { 1593 continue; 1594 } 1595 1596 for (IWifiChip.ChipMode cm: wci.availableModes) { 1597 for (IWifiChip.ChipIfaceCombination cic: cm.availableCombinations) { 1598 for (IWifiChip.ChipIfaceCombinationLimit cicl: cic.limits) { 1599 for (int type: cicl.types) { 1600 results.add(type); 1601 } 1602 } 1603 } 1604 } 1605 } 1606 1607 return results; 1608 } 1609 createIface(@dmIfaceTypeForCreation int createIfaceType, long requiredChipCapabilities, InterfaceDestroyedListener destroyedListener, Handler handler, WorkSource requestorWs)1610 private IWifiIface createIface(@HdmIfaceTypeForCreation int createIfaceType, 1611 long requiredChipCapabilities, InterfaceDestroyedListener destroyedListener, 1612 Handler handler, WorkSource requestorWs) { 1613 if (mDbg) { 1614 Log.d(TAG, "createIface: createIfaceType=" + createIfaceType 1615 + ", requiredChipCapabilities=" + requiredChipCapabilities 1616 + ", requestorWs=" + requestorWs); 1617 } 1618 1619 synchronized (mLock) { 1620 WifiChipInfo[] chipInfos = getAllChipInfo(); 1621 if (chipInfos == null) { 1622 Log.e(TAG, "createIface: no chip info found"); 1623 stopWifi(); // major error: shutting down 1624 return null; 1625 } 1626 1627 if (!validateInterfaceCacheAndRetrieveRequestorWs(chipInfos)) { 1628 Log.e(TAG, "createIface: local cache is invalid!"); 1629 stopWifi(); // major error: shutting down 1630 return null; 1631 } 1632 1633 return createIfaceIfPossible( 1634 chipInfos, createIfaceType, requiredChipCapabilities, 1635 destroyedListener, handler, requestorWs); 1636 } 1637 } 1638 isChipCapabilitiesSupported(@onNull WifiChipInfo chipInfo, long requiredChipCapabilities)1639 private static boolean isChipCapabilitiesSupported(@NonNull WifiChipInfo chipInfo, 1640 long requiredChipCapabilities) { 1641 if (chipInfo == null) return false; 1642 1643 if (requiredChipCapabilities == CHIP_CAPABILITY_ANY) return true; 1644 1645 if (CHIP_CAPABILITY_UNINITIALIZED == chipInfo.chipCapabilities) return true; 1646 1647 return (chipInfo.chipCapabilities & requiredChipCapabilities) 1648 == requiredChipCapabilities; 1649 } 1650 createIfaceIfPossible( WifiChipInfo[] chipInfos, @HdmIfaceTypeForCreation int createIfaceType, long requiredChipCapabilities, InterfaceDestroyedListener destroyedListener, Handler handler, WorkSource requestorWs)1651 private IWifiIface createIfaceIfPossible( 1652 WifiChipInfo[] chipInfos, @HdmIfaceTypeForCreation int createIfaceType, 1653 long requiredChipCapabilities, InterfaceDestroyedListener destroyedListener, 1654 Handler handler, WorkSource requestorWs) { 1655 int targetHalIfaceType = mHalIfaceMap.get(createIfaceType); 1656 if (VDBG) { 1657 Log.d(TAG, "createIfaceIfPossible: chipInfos=" + Arrays.deepToString(chipInfos) 1658 + ", createIfaceType=" + createIfaceType 1659 + ", targetHalIfaceType=" + targetHalIfaceType 1660 + ", requiredChipCapabilities=" + requiredChipCapabilities 1661 + ", requestorWs=" + requestorWs); 1662 } 1663 synchronized (mLock) { 1664 IfaceCreationData bestIfaceCreationProposal = null; 1665 for (WifiChipInfo chipInfo: chipInfos) { 1666 if (!isChipCapabilitiesSupported(chipInfo, requiredChipCapabilities)) continue; 1667 for (IWifiChip.ChipMode chipMode: chipInfo.availableModes) { 1668 for (IWifiChip.ChipIfaceCombination chipIfaceCombo : chipMode 1669 .availableCombinations) { 1670 int[][] expandedIfaceCombos = expandIfaceCombos(chipIfaceCombo); 1671 if (VDBG) { 1672 Log.d(TAG, chipIfaceCombo + " expands to " 1673 + Arrays.deepToString(expandedIfaceCombos)); 1674 } 1675 1676 for (int[] expandedIfaceCombo: expandedIfaceCombos) { 1677 IfaceCreationData currentProposal = canIfaceComboSupportRequest( 1678 chipInfo, chipMode, expandedIfaceCombo, targetHalIfaceType, 1679 requestorWs); 1680 if (compareIfaceCreationData(currentProposal, 1681 bestIfaceCreationProposal)) { 1682 if (VDBG) Log.d(TAG, "new proposal accepted"); 1683 bestIfaceCreationProposal = currentProposal; 1684 } 1685 } 1686 } 1687 } 1688 } 1689 1690 if (bestIfaceCreationProposal != null) { 1691 IWifiIface iface = executeChipReconfiguration(bestIfaceCreationProposal, 1692 createIfaceType); 1693 if (iface != null) { 1694 InterfaceCacheEntry cacheEntry = new InterfaceCacheEntry(); 1695 1696 cacheEntry.chip = bestIfaceCreationProposal.chipInfo.chip; 1697 cacheEntry.chipId = bestIfaceCreationProposal.chipInfo.chipId; 1698 cacheEntry.name = getName(iface); 1699 cacheEntry.type = targetHalIfaceType; 1700 cacheEntry.requestorWsHelper = mWifiInjector.makeWsHelper(requestorWs); 1701 if (destroyedListener != null) { 1702 cacheEntry.destroyedListeners.add( 1703 new InterfaceDestroyedListenerProxy( 1704 cacheEntry.name, destroyedListener, handler)); 1705 } 1706 cacheEntry.creationTime = mClock.getUptimeSinceBootMillis(); 1707 1708 if (mDbg) Log.d(TAG, "createIfaceIfPossible: added cacheEntry=" + cacheEntry); 1709 mInterfaceInfoCache.put( 1710 Pair.create(cacheEntry.name, cacheEntry.type), cacheEntry); 1711 return iface; 1712 } 1713 } 1714 } 1715 1716 Log.d(TAG, "createIfaceIfPossible: Failed to create iface for ifaceType=" + createIfaceType 1717 + ", requestorWs=" + requestorWs); 1718 return null; 1719 } 1720 1721 // similar to createIfaceIfPossible - but simpler code: not looking for best option just 1722 // for any option (so terminates on first one). isItPossibleToCreateIface(WifiChipInfo[] chipInfos, int ifaceType, long requiredChipCapabilities, WorkSource requestorWs)1723 private boolean isItPossibleToCreateIface(WifiChipInfo[] chipInfos, 1724 int ifaceType, long requiredChipCapabilities, 1725 WorkSource requestorWs) { 1726 if (VDBG) { 1727 Log.d(TAG, "isItPossibleToCreateIface: chipInfos=" + Arrays.deepToString(chipInfos) 1728 + ", ifaceType=" + ifaceType 1729 + ", requiredChipCapabilities=" + requiredChipCapabilities); 1730 } 1731 1732 for (WifiChipInfo chipInfo: chipInfos) { 1733 if (!isChipCapabilitiesSupported(chipInfo, requiredChipCapabilities)) continue; 1734 for (IWifiChip.ChipMode chipMode: chipInfo.availableModes) { 1735 for (IWifiChip.ChipIfaceCombination chipIfaceCombo : chipMode 1736 .availableCombinations) { 1737 int[][] expandedIfaceCombos = expandIfaceCombos(chipIfaceCombo); 1738 if (VDBG) { 1739 Log.d(TAG, chipIfaceCombo + " expands to " 1740 + Arrays.deepToString(expandedIfaceCombos)); 1741 } 1742 1743 for (int[] expandedIfaceCombo: expandedIfaceCombos) { 1744 if (canIfaceComboSupportRequest(chipInfo, chipMode, expandedIfaceCombo, 1745 ifaceType, requestorWs) != null) { 1746 return true; 1747 } 1748 } 1749 } 1750 } 1751 } 1752 1753 return false; 1754 } 1755 1756 /** 1757 * Expands (or provides an alternative representation) of the ChipIfaceCombination as all 1758 * possible combinations of interface. 1759 * 1760 * Returns [# of combinations][4 (IfaceType)] 1761 * 1762 * Note: there could be duplicates - allow (inefficient but ...). 1763 * TODO: optimize by using a Set as opposed to a []: will remove duplicates. Will need to 1764 * provide correct hashes. 1765 */ expandIfaceCombos(IWifiChip.ChipIfaceCombination chipIfaceCombo)1766 private int[][] expandIfaceCombos(IWifiChip.ChipIfaceCombination chipIfaceCombo) { 1767 int numOfCombos = 1; 1768 for (IWifiChip.ChipIfaceCombinationLimit limit: chipIfaceCombo.limits) { 1769 for (int i = 0; i < limit.maxIfaces; ++i) { 1770 numOfCombos *= limit.types.size(); 1771 } 1772 } 1773 1774 int[][] expandedIfaceCombos = new int[numOfCombos][IFACE_TYPES_BY_PRIORITY.length]; 1775 1776 int span = numOfCombos; // span of an individual type (or sub-tree size) 1777 for (IWifiChip.ChipIfaceCombinationLimit limit: chipIfaceCombo.limits) { 1778 for (int i = 0; i < limit.maxIfaces; ++i) { 1779 span /= limit.types.size(); 1780 for (int k = 0; k < numOfCombos; ++k) { 1781 expandedIfaceCombos[k][limit.types.get((k / span) % limit.types.size())]++; 1782 } 1783 } 1784 } 1785 1786 return expandedIfaceCombos; 1787 } 1788 1789 private class IfaceCreationData { 1790 public WifiChipInfo chipInfo; 1791 public int chipModeId; 1792 public List<WifiIfaceInfo> interfacesToBeRemovedFirst; 1793 1794 @Override toString()1795 public String toString() { 1796 StringBuilder sb = new StringBuilder(); 1797 sb.append("{chipInfo=").append(chipInfo).append(", chipModeId=").append(chipModeId) 1798 .append(", interfacesToBeRemovedFirst=").append(interfacesToBeRemovedFirst) 1799 .append(")"); 1800 return sb.toString(); 1801 } 1802 } 1803 1804 /** 1805 * Checks whether the input chip-iface-combo can support the requested interface type: if not 1806 * then returns null, if yes then returns information containing the list of interfaces which 1807 * would have to be removed first before the requested interface can be created. 1808 * 1809 * Note: the list of interfaces to be removed is EMPTY if a chip mode change is required - in 1810 * that case ALL the interfaces on the current chip have to be removed first. 1811 * 1812 * Response determined based on: 1813 * - Mode configuration: i.e. could the mode support the interface type in principle 1814 */ canIfaceComboSupportRequest(WifiChipInfo chipInfo, IWifiChip.ChipMode chipMode, int[] chipIfaceCombo, int ifaceType, WorkSource requestorWs)1815 private IfaceCreationData canIfaceComboSupportRequest(WifiChipInfo chipInfo, 1816 IWifiChip.ChipMode chipMode, int[] chipIfaceCombo, int ifaceType, 1817 WorkSource requestorWs) { 1818 if (VDBG) { 1819 Log.d(TAG, "canIfaceComboSupportRequest: chipInfo=" + chipInfo + ", chipMode=" 1820 + chipMode + ", chipIfaceCombo=" + Arrays.toString(chipIfaceCombo) 1821 + ", ifaceType=" + ifaceType + ", requestorWs=" + requestorWs); 1822 } 1823 1824 // short-circuit: does the chipIfaceCombo even support the requested type? 1825 if (chipIfaceCombo[ifaceType] == 0) { 1826 if (VDBG) Log.d(TAG, "Requested type not supported by combo"); 1827 return null; 1828 } 1829 1830 boolean isChipModeChangeProposed = 1831 chipInfo.currentModeIdValid && chipInfo.currentModeId != chipMode.id; 1832 1833 // short-circuit: can't change chip-mode if an existing interface on this chip has a higher 1834 // priority than the requested interface 1835 if (isChipModeChangeProposed) { 1836 for (int type: IFACE_TYPES_BY_PRIORITY) { 1837 if (chipInfo.ifaces[type].length != 0) { 1838 if (!allowedToDeleteIfaceTypeForRequestedType( 1839 ifaceType, requestorWs, type, chipInfo.ifaces)) { 1840 if (VDBG) { 1841 Log.d(TAG, "Couldn't delete existing type " + type 1842 + " interfaces for requested type"); 1843 } 1844 return null; 1845 } 1846 } 1847 } 1848 1849 // but if priority allows the mode change then we're good to go 1850 IfaceCreationData ifaceCreationData = new IfaceCreationData(); 1851 ifaceCreationData.chipInfo = chipInfo; 1852 ifaceCreationData.chipModeId = chipMode.id; 1853 1854 return ifaceCreationData; 1855 } 1856 1857 // possibly supported 1858 List<WifiIfaceInfo> interfacesToBeRemovedFirst = new ArrayList<>(); 1859 1860 for (int type: IFACE_TYPES_BY_PRIORITY) { 1861 int tooManyInterfaces = chipInfo.ifaces[type].length - chipIfaceCombo[type]; 1862 1863 // need to count the requested interface as well 1864 if (type == ifaceType) { 1865 tooManyInterfaces += 1; 1866 } 1867 1868 if (tooManyInterfaces > 0) { // may need to delete some 1869 if (!allowedToDeleteIfaceTypeForRequestedType( 1870 ifaceType, requestorWs, type, chipInfo.ifaces)) { 1871 if (VDBG) { 1872 Log.d(TAG, "Would need to delete some higher priority interfaces"); 1873 } 1874 return null; 1875 } 1876 1877 // delete the most recently created interfaces 1878 interfacesToBeRemovedFirst.addAll(selectInterfacesToDelete(tooManyInterfaces, 1879 ifaceType, requestorWs, type, chipInfo.ifaces[type])); 1880 } 1881 } 1882 1883 IfaceCreationData ifaceCreationData = new IfaceCreationData(); 1884 ifaceCreationData.chipInfo = chipInfo; 1885 ifaceCreationData.chipModeId = chipMode.id; 1886 ifaceCreationData.interfacesToBeRemovedFirst = interfacesToBeRemovedFirst; 1887 1888 return ifaceCreationData; 1889 } 1890 1891 /** 1892 * Compares two options to create an interface and determines which is the 'best'. Returns 1893 * true if proposal 1 (val1) is better, other false. 1894 * 1895 * Note: both proposals are 'acceptable' bases on priority criteria. 1896 * 1897 * Criteria: 1898 * - Proposal is better if it means removing fewer high priority interfaces 1899 */ compareIfaceCreationData(IfaceCreationData val1, IfaceCreationData val2)1900 private boolean compareIfaceCreationData(IfaceCreationData val1, IfaceCreationData val2) { 1901 if (VDBG) Log.d(TAG, "compareIfaceCreationData: val1=" + val1 + ", val2=" + val2); 1902 1903 // deal with trivial case of one or the other being null 1904 if (val1 == null) { 1905 return false; 1906 } else if (val2 == null) { 1907 return true; 1908 } 1909 1910 for (int type: IFACE_TYPES_BY_PRIORITY) { 1911 // # of interfaces to be deleted: the list or all interfaces of the type if mode change 1912 int numIfacesToDelete1 = 0; 1913 if (val1.chipInfo.currentModeIdValid 1914 && val1.chipInfo.currentModeId != val1.chipModeId) { 1915 numIfacesToDelete1 = val1.chipInfo.ifaces[type].length; 1916 } else { 1917 numIfacesToDelete1 = val1.interfacesToBeRemovedFirst.size(); 1918 } 1919 1920 int numIfacesToDelete2 = 0; 1921 if (val2.chipInfo.currentModeIdValid 1922 && val2.chipInfo.currentModeId != val2.chipModeId) { 1923 numIfacesToDelete2 = val2.chipInfo.ifaces[type].length; 1924 } else { 1925 numIfacesToDelete2 = val2.interfacesToBeRemovedFirst.size(); 1926 } 1927 1928 if (numIfacesToDelete1 < numIfacesToDelete2) { 1929 if (VDBG) { 1930 Log.d(TAG, "decision based on type=" + type + ": " + numIfacesToDelete1 1931 + " < " + numIfacesToDelete2); 1932 } 1933 return true; 1934 } 1935 } 1936 1937 // arbitrary - flip a coin 1938 if (VDBG) Log.d(TAG, "proposals identical - flip a coin"); 1939 return false; 1940 } 1941 1942 private static final int PRIORITY_PRIVILEGED = 0; 1943 private static final int PRIORITY_SYSTEM = 1; 1944 private static final int PRIORITY_FG_APP = 2; 1945 private static final int PRIORITY_FG_SERVICE = 3; 1946 private static final int PRIORITY_BG = 4; 1947 private static final int PRIORITY_INTERNAL = 5; 1948 // Keep these in sync with any additions/deletions to above buckets. 1949 private static final int PRIORITY_MIN = PRIORITY_PRIVILEGED; 1950 private static final int PRIORITY_MAX = PRIORITY_INTERNAL; 1951 @IntDef(prefix = { "PRIORITY_" }, value = { 1952 PRIORITY_PRIVILEGED, 1953 PRIORITY_SYSTEM, 1954 PRIORITY_FG_APP, 1955 PRIORITY_FG_SERVICE, 1956 PRIORITY_BG, 1957 PRIORITY_INTERNAL, 1958 }) 1959 @Retention(RetentionPolicy.SOURCE) 1960 public @interface RequestorWsPriority {} 1961 1962 /** 1963 * Returns integer priority level for the provided |ws| based on rules mentioned in 1964 * {@link #allowedToDeleteIfaceTypeForRequestedType(int, WorkSource, int, WifiIfaceInfo[][])}. 1965 */ getRequestorWsPriority(WorkSourceHelper ws)1966 private static @RequestorWsPriority int getRequestorWsPriority(WorkSourceHelper ws) { 1967 if (ws.hasAnyPrivilegedAppRequest()) return PRIORITY_PRIVILEGED; 1968 if (ws.hasAnySystemAppRequest()) return PRIORITY_SYSTEM; 1969 if (ws.hasAnyForegroundAppRequest()) return PRIORITY_FG_APP; 1970 if (ws.hasAnyForegroundServiceRequest()) return PRIORITY_FG_SERVICE; 1971 if (ws.hasAnyInternalRequest()) return PRIORITY_INTERNAL; 1972 return PRIORITY_BG; 1973 } 1974 1975 /** 1976 * Returns whether interface request from |newRequestorWsPriority| is allowed to delete an 1977 * interface request from |existingRequestorWsPriority|. 1978 * 1979 * Rule: 1980 * - If |newRequestorWsPriority| < |existingRequestorWsPriority|, then YES. 1981 * - If they are at the same priority level, then 1982 * - If both are privileged and not for the same interface type, then YES. 1983 * - Else, NO. 1984 */ allowedToDelete( int requestedIfaceType, @RequestorWsPriority int newRequestorWsPriority, int existingIfaceType, @RequestorWsPriority int existingRequestorWsPriority)1985 private static boolean allowedToDelete( 1986 int requestedIfaceType, @RequestorWsPriority int newRequestorWsPriority, 1987 int existingIfaceType, @RequestorWsPriority int existingRequestorWsPriority) { 1988 if (!SdkLevel.isAtLeastS()) { 1989 return allowedToDeleteForR(requestedIfaceType, existingIfaceType); 1990 } 1991 // If the new request is higher priority than existing priority, then the new requestor 1992 // wins. This is because at all other priority levels (except privileged), existing caller 1993 // wins if both the requests are at the same priority level. 1994 if (newRequestorWsPriority < existingRequestorWsPriority) { 1995 return true; 1996 } 1997 if (newRequestorWsPriority == existingRequestorWsPriority) { 1998 // If both the requests are same priority for the same iface type, the existing 1999 // requestor wins. 2000 if (requestedIfaceType == existingIfaceType) { 2001 return false; 2002 } 2003 // If both the requests are privileged, the new requestor wins. 2004 if (newRequestorWsPriority == PRIORITY_PRIVILEGED) { 2005 return true; 2006 } 2007 } 2008 return false; 2009 } 2010 2011 /** 2012 * Returns true if we're allowed to delete the existing interface type for the requested 2013 * interface type. 2014 * 2015 * Rules - applies in order: 2016 * 2017 * General rules: 2018 * 1. No interface will be destroyed for a requested interface of the same type 2019 * 2020 * Type-specific rules (but note that the general rules are applied first): 2021 * 2. Request for AP or STA will destroy any other interface 2022 * 3. Request for P2P will destroy NAN-only 2023 * 4. Request for NAN will destroy P2P-only 2024 */ allowedToDeleteForR(int requestedIfaceType, int existingIfaceType)2025 private static boolean allowedToDeleteForR(int requestedIfaceType, int existingIfaceType) { 2026 // rule 1 2027 if (existingIfaceType == requestedIfaceType) { 2028 return false; 2029 } 2030 2031 // rule 2 2032 if (requestedIfaceType == IfaceType.P2P) { 2033 return existingIfaceType == IfaceType.NAN; 2034 } 2035 2036 // rule 3 2037 if (requestedIfaceType == IfaceType.NAN) { 2038 return existingIfaceType == IfaceType.P2P; 2039 } 2040 2041 // rule 4, the requestIfaceType is either AP or STA 2042 return true; 2043 } 2044 2045 /** 2046 * Returns true if we're allowed to delete the existing interface type for the requested 2047 * interface type. 2048 * 2049 * General rules: 2050 * 1. Requests for interfaces have the following priority which are based on corresponding 2051 * requesting app's context. Priorities in decreasing order (i.e (i) has the highest priority, 2052 * (v) has the lowest priority). 2053 * - (i) Requests from privileged apps (i.e settings, setup wizard, connectivity stack, etc) 2054 * - (ii) Requests from system apps. 2055 * - (iii) Requests from foreground apps. 2056 * - (iv) Requests from foreground services. 2057 * - (v) Requests from everything else (lumped together as "background"). 2058 * Note: If there are more than 1 app requesting for a particular interface, then we consider 2059 * the priority of the highest priority app among them. 2060 * For ex: If there is a system app and a foreground requesting for NAN iface, then we use the 2061 * system app to determine the priority of the interface request. 2062 * 2. If there are 2 conflicting interface requests from apps with the same priority, then 2063 * - (i) If both the apps are privileged and not for the same interface type, the new request 2064 * wins (last caller wins). 2065 * - (ii) Else, the existing request wins (first caller wins). 2066 * Note: Privileged apps are the ones that the user is directly interacting with, hence we use 2067 * last caller wins to decide among those, for all other apps we try to minimize disruption to 2068 * existing requests. 2069 * For ex: User turns on wifi, then hotspot on legacy devices which do not support STA + AP, we 2070 * want the last request from the user (i.e hotspot) to be honored. 2071 */ allowedToDeleteIfaceTypeForRequestedType( int requestedIfaceType, WorkSource requestorWs, int existingIfaceType, WifiIfaceInfo[][] existingIfaces)2072 private boolean allowedToDeleteIfaceTypeForRequestedType( 2073 int requestedIfaceType, WorkSource requestorWs, int existingIfaceType, 2074 WifiIfaceInfo[][] existingIfaces) { 2075 WorkSourceHelper newRequestorWsHelper = mWifiInjector.makeWsHelper(requestorWs); 2076 WifiIfaceInfo[] ifaceInfosForExistingIfaceType = existingIfaces[existingIfaceType]; 2077 // No ifaces of the existing type, error! 2078 if (ifaceInfosForExistingIfaceType.length == 0) { 2079 Log.wtf(TAG, "allowedToDeleteIfaceTypeForRequestedType: Num existings ifaces is 0!"); 2080 return false; 2081 } 2082 for (WifiIfaceInfo ifaceInfo : ifaceInfosForExistingIfaceType) { 2083 int newRequestorWsPriority = getRequestorWsPriority(newRequestorWsHelper); 2084 int existingRequestorWsPriority = getRequestorWsPriority(ifaceInfo.requestorWsHelper); 2085 if (allowedToDelete( 2086 requestedIfaceType, newRequestorWsPriority, existingIfaceType, 2087 existingRequestorWsPriority)) { 2088 if (mDbg) { 2089 Log.d(TAG, "allowedToDeleteIfaceTypeForRequestedType: Allowed to delete " 2090 + "requestedIfaceType=" + requestedIfaceType 2091 + "existingIfaceType=" + existingIfaceType 2092 + ", newRequestorWsPriority=" + newRequestorWsHelper 2093 + ", existingRequestorWsPriority" + existingRequestorWsPriority); 2094 } 2095 return true; 2096 } 2097 } 2098 return false; 2099 } 2100 2101 /** 2102 * Selects the interfaces to delete. 2103 * 2104 * Rule: 2105 * - Select interfaces that are lower priority than the request priority. 2106 * - If they are at the same priority level, then 2107 * - If both are privileged and different iface type, then delete existing interfaces. 2108 * - Else, not allowed to delete. 2109 * - Delete ifaces based on the descending requestor priority 2110 * (i.e bg app requests are deleted first, privileged app requests are deleted last) 2111 * - If there are > 1 ifaces within the same priority group to delete, select them randomly. 2112 * 2113 * @param excessInterfaces Number of interfaces which need to be selected. 2114 * @param requestedIfaceType Requested iface type. 2115 * @param requestorWs Requestor worksource. 2116 * @param existingIfaceType Existing iface type. 2117 * @param interfaces Array of interfaces. 2118 */ selectInterfacesToDelete(int excessInterfaces, int requestedIfaceType, WorkSource requestorWs, int existingIfaceType, WifiIfaceInfo[] interfaces)2119 private List<WifiIfaceInfo> selectInterfacesToDelete(int excessInterfaces, 2120 int requestedIfaceType, WorkSource requestorWs, int existingIfaceType, 2121 WifiIfaceInfo[] interfaces) { 2122 if (VDBG) { 2123 Log.d(TAG, "selectInterfacesToDelete: excessInterfaces=" + excessInterfaces 2124 + ", requestedIfaceType=" + requestedIfaceType 2125 + ", requestorWs=" + requestorWs 2126 + ", existingIfaceType=" + existingIfaceType 2127 + ", interfaces=" + Arrays.toString(interfaces)); 2128 } 2129 WorkSourceHelper newRequestorWsHelper = mWifiInjector.makeWsHelper(requestorWs); 2130 2131 boolean lookupError = false; 2132 // Map of priority levels to ifaces to delete. 2133 Map<Integer, List<WifiIfaceInfo>> ifacesToDeleteMap = new HashMap<>(); 2134 for (WifiIfaceInfo info : interfaces) { 2135 InterfaceCacheEntry cacheEntry; 2136 synchronized (mLock) { 2137 cacheEntry = mInterfaceInfoCache.get(Pair.create(info.name, getType(info.iface))); 2138 } 2139 if (cacheEntry == null) { 2140 Log.e(TAG, 2141 "selectInterfacesToDelete: can't find cache entry with name=" + info.name); 2142 lookupError = true; 2143 break; 2144 } 2145 int newRequestorWsPriority = getRequestorWsPriority(newRequestorWsHelper); 2146 int existingRequestorWsPriority = getRequestorWsPriority(cacheEntry.requestorWsHelper); 2147 if (allowedToDelete(requestedIfaceType, newRequestorWsPriority, existingIfaceType, 2148 existingRequestorWsPriority)) { 2149 ifacesToDeleteMap.computeIfAbsent( 2150 existingRequestorWsPriority, v -> new ArrayList<>()).add(info); 2151 } 2152 } 2153 2154 if (lookupError) { 2155 Log.e(TAG, "selectInterfacesToDelete: falling back to arbitrary selection"); 2156 return Arrays.asList(Arrays.copyOf(interfaces, excessInterfaces)); 2157 } else { 2158 int numIfacesToDelete = 0; 2159 List<WifiIfaceInfo> ifacesToDelete = new ArrayList<>(excessInterfaces); 2160 // Iterate from lowest priority to highest priority ifaces. 2161 for (int i = PRIORITY_MAX; i >= PRIORITY_MIN; i--) { 2162 List<WifiIfaceInfo> ifacesToDeleteListWithinPriority = 2163 ifacesToDeleteMap.getOrDefault(i, new ArrayList<>()); 2164 int numIfacesToDeleteWithinPriority = 2165 Math.min(excessInterfaces - numIfacesToDelete, 2166 ifacesToDeleteListWithinPriority.size()); 2167 ifacesToDelete.addAll( 2168 ifacesToDeleteListWithinPriority.subList( 2169 0, numIfacesToDeleteWithinPriority)); 2170 numIfacesToDelete += numIfacesToDeleteWithinPriority; 2171 if (numIfacesToDelete == excessInterfaces) { 2172 break; 2173 } 2174 } 2175 return ifacesToDelete; 2176 } 2177 } 2178 2179 /** 2180 * Checks whether the input chip-iface-combo can support the requested interface type. 2181 */ canIfaceComboSupportRequestedIfaceCombo( int[] chipIfaceCombo, int[] requestedIfaceCombo)2182 private boolean canIfaceComboSupportRequestedIfaceCombo( 2183 int[] chipIfaceCombo, int[] requestedIfaceCombo) { 2184 if (VDBG) { 2185 Log.d(TAG, "canIfaceComboSupportRequest: chipIfaceCombo=" + chipIfaceCombo 2186 + ", requestedIfaceCombo=" + requestedIfaceCombo); 2187 } 2188 for (int ifaceType : IFACE_TYPES_BY_PRIORITY) { 2189 if (chipIfaceCombo[ifaceType] < requestedIfaceCombo[ifaceType]) { 2190 if (VDBG) Log.d(TAG, "Requested type not supported by combo"); 2191 return false; 2192 } 2193 } 2194 return true; 2195 } 2196 2197 // Is it possible to create iface combo just looking at the device capabilities. isItPossibleToCreateIfaceCombo(WifiChipInfo[] chipInfos, long requiredChipCapabilities, int[] ifaceCombo)2198 private boolean isItPossibleToCreateIfaceCombo(WifiChipInfo[] chipInfos, 2199 long requiredChipCapabilities, int[] ifaceCombo) { 2200 if (VDBG) { 2201 Log.d(TAG, "isItPossibleToCreateIfaceCombo: chipInfos=" + Arrays.deepToString(chipInfos) 2202 + ", ifaceType=" + ifaceCombo 2203 + ", requiredChipCapabilities=" + requiredChipCapabilities); 2204 } 2205 2206 for (WifiChipInfo chipInfo: chipInfos) { 2207 if (!isChipCapabilitiesSupported(chipInfo, requiredChipCapabilities)) continue; 2208 for (IWifiChip.ChipMode chipMode: chipInfo.availableModes) { 2209 for (IWifiChip.ChipIfaceCombination chipIfaceCombo 2210 : chipMode.availableCombinations) { 2211 int[][] expandedIfaceCombos = expandIfaceCombos(chipIfaceCombo); 2212 if (VDBG) { 2213 Log.d(TAG, chipIfaceCombo + " expands to " 2214 + Arrays.deepToString(expandedIfaceCombos)); 2215 } 2216 2217 for (int[] expandedIfaceCombo: expandedIfaceCombos) { 2218 if (canIfaceComboSupportRequestedIfaceCombo( 2219 expandedIfaceCombo, ifaceCombo)) { 2220 return true; 2221 } 2222 } 2223 } 2224 } 2225 } 2226 return false; 2227 } 2228 2229 /** 2230 * Performs chip reconfiguration per the input: 2231 * - Removes the specified interfaces 2232 * - Reconfigures the chip to the new chip mode (if necessary) 2233 * - Creates the new interface 2234 * 2235 * Returns the newly created interface or a null on any error. 2236 */ executeChipReconfiguration(IfaceCreationData ifaceCreationData, @HdmIfaceTypeForCreation int createIfaceType)2237 private IWifiIface executeChipReconfiguration(IfaceCreationData ifaceCreationData, 2238 @HdmIfaceTypeForCreation int createIfaceType) { 2239 if (mDbg) { 2240 Log.d(TAG, "executeChipReconfiguration: ifaceCreationData=" + ifaceCreationData 2241 + ", createIfaceType=" + createIfaceType); 2242 } 2243 synchronized (mLock) { 2244 try { 2245 // is this a mode change? 2246 boolean isModeConfigNeeded = !ifaceCreationData.chipInfo.currentModeIdValid 2247 || ifaceCreationData.chipInfo.currentModeId != ifaceCreationData.chipModeId; 2248 if (mDbg) Log.d(TAG, "isModeConfigNeeded=" + isModeConfigNeeded); 2249 2250 // first delete interfaces/change modes 2251 if (isModeConfigNeeded) { 2252 // remove all interfaces pre mode-change 2253 // TODO: is this necessary? note that even if we don't want to explicitly 2254 // remove the interfaces we do need to call the onDeleted callbacks - which 2255 // this does 2256 for (WifiIfaceInfo[] ifaceInfos: ifaceCreationData.chipInfo.ifaces) { 2257 for (WifiIfaceInfo ifaceInfo: ifaceInfos) { 2258 removeIfaceInternal(ifaceInfo.iface); // ignore return value 2259 } 2260 } 2261 2262 WifiStatus status = ifaceCreationData.chipInfo.chip.configureChip( 2263 ifaceCreationData.chipModeId); 2264 updateRttControllerOnModeChange(); 2265 if (status.code != WifiStatusCode.SUCCESS) { 2266 Log.e(TAG, "executeChipReconfiguration: configureChip error: " 2267 + statusString(status)); 2268 return null; 2269 } 2270 } else { 2271 // remove all interfaces on the delete list 2272 for (WifiIfaceInfo ifaceInfo: ifaceCreationData.interfacesToBeRemovedFirst) { 2273 removeIfaceInternal(ifaceInfo.iface); // ignore return value 2274 } 2275 } 2276 2277 // create new interface 2278 Mutable<WifiStatus> statusResp = new Mutable<>(); 2279 Mutable<IWifiIface> ifaceResp = new Mutable<>(); 2280 switch (createIfaceType) { 2281 case HDM_CREATE_IFACE_STA: 2282 ifaceCreationData.chipInfo.chip.createStaIface( 2283 (WifiStatus status, IWifiStaIface iface) -> { 2284 statusResp.value = status; 2285 ifaceResp.value = iface; 2286 }); 2287 break; 2288 case HDM_CREATE_IFACE_AP_BRIDGE: 2289 android.hardware.wifi.V1_5.IWifiChip chip15 = 2290 getWifiChipForV1_5Mockable(ifaceCreationData.chipInfo.chip); 2291 if (chip15 != null) { 2292 chip15.createBridgedApIface( 2293 (WifiStatus status, 2294 android.hardware.wifi.V1_5.IWifiApIface iface) -> { 2295 statusResp.value = status; 2296 ifaceResp.value = iface; 2297 }); 2298 } else { 2299 Log.e(TAG, "Hal doesn't support to create AP bridge mode"); 2300 statusResp.value.code = WifiStatusCode.ERROR_NOT_SUPPORTED; 2301 } 2302 break; 2303 case HDM_CREATE_IFACE_AP: 2304 ifaceCreationData.chipInfo.chip.createApIface( 2305 (WifiStatus status, IWifiApIface iface) -> { 2306 statusResp.value = status; 2307 ifaceResp.value = iface; 2308 }); 2309 break; 2310 case HDM_CREATE_IFACE_P2P: 2311 ifaceCreationData.chipInfo.chip.createP2pIface( 2312 (WifiStatus status, IWifiP2pIface iface) -> { 2313 statusResp.value = status; 2314 ifaceResp.value = iface; 2315 }); 2316 break; 2317 case HDM_CREATE_IFACE_NAN: 2318 ifaceCreationData.chipInfo.chip.createNanIface( 2319 (WifiStatus status, IWifiNanIface iface) -> { 2320 statusResp.value = status; 2321 ifaceResp.value = iface; 2322 }); 2323 break; 2324 } 2325 2326 if (statusResp.value.code != WifiStatusCode.SUCCESS) { 2327 Log.e(TAG, "executeChipReconfiguration: failed to create interface" 2328 + " createIfaceType=" + createIfaceType + ": " 2329 + statusString(statusResp.value)); 2330 return null; 2331 } 2332 2333 return ifaceResp.value; 2334 } catch (RemoteException e) { 2335 Log.e(TAG, "executeChipReconfiguration exception: " + e); 2336 return null; 2337 } 2338 } 2339 } 2340 removeIfaceInternal(IWifiIface iface)2341 private boolean removeIfaceInternal(IWifiIface iface) { 2342 String name = getName(iface); 2343 int type = getType(iface); 2344 if (mDbg) Log.d(TAG, "removeIfaceInternal: iface(name)=" + name + ", type=" + type); 2345 2346 if (type == -1) { 2347 Log.e(TAG, "removeIfaceInternal: can't get type -- iface(name)=" + name); 2348 return false; 2349 } 2350 2351 synchronized (mLock) { 2352 if (mWifi == null) { 2353 Log.e(TAG, "removeIfaceInternal: null IWifi -- iface(name)=" + name); 2354 return false; 2355 } 2356 2357 IWifiChip chip = getChip(iface); 2358 if (chip == null) { 2359 Log.e(TAG, "removeIfaceInternal: null IWifiChip -- iface(name)=" + name); 2360 return false; 2361 } 2362 2363 if (name == null) { 2364 Log.e(TAG, "removeIfaceInternal: can't get name"); 2365 return false; 2366 } 2367 2368 WifiStatus status = null; 2369 try { 2370 switch (type) { 2371 case IfaceType.STA: 2372 status = chip.removeStaIface(name); 2373 break; 2374 case IfaceType.AP: 2375 status = chip.removeApIface(name); 2376 break; 2377 case IfaceType.P2P: 2378 status = chip.removeP2pIface(name); 2379 break; 2380 case IfaceType.NAN: 2381 status = chip.removeNanIface(name); 2382 break; 2383 default: 2384 Log.wtf(TAG, "removeIfaceInternal: invalid type=" + type); 2385 return false; 2386 } 2387 } catch (RemoteException e) { 2388 Log.e(TAG, "IWifiChip.removeXxxIface exception: " + e); 2389 } 2390 2391 // dispatch listeners no matter what status 2392 dispatchDestroyedListeners(name, type); 2393 2394 if (status != null && status.code == WifiStatusCode.SUCCESS) { 2395 return true; 2396 } else { 2397 Log.e(TAG, "IWifiChip.removeXxxIface failed: " + statusString(status)); 2398 return false; 2399 } 2400 } 2401 } 2402 2403 // dispatch all destroyed listeners registered for the specified interface AND remove the 2404 // cache entry dispatchDestroyedListeners(String name, int type)2405 private void dispatchDestroyedListeners(String name, int type) { 2406 if (VDBG) Log.d(TAG, "dispatchDestroyedListeners: iface(name)=" + name); 2407 2408 synchronized (mLock) { 2409 InterfaceCacheEntry entry = mInterfaceInfoCache.get(Pair.create(name, type)); 2410 if (entry == null) { 2411 Log.e(TAG, "dispatchDestroyedListeners: no cache entry for iface(name)=" + name); 2412 return; 2413 } 2414 2415 for (InterfaceDestroyedListenerProxy listener : entry.destroyedListeners) { 2416 listener.trigger(); 2417 } 2418 entry.destroyedListeners.clear(); // for insurance (though cache entry is removed) 2419 mInterfaceInfoCache.remove(Pair.create(name, type)); 2420 } 2421 } 2422 2423 // dispatch all destroyed listeners registered to all interfaces dispatchAllDestroyedListeners()2424 private void dispatchAllDestroyedListeners() { 2425 if (VDBG) Log.d(TAG, "dispatchAllDestroyedListeners"); 2426 2427 List<InterfaceDestroyedListenerProxy> triggerList = new ArrayList<>(); 2428 synchronized (mLock) { 2429 for (InterfaceCacheEntry cacheEntry: mInterfaceInfoCache.values()) { 2430 for (InterfaceDestroyedListenerProxy listener : cacheEntry.destroyedListeners) { 2431 triggerList.add(listener); 2432 } 2433 cacheEntry.destroyedListeners.clear(); // for insurance 2434 } 2435 mInterfaceInfoCache.clear(); 2436 } 2437 2438 for (InterfaceDestroyedListenerProxy listener : triggerList) { 2439 listener.trigger(); 2440 } 2441 } 2442 2443 private abstract class ListenerProxy<LISTENER> { 2444 protected LISTENER mListener; 2445 private Handler mHandler; 2446 2447 // override equals & hash to make sure that the container HashSet is unique with respect to 2448 // the contained listener 2449 @Override equals(Object obj)2450 public boolean equals(Object obj) { 2451 return mListener == ((ListenerProxy<LISTENER>) obj).mListener; 2452 } 2453 2454 @Override hashCode()2455 public int hashCode() { 2456 return mListener.hashCode(); 2457 } 2458 trigger()2459 void trigger() { 2460 if (mHandler != null) { 2461 mHandler.post(() -> { 2462 action(); 2463 }); 2464 } else { 2465 action(); 2466 } 2467 } 2468 triggerWithArg(boolean arg)2469 void triggerWithArg(boolean arg) { 2470 if (mHandler != null) { 2471 mHandler.post(() -> { 2472 actionWithArg(arg); 2473 }); 2474 } else { 2475 actionWithArg(arg); 2476 } 2477 } 2478 action()2479 protected void action() {} actionWithArg(boolean arg)2480 protected void actionWithArg(boolean arg) {} 2481 ListenerProxy(LISTENER listener, Handler handler, String tag)2482 ListenerProxy(LISTENER listener, Handler handler, String tag) { 2483 mListener = listener; 2484 mHandler = handler; 2485 } 2486 } 2487 2488 private class SubsystemRestartListenerProxy extends 2489 ListenerProxy<SubsystemRestartListener> { SubsystemRestartListenerProxy(@onNull SubsystemRestartListener subsystemRestartListener, Handler handler)2490 SubsystemRestartListenerProxy(@NonNull SubsystemRestartListener subsystemRestartListener, 2491 Handler handler) { 2492 super(subsystemRestartListener, handler, "SubsystemRestartListenerProxy"); 2493 } 2494 2495 @Override action()2496 protected void action() { 2497 mListener.onSubsystemRestart(); 2498 } 2499 } 2500 2501 private class InterfaceDestroyedListenerProxy extends 2502 ListenerProxy<InterfaceDestroyedListener> { 2503 private final String mIfaceName; InterfaceDestroyedListenerProxy(@onNull String ifaceName, InterfaceDestroyedListener destroyedListener, Handler handler)2504 InterfaceDestroyedListenerProxy(@NonNull String ifaceName, 2505 InterfaceDestroyedListener destroyedListener, 2506 Handler handler) { 2507 super(destroyedListener, handler, "InterfaceDestroyedListenerProxy"); 2508 mIfaceName = ifaceName; 2509 } 2510 2511 @Override action()2512 protected void action() { 2513 mListener.onDestroyed(mIfaceName); 2514 } 2515 } 2516 2517 private class InterfaceRttControllerLifecycleCallbackProxy implements 2518 InterfaceRttControllerLifecycleCallback { 2519 private InterfaceRttControllerLifecycleCallback mCallback; 2520 private Handler mHandler; 2521 InterfaceRttControllerLifecycleCallbackProxy( InterfaceRttControllerLifecycleCallback callback, Handler handler)2522 InterfaceRttControllerLifecycleCallbackProxy( 2523 InterfaceRttControllerLifecycleCallback callback, Handler handler) { 2524 mCallback = callback; 2525 mHandler = handler; 2526 } 2527 2528 // override equals & hash to make sure that the container HashSet is unique with respect to 2529 // the contained listener 2530 @Override equals(Object obj)2531 public boolean equals(Object obj) { 2532 return mCallback == ((InterfaceRttControllerLifecycleCallbackProxy) obj).mCallback; 2533 } 2534 2535 @Override hashCode()2536 public int hashCode() { 2537 return mCallback.hashCode(); 2538 } 2539 2540 @Override onNewRttController(IWifiRttController controller)2541 public void onNewRttController(IWifiRttController controller) { 2542 mHandler.post(() -> mCallback.onNewRttController(controller)); 2543 } 2544 2545 @Override onRttControllerDestroyed()2546 public void onRttControllerDestroyed() { 2547 mHandler.post(() -> mCallback.onRttControllerDestroyed()); 2548 } 2549 } 2550 dispatchRttControllerLifecycleOnNew()2551 private void dispatchRttControllerLifecycleOnNew() { 2552 if (VDBG) { 2553 Log.v(TAG, "dispatchRttControllerLifecycleOnNew: # cbs=" 2554 + mRttControllerLifecycleCallbacks.size()); 2555 } 2556 for (InterfaceRttControllerLifecycleCallbackProxy cbp : mRttControllerLifecycleCallbacks) { 2557 cbp.onNewRttController(mIWifiRttController); 2558 } 2559 } 2560 dispatchRttControllerLifecycleOnDestroyed()2561 private void dispatchRttControllerLifecycleOnDestroyed() { 2562 for (InterfaceRttControllerLifecycleCallbackProxy cbp : mRttControllerLifecycleCallbacks) { 2563 cbp.onRttControllerDestroyed(); 2564 } 2565 } 2566 2567 2568 /** 2569 * Updates the RttController when the chip mode is changed: 2570 * - Handles callbacks to registered listeners 2571 * - Handles creation of new RttController 2572 */ updateRttControllerOnModeChange()2573 private void updateRttControllerOnModeChange() { 2574 synchronized (mLock) { 2575 boolean controllerDestroyed = mIWifiRttController != null; 2576 mIWifiRttController = null; 2577 if (mRttControllerLifecycleCallbacks.size() == 0) { 2578 Log.d(TAG, "updateRttController: no one is interested in RTT controllers"); 2579 return; 2580 } 2581 2582 IWifiRttController newRttController = createRttControllerIfPossible(); 2583 if (newRttController == null) { 2584 if (controllerDestroyed) { 2585 dispatchRttControllerLifecycleOnDestroyed(); 2586 } 2587 } else { 2588 mIWifiRttController = newRttController; 2589 dispatchRttControllerLifecycleOnNew(); 2590 } 2591 } 2592 } 2593 2594 /** 2595 * Try to create a new RttController. 2596 * 2597 * @return The new RttController - or null on failure. 2598 */ createRttControllerIfPossible()2599 private IWifiRttController createRttControllerIfPossible() { 2600 synchronized (mLock) { 2601 if (!isWifiStarted()) { 2602 Log.d(TAG, "createRttControllerIfPossible: Wifi is not started"); 2603 return null; 2604 } 2605 2606 WifiChipInfo[] chipInfos = getAllChipInfo(); 2607 if (chipInfos == null) { 2608 Log.d(TAG, "createRttControllerIfPossible: no chip info found - most likely chip " 2609 + "not up yet"); 2610 return null; 2611 } 2612 2613 for (WifiChipInfo chipInfo : chipInfos) { 2614 if (!chipInfo.currentModeIdValid) { 2615 if (VDBG) { 2616 Log.d(TAG, "createRttControllerIfPossible: chip not configured yet: " 2617 + chipInfo); 2618 } 2619 continue; 2620 } 2621 2622 Mutable<IWifiRttController> rttResp = new Mutable<>(); 2623 try { 2624 android.hardware.wifi.V1_4.IWifiChip chip14 = 2625 android.hardware.wifi.V1_4.IWifiChip.castFrom(chipInfo.chip); 2626 if (chip14 != null) { 2627 chip14.createRttController_1_4(null, 2628 (WifiStatus status, 2629 android.hardware.wifi.V1_4.IWifiRttController rtt) -> { 2630 if (status.code == WifiStatusCode.SUCCESS) { 2631 rttResp.value = rtt; 2632 } else { 2633 Log.e(TAG, "IWifiChip.createRttController_1_4 failed: " 2634 + statusString(status)); 2635 } 2636 }); 2637 } else { 2638 chipInfo.chip.createRttController(null, 2639 (WifiStatus status, IWifiRttController rtt) -> { 2640 if (status.code == WifiStatusCode.SUCCESS) { 2641 rttResp.value = rtt; 2642 } else { 2643 Log.e(TAG, "IWifiChip.createRttController failed: " 2644 + statusString(status)); 2645 } 2646 }); 2647 } 2648 } catch (RemoteException e) { 2649 Log.e(TAG, "IWifiChip.createRttController exception: " + e); 2650 } 2651 if (rttResp.value != null) { 2652 return rttResp.value; 2653 } 2654 } 2655 } 2656 2657 Log.w(TAG, "createRttControllerIfPossible: not available from any of the chips"); 2658 return null; 2659 } 2660 2661 // general utilities 2662 statusString(WifiStatus status)2663 private static String statusString(WifiStatus status) { 2664 if (status == null) { 2665 return "status=null"; 2666 } 2667 StringBuilder sb = new StringBuilder(); 2668 sb.append(status.code).append(" (").append(status.description).append(")"); 2669 return sb.toString(); 2670 } 2671 2672 // Will return -1 for invalid results! Otherwise will return one of the 4 valid values. getType(IWifiIface iface)2673 private static int getType(IWifiIface iface) { 2674 Mutable<Integer> typeResp = new Mutable<>(-1); 2675 try { 2676 iface.getType((WifiStatus status, int type) -> { 2677 if (status.code == WifiStatusCode.SUCCESS) { 2678 typeResp.value = type; 2679 } else { 2680 Log.e(TAG, "Error on getType: " + statusString(status)); 2681 } 2682 }); 2683 } catch (RemoteException e) { 2684 Log.e(TAG, "Exception on getType: " + e); 2685 } 2686 2687 return typeResp.value; 2688 } 2689 2690 /** 2691 * Checks for a successful status result. 2692 * 2693 * Failures are logged to mLog. 2694 * 2695 * @param status is the WifiStatus generated by a hal call 2696 * @return true for success, false for failure 2697 */ ok(String method, WifiStatus status)2698 private boolean ok(String method, WifiStatus status) { 2699 if (status.code == WifiStatusCode.SUCCESS) return true; 2700 2701 Log.e(TAG, "Error on " + method + ": " + statusString(status)); 2702 return false; 2703 } 2704 2705 /** 2706 * Get the chip capabilities 2707 * 2708 * This is called before creating an interface and needs at least v1.5 HAL. 2709 * 2710 * @param wifiChip WifiChip 2711 * @return bitmask defined by HAL interface 2712 */ getChipCapabilities(@onNull IWifiChip wifiChip)2713 public long getChipCapabilities(@NonNull IWifiChip wifiChip) { 2714 long featureSet = 0; 2715 if (wifiChip == null) return featureSet; 2716 2717 try { 2718 final Mutable<Long> feat = new Mutable<>(CHIP_CAPABILITY_UNINITIALIZED); 2719 synchronized (mLock) { 2720 android.hardware.wifi.V1_5.IWifiChip iWifiChipV15 = 2721 getWifiChipForV1_5Mockable(wifiChip); 2722 // HAL newer than v1.5 support getting capabilities before creating an interface. 2723 if (iWifiChipV15 != null) { 2724 iWifiChipV15.getCapabilities_1_5((status, capabilities) -> { 2725 if (!ok("getCapabilities_1_5", status)) return; 2726 feat.value = (long) capabilities; 2727 }); 2728 } 2729 } 2730 featureSet = feat.value; 2731 } catch (RemoteException e) { 2732 Log.e(TAG, "Exception on getCapabilities: " + e); 2733 return 0; 2734 } 2735 return featureSet; 2736 } 2737 2738 /** 2739 * Dump the internal state of the class. 2740 */ dump(FileDescriptor fd, PrintWriter pw, String[] args)2741 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 2742 pw.println("Dump of HalDeviceManager:"); 2743 pw.println(" mServiceManager: " + mServiceManager); 2744 pw.println(" mWifi: " + mWifi); 2745 pw.println(" mManagerStatusListeners: " + mManagerStatusListeners); 2746 pw.println(" mInterfaceInfoCache: " + mInterfaceInfoCache); 2747 pw.println(" mDebugChipsInfo: " + Arrays.toString(getAllChipInfo())); 2748 } 2749 } 2750