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