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