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 android.net.wifi.nl80211; 18 19 import android.annotation.CallbackExecutor; 20 import android.annotation.IntDef; 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.annotation.SuppressLint; 24 import android.annotation.SystemApi; 25 import android.annotation.SystemService; 26 import android.app.AlarmManager; 27 import android.content.Context; 28 import android.net.wifi.SoftApInfo; 29 import android.net.wifi.WifiAnnotations; 30 import android.net.wifi.WifiScanner; 31 import android.os.Binder; 32 import android.os.Bundle; 33 import android.os.Handler; 34 import android.os.IBinder; 35 import android.os.RemoteException; 36 import android.os.ServiceManager; 37 import android.os.SystemClock; 38 import android.util.Log; 39 40 import com.android.internal.annotations.VisibleForTesting; 41 42 import java.lang.annotation.Retention; 43 import java.lang.annotation.RetentionPolicy; 44 import java.util.ArrayList; 45 import java.util.Arrays; 46 import java.util.HashMap; 47 import java.util.List; 48 import java.util.Map; 49 import java.util.Set; 50 import java.util.concurrent.Executor; 51 import java.util.concurrent.atomic.AtomicBoolean; 52 53 /** 54 * This class encapsulates the interface the wificond daemon presents to the Wi-Fi framework - used 55 * to encapsulate the Wi-Fi 80211nl management interface. The 56 * interface is only for use by the Wi-Fi framework and access is protected by SELinux permissions. 57 * 58 * @hide 59 */ 60 @SystemApi 61 @SystemService(Context.WIFI_NL80211_SERVICE) 62 public class WifiNl80211Manager { 63 private static final String TAG = "WifiNl80211Manager"; 64 private boolean mVerboseLoggingEnabled = false; 65 66 /** 67 * The {@link #sendMgmtFrame(String, byte[], int, Executor, SendMgmtFrameCallback)} 68 * timeout, in milliseconds, after which 69 * {@link SendMgmtFrameCallback#onFailure(int)} will be called with reason 70 * {@link #SEND_MGMT_FRAME_ERROR_TIMEOUT}. 71 */ 72 private static final int SEND_MGMT_FRAME_TIMEOUT_MS = 1000; 73 74 private static final String TIMEOUT_ALARM_TAG = TAG + " Send Management Frame Timeout"; 75 76 /** @hide */ 77 @Retention(RetentionPolicy.SOURCE) 78 @IntDef(prefix = {"SCAN_TYPE_"}, 79 value = {SCAN_TYPE_SINGLE_SCAN, 80 SCAN_TYPE_PNO_SCAN}) 81 public @interface ScanResultType {} 82 83 /** 84 * Specifies a scan type: single scan initiated by the framework. Can be used in 85 * {@link #getScanResults(String, int)} to specify the type of scan result to fetch. 86 */ 87 public static final int SCAN_TYPE_SINGLE_SCAN = 0; 88 89 /** 90 * Specifies a scan type: PNO scan. Can be used in {@link #getScanResults(String, int)} to 91 * specify the type of scan result to fetch. 92 */ 93 public static final int SCAN_TYPE_PNO_SCAN = 1; 94 95 // Extra scanning parameter used to enable 6Ghz RNR (Reduced Neighbour Support). 96 public static final String SCANNING_PARAM_ENABLE_6GHZ_RNR = 97 "android.net.wifi.nl80211.SCANNING_PARAM_ENABLE_6GHZ_RNR"; 98 99 // Extra scanning parameter used to add vendor IEs (byte[]). 100 public static final String EXTRA_SCANNING_PARAM_VENDOR_IES = 101 "android.net.wifi.nl80211.extra.SCANNING_PARAM_VENDOR_IES"; 102 103 private AlarmManager mAlarmManager; 104 private Handler mEventHandler; 105 106 // Cached wificond binder handlers. 107 private IWificond mWificond; 108 private Context mContext; 109 private InstantWifi mInstantWifi; 110 private WificondEventHandler mWificondEventHandler = new WificondEventHandler(); 111 private HashMap<String, IClientInterface> mClientInterfaces = new HashMap<>(); 112 private HashMap<String, IApInterface> mApInterfaces = new HashMap<>(); 113 private HashMap<String, IWifiScannerImpl> mWificondScanners = new HashMap<>(); 114 private HashMap<String, IScanEvent> mScanEventHandlers = new HashMap<>(); 115 private HashMap<String, IPnoScanEvent> mPnoScanEventHandlers = new HashMap<>(); 116 private HashMap<String, IApInterfaceEventCallback> mApInterfaceListeners = new HashMap<>(); 117 private Runnable mDeathEventHandler; 118 /** 119 * Ensures that no more than one sendMgmtFrame operation runs concurrently. 120 */ 121 private AtomicBoolean mSendMgmtFrameInProgress = new AtomicBoolean(false); 122 123 /** 124 * Interface used to listen country code event 125 */ 126 public interface CountryCodeChangedListener { 127 /** 128 * Called when country code changed. 129 * 130 * @param countryCode An ISO-3166-alpha2 country code which is 2-Character alphanumeric. 131 */ onCountryCodeChanged(@onNull String countryCode)132 void onCountryCodeChanged(@NonNull String countryCode); 133 } 134 135 /** 136 * Interface used when waiting for scans to be completed (with results). 137 */ 138 public interface ScanEventCallback { 139 /** 140 * Called when scan results are available. Scans results should then be obtained from 141 * {@link #getScanResults(String, int)}. 142 */ onScanResultReady()143 void onScanResultReady(); 144 145 /** 146 * Deprecated in Android 14. Newer wificond implementation should call 147 * onScanRequestFailed(). 148 * Called when a scan has failed. 149 * @deprecated The usage is replaced by {@link ScanEventCallback#onScanFailed(int)} 150 */ 151 onScanFailed()152 void onScanFailed(); 153 /** 154 * Called when a scan has failed with errorCode. 155 */ onScanFailed(int errorCode)156 default void onScanFailed(int errorCode) {} 157 } 158 159 /** 160 * Interface for a callback to provide information about PNO scan request requested with 161 * {@link #startPnoScan(String, PnoSettings, Executor, PnoScanRequestCallback)}. Note that the 162 * callback are for the status of the request - not the scan itself. The results of the scan 163 * are returned with {@link ScanEventCallback}. 164 */ 165 public interface PnoScanRequestCallback { 166 /** 167 * Called when a PNO scan request has been successfully submitted. 168 */ onPnoRequestSucceeded()169 void onPnoRequestSucceeded(); 170 171 /** 172 * Called when a PNO scan request fails. 173 */ onPnoRequestFailed()174 void onPnoRequestFailed(); 175 } 176 177 /** @hide */ 178 @VisibleForTesting getInstantWifiMockable()179 protected InstantWifi getInstantWifiMockable() { 180 return mInstantWifi; 181 } 182 183 /** @hide */ 184 @VisibleForTesting 185 public class WificondEventHandler extends IWificondEventCallback.Stub { 186 private Map<CountryCodeChangedListener, Executor> mCountryCodeChangedListenerHolder = 187 new HashMap<>(); 188 189 /** 190 * Register CountryCodeChangedListener with pid. 191 * 192 * @param executor The Executor on which to execute the callbacks. 193 * @param listener listener for country code changed events. 194 */ registerCountryCodeChangedListener(Executor executor, CountryCodeChangedListener listener)195 public void registerCountryCodeChangedListener(Executor executor, 196 CountryCodeChangedListener listener) { 197 mCountryCodeChangedListenerHolder.put(listener, executor); 198 } 199 200 /** 201 * Unregister CountryCodeChangedListener with pid. 202 * 203 * @param listener listener which registered country code changed events. 204 */ unregisterCountryCodeChangedListener(CountryCodeChangedListener listener)205 public void unregisterCountryCodeChangedListener(CountryCodeChangedListener listener) { 206 mCountryCodeChangedListenerHolder.remove(listener); 207 } 208 209 @Override OnRegDomainChanged(String countryCode)210 public void OnRegDomainChanged(String countryCode) { 211 Log.d(TAG, "OnRegDomainChanged " + countryCode); 212 final long token = Binder.clearCallingIdentity(); 213 try { 214 mCountryCodeChangedListenerHolder.forEach((listener, executor) -> { 215 executor.execute(() -> listener.onCountryCodeChanged(countryCode)); 216 }); 217 } finally { 218 Binder.restoreCallingIdentity(token); 219 } 220 } 221 } 222 223 private class ScanEventHandler extends IScanEvent.Stub { 224 private Executor mExecutor; 225 private ScanEventCallback mCallback; 226 ScanEventHandler(@onNull Executor executor, @NonNull ScanEventCallback callback)227 ScanEventHandler(@NonNull Executor executor, @NonNull ScanEventCallback callback) { 228 mExecutor = executor; 229 mCallback = callback; 230 } 231 232 @Override OnScanResultReady()233 public void OnScanResultReady() { 234 Log.d(TAG, "Scan result ready event"); 235 final long token = Binder.clearCallingIdentity(); 236 try { 237 mExecutor.execute(() -> mCallback.onScanResultReady()); 238 } finally { 239 Binder.restoreCallingIdentity(token); 240 } 241 } 242 243 @Override OnScanFailed()244 public void OnScanFailed() { 245 Log.d(TAG, "Scan failed event"); 246 final long token = Binder.clearCallingIdentity(); 247 try { 248 mExecutor.execute(() -> mCallback.onScanFailed()); 249 } finally { 250 Binder.restoreCallingIdentity(token); 251 } 252 } 253 254 @Override OnScanRequestFailed(int errorCode)255 public void OnScanRequestFailed(int errorCode) { 256 Log.d(TAG, "Scan failed event with error code: " + errorCode); 257 final long token = Binder.clearCallingIdentity(); 258 try { 259 mExecutor.execute(() -> mCallback.onScanFailed( 260 toFrameworkScanStatusCode(errorCode))); 261 } finally { 262 Binder.restoreCallingIdentity(token); 263 } 264 } 265 } 266 267 /** 268 * Result of a signal poll requested using {@link #signalPoll(String)}. 269 * 270 * @deprecated The usage is replaced by 271 * {@code com.android.server.wifi.WifiSignalPollResults}. 272 */ 273 @Deprecated 274 public static class SignalPollResult { 275 /** @hide */ SignalPollResult(int currentRssiDbm, int txBitrateMbps, int rxBitrateMbps, int associationFrequencyMHz)276 public SignalPollResult(int currentRssiDbm, int txBitrateMbps, int rxBitrateMbps, 277 int associationFrequencyMHz) { 278 this.currentRssiDbm = currentRssiDbm; 279 this.txBitrateMbps = txBitrateMbps; 280 this.rxBitrateMbps = rxBitrateMbps; 281 this.associationFrequencyMHz = associationFrequencyMHz; 282 } 283 284 /** 285 * RSSI value in dBM. 286 */ 287 public final int currentRssiDbm; 288 289 /** 290 * Transmission bit rate in Mbps. 291 */ 292 public final int txBitrateMbps; 293 294 /** 295 * Last received packet bit rate in Mbps. 296 */ 297 public final int rxBitrateMbps; 298 299 /** 300 * Association frequency in MHz. 301 */ 302 public final int associationFrequencyMHz; 303 } 304 305 /** 306 * Transmission counters obtained using {@link #getTxPacketCounters(String)}. 307 */ 308 public static class TxPacketCounters { 309 /** @hide */ TxPacketCounters(int txPacketSucceeded, int txPacketFailed)310 public TxPacketCounters(int txPacketSucceeded, int txPacketFailed) { 311 this.txPacketSucceeded = txPacketSucceeded; 312 this.txPacketFailed = txPacketFailed; 313 } 314 315 /** 316 * Number of successfully transmitted packets. 317 */ 318 public final int txPacketSucceeded; 319 320 /** 321 * Number of packet transmission failures. 322 */ 323 public final int txPacketFailed; 324 } 325 326 /** 327 * Callbacks for SoftAp interface registered using 328 * {@link #registerApCallback(String, Executor, SoftApCallback)}. 329 * 330 * @deprecated The usage is replaced by vendor HAL 331 * {@code android.hardware.wifi.hostapd.V1_3.IHostapdCallback}. 332 */ 333 @Deprecated 334 public interface SoftApCallback { 335 /** 336 * Invoked when there is a fatal failure and the SoftAp is shutdown. 337 */ onFailure()338 void onFailure(); 339 340 /** 341 * Invoked when there is a change in the associated station (STA). 342 * @param client Information about the client whose status has changed. 343 * @param isConnected Indication as to whether the client is connected (true), or 344 * disconnected (false). 345 */ onConnectedClientsChanged(@onNull NativeWifiClient client, boolean isConnected)346 void onConnectedClientsChanged(@NonNull NativeWifiClient client, boolean isConnected); 347 348 /** 349 * Invoked when a channel switch event happens - i.e. the SoftAp is moved to a different 350 * channel. Also called on initial registration. 351 * @param frequencyMhz The new frequency of the SoftAp. A value of 0 is invalid and is an 352 * indication that the SoftAp is not enabled. 353 * @param bandwidth The new bandwidth of the SoftAp. 354 */ onSoftApChannelSwitched(int frequencyMhz, @WifiAnnotations.Bandwidth int bandwidth)355 void onSoftApChannelSwitched(int frequencyMhz, @WifiAnnotations.Bandwidth int bandwidth); 356 } 357 358 /** 359 * Callback to notify the results of a 360 * {@link #sendMgmtFrame(String, byte[], int, Executor, SendMgmtFrameCallback)} call. 361 * Note: no callbacks will be triggered if the interface dies while sending a frame. 362 */ 363 public interface SendMgmtFrameCallback { 364 /** 365 * Called when the management frame was successfully sent and ACKed by the recipient. 366 * @param elapsedTimeMs The elapsed time between when the management frame was sent and when 367 * the ACK was processed, in milliseconds, as measured by wificond. 368 * This includes the time that the send frame spent queuing before it 369 * was sent, any firmware retries, and the time the received ACK spent 370 * queuing before it was processed. 371 */ onAck(int elapsedTimeMs)372 void onAck(int elapsedTimeMs); 373 374 /** 375 * Called when the send failed. 376 * @param reason The error code for the failure. 377 */ onFailure(@endMgmtFrameError int reason)378 void onFailure(@SendMgmtFrameError int reason); 379 } 380 381 /** @hide */ 382 @Retention(RetentionPolicy.SOURCE) 383 @IntDef(prefix = {"SEND_MGMT_FRAME_ERROR_"}, 384 value = {SEND_MGMT_FRAME_ERROR_UNKNOWN, 385 SEND_MGMT_FRAME_ERROR_MCS_UNSUPPORTED, 386 SEND_MGMT_FRAME_ERROR_NO_ACK, 387 SEND_MGMT_FRAME_ERROR_TIMEOUT, 388 SEND_MGMT_FRAME_ERROR_ALREADY_STARTED}) 389 public @interface SendMgmtFrameError {} 390 391 // Send management frame error codes 392 393 /** 394 * Unknown error occurred during call to 395 * {@link #sendMgmtFrame(String, byte[], int, Executor, SendMgmtFrameCallback)}. 396 */ 397 public static final int SEND_MGMT_FRAME_ERROR_UNKNOWN = 1; 398 399 /** 400 * Specifying the MCS rate in 401 * {@link #sendMgmtFrame(String, byte[], int, Executor, SendMgmtFrameCallback)} is not 402 * supported by this device. 403 */ 404 public static final int SEND_MGMT_FRAME_ERROR_MCS_UNSUPPORTED = 2; 405 406 /** 407 * Driver reported that no ACK was received for the frame transmitted using 408 * {@link #sendMgmtFrame(String, byte[], int, Executor, SendMgmtFrameCallback)}. 409 */ 410 public static final int SEND_MGMT_FRAME_ERROR_NO_ACK = 3; 411 412 /** 413 * Error code for when the driver fails to report on the status of the frame sent by 414 * {@link #sendMgmtFrame(String, byte[], int, Executor, SendMgmtFrameCallback)} 415 * after {@link #SEND_MGMT_FRAME_TIMEOUT_MS} milliseconds. 416 */ 417 public static final int SEND_MGMT_FRAME_ERROR_TIMEOUT = 4; 418 419 /** 420 * An existing call to 421 * {@link #sendMgmtFrame(String, byte[], int, Executor, SendMgmtFrameCallback)} 422 * is in progress. Another frame cannot be sent until the first call completes. 423 */ 424 public static final int SEND_MGMT_FRAME_ERROR_ALREADY_STARTED = 5; 425 426 /** @hide */ WifiNl80211Manager(Context context)427 public WifiNl80211Manager(Context context) { 428 mAlarmManager = context.getSystemService(AlarmManager.class); 429 mEventHandler = new Handler(context.getMainLooper()); 430 mContext = context; 431 } 432 433 /** 434 * Construct WifiNl80211Manager with giving context and binder which is an interface of 435 * IWificond. 436 * 437 * @param context Android context. 438 * @param binder a binder of IWificond. 439 */ WifiNl80211Manager(@onNull Context context, @NonNull IBinder binder)440 public WifiNl80211Manager(@NonNull Context context, @NonNull IBinder binder) { 441 this(context); 442 mWificond = IWificond.Stub.asInterface(binder); 443 if (mWificond == null) { 444 Log.e(TAG, "Failed to get reference to wificond"); 445 } 446 mContext = context; 447 } 448 449 /** @hide */ 450 @VisibleForTesting WifiNl80211Manager(Context context, IWificond wificond)451 public WifiNl80211Manager(Context context, IWificond wificond) { 452 this(context); 453 mWificond = wificond; 454 mContext = context; 455 } 456 457 /** @hide */ 458 @VisibleForTesting getWificondEventHandler()459 public WificondEventHandler getWificondEventHandler() { 460 return mWificondEventHandler; 461 } 462 463 private class PnoScanEventHandler extends IPnoScanEvent.Stub { 464 private Executor mExecutor; 465 private ScanEventCallback mCallback; 466 PnoScanEventHandler(@onNull Executor executor, @NonNull ScanEventCallback callback)467 PnoScanEventHandler(@NonNull Executor executor, @NonNull ScanEventCallback callback) { 468 mExecutor = executor; 469 mCallback = callback; 470 } 471 472 @Override OnPnoNetworkFound()473 public void OnPnoNetworkFound() { 474 Log.d(TAG, "Pno scan result event"); 475 final long token = Binder.clearCallingIdentity(); 476 try { 477 mExecutor.execute(() -> mCallback.onScanResultReady()); 478 } finally { 479 Binder.restoreCallingIdentity(token); 480 } 481 } 482 483 @Override OnPnoScanFailed()484 public void OnPnoScanFailed() { 485 Log.d(TAG, "Pno Scan failed event"); 486 final long token = Binder.clearCallingIdentity(); 487 try { 488 mExecutor.execute(() -> mCallback.onScanFailed()); 489 } finally { 490 Binder.restoreCallingIdentity(token); 491 } 492 } 493 } 494 495 /** 496 * Listener for AP Interface events. 497 */ 498 private class ApInterfaceEventCallback extends IApInterfaceEventCallback.Stub { 499 private Executor mExecutor; 500 private SoftApCallback mSoftApListener; 501 ApInterfaceEventCallback(Executor executor, SoftApCallback listener)502 ApInterfaceEventCallback(Executor executor, SoftApCallback listener) { 503 mExecutor = executor; 504 mSoftApListener = listener; 505 } 506 507 @Override onConnectedClientsChanged(NativeWifiClient client, boolean isConnected)508 public void onConnectedClientsChanged(NativeWifiClient client, boolean isConnected) { 509 if (mVerboseLoggingEnabled) { 510 Log.d(TAG, "onConnectedClientsChanged called with " 511 + client.getMacAddress() + " isConnected: " + isConnected); 512 } 513 514 final long token = Binder.clearCallingIdentity(); 515 try { 516 mExecutor.execute( 517 () -> mSoftApListener.onConnectedClientsChanged(client, isConnected)); 518 } finally { 519 Binder.restoreCallingIdentity(token); 520 } 521 } 522 523 @Override onSoftApChannelSwitched(int frequency, int bandwidth)524 public void onSoftApChannelSwitched(int frequency, int bandwidth) { 525 final long token = Binder.clearCallingIdentity(); 526 try { 527 mExecutor.execute(() -> mSoftApListener.onSoftApChannelSwitched(frequency, 528 toFrameworkBandwidth(bandwidth))); 529 } finally { 530 Binder.restoreCallingIdentity(token); 531 } 532 } 533 toFrameworkBandwidth(int bandwidth)534 private @WifiAnnotations.Bandwidth int toFrameworkBandwidth(int bandwidth) { 535 switch(bandwidth) { 536 case IApInterfaceEventCallback.BANDWIDTH_INVALID: 537 return SoftApInfo.CHANNEL_WIDTH_INVALID; 538 case IApInterfaceEventCallback.BANDWIDTH_20_NOHT: 539 return SoftApInfo.CHANNEL_WIDTH_20MHZ_NOHT; 540 case IApInterfaceEventCallback.BANDWIDTH_20: 541 return SoftApInfo.CHANNEL_WIDTH_20MHZ; 542 case IApInterfaceEventCallback.BANDWIDTH_40: 543 return SoftApInfo.CHANNEL_WIDTH_40MHZ; 544 case IApInterfaceEventCallback.BANDWIDTH_80: 545 return SoftApInfo.CHANNEL_WIDTH_80MHZ; 546 case IApInterfaceEventCallback.BANDWIDTH_80P80: 547 return SoftApInfo.CHANNEL_WIDTH_80MHZ_PLUS_MHZ; 548 case IApInterfaceEventCallback.BANDWIDTH_160: 549 return SoftApInfo.CHANNEL_WIDTH_160MHZ; 550 case IApInterfaceEventCallback.BANDWIDTH_320: 551 return SoftApInfo.CHANNEL_WIDTH_320MHZ; 552 default: 553 return SoftApInfo.CHANNEL_WIDTH_INVALID; 554 } 555 } 556 } 557 558 /** 559 * Callback triggered by wificond. 560 */ 561 private class SendMgmtFrameEvent extends ISendMgmtFrameEvent.Stub { 562 private Executor mExecutor; 563 private SendMgmtFrameCallback mCallback; 564 private AlarmManager.OnAlarmListener mTimeoutCallback; 565 /** 566 * ensures that mCallback is only called once 567 */ 568 private boolean mWasCalled; 569 runIfFirstCall(Runnable r)570 private void runIfFirstCall(Runnable r) { 571 if (mWasCalled) return; 572 mWasCalled = true; 573 574 mSendMgmtFrameInProgress.set(false); 575 r.run(); 576 } 577 SendMgmtFrameEvent(@onNull Executor executor, @NonNull SendMgmtFrameCallback callback)578 SendMgmtFrameEvent(@NonNull Executor executor, @NonNull SendMgmtFrameCallback callback) { 579 mExecutor = executor; 580 mCallback = callback; 581 // called in main thread 582 mTimeoutCallback = () -> runIfFirstCall(() -> { 583 if (mVerboseLoggingEnabled) { 584 Log.e(TAG, "Timed out waiting for ACK"); 585 } 586 final long token = Binder.clearCallingIdentity(); 587 try { 588 mExecutor.execute(() -> mCallback.onFailure(SEND_MGMT_FRAME_ERROR_TIMEOUT)); 589 } finally { 590 Binder.restoreCallingIdentity(token); 591 } 592 }); 593 mWasCalled = false; 594 595 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 596 SystemClock.elapsedRealtime() + SEND_MGMT_FRAME_TIMEOUT_MS, 597 TIMEOUT_ALARM_TAG, mTimeoutCallback, mEventHandler); 598 } 599 600 // called in binder thread 601 @Override OnAck(int elapsedTimeMs)602 public void OnAck(int elapsedTimeMs) { 603 // post to main thread 604 mEventHandler.post(() -> runIfFirstCall(() -> { 605 mAlarmManager.cancel(mTimeoutCallback); 606 final long token = Binder.clearCallingIdentity(); 607 try { 608 mExecutor.execute(() -> mCallback.onAck(elapsedTimeMs)); 609 } finally { 610 Binder.restoreCallingIdentity(token); 611 } 612 })); 613 } 614 615 // called in binder thread 616 @Override OnFailure(int reason)617 public void OnFailure(int reason) { 618 // post to main thread 619 mEventHandler.post(() -> runIfFirstCall(() -> { 620 mAlarmManager.cancel(mTimeoutCallback); 621 final long token = Binder.clearCallingIdentity(); 622 try { 623 mExecutor.execute(() -> mCallback.onFailure(reason)); 624 } finally { 625 Binder.restoreCallingIdentity(token); 626 } 627 })); 628 } 629 } 630 631 /** 632 * Called by the binder subsystem upon remote object death. 633 * Invoke all the register death handlers and clear state. 634 * @hide 635 */ 636 @VisibleForTesting binderDied()637 public void binderDied() { 638 mEventHandler.post(() -> { 639 Log.e(TAG, "Wificond died!"); 640 clearState(); 641 // Invalidate the global wificond handle on death. Will be refreshed 642 // on the next setup call. 643 mWificond = null; 644 if (mDeathEventHandler != null) { 645 mDeathEventHandler.run(); 646 } 647 }); 648 } 649 650 /** 651 * Enable or disable verbose logging of the WifiNl80211Manager module. 652 * @param enable True to enable verbose logging. False to disable verbose logging. 653 */ enableVerboseLogging(boolean enable)654 public void enableVerboseLogging(boolean enable) { 655 mVerboseLoggingEnabled = enable; 656 } 657 658 /** 659 * Register a death notification for the WifiNl80211Manager which acts as a proxy for the 660 * wificond daemon (i.e. the death listener will be called when and if the wificond daemon 661 * dies). 662 * 663 * @param deathEventHandler A {@link Runnable} to be called whenever the wificond daemon dies. 664 */ setOnServiceDeadCallback(@onNull Runnable deathEventHandler)665 public void setOnServiceDeadCallback(@NonNull Runnable deathEventHandler) { 666 if (mDeathEventHandler != null) { 667 Log.e(TAG, "Death handler already present"); 668 } 669 mDeathEventHandler = deathEventHandler; 670 } 671 672 /** 673 * Helper method to retrieve the global wificond handle and register for 674 * death notifications. 675 */ retrieveWificondAndRegisterForDeath()676 private boolean retrieveWificondAndRegisterForDeath() { 677 if (mWificond != null) { 678 if (mVerboseLoggingEnabled) { 679 Log.d(TAG, "Wificond handle already retrieved"); 680 } 681 // We already have a wificond handle. 682 return true; 683 } 684 IBinder binder = ServiceManager.getService(Context.WIFI_NL80211_SERVICE); 685 mWificond = IWificond.Stub.asInterface(binder); 686 if (mWificond == null) { 687 Log.e(TAG, "Failed to get reference to wificond"); 688 return false; 689 } 690 try { 691 mWificond.asBinder().linkToDeath(() -> binderDied(), 0); 692 mWificond.registerWificondEventCallback(mWificondEventHandler); 693 } catch (RemoteException e) { 694 Log.e(TAG, "Failed to register death notification for wificond"); 695 // The remote has already died. 696 return false; 697 } 698 return true; 699 } 700 701 /** 702 * Set up an interface for client (STA) mode. 703 * 704 * @param ifaceName Name of the interface to configure. 705 * @param executor The Executor on which to execute the callbacks. 706 * @param scanCallback A callback for framework initiated scans. 707 * @param pnoScanCallback A callback for PNO (offloaded) scans. 708 * @return true on success. 709 */ setupInterfaceForClientMode(@onNull String ifaceName, @NonNull @CallbackExecutor Executor executor, @NonNull ScanEventCallback scanCallback, @NonNull ScanEventCallback pnoScanCallback)710 public boolean setupInterfaceForClientMode(@NonNull String ifaceName, 711 @NonNull @CallbackExecutor Executor executor, 712 @NonNull ScanEventCallback scanCallback, @NonNull ScanEventCallback pnoScanCallback) { 713 Log.d(TAG, "Setting up interface for client mode: " + ifaceName); 714 if (!retrieveWificondAndRegisterForDeath()) { 715 return false; 716 } 717 718 if (scanCallback == null || pnoScanCallback == null || executor == null) { 719 Log.e(TAG, "setupInterfaceForClientMode invoked with null callbacks"); 720 return false; 721 } 722 723 IClientInterface clientInterface = null; 724 try { 725 clientInterface = mWificond.createClientInterface(ifaceName); 726 } catch (RemoteException e1) { 727 Log.e(TAG, "Failed to get IClientInterface due to remote exception"); 728 return false; 729 } 730 731 if (clientInterface == null) { 732 Log.e(TAG, "Could not get IClientInterface instance from wificond"); 733 return false; 734 } 735 Binder.allowBlocking(clientInterface.asBinder()); 736 737 // Refresh Handlers 738 mClientInterfaces.put(ifaceName, clientInterface); 739 try { 740 IWifiScannerImpl wificondScanner = clientInterface.getWifiScannerImpl(); 741 if (wificondScanner == null) { 742 Log.e(TAG, "Failed to get WificondScannerImpl"); 743 return false; 744 } 745 mWificondScanners.put(ifaceName, wificondScanner); 746 Binder.allowBlocking(wificondScanner.asBinder()); 747 ScanEventHandler scanEventHandler = new ScanEventHandler(executor, scanCallback); 748 mScanEventHandlers.put(ifaceName, scanEventHandler); 749 wificondScanner.subscribeScanEvents(scanEventHandler); 750 PnoScanEventHandler pnoScanEventHandler = new PnoScanEventHandler(executor, 751 pnoScanCallback); 752 mPnoScanEventHandlers.put(ifaceName, pnoScanEventHandler); 753 wificondScanner.subscribePnoScanEvents(pnoScanEventHandler); 754 } catch (RemoteException e) { 755 Log.e(TAG, "Failed to refresh wificond scanner due to remote exception"); 756 } 757 758 if (getInstantWifiMockable() == null) { 759 mInstantWifi = new InstantWifi(mContext, mAlarmManager, mEventHandler); 760 } 761 return true; 762 } 763 764 /** 765 * Tear down a specific client (STA) interface configured using 766 * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)}. 767 * 768 * @param ifaceName Name of the interface to tear down. 769 * @return Returns true on success, false on failure (e.g. when called before an interface was 770 * set up). 771 */ tearDownClientInterface(@onNull String ifaceName)772 public boolean tearDownClientInterface(@NonNull String ifaceName) { 773 if (getClientInterface(ifaceName) == null) { 774 Log.e(TAG, "No valid wificond client interface handler for iface=" + ifaceName); 775 return false; 776 } 777 try { 778 IWifiScannerImpl scannerImpl = mWificondScanners.get(ifaceName); 779 if (scannerImpl != null) { 780 scannerImpl.unsubscribeScanEvents(); 781 scannerImpl.unsubscribePnoScanEvents(); 782 } 783 } catch (RemoteException e) { 784 Log.e(TAG, "Failed to unsubscribe wificond scanner due to remote exception"); 785 return false; 786 } 787 788 if (mWificond == null) { 789 Log.e(TAG, "tearDownClientInterface: mWificond binder is null! Did wificond die?"); 790 return false; 791 } 792 793 boolean success; 794 try { 795 success = mWificond.tearDownClientInterface(ifaceName); 796 } catch (RemoteException e1) { 797 Log.e(TAG, "Failed to teardown client interface due to remote exception"); 798 return false; 799 } 800 if (!success) { 801 Log.e(TAG, "Failed to teardown client interface"); 802 return false; 803 } 804 805 mClientInterfaces.remove(ifaceName); 806 mWificondScanners.remove(ifaceName); 807 mScanEventHandlers.remove(ifaceName); 808 mPnoScanEventHandlers.remove(ifaceName); 809 return true; 810 } 811 812 /** 813 * Set up interface as a Soft AP. 814 * 815 * @param ifaceName Name of the interface to configure. 816 * @return true on success. 817 */ setupInterfaceForSoftApMode(@onNull String ifaceName)818 public boolean setupInterfaceForSoftApMode(@NonNull String ifaceName) { 819 Log.d(TAG, "Setting up interface for soft ap mode for iface=" + ifaceName); 820 if (!retrieveWificondAndRegisterForDeath()) { 821 return false; 822 } 823 824 IApInterface apInterface = null; 825 try { 826 apInterface = mWificond.createApInterface(ifaceName); 827 } catch (RemoteException e1) { 828 Log.e(TAG, "Failed to get IApInterface due to remote exception"); 829 return false; 830 } 831 832 if (apInterface == null) { 833 Log.e(TAG, "Could not get IApInterface instance from wificond"); 834 return false; 835 } 836 Binder.allowBlocking(apInterface.asBinder()); 837 838 // Refresh Handlers 839 mApInterfaces.put(ifaceName, apInterface); 840 return true; 841 } 842 843 /** 844 * Tear down a Soft AP interface configured using 845 * {@link #setupInterfaceForSoftApMode(String)}. 846 * 847 * @param ifaceName Name of the interface to tear down. 848 * @return Returns true on success, false on failure (e.g. when called before an interface was 849 * set up). 850 */ tearDownSoftApInterface(@onNull String ifaceName)851 public boolean tearDownSoftApInterface(@NonNull String ifaceName) { 852 if (getApInterface(ifaceName) == null) { 853 Log.e(TAG, "No valid wificond ap interface handler for iface=" + ifaceName); 854 return false; 855 } 856 857 if (mWificond == null) { 858 Log.e(TAG, "tearDownSoftApInterface: mWificond binder is null! Did wificond die?"); 859 return false; 860 } 861 862 boolean success; 863 try { 864 success = mWificond.tearDownApInterface(ifaceName); 865 } catch (RemoteException e1) { 866 Log.e(TAG, "Failed to teardown AP interface due to remote exception"); 867 return false; 868 } 869 if (!success) { 870 Log.e(TAG, "Failed to teardown AP interface"); 871 return false; 872 } 873 mApInterfaces.remove(ifaceName); 874 mApInterfaceListeners.remove(ifaceName); 875 return true; 876 } 877 878 /** 879 * Tear down all interfaces, whether clients (STA) or Soft AP. 880 * 881 * @return Returns true on success. 882 */ tearDownInterfaces()883 public boolean tearDownInterfaces() { 884 Log.d(TAG, "tearing down interfaces in wificond"); 885 // Explicitly refresh the wificodn handler because |tearDownInterfaces()| 886 // could be used to cleanup before we setup any interfaces. 887 if (!retrieveWificondAndRegisterForDeath()) { 888 return false; 889 } 890 891 try { 892 for (Map.Entry<String, IWifiScannerImpl> entry : mWificondScanners.entrySet()) { 893 entry.getValue().unsubscribeScanEvents(); 894 entry.getValue().unsubscribePnoScanEvents(); 895 } 896 mWificond.tearDownInterfaces(); 897 clearState(); 898 return true; 899 } catch (RemoteException e) { 900 Log.e(TAG, "Failed to tear down interfaces due to remote exception"); 901 } 902 903 return false; 904 } 905 906 /** Helper function to look up the interface handle using name */ getClientInterface(@onNull String ifaceName)907 private IClientInterface getClientInterface(@NonNull String ifaceName) { 908 return mClientInterfaces.get(ifaceName); 909 } 910 911 /** 912 * Request signal polling. 913 * 914 * @param ifaceName Name of the interface on which to poll. The interface must have been 915 * already set up using 916 *{@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)} 917 * or {@link #setupInterfaceForSoftApMode(String)}. 918 * 919 * @return A {@link SignalPollResult} object containing interface statistics, or a null on 920 * error (e.g. the interface hasn't been set up yet). 921 * 922 * @deprecated replaced by 923 * {@link com.android.server.wifi.SupplicantStaIfaceHal#getSignalPollResults} 924 */ 925 @Deprecated signalPoll(@onNull String ifaceName)926 @Nullable public SignalPollResult signalPoll(@NonNull String ifaceName) { 927 IClientInterface iface = getClientInterface(ifaceName); 928 if (iface == null) { 929 Log.e(TAG, "No valid wificond client interface handler for iface=" + ifaceName); 930 return null; 931 } 932 933 int[] resultArray; 934 try { 935 resultArray = iface.signalPoll(); 936 if (resultArray == null || resultArray.length != 4) { 937 Log.e(TAG, "Invalid signal poll result from wificond"); 938 return null; 939 } 940 } catch (RemoteException e) { 941 Log.e(TAG, "Failed to do signal polling due to remote exception"); 942 return null; 943 } 944 return new SignalPollResult(resultArray[0], resultArray[1], resultArray[3], resultArray[2]); 945 } 946 947 /** 948 * Get current transmit (Tx) packet counters of the specified interface. The interface must 949 * have been already set up using 950 * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)} 951 * or {@link #setupInterfaceForSoftApMode(String)}. 952 * 953 * @param ifaceName Name of the interface. 954 * @return {@link TxPacketCounters} of the current interface or null on error (e.g. when 955 * called before the interface has been set up). 956 */ getTxPacketCounters(@onNull String ifaceName)957 @Nullable public TxPacketCounters getTxPacketCounters(@NonNull String ifaceName) { 958 IClientInterface iface = getClientInterface(ifaceName); 959 if (iface == null) { 960 Log.e(TAG, "No valid wificond client interface handler for iface=" + ifaceName); 961 return null; 962 } 963 964 int[] resultArray; 965 try { 966 resultArray = iface.getPacketCounters(); 967 if (resultArray == null || resultArray.length != 2) { 968 Log.e(TAG, "Invalid signal poll result from wificond"); 969 return null; 970 } 971 } catch (RemoteException e) { 972 Log.e(TAG, "Failed to do signal polling due to remote exception"); 973 return null; 974 } 975 return new TxPacketCounters(resultArray[0], resultArray[1]); 976 } 977 978 /** Helper function to look up the scanner impl handle using name */ getScannerImpl(@onNull String ifaceName)979 private IWifiScannerImpl getScannerImpl(@NonNull String ifaceName) { 980 return mWificondScanners.get(ifaceName); 981 } 982 983 /** 984 * Fetch the latest scan results of the indicated type for the specified interface. Note that 985 * this method fetches the latest results - it does not initiate a scan. Initiating a scan can 986 * be done using {@link #startScan(String, int, Set, List)} or 987 * {@link #startPnoScan(String, PnoSettings, Executor, PnoScanRequestCallback)}. 988 * 989 * Note: The interface must have been already set up using 990 * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)} 991 * or {@link #setupInterfaceForSoftApMode(String)}. 992 * 993 * @param ifaceName Name of the interface. 994 * @param scanType The type of scan result to be returned, can be 995 * {@link #SCAN_TYPE_SINGLE_SCAN} or {@link #SCAN_TYPE_PNO_SCAN}. 996 * @return Returns an array of {@link NativeScanResult} or an empty array on failure (e.g. when 997 * called before the interface has been set up). 998 */ getScanResults(@onNull String ifaceName, @ScanResultType int scanType)999 @NonNull public List<NativeScanResult> getScanResults(@NonNull String ifaceName, 1000 @ScanResultType int scanType) { 1001 IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName); 1002 if (scannerImpl == null) { 1003 Log.e(TAG, "No valid wificond scanner interface handler for iface=" + ifaceName); 1004 return new ArrayList<>(); 1005 } 1006 List<NativeScanResult> results = null; 1007 try { 1008 if (scanType == SCAN_TYPE_SINGLE_SCAN) { 1009 results = Arrays.asList(scannerImpl.getScanResults()); 1010 } else { 1011 results = Arrays.asList(scannerImpl.getPnoScanResults()); 1012 } 1013 } catch (RemoteException e1) { 1014 Log.e(TAG, "Failed to create ScanDetail ArrayList"); 1015 } 1016 if (results == null) { 1017 results = new ArrayList<>(); 1018 } 1019 if (mVerboseLoggingEnabled) { 1020 Log.d(TAG, "get " + results.size() + " scan results from wificond"); 1021 } 1022 1023 return results; 1024 } 1025 1026 /** 1027 * Get the max number of SSIDs that the driver supports per scan. 1028 * 1029 * @param ifaceName Name of the interface. 1030 */ getMaxSsidsPerScan(@onNull String ifaceName)1031 public int getMaxSsidsPerScan(@NonNull String ifaceName) { 1032 IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName); 1033 if (scannerImpl == null) { 1034 Log.e(TAG, "No valid wificond scanner interface handler for iface=" + ifaceName); 1035 return 0; 1036 } 1037 try { 1038 return scannerImpl.getMaxSsidsPerScan(); 1039 } catch (RemoteException e1) { 1040 Log.e(TAG, "Failed to getMaxSsidsPerScan"); 1041 } 1042 return 0; 1043 } 1044 1045 /** 1046 * Return scan type for the parcelable {@link SingleScanSettings} 1047 */ getScanType(@ifiAnnotations.ScanType int scanType)1048 private static int getScanType(@WifiAnnotations.ScanType int scanType) { 1049 switch (scanType) { 1050 case WifiScanner.SCAN_TYPE_LOW_LATENCY: 1051 return IWifiScannerImpl.SCAN_TYPE_LOW_SPAN; 1052 case WifiScanner.SCAN_TYPE_LOW_POWER: 1053 return IWifiScannerImpl.SCAN_TYPE_LOW_POWER; 1054 case WifiScanner.SCAN_TYPE_HIGH_ACCURACY: 1055 return IWifiScannerImpl.SCAN_TYPE_HIGH_ACCURACY; 1056 default: 1057 throw new IllegalArgumentException("Invalid scan type " + scanType); 1058 } 1059 } 1060 1061 /** 1062 * @deprecated replaced by {@link #startScan(String, int, Set, List, Bundle)} 1063 **/ 1064 @Deprecated startScan(@onNull String ifaceName, @WifiAnnotations.ScanType int scanType, @Nullable Set<Integer> freqs, @Nullable List<byte[]> hiddenNetworkSSIDs)1065 public boolean startScan(@NonNull String ifaceName, @WifiAnnotations.ScanType int scanType, 1066 @Nullable Set<Integer> freqs, @Nullable List<byte[]> hiddenNetworkSSIDs) { 1067 return startScan(ifaceName, scanType, freqs, hiddenNetworkSSIDs, null); 1068 } 1069 1070 /** 1071 * @deprecated replaced by {@link #startScan2(String, int, Set, List, Bundle)} 1072 */ 1073 @Deprecated startScan(@onNull String ifaceName, @WifiAnnotations.ScanType int scanType, @SuppressLint(R) @Nullable Set<Integer> freqs, @SuppressLint(R) @Nullable List<byte[]> hiddenNetworkSSIDs, @SuppressLint(R) @Nullable Bundle extraScanningParams)1074 public boolean startScan(@NonNull String ifaceName, @WifiAnnotations.ScanType int scanType, 1075 @SuppressLint("NullableCollection") @Nullable Set<Integer> freqs, 1076 @SuppressLint("NullableCollection") @Nullable List<byte[]> hiddenNetworkSSIDs, 1077 @SuppressLint("NullableCollection") @Nullable Bundle extraScanningParams) { 1078 IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName); 1079 if (scannerImpl == null) { 1080 Log.e(TAG, "No valid wificond scanner interface handler for iface=" + ifaceName); 1081 return false; 1082 } 1083 SingleScanSettings settings = createSingleScanSettings(scanType, freqs, hiddenNetworkSSIDs, 1084 extraScanningParams); 1085 if (settings == null) { 1086 return false; 1087 } 1088 if (getInstantWifiMockable() != null) { 1089 getInstantWifiMockable().overrideFreqsForSingleScanSettingsIfNecessary(settings, 1090 getInstantWifiMockable().getPredictedScanningChannels()); 1091 } 1092 try { 1093 return scannerImpl.scan(settings); 1094 } catch (RemoteException e1) { 1095 Log.e(TAG, "Failed to request scan due to remote exception"); 1096 } 1097 return false; 1098 } 1099 1100 /** 1101 * Start a scan using the specified parameters. A scan is an asynchronous operation. The 1102 * result of the operation is returned in the {@link ScanEventCallback} registered when 1103 * setting up an interface using 1104 * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)}. 1105 * The latest scans can be obtained using {@link #getScanResults(String, int)} and using a 1106 * {@link #SCAN_TYPE_SINGLE_SCAN} for the {@code scanType}. 1107 * 1108 * Note: The interface must have been already set up using 1109 * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)} 1110 * or {@link #setupInterfaceForSoftApMode(String)}. 1111 * 1112 * @param ifaceName Name of the interface on which to initiate the scan. 1113 * @param scanType Type of scan to perform, can be any of 1114 * {@link WifiScanner#SCAN_TYPE_HIGH_ACCURACY}, {@link WifiScanner#SCAN_TYPE_LOW_POWER}, or 1115 * {@link WifiScanner#SCAN_TYPE_LOW_LATENCY}. 1116 * @param freqs list of frequencies to scan for, if null scan all supported channels. 1117 * @param hiddenNetworkSSIDs List of hidden networks to be scanned for, a null indicates that 1118 * no hidden frequencies will be scanned for. 1119 * @param extraScanningParams bundle of extra scanning parameters. 1120 * @return Returns one of the scan status codes defined in {@code WifiScanner#REASON_*} 1121 */ startScan2(@onNull String ifaceName, @WifiAnnotations.ScanType int scanType, @SuppressLint(R) @Nullable Set<Integer> freqs, @SuppressLint(R) @Nullable List<byte[]> hiddenNetworkSSIDs, @SuppressLint(R) @Nullable Bundle extraScanningParams)1122 public int startScan2(@NonNull String ifaceName, @WifiAnnotations.ScanType int scanType, 1123 @SuppressLint("NullableCollection") @Nullable Set<Integer> freqs, 1124 @SuppressLint("NullableCollection") @Nullable List<byte[]> hiddenNetworkSSIDs, 1125 @SuppressLint("NullableCollection") @Nullable Bundle extraScanningParams) { 1126 IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName); 1127 if (scannerImpl == null) { 1128 Log.e(TAG, "No valid wificond scanner interface handler for iface=" + ifaceName); 1129 return WifiScanner.REASON_INVALID_ARGS; 1130 } 1131 SingleScanSettings settings = createSingleScanSettings(scanType, freqs, hiddenNetworkSSIDs, 1132 extraScanningParams); 1133 if (settings == null) { 1134 return WifiScanner.REASON_INVALID_ARGS; 1135 } 1136 if (getInstantWifiMockable() != null) { 1137 getInstantWifiMockable().overrideFreqsForSingleScanSettingsIfNecessary(settings, 1138 getInstantWifiMockable().getPredictedScanningChannels()); 1139 } 1140 try { 1141 int status = scannerImpl.scanRequest(settings); 1142 return toFrameworkScanStatusCode(status); 1143 } catch (RemoteException e1) { 1144 Log.e(TAG, "Failed to request scan due to remote exception"); 1145 } 1146 return WifiScanner.REASON_UNSPECIFIED; 1147 } 1148 createSingleScanSettings(@ifiAnnotations.ScanType int scanType, @SuppressLint(R) @Nullable Set<Integer> freqs, @SuppressLint(R) @Nullable List<byte[]> hiddenNetworkSSIDs, @SuppressLint(R) @Nullable Bundle extraScanningParams)1149 private SingleScanSettings createSingleScanSettings(@WifiAnnotations.ScanType int scanType, 1150 @SuppressLint("NullableCollection") @Nullable Set<Integer> freqs, 1151 @SuppressLint("NullableCollection") @Nullable List<byte[]> hiddenNetworkSSIDs, 1152 @SuppressLint("NullableCollection") @Nullable Bundle extraScanningParams) { 1153 SingleScanSettings settings = new SingleScanSettings(); 1154 try { 1155 settings.scanType = getScanType(scanType); 1156 } catch (IllegalArgumentException e) { 1157 Log.e(TAG, "Invalid scan type ", e); 1158 return null; 1159 } 1160 settings.channelSettings = new ArrayList<>(); 1161 settings.hiddenNetworks = new ArrayList<>(); 1162 if (extraScanningParams != null) { 1163 settings.enable6GhzRnr = extraScanningParams.getBoolean(SCANNING_PARAM_ENABLE_6GHZ_RNR); 1164 settings.vendorIes = extraScanningParams.getByteArray(EXTRA_SCANNING_PARAM_VENDOR_IES); 1165 } 1166 1167 if (freqs != null) { 1168 for (Integer freq : freqs) { 1169 ChannelSettings channel = new ChannelSettings(); 1170 channel.frequency = freq; 1171 settings.channelSettings.add(channel); 1172 } 1173 } 1174 if (hiddenNetworkSSIDs != null) { 1175 for (byte[] ssid : hiddenNetworkSSIDs) { 1176 HiddenNetwork network = new HiddenNetwork(); 1177 network.ssid = ssid; 1178 1179 // settings.hiddenNetworks is expected to be very small, so this shouldn't cause 1180 // any performance issues. 1181 if (!settings.hiddenNetworks.contains(network)) { 1182 settings.hiddenNetworks.add(network); 1183 } 1184 } 1185 } 1186 1187 return settings; 1188 } 1189 toFrameworkScanStatusCode(int scanStatus)1190 private int toFrameworkScanStatusCode(int scanStatus) { 1191 switch(scanStatus) { 1192 case IWifiScannerImpl.SCAN_STATUS_SUCCESS: 1193 return WifiScanner.REASON_SUCCEEDED; 1194 case IWifiScannerImpl.SCAN_STATUS_FAILED_BUSY: 1195 return WifiScanner.REASON_BUSY; 1196 case IWifiScannerImpl.SCAN_STATUS_FAILED_ABORT: 1197 return WifiScanner.REASON_ABORT; 1198 case IWifiScannerImpl.SCAN_STATUS_FAILED_NODEV: 1199 return WifiScanner.REASON_NO_DEVICE; 1200 case IWifiScannerImpl.SCAN_STATUS_FAILED_INVALID_ARGS: 1201 return WifiScanner.REASON_INVALID_ARGS; 1202 case IWifiScannerImpl.SCAN_STATUS_FAILED_GENERIC: 1203 default: 1204 return WifiScanner.REASON_UNSPECIFIED; 1205 } 1206 } 1207 1208 /** 1209 * Request a PNO (Preferred Network Offload). The offload request and the scans are asynchronous 1210 * operations. The result of the request are returned in the {@code callback} parameter which 1211 * is an {@link PnoScanRequestCallback}. The scan results are are return in the 1212 * {@link ScanEventCallback} which is registered when setting up an interface using 1213 * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)}. 1214 * The latest PNO scans can be obtained using {@link #getScanResults(String, int)} with the 1215 * {@code scanType} set to {@link #SCAN_TYPE_PNO_SCAN}. 1216 * 1217 * Note: The interface must have been already set up using 1218 * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)} 1219 * or {@link #setupInterfaceForSoftApMode(String)}. 1220 * 1221 * @param ifaceName Name of the interface on which to request a PNO. 1222 * @param pnoSettings PNO scan configuration. 1223 * @param executor The Executor on which to execute the callback. 1224 * @param callback Callback for the results of the offload request. 1225 * @return true on success, false on failure (e.g. when called before the interface has been set 1226 * up). 1227 */ startPnoScan(@onNull String ifaceName, @NonNull PnoSettings pnoSettings, @NonNull @CallbackExecutor Executor executor, @NonNull PnoScanRequestCallback callback)1228 public boolean startPnoScan(@NonNull String ifaceName, @NonNull PnoSettings pnoSettings, 1229 @NonNull @CallbackExecutor Executor executor, 1230 @NonNull PnoScanRequestCallback callback) { 1231 IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName); 1232 if (scannerImpl == null) { 1233 Log.e(TAG, "No valid wificond scanner interface handler for iface=" + ifaceName); 1234 return false; 1235 } 1236 1237 if (callback == null || executor == null) { 1238 Log.e(TAG, "startPnoScan called with a null callback"); 1239 return false; 1240 } 1241 1242 try { 1243 boolean success = scannerImpl.startPnoScan(pnoSettings); 1244 if (success) { 1245 executor.execute(callback::onPnoRequestSucceeded); 1246 } else { 1247 executor.execute(callback::onPnoRequestFailed); 1248 } 1249 return success; 1250 } catch (RemoteException e1) { 1251 Log.e(TAG, "Failed to start pno scan due to remote exception"); 1252 } 1253 return false; 1254 } 1255 1256 /** 1257 * Stop PNO scan configured with 1258 * {@link #startPnoScan(String, PnoSettings, Executor, PnoScanRequestCallback)}. 1259 * 1260 * Note: The interface must have been already set up using 1261 * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)} 1262 * or {@link #setupInterfaceForSoftApMode(String)}. 1263 * 1264 * @param ifaceName Name of the interface on which the PNO scan was configured. 1265 * @return true on success, false on failure (e.g. when called before the interface has been 1266 * set up). 1267 */ stopPnoScan(@onNull String ifaceName)1268 public boolean stopPnoScan(@NonNull String ifaceName) { 1269 IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName); 1270 if (scannerImpl == null) { 1271 Log.e(TAG, "No valid wificond scanner interface handler for iface=" + ifaceName); 1272 return false; 1273 } 1274 try { 1275 return scannerImpl.stopPnoScan(); 1276 } catch (RemoteException e1) { 1277 Log.e(TAG, "Failed to stop pno scan due to remote exception"); 1278 } 1279 return false; 1280 } 1281 1282 /** 1283 * Abort ongoing single scan started with {@link #startScan(String, int, Set, List)}. No failure 1284 * callback, e.g. {@link ScanEventCallback#onScanFailed()}, is triggered by this operation. 1285 * 1286 * Note: The interface must have been already set up using 1287 * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)} 1288 * or {@link #setupInterfaceForSoftApMode(String)}. If the interface has not been set up then 1289 * this method has no impact. 1290 * 1291 * @param ifaceName Name of the interface on which the scan was started. 1292 */ abortScan(@onNull String ifaceName)1293 public void abortScan(@NonNull String ifaceName) { 1294 IWifiScannerImpl scannerImpl = getScannerImpl(ifaceName); 1295 if (scannerImpl == null) { 1296 Log.e(TAG, "No valid wificond scanner interface handler for iface=" + ifaceName); 1297 return; 1298 } 1299 try { 1300 scannerImpl.abortScan(); 1301 } catch (RemoteException e1) { 1302 Log.e(TAG, "Failed to request abortScan due to remote exception"); 1303 } 1304 } 1305 1306 /** 1307 * Query the list of valid frequencies (in MHz) for the provided band. 1308 * The result depends on the on the country code that has been set. 1309 * 1310 * @param band as specified by one of the WifiScanner.WIFI_BAND_* constants. 1311 * The following bands are supported: 1312 * {@link WifiScanner#WIFI_BAND_24_GHZ}, 1313 * {@link WifiScanner#WIFI_BAND_5_GHZ}, 1314 * {@link WifiScanner#WIFI_BAND_5_GHZ_DFS_ONLY}, 1315 * {@link WifiScanner#WIFI_BAND_6_GHZ} 1316 * {@link WifiScanner.WIFI_BAND_60_GHZ} 1317 * @return frequencies vector of valid frequencies (MHz), or an empty array for error. 1318 * @throws IllegalArgumentException if band is not recognized. 1319 */ getChannelsMhzForBand(@ifiAnnotations.WifiBandBasic int band)1320 public @NonNull int[] getChannelsMhzForBand(@WifiAnnotations.WifiBandBasic int band) { 1321 if (mWificond == null) { 1322 Log.e(TAG, "getChannelsMhzForBand: mWificond binder is null! Did wificond die?"); 1323 return new int[0]; 1324 } 1325 int[] result = null; 1326 try { 1327 switch (band) { 1328 case WifiScanner.WIFI_BAND_24_GHZ: 1329 result = mWificond.getAvailable2gChannels(); 1330 break; 1331 case WifiScanner.WIFI_BAND_5_GHZ: 1332 result = mWificond.getAvailable5gNonDFSChannels(); 1333 break; 1334 case WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY: 1335 result = mWificond.getAvailableDFSChannels(); 1336 break; 1337 case WifiScanner.WIFI_BAND_6_GHZ: 1338 result = mWificond.getAvailable6gChannels(); 1339 break; 1340 case WifiScanner.WIFI_BAND_60_GHZ: 1341 result = mWificond.getAvailable60gChannels(); 1342 break; 1343 default: 1344 throw new IllegalArgumentException("unsupported band " + band); 1345 } 1346 } catch (RemoteException e1) { 1347 Log.e(TAG, "Failed to request getChannelsForBand due to remote exception"); 1348 } 1349 if (result == null) { 1350 result = new int[0]; 1351 } 1352 return result; 1353 } 1354 1355 /** Helper function to look up the interface handle using name */ getApInterface(@onNull String ifaceName)1356 private IApInterface getApInterface(@NonNull String ifaceName) { 1357 return mApInterfaces.get(ifaceName); 1358 } 1359 1360 /** 1361 * Get the device phy capabilities for a given interface. 1362 * 1363 * Note: The interface must have been already set up using 1364 * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)} 1365 * or {@link #setupInterfaceForSoftApMode(String)}. 1366 * 1367 * @return DeviceWiphyCapabilities or null on error (e.g. when called on an interface which has 1368 * not been set up). 1369 */ getDeviceWiphyCapabilities(@onNull String ifaceName)1370 @Nullable public DeviceWiphyCapabilities getDeviceWiphyCapabilities(@NonNull String ifaceName) { 1371 if (mWificond == null) { 1372 Log.e(TAG, "getDeviceWiphyCapabilities: mWificond binder is null! Did wificond die?"); 1373 return null; 1374 } 1375 1376 try { 1377 return mWificond.getDeviceWiphyCapabilities(ifaceName); 1378 } catch (RemoteException e) { 1379 return null; 1380 } 1381 } 1382 1383 /** 1384 * Register the provided listener for country code event. 1385 * 1386 * @param executor The Executor on which to execute the callbacks. 1387 * @param listener listener for country code changed events. 1388 * @return true on success, false on failure. 1389 */ registerCountryCodeChangedListener(@onNull @allbackExecutor Executor executor, @NonNull CountryCodeChangedListener listener)1390 public boolean registerCountryCodeChangedListener(@NonNull @CallbackExecutor Executor executor, 1391 @NonNull CountryCodeChangedListener listener) { 1392 if (!retrieveWificondAndRegisterForDeath()) { 1393 return false; 1394 } 1395 Log.d(TAG, "registerCountryCodeEventListener called"); 1396 mWificondEventHandler.registerCountryCodeChangedListener(executor, listener); 1397 return true; 1398 } 1399 1400 1401 /** 1402 * Unregister CountryCodeChangedListener with pid. 1403 * 1404 * @param listener listener which registered country code changed events. 1405 */ unregisterCountryCodeChangedListener(@onNull CountryCodeChangedListener listener)1406 public void unregisterCountryCodeChangedListener(@NonNull CountryCodeChangedListener listener) { 1407 Log.d(TAG, "unregisterCountryCodeEventListener called"); 1408 mWificondEventHandler.unregisterCountryCodeChangedListener(listener); 1409 } 1410 1411 /** 1412 * Notifies the wificond daemon that the WiFi framework has successfully updated the Country 1413 * Code of the driver. The wificond daemon needs this notification if the device does not 1414 * support the NL80211_CMD_REG_CHANGED (otherwise it will find out on its own). The wificond 1415 * updates in internal state in response to this Country Code update. 1416 * 1417 * @param newCountryCode new country code. An ISO-3166-alpha2 country code which is 2-Character 1418 * alphanumeric. 1419 */ notifyCountryCodeChanged(@ullable String newCountryCode)1420 public void notifyCountryCodeChanged(@Nullable String newCountryCode) { 1421 if (mWificond == null) { 1422 new RemoteException("Wificond service doesn't exist!").rethrowFromSystemServer(); 1423 } 1424 try { 1425 mWificond.notifyCountryCodeChanged(); 1426 Log.i(TAG, "Receive country code change to " + newCountryCode); 1427 } catch (RemoteException re) { 1428 re.rethrowFromSystemServer(); 1429 } 1430 } 1431 1432 /** 1433 * Register the provided callback handler for SoftAp events. The interface must first be created 1434 * using {@link #setupInterfaceForSoftApMode(String)}. The callback registration is valid until 1435 * the interface is deleted using {@link #tearDownSoftApInterface(String)} (no deregistration 1436 * method is provided). 1437 * <p> 1438 * Note that only one callback can be registered at a time - any registration overrides previous 1439 * registrations. 1440 * 1441 * @param ifaceName Name of the interface on which to register the callback. 1442 * @param executor The Executor on which to execute the callbacks. 1443 * @param callback Callback for AP events. 1444 * @return true on success, false on failure (e.g. when called on an interface which has not 1445 * been set up). 1446 * 1447 * @deprecated The usage is replaced by vendor HAL 1448 * {@code android.hardware.wifi.hostapd.V1_3.IHostapdCallback}. 1449 */ 1450 @Deprecated registerApCallback(@onNull String ifaceName, @NonNull @CallbackExecutor Executor executor, @NonNull SoftApCallback callback)1451 public boolean registerApCallback(@NonNull String ifaceName, 1452 @NonNull @CallbackExecutor Executor executor, 1453 @NonNull SoftApCallback callback) { 1454 IApInterface iface = getApInterface(ifaceName); 1455 if (iface == null) { 1456 Log.e(TAG, "No valid ap interface handler for iface=" + ifaceName); 1457 return false; 1458 } 1459 1460 if (callback == null || executor == null) { 1461 Log.e(TAG, "registerApCallback called with a null callback"); 1462 return false; 1463 } 1464 1465 try { 1466 IApInterfaceEventCallback wificondCallback = new ApInterfaceEventCallback(executor, 1467 callback); 1468 mApInterfaceListeners.put(ifaceName, wificondCallback); 1469 boolean success = iface.registerCallback(wificondCallback); 1470 if (!success) { 1471 Log.e(TAG, "Failed to register ap callback."); 1472 return false; 1473 } 1474 } catch (RemoteException e) { 1475 Log.e(TAG, "Exception in registering AP callback: " + e); 1476 return false; 1477 } 1478 return true; 1479 } 1480 1481 /** 1482 * Send a management frame on the specified interface at the specified rate. Useful for probing 1483 * the link with arbitrary frames. 1484 * 1485 * Note: The interface must have been already set up using 1486 * {@link #setupInterfaceForClientMode(String, Executor, ScanEventCallback, ScanEventCallback)} 1487 * or {@link #setupInterfaceForSoftApMode(String)}. 1488 * 1489 * @param ifaceName The interface on which to send the frame. 1490 * @param frame The raw byte array of the management frame to tramit. 1491 * @param mcs The MCS (modulation and coding scheme), i.e. rate, at which to transmit the 1492 * frame. Specified per IEEE 802.11. 1493 * @param executor The Executor on which to execute the callbacks. 1494 * @param callback A {@link SendMgmtFrameCallback} callback for results of the operation. 1495 */ sendMgmtFrame(@onNull String ifaceName, @NonNull byte[] frame, int mcs, @NonNull @CallbackExecutor Executor executor, @NonNull SendMgmtFrameCallback callback)1496 public void sendMgmtFrame(@NonNull String ifaceName, @NonNull byte[] frame, int mcs, 1497 @NonNull @CallbackExecutor Executor executor, 1498 @NonNull SendMgmtFrameCallback callback) { 1499 1500 if (callback == null || executor == null) { 1501 Log.e(TAG, "callback cannot be null!"); 1502 return; 1503 } 1504 1505 if (frame == null) { 1506 Log.e(TAG, "frame cannot be null!"); 1507 executor.execute(() -> callback.onFailure(SEND_MGMT_FRAME_ERROR_UNKNOWN)); 1508 return; 1509 } 1510 1511 // TODO (b/112029045) validate mcs 1512 IClientInterface clientInterface = getClientInterface(ifaceName); 1513 if (clientInterface == null) { 1514 Log.e(TAG, "No valid wificond client interface handler for iface=" + ifaceName); 1515 executor.execute(() -> callback.onFailure(SEND_MGMT_FRAME_ERROR_UNKNOWN)); 1516 return; 1517 } 1518 1519 if (!mSendMgmtFrameInProgress.compareAndSet(false, true)) { 1520 Log.e(TAG, "An existing management frame transmission is in progress!"); 1521 executor.execute(() -> callback.onFailure(SEND_MGMT_FRAME_ERROR_ALREADY_STARTED)); 1522 return; 1523 } 1524 1525 SendMgmtFrameEvent sendMgmtFrameEvent = new SendMgmtFrameEvent(executor, callback); 1526 try { 1527 clientInterface.SendMgmtFrame(frame, sendMgmtFrameEvent, mcs); 1528 } catch (RemoteException e) { 1529 Log.e(TAG, "Exception while starting link probe: " + e); 1530 // Call sendMgmtFrameEvent.OnFailure() instead of callback.onFailure() so that 1531 // sendMgmtFrameEvent can clean up internal state, such as cancelling the timer. 1532 sendMgmtFrameEvent.OnFailure(SEND_MGMT_FRAME_ERROR_UNKNOWN); 1533 } 1534 } 1535 1536 /** 1537 * Clear all internal handles. 1538 */ clearState()1539 private void clearState() { 1540 // Refresh handlers 1541 mClientInterfaces.clear(); 1542 mWificondScanners.clear(); 1543 mPnoScanEventHandlers.clear(); 1544 mScanEventHandlers.clear(); 1545 mApInterfaces.clear(); 1546 mApInterfaceListeners.clear(); 1547 mSendMgmtFrameInProgress.set(false); 1548 } 1549 1550 /** 1551 * OEM parsed security type 1552 */ 1553 public static class OemSecurityType { 1554 /** The protocol defined in {@link android.net.wifi.WifiAnnotations.Protocol}. */ 1555 public final @WifiAnnotations.Protocol int protocol; 1556 /** 1557 * Supported key management types defined 1558 * in {@link android.net.wifi.WifiAnnotations.KeyMgmt}. 1559 */ 1560 @NonNull public final List<Integer> keyManagement; 1561 /** 1562 * Supported pairwise cipher types defined 1563 * in {@link android.net.wifi.WifiAnnotations.Cipher}. 1564 */ 1565 @NonNull public final List<Integer> pairwiseCipher; 1566 /** The group cipher type defined in {@link android.net.wifi.WifiAnnotations.Cipher}. */ 1567 public final @WifiAnnotations.Cipher int groupCipher; 1568 /** 1569 * Default constructor for OemSecurityType 1570 * 1571 * @param protocol The protocol defined in 1572 * {@link android.net.wifi.WifiAnnotations.Protocol}. 1573 * @param keyManagement Supported key management types defined 1574 * in {@link android.net.wifi.WifiAnnotations.KeyMgmt}. 1575 * @param pairwiseCipher Supported pairwise cipher types defined 1576 * in {@link android.net.wifi.WifiAnnotations.Cipher}. 1577 * @param groupCipher The group cipher type defined 1578 * in {@link android.net.wifi.WifiAnnotations.Cipher}. 1579 */ OemSecurityType( @ifiAnnotations.Protocol int protocol, @NonNull List<Integer> keyManagement, @NonNull List<Integer> pairwiseCipher, @WifiAnnotations.Cipher int groupCipher)1580 public OemSecurityType( 1581 @WifiAnnotations.Protocol int protocol, 1582 @NonNull List<Integer> keyManagement, 1583 @NonNull List<Integer> pairwiseCipher, 1584 @WifiAnnotations.Cipher int groupCipher) { 1585 this.protocol = protocol; 1586 this.keyManagement = (keyManagement != null) 1587 ? keyManagement : new ArrayList<Integer>(); 1588 this.pairwiseCipher = (pairwiseCipher != null) 1589 ? pairwiseCipher : new ArrayList<Integer>(); 1590 this.groupCipher = groupCipher; 1591 } 1592 } 1593 1594 /** 1595 * OEM information element parser for security types not parsed by the framework. 1596 * 1597 * The OEM method should use the method inputs {@code id}, {@code idExt}, and {@code bytes} 1598 * to perform the parsing. The method should place the results in an OemSecurityType objct. 1599 * 1600 * @param id The information element id. 1601 * @param idExt The information element extension id. This is valid only when id is 1602 * the extension id, {@code 255}. 1603 * @param bytes The raw bytes of information element data, 'Element ID' and 'Length' are 1604 * stripped off already. 1605 * @return an OemSecurityType object if this IE is parsed successfully, null otherwise. 1606 */ parseOemSecurityTypeElement( int id, int idExt, @NonNull byte[] bytes)1607 @Nullable public static OemSecurityType parseOemSecurityTypeElement( 1608 int id, 1609 int idExt, 1610 @NonNull byte[] bytes) { 1611 return null; 1612 } 1613 } 1614