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