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.NonNull;
20 import android.annotation.Nullable;
21 import android.hardware.wifi.V1_0.IWifi;
22 import android.hardware.wifi.V1_0.IWifiApIface;
23 import android.hardware.wifi.V1_0.IWifiChip;
24 import android.hardware.wifi.V1_0.IWifiChipEventCallback;
25 import android.hardware.wifi.V1_0.IWifiEventCallback;
26 import android.hardware.wifi.V1_0.IWifiIface;
27 import android.hardware.wifi.V1_0.IWifiNanIface;
28 import android.hardware.wifi.V1_0.IWifiP2pIface;
29 import android.hardware.wifi.V1_0.IWifiRttController;
30 import android.hardware.wifi.V1_0.IWifiStaIface;
31 import android.hardware.wifi.V1_0.IfaceType;
32 import android.hardware.wifi.V1_0.WifiDebugRingBufferStatus;
33 import android.hardware.wifi.V1_0.WifiStatus;
34 import android.hardware.wifi.V1_0.WifiStatusCode;
35 import android.hidl.manager.V1_0.IServiceNotification;
36 import android.hidl.manager.V1_2.IServiceManager;
37 import android.os.Handler;
38 import android.os.HidlSupport.Mutable;
39 import android.os.HwRemoteBinder;
40 import android.os.Looper;
41 import android.os.RemoteException;
42 import android.util.Log;
43 import android.util.LongSparseArray;
44 import android.util.MutableBoolean;
45 import android.util.MutableInt;
46 import android.util.Pair;
47 import android.util.SparseArray;
48 
49 import com.android.internal.annotations.VisibleForTesting;
50 
51 import java.io.FileDescriptor;
52 import java.io.PrintWriter;
53 import java.util.ArrayList;
54 import java.util.Arrays;
55 import java.util.HashMap;
56 import java.util.HashSet;
57 import java.util.Iterator;
58 import java.util.List;
59 import java.util.Map;
60 import java.util.Set;
61 
62 /**
63  * Handles device management through the HAL (HIDL) interface.
64  */
65 public class HalDeviceManager {
66     private static final String TAG = "HalDevMgr";
67     private static final boolean VDBG = false;
68     private boolean mDbg = false;
69 
70     private static final int START_HAL_RETRY_INTERVAL_MS = 20;
71     // Number of attempts a start() is re-tried. A value of 0 means no retries after a single
72     // attempt.
73     @VisibleForTesting
74     public static final int START_HAL_RETRY_TIMES = 3;
75 
76     private final Clock mClock;
77     private final Handler mEventHandler;
78     private WifiDeathRecipient mIWifiDeathRecipient;
79     private ServiceManagerDeathRecipient mServiceManagerDeathRecipient;
80 
81     // cache the value for supporting vendor HAL or not
82     private boolean mIsVendorHalSupported = false;
83 
84     // public API
HalDeviceManager(Clock clock, Looper looper)85     public HalDeviceManager(Clock clock, Looper looper) {
86         mClock = clock;
87         mEventHandler = new Handler(looper);
88         mIWifiDeathRecipient = new WifiDeathRecipient();
89         mServiceManagerDeathRecipient = new ServiceManagerDeathRecipient();
90 
91         mInterfaceAvailableForRequestListeners.put(IfaceType.STA, new HashMap<>());
92         mInterfaceAvailableForRequestListeners.put(IfaceType.AP, new HashMap<>());
93         mInterfaceAvailableForRequestListeners.put(IfaceType.P2P, new HashMap<>());
94         mInterfaceAvailableForRequestListeners.put(IfaceType.NAN, new HashMap<>());
95     }
96 
enableVerboseLogging(int verbose)97     /* package */ void enableVerboseLogging(int verbose) {
98         if (verbose > 0) {
99             mDbg = true;
100         } else {
101             mDbg = false;
102         }
103         if (VDBG) {
104             mDbg = true; // just override
105         }
106     }
107 
108     /**
109      * Actually starts the HalDeviceManager: separate from constructor since may want to phase
110      * at a later time.
111      *
112      * TODO: if decide that no need for separating construction from initialization (e.g. both are
113      * done at injector) then move to constructor.
114      */
initialize()115     public void initialize() {
116         initializeInternal();
117     }
118 
119     /**
120      * Register a ManagerStatusListener to get information about the status of the manager. Use the
121      * isReady() and isStarted() methods to check status immediately after registration and when
122      * triggered.
123      *
124      * It is safe to re-register the same callback object - duplicates are detected and only a
125      * single copy kept.
126      *
127      * @param listener ManagerStatusListener listener object.
128      * @param handler Handler on which to dispatch listener. Null implies the listener will be
129      *                invoked synchronously from the context of the client which triggered the
130      *                state change.
131      */
registerStatusListener(@onNull ManagerStatusListener listener, @Nullable Handler handler)132     public void registerStatusListener(@NonNull ManagerStatusListener listener,
133             @Nullable Handler handler) {
134         synchronized (mLock) {
135             if (!mManagerStatusListeners.add(new ManagerStatusListenerProxy(listener, handler))) {
136                 Log.w(TAG, "registerStatusListener: duplicate registration ignored");
137             }
138         }
139     }
140 
141     /**
142      * Returns whether the vendor HAL is supported on this device or not.
143      */
isSupported()144     public boolean isSupported() {
145         return mIsVendorHalSupported;
146     }
147 
148     /**
149      * Returns the current status of the HalDeviceManager: whether or not it is ready to execute
150      * commands. A return of 'false' indicates that the HAL service (IWifi) is not available. Use
151      * the registerStatusListener() to listener for status changes.
152      */
isReady()153     public boolean isReady() {
154         return mIsReady;
155     }
156 
157     /**
158      * Returns the current status of Wi-Fi: started (true) or stopped (false).
159      *
160      * Note: direct call to HIDL.
161      */
isStarted()162     public boolean isStarted() {
163         return isWifiStarted();
164     }
165 
166     /**
167      * Attempts to start Wi-Fi (using HIDL). Returns the success (true) or failure (false) or
168      * the start operation. Will also dispatch any registered ManagerStatusCallback.onStart() on
169      * success.
170      *
171      * Note: direct call to HIDL.
172      */
start()173     public boolean start() {
174         return startWifi();
175     }
176 
177     /**
178      * Stops Wi-Fi. Will also dispatch any registeredManagerStatusCallback.onStop().
179      *
180      * Note: direct call to HIDL - failure is not-expected.
181      */
stop()182     public void stop() {
183         stopWifi();
184         mWifi = null;
185     }
186 
187     /**
188      * HAL device manager status change listener.
189      */
190     public interface ManagerStatusListener {
191         /**
192          * Indicates that the status of the HalDeviceManager has changed. Use isReady() and
193          * isStarted() to obtain status information.
194          */
onStatusChanged()195         void onStatusChanged();
196     }
197 
198     /**
199      * Return the set of supported interface types across all Wi-Fi chips on the device.
200      *
201      * @return A set of IfaceTypes constants (possibly empty, e.g. on error).
202      */
getSupportedIfaceTypes()203     public Set<Integer> getSupportedIfaceTypes() {
204         return getSupportedIfaceTypesInternal(null);
205     }
206 
207     /**
208      * Return the set of supported interface types for the specified Wi-Fi chip.
209      *
210      * @return A set of IfaceTypes constants  (possibly empty, e.g. on error).
211      */
getSupportedIfaceTypes(IWifiChip chip)212     public Set<Integer> getSupportedIfaceTypes(IWifiChip chip) {
213         return getSupportedIfaceTypesInternal(chip);
214     }
215 
216     // interface-specific behavior
217 
218     /**
219      * Create a STA interface if possible. Changes chip mode and removes conflicting interfaces if
220      * needed and permitted by priority.
221      *
222      * @param lowPrioritySta Indicates whether the requested STA is a low priority STA. The priority
223      *                       and preemption rules for low priority STA are:
224      *                       - Do not destroy any interface for it (even another low priority STA)
225      *                       - Destroy it for any other request
226      * @param destroyedListener Optional (nullable) listener to call when the allocated interface
227      *                          is removed. Will only be registered and used if an interface is
228      *                          created successfully.
229      * @param handler Handler on which to dispatch listener. Null implies the listener will be
230      *                invoked synchronously from the context of the client which triggered the
231      *                iface destruction.
232      * @return A newly created interface - or null if the interface could not be created.
233      */
createStaIface(boolean lowPrioritySta, @Nullable InterfaceDestroyedListener destroyedListener, @Nullable Handler handler)234     public IWifiStaIface createStaIface(boolean lowPrioritySta,
235             @Nullable InterfaceDestroyedListener destroyedListener, @Nullable Handler handler) {
236         return (IWifiStaIface) createIface(IfaceType.STA, lowPrioritySta, destroyedListener,
237                 handler);
238     }
239 
240     /**
241      * Create AP interface if possible (see createStaIface doc).
242      */
createApIface(@ullable InterfaceDestroyedListener destroyedListener, @Nullable Handler handler)243     public IWifiApIface createApIface(@Nullable InterfaceDestroyedListener destroyedListener,
244             @Nullable Handler handler) {
245         return (IWifiApIface) createIface(IfaceType.AP, false, destroyedListener, handler);
246     }
247 
248     /**
249      * Create P2P interface if possible (see createStaIface doc).
250      */
createP2pIface(@ullable InterfaceDestroyedListener destroyedListener, @Nullable Handler handler)251     public IWifiP2pIface createP2pIface(@Nullable InterfaceDestroyedListener destroyedListener,
252             @Nullable Handler handler) {
253         return (IWifiP2pIface) createIface(IfaceType.P2P, false, destroyedListener, handler);
254     }
255 
256     /**
257      * Create NAN interface if possible (see createStaIface doc).
258      */
createNanIface(@ullable InterfaceDestroyedListener destroyedListener, @Nullable Handler handler)259     public IWifiNanIface createNanIface(@Nullable InterfaceDestroyedListener destroyedListener,
260             @Nullable Handler handler) {
261         return (IWifiNanIface) createIface(IfaceType.NAN, false, destroyedListener, handler);
262     }
263 
264     /**
265      * Removes (releases/destroys) the given interface. Will trigger any registered
266      * InterfaceDestroyedListeners and possibly some InterfaceAvailableForRequestListeners if we
267      * can potentially create some other interfaces as a result of removing this interface.
268      */
removeIface(IWifiIface iface)269     public boolean removeIface(IWifiIface iface) {
270         boolean success = removeIfaceInternal(iface);
271         dispatchAvailableForRequestListeners();
272         return success;
273     }
274 
275     /**
276      * Returns the IWifiChip corresponding to the specified interface (or null on error).
277      *
278      * Note: clients must not perform chip mode changes or interface management (create/delete)
279      * operations on IWifiChip directly. However, they can use the IWifiChip interface to perform
280      * other functions - e.g. calling the debug/trace methods.
281      */
getChip(IWifiIface iface)282     public IWifiChip getChip(IWifiIface iface) {
283         String name = getName(iface);
284         int type = getType(iface);
285         if (VDBG) Log.d(TAG, "getChip: iface(name)=" + name);
286 
287         synchronized (mLock) {
288             InterfaceCacheEntry cacheEntry = mInterfaceInfoCache.get(Pair.create(name, type));
289             if (cacheEntry == null) {
290                 Log.e(TAG, "getChip: no entry for iface(name)=" + name);
291                 return null;
292             }
293 
294             return cacheEntry.chip;
295         }
296     }
297 
298     /**
299      * Register an InterfaceDestroyedListener to the specified iface - returns true on success
300      * and false on failure. This listener is in addition to the one registered when the interface
301      * was created - allowing non-creators to monitor interface status.
302      *
303      * @param destroyedListener Listener to call when the allocated interface is removed.
304      *                          Will only be registered and used if an interface is created
305      *                          successfully.
306      * @param handler Handler on which to dispatch listener. Null implies the listener will be
307      *                invoked synchronously from the context of the client which triggered the
308      *                iface destruction.
309      */
registerDestroyedListener(IWifiIface iface, @NonNull InterfaceDestroyedListener destroyedListener, @Nullable Handler handler)310     public boolean registerDestroyedListener(IWifiIface iface,
311             @NonNull InterfaceDestroyedListener destroyedListener,
312             @Nullable Handler handler) {
313         String name = getName(iface);
314         int type = getType(iface);
315         if (VDBG) Log.d(TAG, "registerDestroyedListener: iface(name)=" + name);
316 
317         synchronized (mLock) {
318             InterfaceCacheEntry cacheEntry = mInterfaceInfoCache.get(Pair.create(name, type));
319             if (cacheEntry == null) {
320                 Log.e(TAG, "registerDestroyedListener: no entry for iface(name)=" + name);
321                 return false;
322             }
323 
324             return cacheEntry.destroyedListeners.add(
325                     new InterfaceDestroyedListenerProxy(name, destroyedListener, handler));
326         }
327     }
328 
329     /**
330      * Register a listener to be called when an interface of the specified type could be requested.
331      * No guarantees are provided (some other entity could request it first). The listener is
332      * active from registration until unregistration - using
333      * unregisterInterfaceAvailableForRequestListener().
334      *
335      * Only a single instance of a listener will be registered (even if the specified looper is
336      * different).
337      *
338      * Note that if it is possible to create the specified interface type at registration time
339      * then the callback will be triggered immediately.
340      *
341      * @param ifaceType The interface type (IfaceType) to be monitored.
342      * @param listener Listener to call when an interface of the requested
343      *                 type could be created
344      * @param handler Handler on which to dispatch listener. Null implies the listener will be
345      *                invoked synchronously from the context of the client which triggered the
346      *                mode change.
347      */
registerInterfaceAvailableForRequestListener(int ifaceType, @NonNull InterfaceAvailableForRequestListener listener, @Nullable Handler handler)348     public void registerInterfaceAvailableForRequestListener(int ifaceType,
349             @NonNull InterfaceAvailableForRequestListener listener, @Nullable Handler handler) {
350         if (VDBG) {
351             Log.d(TAG, "registerInterfaceAvailableForRequestListener: ifaceType=" + ifaceType
352                     + ", listener=" + listener + ", handler=" + handler);
353         }
354 
355         synchronized (mLock) {
356             InterfaceAvailableForRequestListenerProxy proxy =
357                     new InterfaceAvailableForRequestListenerProxy(listener, handler);
358             if (mInterfaceAvailableForRequestListeners.get(ifaceType).containsKey(proxy)) {
359                 if (VDBG) {
360                     Log.d(TAG,
361                             "registerInterfaceAvailableForRequestListener: dup listener skipped: "
362                                     + listener);
363                 }
364                 return;
365             }
366             mInterfaceAvailableForRequestListeners.get(ifaceType).put(proxy, null);
367         }
368 
369         WifiChipInfo[] chipInfos = getAllChipInfo();
370         if (chipInfos == null) {
371             Log.e(TAG,
372                     "registerInterfaceAvailableForRequestListener: no chip info found - but "
373                             + "possibly registered pre-started - ignoring");
374             return;
375         }
376         dispatchAvailableForRequestListenersForType(ifaceType, chipInfos);
377     }
378 
379     /**
380      * Unregisters a listener registered with registerInterfaceAvailableForRequestListener().
381      */
unregisterInterfaceAvailableForRequestListener( int ifaceType, InterfaceAvailableForRequestListener listener)382     public void unregisterInterfaceAvailableForRequestListener(
383             int ifaceType,
384             InterfaceAvailableForRequestListener listener) {
385         if (VDBG) {
386             Log.d(TAG, "unregisterInterfaceAvailableForRequestListener: ifaceType=" + ifaceType);
387         }
388 
389         synchronized (mLock) {
390             mInterfaceAvailableForRequestListeners.get(ifaceType).remove(
391                     new InterfaceAvailableForRequestListenerProxy(listener, null));
392         }
393     }
394 
395     /**
396      * Register a callback object for RTT life-cycle events. The callback object registration
397      * indicates that an RTT controller should be created whenever possible. The callback object
398      * will be called with a new RTT controller whenever it is created (or at registration time
399      * if an RTT controller already exists). The callback object will also be triggered whenever
400      * an existing RTT controller is destroyed (the previous copies must be discarded by the
401      * recipient).
402      *
403      * @param callback InterfaceRttControllerLifecycleCallback object.
404      * @param handler Handler on which to dispatch callback
405      */
registerRttControllerLifecycleCallback( @onNull InterfaceRttControllerLifecycleCallback callback, @NonNull Handler handler)406     public void registerRttControllerLifecycleCallback(
407             @NonNull InterfaceRttControllerLifecycleCallback callback, @NonNull Handler handler) {
408         if (VDBG) {
409             Log.d(TAG, "registerRttControllerLifecycleCallback: callback=" + callback + ", handler="
410                     + handler);
411         }
412 
413         if (callback == null || handler == null) {
414             Log.wtf(TAG, "registerRttControllerLifecycleCallback with nulls!? callback=" + callback
415                     + ", handler=" + handler);
416             return;
417         }
418 
419         synchronized (mLock) {
420             InterfaceRttControllerLifecycleCallbackProxy proxy =
421                     new InterfaceRttControllerLifecycleCallbackProxy(callback, handler);
422             if (!mRttControllerLifecycleCallbacks.add(proxy)) {
423                 Log.d(TAG,
424                         "registerRttControllerLifecycleCallback: registering an existing callback="
425                                 + callback);
426                 return;
427             }
428 
429             if (mIWifiRttController == null) {
430                 mIWifiRttController = createRttControllerIfPossible();
431             }
432             if (mIWifiRttController != null) {
433                 proxy.onNewRttController(mIWifiRttController);
434             }
435         }
436     }
437 
438     /**
439      * Return the name of the input interface or null on error.
440      */
getName(IWifiIface iface)441     public static String getName(IWifiIface iface) {
442         if (iface == null) {
443             return "<null>";
444         }
445 
446         Mutable<String> nameResp = new Mutable<>();
447         try {
448             iface.getName((WifiStatus status, String name) -> {
449                 if (status.code == WifiStatusCode.SUCCESS) {
450                     nameResp.value = name;
451                 } else {
452                     Log.e(TAG, "Error on getName: " + statusString(status));
453                 }
454             });
455         } catch (RemoteException e) {
456             Log.e(TAG, "Exception on getName: " + e);
457         }
458 
459         return nameResp.value;
460     }
461 
462     /**
463      * Called when interface is destroyed.
464      */
465     public interface InterfaceDestroyedListener {
466         /**
467          * Called for every interface on which registered when destroyed - whether
468          * destroyed by releaseIface() or through chip mode change or through Wi-Fi
469          * going down.
470          *
471          * Can be registered when the interface is requested with createXxxIface() - will
472          * only be valid if the interface creation was successful - i.e. a non-null was returned.
473          *
474          * @param ifaceName Name of the interface that was destroyed.
475          */
onDestroyed(@onNull String ifaceName)476         void onDestroyed(@NonNull String ifaceName);
477     }
478 
479     /**
480      * Called when an interface type availability for creation is changed.
481      */
482     public interface InterfaceAvailableForRequestListener {
483         /**
484          * Called when an interface type availability for creation is updated. Registered with
485          * registerInterfaceAvailableForRequestListener() and unregistered with
486          * unregisterInterfaceAvailableForRequestListener().
487          */
onAvailabilityChanged(boolean isAvailable)488         void onAvailabilityChanged(boolean isAvailable);
489     }
490 
491     /**
492      * Called on RTT controller lifecycle events. RTT controller is a singleton which will be
493      * created when possible (after first lifecycle registration) and destroyed if necessary.
494      *
495      * Determination of availability is determined by the HAL. Creation attempts (if requested
496      * by registration of interface) will be done on any mode changes.
497      */
498     public interface InterfaceRttControllerLifecycleCallback {
499         /**
500          * Called when an RTT controller was created (or for newly registered listeners - if it
501          * was already available). The controller provided by this callback may be destroyed by
502          * the HAL at which point the {@link #onRttControllerDestroyed()} will be called.
503          *
504          * Note: this callback can be triggered to replace an existing controller (instead of
505          * calling the Destroyed callback in between).
506          *
507          * @param controller The RTT controller object.
508          */
onNewRttController(@onNull IWifiRttController controller)509         void onNewRttController(@NonNull IWifiRttController controller);
510 
511         /**
512          * Called when the previously provided RTT controller is destroyed. Clients must discard
513          * their copy. A new copy may be provided later by
514          * {@link #onNewRttController(IWifiRttController)}.
515          */
onRttControllerDestroyed()516         void onRttControllerDestroyed();
517     }
518 
519     // internal state
520 
521     /* This "PRIORITY" is not for deciding interface elimination (that is controlled by
522      * allowedToDeleteIfaceTypeForRequestedType. This priority is used for:
523      * - Comparing 2 configuration options
524      * - Order of dispatch of available for request listeners
525      */
526     private static final int[] IFACE_TYPES_BY_PRIORITY =
527             {IfaceType.AP, IfaceType.STA, IfaceType.P2P, IfaceType.NAN};
528 
529     private final Object mLock = new Object();
530 
531     private IServiceManager mServiceManager;
532     private IWifi mWifi;
533     private IWifiRttController mIWifiRttController;
534     private final WifiEventCallback mWifiEventCallback = new WifiEventCallback();
535     private final Set<ManagerStatusListenerProxy> mManagerStatusListeners = new HashSet<>();
536     private final Set<InterfaceRttControllerLifecycleCallbackProxy>
537             mRttControllerLifecycleCallbacks = new HashSet<>();
538     private final SparseArray<Map<InterfaceAvailableForRequestListenerProxy, Boolean>>
539             mInterfaceAvailableForRequestListeners = new SparseArray<>();
540     private final SparseArray<IWifiChipEventCallback.Stub> mDebugCallbacks = new SparseArray<>();
541     private boolean mIsReady;
542 
543     /*
544      * This is the only place where we cache HIDL information in this manager. Necessary since
545      * we need to keep a list of registered destroyed listeners. Will be validated regularly
546      * in getAllChipInfoAndValidateCache().
547      */
548     private final Map<Pair<String, Integer>, InterfaceCacheEntry> mInterfaceInfoCache =
549             new HashMap<>();
550 
551     private class InterfaceCacheEntry {
552         public IWifiChip chip;
553         public int chipId;
554         public String name;
555         public int type;
556         public Set<InterfaceDestroyedListenerProxy> destroyedListeners = new HashSet<>();
557         public long creationTime;
558         public boolean isLowPriority;
559 
560         @Override
toString()561         public String toString() {
562             StringBuilder sb = new StringBuilder();
563             sb.append("{name=").append(name).append(", type=").append(type)
564                     .append(", destroyedListeners.size()=").append(destroyedListeners.size())
565                     .append(", creationTime=").append(creationTime).append(
566                     ", isLowPriority=").append(isLowPriority).append("}");
567             return sb.toString();
568         }
569     }
570 
571     private class WifiIfaceInfo {
572         public String name;
573         public IWifiIface iface;
574     }
575 
576     private class WifiChipInfo {
577         public IWifiChip chip;
578         public int chipId;
579         public ArrayList<IWifiChip.ChipMode> availableModes;
580         public boolean currentModeIdValid;
581         public int currentModeId;
582         public WifiIfaceInfo[][] ifaces = new WifiIfaceInfo[IFACE_TYPES_BY_PRIORITY.length][];
583 
584         @Override
toString()585         public String toString() {
586             StringBuilder sb = new StringBuilder();
587             sb.append("{chipId=").append(chipId).append(", availableModes=").append(availableModes)
588                     .append(", currentModeIdValid=").append(currentModeIdValid)
589                     .append(", currentModeId=").append(currentModeId);
590             for (int type: IFACE_TYPES_BY_PRIORITY) {
591                 sb.append(", ifaces[" + type + "].length=").append(ifaces[type].length);
592             }
593             sb.append(")");
594             return sb.toString();
595         }
596     }
597 
598     /**
599      * Wrapper function to access the HIDL services. Created to be mockable in unit-tests.
600      */
getWifiServiceMockable()601     protected IWifi getWifiServiceMockable() {
602         try {
603             return IWifi.getService(true /* retry */);
604         } catch (RemoteException e) {
605             Log.e(TAG, "Exception getting IWifi service: " + e);
606             return null;
607         }
608     }
609 
getServiceManagerMockable()610     protected IServiceManager getServiceManagerMockable() {
611         try {
612             return IServiceManager.getService();
613         } catch (RemoteException e) {
614             Log.e(TAG, "Exception getting IServiceManager: " + e);
615             return null;
616         }
617     }
618 
619     // internal implementation
620 
initializeInternal()621     private void initializeInternal() {
622         initIServiceManagerIfNecessary();
623         if (mIsVendorHalSupported) {
624             initIWifiIfNecessary();
625         }
626     }
627 
teardownInternal()628     private void teardownInternal() {
629         managerStatusListenerDispatch();
630         dispatchAllDestroyedListeners();
631         mInterfaceAvailableForRequestListeners.get(IfaceType.STA).clear();
632         mInterfaceAvailableForRequestListeners.get(IfaceType.AP).clear();
633         mInterfaceAvailableForRequestListeners.get(IfaceType.P2P).clear();
634         mInterfaceAvailableForRequestListeners.get(IfaceType.NAN).clear();
635 
636         mIWifiRttController = null;
637         dispatchRttControllerLifecycleOnDestroyed();
638         mRttControllerLifecycleCallbacks.clear();
639     }
640 
641     private class ServiceManagerDeathRecipient implements HwRemoteBinder.DeathRecipient {
642         @Override
serviceDied(long cookie)643         public void serviceDied(long cookie) {
644             mEventHandler.post(() -> {
645                 Log.wtf(TAG, "IServiceManager died: cookie=" + cookie);
646                 synchronized (mLock) {
647                     mServiceManager = null;
648                     // theoretically can call initServiceManager again here - but
649                     // there's no point since most likely system is going to reboot
650                 }
651             });
652         }
653     }
654 
655     private final IServiceNotification mServiceNotificationCallback =
656             new IServiceNotification.Stub() {
657                 @Override
658                 public void onRegistration(String fqName, String name,
659                                            boolean preexisting) {
660                     Log.d(TAG, "IWifi registration notification: fqName=" + fqName
661                             + ", name=" + name + ", preexisting=" + preexisting);
662                     synchronized (mLock) {
663                         initIWifiIfNecessary();
664                     }
665                 }
666             };
667 
668     /**
669      * Failures of IServiceManager are most likely system breaking in any case. Behavior here
670      * will be to WTF and continue.
671      */
initIServiceManagerIfNecessary()672     private void initIServiceManagerIfNecessary() {
673         if (mDbg) Log.d(TAG, "initIServiceManagerIfNecessary");
674 
675         synchronized (mLock) {
676             if (mServiceManager != null) {
677                 return;
678             }
679 
680             mServiceManager = getServiceManagerMockable();
681             if (mServiceManager == null) {
682                 Log.wtf(TAG, "Failed to get IServiceManager instance");
683             } else {
684                 try {
685                     if (!mServiceManager.linkToDeath(
686                             mServiceManagerDeathRecipient, /* don't care */ 0)) {
687                         Log.wtf(TAG, "Error on linkToDeath on IServiceManager");
688                         mServiceManager = null;
689                         return;
690                     }
691 
692                     if (!mServiceManager.registerForNotifications(IWifi.kInterfaceName, "",
693                             mServiceNotificationCallback)) {
694                         Log.wtf(TAG, "Failed to register a listener for IWifi service");
695                         mServiceManager = null;
696                     }
697                 } catch (RemoteException e) {
698                     Log.wtf(TAG, "Exception while operating on IServiceManager: " + e);
699                     mServiceManager = null;
700                 }
701 
702                 // Cache the result for the supporting vendor hal or not
703                 mIsVendorHalSupported = isSupportedInternal();
704             }
705         }
706     }
707 
708     /**
709      * Uses the IServiceManager to query if the vendor HAL is present in the VINTF for the device
710      * or not.
711      * @return true if supported, false otherwise.
712      */
isSupportedInternal()713     private boolean isSupportedInternal() {
714         if (VDBG) Log.d(TAG, "isSupportedInternal");
715 
716         synchronized (mLock) {
717             if (mServiceManager == null) {
718                 Log.e(TAG, "isSupported: called but mServiceManager is null!?");
719                 return false;
720             }
721             try {
722                 List<String> wifiServices =
723                         mServiceManager.listManifestByInterface(IWifi.kInterfaceName);
724                 return !wifiServices.isEmpty();
725             } catch (RemoteException e) {
726                 Log.wtf(TAG, "Exception while operating on IServiceManager: " + e);
727                 return false;
728             }
729         }
730     }
731 
732     private class WifiDeathRecipient implements HwRemoteBinder.DeathRecipient {
733         @Override
serviceDied(long cookie)734         public void serviceDied(long cookie) {
735             mEventHandler.post(() -> {
736                 Log.e(TAG, "IWifi HAL service died! Have a listener for it ... cookie=" + cookie);
737                 synchronized (mLock) { // prevents race condition with surrounding method
738                     mWifi = null;
739                     mIsReady = false;
740                     teardownInternal();
741                     // don't restart: wait for registration notification
742                 }
743             });
744         }
745     }
746 
747     /**
748      * Initialize IWifi and register death listener and event callback.
749      *
750      * - It is possible that IWifi is not ready - we have a listener on IServiceManager for it.
751      * - It is not expected that any of the registrations will fail. Possible indication that
752      *   service died after we obtained a handle to it.
753      *
754      * Here and elsewhere we assume that death listener will do the right thing!
755     */
initIWifiIfNecessary()756     private void initIWifiIfNecessary() {
757         if (mDbg) Log.d(TAG, "initIWifiIfNecessary");
758 
759         synchronized (mLock) {
760             if (mWifi != null) {
761                 return;
762             }
763 
764             try {
765                 mWifi = getWifiServiceMockable();
766                 if (mWifi == null) {
767                     Log.e(TAG, "IWifi not (yet) available - but have a listener for it ...");
768                     return;
769                 }
770 
771                 if (!mWifi.linkToDeath(mIWifiDeathRecipient, /* don't care */ 0)) {
772                     Log.e(TAG, "Error on linkToDeath on IWifi - will retry later");
773                     return;
774                 }
775 
776                 WifiStatus status = mWifi.registerEventCallback(mWifiEventCallback);
777                 if (status.code != WifiStatusCode.SUCCESS) {
778                     Log.e(TAG, "IWifi.registerEventCallback failed: " + statusString(status));
779                     mWifi = null;
780                     return;
781                 }
782                 // Stopping wifi just in case. This would also trigger the status callback.
783                 stopWifi();
784                 mIsReady = true;
785             } catch (RemoteException e) {
786                 Log.e(TAG, "Exception while operating on IWifi: " + e);
787             }
788         }
789     }
790 
791     /**
792      * Registers event listeners on all IWifiChips after a successful start: DEBUG only!
793      *
794      * We don't need the listeners since any callbacks are just confirmation of status codes we
795      * obtain directly from mode changes or interface creation/deletion.
796      *
797      * Relies (to the degree we care) on the service removing all listeners when Wi-Fi is stopped.
798      */
initIWifiChipDebugListeners()799     private void initIWifiChipDebugListeners() {
800         if (VDBG) Log.d(TAG, "initIWifiChipDebugListeners");
801 
802         if (!VDBG) {
803             return;
804         }
805 
806         synchronized (mLock) {
807             try {
808                 MutableBoolean statusOk = new MutableBoolean(false);
809                 Mutable<ArrayList<Integer>> chipIdsResp = new Mutable<>();
810 
811                 // get all chip IDs
812                 mWifi.getChipIds((WifiStatus status, ArrayList<Integer> chipIds) -> {
813                     statusOk.value = status.code == WifiStatusCode.SUCCESS;
814                     if (statusOk.value) {
815                         chipIdsResp.value = chipIds;
816                     } else {
817                         Log.e(TAG, "getChipIds failed: " + statusString(status));
818                     }
819                 });
820                 if (!statusOk.value) {
821                     return;
822                 }
823 
824                 Log.d(TAG, "getChipIds=" + chipIdsResp.value);
825                 if (chipIdsResp.value.size() == 0) {
826                     Log.e(TAG, "Should have at least 1 chip!");
827                     return;
828                 }
829 
830                 // register a callback for each chip
831                 Mutable<IWifiChip> chipResp = new Mutable<>();
832                 for (Integer chipId: chipIdsResp.value) {
833                     mWifi.getChip(chipId, (WifiStatus status, IWifiChip chip) -> {
834                         statusOk.value = status.code == WifiStatusCode.SUCCESS;
835                         if (statusOk.value) {
836                             chipResp.value = chip;
837                         } else {
838                             Log.e(TAG, "getChip failed: " + statusString(status));
839                         }
840                     });
841                     if (!statusOk.value) {
842                         continue; // still try next one?
843                     }
844 
845                     IWifiChipEventCallback.Stub callback =
846                             new IWifiChipEventCallback.Stub() {
847                                 @Override
848                                 public void onChipReconfigured(int modeId) throws RemoteException {
849                                     Log.d(TAG, "onChipReconfigured: modeId=" + modeId);
850                                 }
851 
852                                 @Override
853                                 public void onChipReconfigureFailure(WifiStatus status)
854                                         throws RemoteException {
855                                     Log.d(TAG, "onChipReconfigureFailure: status=" + statusString(
856                                             status));
857                                 }
858 
859                                 @Override
860                                 public void onIfaceAdded(int type, String name)
861                                         throws RemoteException {
862                                     Log.d(TAG, "onIfaceAdded: type=" + type + ", name=" + name);
863                                 }
864 
865                                 @Override
866                                 public void onIfaceRemoved(int type, String name)
867                                         throws RemoteException {
868                                     Log.d(TAG, "onIfaceRemoved: type=" + type + ", name=" + name);
869                                 }
870 
871                                 @Override
872                                 public void onDebugRingBufferDataAvailable(
873                                         WifiDebugRingBufferStatus status,
874                                         ArrayList<Byte> data) throws RemoteException {
875                                     Log.d(TAG, "onDebugRingBufferDataAvailable");
876                                 }
877 
878                                 @Override
879                                 public void onDebugErrorAlert(int errorCode,
880                                         ArrayList<Byte> debugData)
881                                         throws RemoteException {
882                                     Log.d(TAG, "onDebugErrorAlert");
883                                 }
884                             };
885                     mDebugCallbacks.put(chipId, callback); // store to prevent GC: needed by HIDL
886                     WifiStatus status = chipResp.value.registerEventCallback(callback);
887                     if (status.code != WifiStatusCode.SUCCESS) {
888                         Log.e(TAG, "registerEventCallback failed: " + statusString(status));
889                         continue; // still try next one?
890                     }
891                 }
892             } catch (RemoteException e) {
893                 Log.e(TAG, "initIWifiChipDebugListeners: exception: " + e);
894                 return;
895             }
896         }
897     }
898 
899     /**
900      * Get current information about all the chips in the system: modes, current mode (if any), and
901      * any existing interfaces.
902      *
903      * Intended to be called whenever we need to configure the chips - information is NOT cached (to
904      * reduce the likelihood that we get out-of-sync).
905      */
getAllChipInfo()906     private WifiChipInfo[] getAllChipInfo() {
907         if (VDBG) Log.d(TAG, "getAllChipInfo");
908 
909         synchronized (mLock) {
910             if (mWifi == null) {
911                 Log.e(TAG, "getAllChipInfo: called but mWifi is null!?");
912                 return null;
913             }
914 
915             try {
916                 MutableBoolean statusOk = new MutableBoolean(false);
917                 Mutable<ArrayList<Integer>> chipIdsResp = new Mutable<>();
918 
919                 // get all chip IDs
920                 mWifi.getChipIds((WifiStatus status, ArrayList<Integer> chipIds) -> {
921                     statusOk.value = status.code == WifiStatusCode.SUCCESS;
922                     if (statusOk.value) {
923                         chipIdsResp.value = chipIds;
924                     } else {
925                         Log.e(TAG, "getChipIds failed: " + statusString(status));
926                     }
927                 });
928                 if (!statusOk.value) {
929                     return null;
930                 }
931 
932                 if (VDBG) Log.d(TAG, "getChipIds=" + chipIdsResp.value);
933                 if (chipIdsResp.value.size() == 0) {
934                     Log.e(TAG, "Should have at least 1 chip!");
935                     return null;
936                 }
937 
938                 int chipInfoIndex = 0;
939                 WifiChipInfo[] chipsInfo = new WifiChipInfo[chipIdsResp.value.size()];
940 
941                 Mutable<IWifiChip> chipResp = new Mutable<>();
942                 for (Integer chipId: chipIdsResp.value) {
943                     mWifi.getChip(chipId, (WifiStatus status, IWifiChip chip) -> {
944                         statusOk.value = status.code == WifiStatusCode.SUCCESS;
945                         if (statusOk.value) {
946                             chipResp.value = chip;
947                         } else {
948                             Log.e(TAG, "getChip failed: " + statusString(status));
949                         }
950                     });
951                     if (!statusOk.value) {
952                         return null;
953                     }
954 
955                     Mutable<ArrayList<IWifiChip.ChipMode>> availableModesResp = new Mutable<>();
956                     chipResp.value.getAvailableModes(
957                             (WifiStatus status, ArrayList<IWifiChip.ChipMode> modes) -> {
958                                 statusOk.value = status.code == WifiStatusCode.SUCCESS;
959                                 if (statusOk.value) {
960                                     availableModesResp.value = modes;
961                                 } else {
962                                     Log.e(TAG, "getAvailableModes failed: " + statusString(status));
963                                 }
964                             });
965                     if (!statusOk.value) {
966                         return null;
967                     }
968 
969                     MutableBoolean currentModeValidResp = new MutableBoolean(false);
970                     MutableInt currentModeResp = new MutableInt(0);
971                     chipResp.value.getMode((WifiStatus status, int modeId) -> {
972                         statusOk.value = status.code == WifiStatusCode.SUCCESS;
973                         if (statusOk.value) {
974                             currentModeValidResp.value = true;
975                             currentModeResp.value = modeId;
976                         } else if (status.code == WifiStatusCode.ERROR_NOT_AVAILABLE) {
977                             statusOk.value = true; // valid response
978                         } else {
979                             Log.e(TAG, "getMode failed: " + statusString(status));
980                         }
981                     });
982                     if (!statusOk.value) {
983                         return null;
984                     }
985 
986                     Mutable<ArrayList<String>> ifaceNamesResp = new Mutable<>();
987                     MutableInt ifaceIndex = new MutableInt(0);
988 
989                     chipResp.value.getStaIfaceNames(
990                             (WifiStatus status, ArrayList<String> ifnames) -> {
991                                 statusOk.value = status.code == WifiStatusCode.SUCCESS;
992                                 if (statusOk.value) {
993                                     ifaceNamesResp.value = ifnames;
994                                 } else {
995                                     Log.e(TAG, "getStaIfaceNames failed: " + statusString(status));
996                                 }
997                             });
998                     if (!statusOk.value) {
999                         return null;
1000                     }
1001 
1002                     WifiIfaceInfo[] staIfaces = new WifiIfaceInfo[ifaceNamesResp.value.size()];
1003                     for (String ifaceName: ifaceNamesResp.value) {
1004                         chipResp.value.getStaIface(ifaceName,
1005                                 (WifiStatus status, IWifiStaIface iface) -> {
1006                                     statusOk.value = status.code == WifiStatusCode.SUCCESS;
1007                                     if (statusOk.value) {
1008                                         WifiIfaceInfo ifaceInfo = new WifiIfaceInfo();
1009                                         ifaceInfo.name = ifaceName;
1010                                         ifaceInfo.iface = iface;
1011                                         staIfaces[ifaceIndex.value++] = ifaceInfo;
1012                                     } else {
1013                                         Log.e(TAG, "getStaIface failed: " + statusString(status));
1014                                     }
1015                                 });
1016                         if (!statusOk.value) {
1017                             return null;
1018                         }
1019                     }
1020 
1021                     ifaceIndex.value = 0;
1022                     chipResp.value.getApIfaceNames(
1023                             (WifiStatus status, ArrayList<String> ifnames) -> {
1024                                 statusOk.value = status.code == WifiStatusCode.SUCCESS;
1025                                 if (statusOk.value) {
1026                                     ifaceNamesResp.value = ifnames;
1027                                 } else {
1028                                     Log.e(TAG, "getApIfaceNames failed: " + statusString(status));
1029                                 }
1030                             });
1031                     if (!statusOk.value) {
1032                         return null;
1033                     }
1034 
1035                     WifiIfaceInfo[] apIfaces = new WifiIfaceInfo[ifaceNamesResp.value.size()];
1036                     for (String ifaceName: ifaceNamesResp.value) {
1037                         chipResp.value.getApIface(ifaceName,
1038                                 (WifiStatus status, IWifiApIface iface) -> {
1039                                     statusOk.value = status.code == WifiStatusCode.SUCCESS;
1040                                     if (statusOk.value) {
1041                                         WifiIfaceInfo ifaceInfo = new WifiIfaceInfo();
1042                                         ifaceInfo.name = ifaceName;
1043                                         ifaceInfo.iface = iface;
1044                                         apIfaces[ifaceIndex.value++] = ifaceInfo;
1045                                     } else {
1046                                         Log.e(TAG, "getApIface failed: " + statusString(status));
1047                                     }
1048                                 });
1049                         if (!statusOk.value) {
1050                             return null;
1051                         }
1052                     }
1053 
1054                     ifaceIndex.value = 0;
1055                     chipResp.value.getP2pIfaceNames(
1056                             (WifiStatus status, ArrayList<String> ifnames) -> {
1057                                 statusOk.value = status.code == WifiStatusCode.SUCCESS;
1058                                 if (statusOk.value) {
1059                                     ifaceNamesResp.value = ifnames;
1060                                 } else {
1061                                     Log.e(TAG, "getP2pIfaceNames failed: " + statusString(status));
1062                                 }
1063                             });
1064                     if (!statusOk.value) {
1065                         return null;
1066                     }
1067 
1068                     WifiIfaceInfo[] p2pIfaces = new WifiIfaceInfo[ifaceNamesResp.value.size()];
1069                     for (String ifaceName: ifaceNamesResp.value) {
1070                         chipResp.value.getP2pIface(ifaceName,
1071                                 (WifiStatus status, IWifiP2pIface iface) -> {
1072                                     statusOk.value = status.code == WifiStatusCode.SUCCESS;
1073                                     if (statusOk.value) {
1074                                         WifiIfaceInfo ifaceInfo = new WifiIfaceInfo();
1075                                         ifaceInfo.name = ifaceName;
1076                                         ifaceInfo.iface = iface;
1077                                         p2pIfaces[ifaceIndex.value++] = ifaceInfo;
1078                                     } else {
1079                                         Log.e(TAG, "getP2pIface failed: " + statusString(status));
1080                                     }
1081                                 });
1082                         if (!statusOk.value) {
1083                             return null;
1084                         }
1085                     }
1086 
1087                     ifaceIndex.value = 0;
1088                     chipResp.value.getNanIfaceNames(
1089                             (WifiStatus status, ArrayList<String> ifnames) -> {
1090                                 statusOk.value = status.code == WifiStatusCode.SUCCESS;
1091                                 if (statusOk.value) {
1092                                     ifaceNamesResp.value = ifnames;
1093                                 } else {
1094                                     Log.e(TAG, "getNanIfaceNames failed: " + statusString(status));
1095                                 }
1096                             });
1097                     if (!statusOk.value) {
1098                         return null;
1099                     }
1100 
1101                     WifiIfaceInfo[] nanIfaces = new WifiIfaceInfo[ifaceNamesResp.value.size()];
1102                     for (String ifaceName: ifaceNamesResp.value) {
1103                         chipResp.value.getNanIface(ifaceName,
1104                                 (WifiStatus status, IWifiNanIface iface) -> {
1105                                     statusOk.value = status.code == WifiStatusCode.SUCCESS;
1106                                     if (statusOk.value) {
1107                                         WifiIfaceInfo ifaceInfo = new WifiIfaceInfo();
1108                                         ifaceInfo.name = ifaceName;
1109                                         ifaceInfo.iface = iface;
1110                                         nanIfaces[ifaceIndex.value++] = ifaceInfo;
1111                                     } else {
1112                                         Log.e(TAG, "getNanIface failed: " + statusString(status));
1113                                     }
1114                                 });
1115                         if (!statusOk.value) {
1116                             return null;
1117                         }
1118                     }
1119 
1120                     WifiChipInfo chipInfo = new WifiChipInfo();
1121                     chipsInfo[chipInfoIndex++] = chipInfo;
1122 
1123                     chipInfo.chip = chipResp.value;
1124                     chipInfo.chipId = chipId;
1125                     chipInfo.availableModes = availableModesResp.value;
1126                     chipInfo.currentModeIdValid = currentModeValidResp.value;
1127                     chipInfo.currentModeId = currentModeResp.value;
1128                     chipInfo.ifaces[IfaceType.STA] = staIfaces;
1129                     chipInfo.ifaces[IfaceType.AP] = apIfaces;
1130                     chipInfo.ifaces[IfaceType.P2P] = p2pIfaces;
1131                     chipInfo.ifaces[IfaceType.NAN] = nanIfaces;
1132                 }
1133 
1134                 return chipsInfo;
1135             } catch (RemoteException e) {
1136                 Log.e(TAG, "getAllChipInfoAndValidateCache exception: " + e);
1137             }
1138         }
1139 
1140         return null;
1141     }
1142 
1143     /**
1144      * Checks the local state of this object (the cached state) against the input 'chipInfos'
1145      * state (which is a live representation of the Wi-Fi firmware status - read through the HAL).
1146      * Returns 'true' if there are no discrepancies - 'false' otherwise.
1147      *
1148      * A discrepancy is if any local state contains references to a chip or interface which are not
1149      * found on the information read from the chip.
1150      */
validateInterfaceCache(WifiChipInfo[] chipInfos)1151     private boolean validateInterfaceCache(WifiChipInfo[] chipInfos) {
1152         if (VDBG) Log.d(TAG, "validateInterfaceCache");
1153 
1154         synchronized (mLock) {
1155             for (InterfaceCacheEntry entry: mInterfaceInfoCache.values()) {
1156                 // search for chip
1157                 WifiChipInfo matchingChipInfo = null;
1158                 for (WifiChipInfo ci: chipInfos) {
1159                     if (ci.chipId == entry.chipId) {
1160                         matchingChipInfo = ci;
1161                         break;
1162                     }
1163                 }
1164                 if (matchingChipInfo == null) {
1165                     Log.e(TAG, "validateInterfaceCache: no chip found for " + entry);
1166                     return false;
1167                 }
1168 
1169                 // search for interface
1170                 WifiIfaceInfo[] ifaceInfoList = matchingChipInfo.ifaces[entry.type];
1171                 if (ifaceInfoList == null) {
1172                     Log.e(TAG, "validateInterfaceCache: invalid type on entry " + entry);
1173                     return false;
1174                 }
1175 
1176                 boolean matchFound = false;
1177                 for (WifiIfaceInfo ifaceInfo: ifaceInfoList) {
1178                     if (ifaceInfo.name.equals(entry.name)) {
1179                         matchFound = true;
1180                         break;
1181                     }
1182                 }
1183                 if (!matchFound) {
1184                     Log.e(TAG, "validateInterfaceCache: no interface found for " + entry);
1185                     return false;
1186                 }
1187             }
1188         }
1189 
1190         return true;
1191     }
1192 
isWifiStarted()1193     private boolean isWifiStarted() {
1194         if (VDBG) Log.d(TAG, "isWifiStart");
1195 
1196         synchronized (mLock) {
1197             try {
1198                 if (mWifi == null) {
1199                     Log.w(TAG, "isWifiStarted called but mWifi is null!?");
1200                     return false;
1201                 } else {
1202                     return mWifi.isStarted();
1203                 }
1204             } catch (RemoteException e) {
1205                 Log.e(TAG, "isWifiStarted exception: " + e);
1206                 return false;
1207             }
1208         }
1209     }
1210 
startWifi()1211     private boolean startWifi() {
1212         if (VDBG) Log.d(TAG, "startWifi");
1213         initIWifiIfNecessary();
1214         synchronized (mLock) {
1215             try {
1216                 if (mWifi == null) {
1217                     Log.w(TAG, "startWifi called but mWifi is null!?");
1218                     return false;
1219                 } else {
1220                     int triedCount = 0;
1221                     while (triedCount <= START_HAL_RETRY_TIMES) {
1222                         WifiStatus status = mWifi.start();
1223                         if (status.code == WifiStatusCode.SUCCESS) {
1224                             initIWifiChipDebugListeners();
1225                             managerStatusListenerDispatch();
1226                             if (triedCount != 0) {
1227                                 Log.d(TAG, "start IWifi succeeded after trying "
1228                                          + triedCount + " times");
1229                             }
1230                             return true;
1231                         } else if (status.code == WifiStatusCode.ERROR_NOT_AVAILABLE) {
1232                             // Should retry. Hal might still be stopping.
1233                             Log.e(TAG, "Cannot start IWifi: " + statusString(status)
1234                                     + ", Retrying...");
1235                             try {
1236                                 Thread.sleep(START_HAL_RETRY_INTERVAL_MS);
1237                             } catch (InterruptedException ignore) {
1238                                 // no-op
1239                             }
1240                             triedCount++;
1241                         } else {
1242                             // Should not retry on other failures.
1243                             Log.e(TAG, "Cannot start IWifi: " + statusString(status));
1244                             return false;
1245                         }
1246                     }
1247                     Log.e(TAG, "Cannot start IWifi after trying " + triedCount + " times");
1248                     return false;
1249                 }
1250             } catch (RemoteException e) {
1251                 Log.e(TAG, "startWifi exception: " + e);
1252                 return false;
1253             }
1254         }
1255     }
1256 
stopWifi()1257     private void stopWifi() {
1258         if (VDBG) Log.d(TAG, "stopWifi");
1259 
1260         synchronized (mLock) {
1261             try {
1262                 if (mWifi == null) {
1263                     Log.w(TAG, "stopWifi called but mWifi is null!?");
1264                 } else {
1265                     WifiStatus status = mWifi.stop();
1266                     if (status.code != WifiStatusCode.SUCCESS) {
1267                         Log.e(TAG, "Cannot stop IWifi: " + statusString(status));
1268                     }
1269 
1270                     // even on failure since WTF??
1271                     teardownInternal();
1272                 }
1273             } catch (RemoteException e) {
1274                 Log.e(TAG, "stopWifi exception: " + e);
1275             }
1276         }
1277     }
1278 
1279     private class WifiEventCallback extends IWifiEventCallback.Stub {
1280         @Override
onStart()1281         public void onStart() throws RemoteException {
1282             mEventHandler.post(() -> {
1283                 if (VDBG) Log.d(TAG, "IWifiEventCallback.onStart");
1284                 // NOP: only happens in reaction to my calls - will handle directly
1285             });
1286         }
1287 
1288         @Override
onStop()1289         public void onStop() throws RemoteException {
1290             mEventHandler.post(() -> {
1291                 if (VDBG) Log.d(TAG, "IWifiEventCallback.onStop");
1292                 // NOP: only happens in reaction to my calls - will handle directly
1293             });
1294         }
1295 
1296         @Override
onFailure(WifiStatus status)1297         public void onFailure(WifiStatus status) throws RemoteException {
1298             mEventHandler.post(() -> {
1299                 Log.e(TAG, "IWifiEventCallback.onFailure: " + statusString(status));
1300                 teardownInternal();
1301             });
1302             // No need to do anything else: listeners may (will) re-start Wi-Fi
1303         }
1304     }
1305 
managerStatusListenerDispatch()1306     private void managerStatusListenerDispatch() {
1307         synchronized (mLock) {
1308             for (ManagerStatusListenerProxy cb : mManagerStatusListeners) {
1309                 cb.trigger();
1310             }
1311         }
1312     }
1313 
1314     private class ManagerStatusListenerProxy  extends
1315             ListenerProxy<ManagerStatusListener> {
ManagerStatusListenerProxy(ManagerStatusListener statusListener, Handler handler)1316         ManagerStatusListenerProxy(ManagerStatusListener statusListener, Handler handler) {
1317             super(statusListener, handler, "ManagerStatusListenerProxy");
1318         }
1319 
1320         @Override
action()1321         protected void action() {
1322             mListener.onStatusChanged();
1323         }
1324     }
1325 
getSupportedIfaceTypesInternal(IWifiChip chip)1326     Set<Integer> getSupportedIfaceTypesInternal(IWifiChip chip) {
1327         Set<Integer> results = new HashSet<>();
1328 
1329         WifiChipInfo[] chipInfos = getAllChipInfo();
1330         if (chipInfos == null) {
1331             Log.e(TAG, "getSupportedIfaceTypesInternal: no chip info found");
1332             return results;
1333         }
1334 
1335         MutableInt chipIdIfProvided = new MutableInt(0); // NOT using 0 as a magic value
1336         if (chip != null) {
1337             MutableBoolean statusOk = new MutableBoolean(false);
1338             try {
1339                 chip.getId((WifiStatus status, int id) -> {
1340                     if (status.code == WifiStatusCode.SUCCESS) {
1341                         chipIdIfProvided.value = id;
1342                         statusOk.value = true;
1343                     } else {
1344                         Log.e(TAG, "getSupportedIfaceTypesInternal: IWifiChip.getId() error: "
1345                                 + statusString(status));
1346                         statusOk.value = false;
1347                     }
1348                 });
1349             } catch (RemoteException e) {
1350                 Log.e(TAG, "getSupportedIfaceTypesInternal IWifiChip.getId() exception: " + e);
1351                 return results;
1352             }
1353             if (!statusOk.value) {
1354                 return results;
1355             }
1356         }
1357 
1358         for (WifiChipInfo wci: chipInfos) {
1359             if (chip != null && wci.chipId != chipIdIfProvided.value) {
1360                 continue;
1361             }
1362 
1363             for (IWifiChip.ChipMode cm: wci.availableModes) {
1364                 for (IWifiChip.ChipIfaceCombination cic: cm.availableCombinations) {
1365                     for (IWifiChip.ChipIfaceCombinationLimit cicl: cic.limits) {
1366                         for (int type: cicl.types) {
1367                             results.add(type);
1368                         }
1369                     }
1370                 }
1371             }
1372         }
1373 
1374         return results;
1375     }
1376 
createIface(int ifaceType, boolean lowPriority, InterfaceDestroyedListener destroyedListener, Handler handler)1377     private IWifiIface createIface(int ifaceType, boolean lowPriority,
1378             InterfaceDestroyedListener destroyedListener, Handler handler) {
1379         if (mDbg) {
1380             Log.d(TAG, "createIface: ifaceType=" + ifaceType + ", lowPriority=" + lowPriority);
1381         }
1382 
1383         synchronized (mLock) {
1384             WifiChipInfo[] chipInfos = getAllChipInfo();
1385             if (chipInfos == null) {
1386                 Log.e(TAG, "createIface: no chip info found");
1387                 stopWifi(); // major error: shutting down
1388                 return null;
1389             }
1390 
1391             if (!validateInterfaceCache(chipInfos)) {
1392                 Log.e(TAG, "createIface: local cache is invalid!");
1393                 stopWifi(); // major error: shutting down
1394                 return null;
1395             }
1396 
1397             IWifiIface iface = createIfaceIfPossible(chipInfos, ifaceType, lowPriority,
1398                     destroyedListener, handler);
1399             if (iface != null) { // means that some configuration has changed
1400                 if (!dispatchAvailableForRequestListeners()) {
1401                     return null; // catastrophic failure - shut down
1402                 }
1403             }
1404 
1405             return iface;
1406         }
1407     }
1408 
createIfaceIfPossible(WifiChipInfo[] chipInfos, int ifaceType, boolean lowPriority, InterfaceDestroyedListener destroyedListener, Handler handler)1409     private IWifiIface createIfaceIfPossible(WifiChipInfo[] chipInfos, int ifaceType,
1410             boolean lowPriority, InterfaceDestroyedListener destroyedListener, Handler handler) {
1411         if (VDBG) {
1412             Log.d(TAG, "createIfaceIfPossible: chipInfos=" + Arrays.deepToString(chipInfos)
1413                     + ", ifaceType=" + ifaceType + ", lowPriority=" + lowPriority);
1414         }
1415         synchronized (mLock) {
1416             IfaceCreationData bestIfaceCreationProposal = null;
1417             for (WifiChipInfo chipInfo: chipInfos) {
1418                 for (IWifiChip.ChipMode chipMode: chipInfo.availableModes) {
1419                     for (IWifiChip.ChipIfaceCombination chipIfaceCombo : chipMode
1420                             .availableCombinations) {
1421                         int[][] expandedIfaceCombos = expandIfaceCombos(chipIfaceCombo);
1422                         if (VDBG) {
1423                             Log.d(TAG, chipIfaceCombo + " expands to "
1424                                     + Arrays.deepToString(expandedIfaceCombos));
1425                         }
1426 
1427                         for (int[] expandedIfaceCombo: expandedIfaceCombos) {
1428                             IfaceCreationData currentProposal = canIfaceComboSupportRequest(
1429                                     chipInfo, chipMode, expandedIfaceCombo, ifaceType, lowPriority);
1430                             if (compareIfaceCreationData(currentProposal,
1431                                     bestIfaceCreationProposal)) {
1432                                 if (VDBG) Log.d(TAG, "new proposal accepted");
1433                                 bestIfaceCreationProposal = currentProposal;
1434                             }
1435                         }
1436                     }
1437                 }
1438             }
1439 
1440             if (bestIfaceCreationProposal != null) {
1441                 IWifiIface iface = executeChipReconfiguration(bestIfaceCreationProposal, ifaceType);
1442                 if (iface != null) {
1443                     InterfaceCacheEntry cacheEntry = new InterfaceCacheEntry();
1444 
1445                     cacheEntry.chip = bestIfaceCreationProposal.chipInfo.chip;
1446                     cacheEntry.chipId = bestIfaceCreationProposal.chipInfo.chipId;
1447                     cacheEntry.name = getName(iface);
1448                     cacheEntry.type = ifaceType;
1449                     if (destroyedListener != null) {
1450                         cacheEntry.destroyedListeners.add(
1451                                 new InterfaceDestroyedListenerProxy(
1452                                         cacheEntry.name, destroyedListener, handler));
1453                     }
1454                     cacheEntry.creationTime = mClock.getUptimeSinceBootMillis();
1455                     cacheEntry.isLowPriority = lowPriority;
1456 
1457                     if (mDbg) Log.d(TAG, "createIfaceIfPossible: added cacheEntry=" + cacheEntry);
1458                     mInterfaceInfoCache.put(
1459                             Pair.create(cacheEntry.name, cacheEntry.type), cacheEntry);
1460                     return iface;
1461                 }
1462             }
1463         }
1464 
1465         return null;
1466     }
1467 
1468     // similar to createIfaceIfPossible - but simpler code: not looking for best option just
1469     // for any option (so terminates on first one).
isItPossibleToCreateIface(WifiChipInfo[] chipInfos, int ifaceType)1470     private boolean isItPossibleToCreateIface(WifiChipInfo[] chipInfos, int ifaceType) {
1471         if (VDBG) {
1472             Log.d(TAG, "isItPossibleToCreateIface: chipInfos=" + Arrays.deepToString(chipInfos)
1473                     + ", ifaceType=" + ifaceType);
1474         }
1475 
1476         for (WifiChipInfo chipInfo: chipInfos) {
1477             for (IWifiChip.ChipMode chipMode: chipInfo.availableModes) {
1478                 for (IWifiChip.ChipIfaceCombination chipIfaceCombo : chipMode
1479                         .availableCombinations) {
1480                     int[][] expandedIfaceCombos = expandIfaceCombos(chipIfaceCombo);
1481                     if (VDBG) {
1482                         Log.d(TAG, chipIfaceCombo + " expands to "
1483                                 + Arrays.deepToString(expandedIfaceCombos));
1484                     }
1485 
1486                     for (int[] expandedIfaceCombo: expandedIfaceCombos) {
1487                         if (canIfaceComboSupportRequest(chipInfo, chipMode, expandedIfaceCombo,
1488                                 ifaceType, false) != null) {
1489                             return true;
1490                         }
1491                     }
1492                 }
1493             }
1494         }
1495 
1496         return false;
1497     }
1498 
1499     /**
1500      * Expands (or provides an alternative representation) of the ChipIfaceCombination as all
1501      * possible combinations of interface.
1502      *
1503      * Returns [# of combinations][4 (IfaceType)]
1504      *
1505      * Note: there could be duplicates - allow (inefficient but ...).
1506      * TODO: optimize by using a Set as opposed to a []: will remove duplicates. Will need to
1507      * provide correct hashes.
1508      */
expandIfaceCombos(IWifiChip.ChipIfaceCombination chipIfaceCombo)1509     private int[][] expandIfaceCombos(IWifiChip.ChipIfaceCombination chipIfaceCombo) {
1510         int numOfCombos = 1;
1511         for (IWifiChip.ChipIfaceCombinationLimit limit: chipIfaceCombo.limits) {
1512             for (int i = 0; i < limit.maxIfaces; ++i) {
1513                 numOfCombos *= limit.types.size();
1514             }
1515         }
1516 
1517         int[][] expandedIfaceCombos = new int[numOfCombos][IFACE_TYPES_BY_PRIORITY.length];
1518 
1519         int span = numOfCombos; // span of an individual type (or sub-tree size)
1520         for (IWifiChip.ChipIfaceCombinationLimit limit: chipIfaceCombo.limits) {
1521             for (int i = 0; i < limit.maxIfaces; ++i) {
1522                 span /= limit.types.size();
1523                 for (int k = 0; k < numOfCombos; ++k) {
1524                     expandedIfaceCombos[k][limit.types.get((k / span) % limit.types.size())]++;
1525                 }
1526             }
1527         }
1528 
1529         return expandedIfaceCombos;
1530     }
1531 
1532     private class IfaceCreationData {
1533         public WifiChipInfo chipInfo;
1534         public int chipModeId;
1535         public List<WifiIfaceInfo> interfacesToBeRemovedFirst;
1536 
1537         @Override
toString()1538         public String toString() {
1539             StringBuilder sb = new StringBuilder();
1540             sb.append("{chipInfo=").append(chipInfo).append(", chipModeId=").append(chipModeId)
1541                     .append(", interfacesToBeRemovedFirst=").append(interfacesToBeRemovedFirst)
1542                     .append(")");
1543             return sb.toString();
1544         }
1545     }
1546 
1547     /**
1548      * Checks whether the input chip-iface-combo can support the requested interface type: if not
1549      * then returns null, if yes then returns information containing the list of interfaces which
1550      * would have to be removed first before the requested interface can be created.
1551      *
1552      * Note: the list of interfaces to be removed is EMPTY if a chip mode change is required - in
1553      * that case ALL the interfaces on the current chip have to be removed first.
1554      *
1555      * Response determined based on:
1556      * - Mode configuration: i.e. could the mode support the interface type in principle
1557      * - Priority information: i.e. are we 'allowed' to remove interfaces in order to create the
1558      *   requested interface
1559      */
canIfaceComboSupportRequest(WifiChipInfo chipInfo, IWifiChip.ChipMode chipMode, int[] chipIfaceCombo, int ifaceType, boolean lowPriority)1560     private IfaceCreationData canIfaceComboSupportRequest(WifiChipInfo chipInfo,
1561             IWifiChip.ChipMode chipMode, int[] chipIfaceCombo, int ifaceType, boolean lowPriority) {
1562         if (VDBG) {
1563             Log.d(TAG, "canIfaceComboSupportRequest: chipInfo=" + chipInfo + ", chipMode="
1564                     + chipMode + ", chipIfaceCombo=" + chipIfaceCombo + ", ifaceType=" + ifaceType
1565                     + ", lowPriority=" + lowPriority);
1566         }
1567 
1568         // short-circuit: does the chipIfaceCombo even support the requested type?
1569         if (chipIfaceCombo[ifaceType] == 0) {
1570             if (VDBG) Log.d(TAG, "Requested type not supported by combo");
1571             return null;
1572         }
1573 
1574         boolean isChipModeChangeProposed =
1575                 chipInfo.currentModeIdValid && chipInfo.currentModeId != chipMode.id;
1576 
1577         // short-circuit: can't change chip-mode if an existing interface on this chip has a higher
1578         // priority than the requested interface
1579         if (isChipModeChangeProposed) {
1580             for (int type: IFACE_TYPES_BY_PRIORITY) {
1581                 if (chipInfo.ifaces[type].length != 0) {
1582                     if (lowPriority) {
1583                         if (VDBG) {
1584                             Log.d(TAG, "Couldn't delete existing type " + type
1585                                     + " interfaces for a low priority request");
1586                         }
1587                         return null;
1588                     }
1589                     if (!allowedToDeleteIfaceTypeForRequestedType(type, ifaceType,
1590                             chipInfo.ifaces, chipInfo.ifaces[type].length)) {
1591                         if (VDBG) {
1592                             Log.d(TAG, "Couldn't delete existing type " + type
1593                                     + " interfaces for requested type");
1594                         }
1595                         return null;
1596                     }
1597                 }
1598             }
1599 
1600             // but if priority allows the mode change then we're good to go
1601             IfaceCreationData ifaceCreationData = new IfaceCreationData();
1602             ifaceCreationData.chipInfo = chipInfo;
1603             ifaceCreationData.chipModeId = chipMode.id;
1604 
1605             return ifaceCreationData;
1606         }
1607 
1608         // possibly supported
1609         List<WifiIfaceInfo> interfacesToBeRemovedFirst = new ArrayList<>();
1610 
1611         for (int type: IFACE_TYPES_BY_PRIORITY) {
1612             int tooManyInterfaces = chipInfo.ifaces[type].length - chipIfaceCombo[type];
1613 
1614             // need to count the requested interface as well
1615             if (type == ifaceType) {
1616                 tooManyInterfaces += 1;
1617             }
1618 
1619             if (tooManyInterfaces > 0) { // may need to delete some
1620                 if (lowPriority) {
1621                     if (VDBG) {
1622                         Log.d(TAG, "Couldn't delete existing type " + type
1623                                 + " interfaces for a low priority request");
1624                     }
1625                     return null;
1626                 }
1627 
1628                 if (!allowedToDeleteIfaceTypeForRequestedType(type, ifaceType, chipInfo.ifaces,
1629                         tooManyInterfaces)) {
1630                     if (VDBG) {
1631                         Log.d(TAG, "Would need to delete some higher priority interfaces");
1632                     }
1633                     return null;
1634                 }
1635 
1636                 // delete the most recently created interfaces or LOW priority interfaces
1637                 interfacesToBeRemovedFirst = selectInterfacesToDelete(tooManyInterfaces,
1638                         chipInfo.ifaces[type]);
1639             }
1640         }
1641 
1642         IfaceCreationData ifaceCreationData = new IfaceCreationData();
1643         ifaceCreationData.chipInfo = chipInfo;
1644         ifaceCreationData.chipModeId = chipMode.id;
1645         ifaceCreationData.interfacesToBeRemovedFirst = interfacesToBeRemovedFirst;
1646 
1647         return ifaceCreationData;
1648     }
1649 
1650     /**
1651      * Compares two options to create an interface and determines which is the 'best'. Returns
1652      * true if proposal 1 (val1) is better, other false.
1653      *
1654      * Note: both proposals are 'acceptable' bases on priority criteria.
1655      *
1656      * Criteria:
1657      * - Proposal is better if it means removing fewer high priority interfaces
1658      */
compareIfaceCreationData(IfaceCreationData val1, IfaceCreationData val2)1659     private boolean compareIfaceCreationData(IfaceCreationData val1, IfaceCreationData val2) {
1660         if (VDBG) Log.d(TAG, "compareIfaceCreationData: val1=" + val1 + ", val2=" + val2);
1661 
1662         // deal with trivial case of one or the other being null
1663         if (val1 == null) {
1664             return false;
1665         } else if (val2 == null) {
1666             return true;
1667         }
1668 
1669         for (int type: IFACE_TYPES_BY_PRIORITY) {
1670             // # of interfaces to be deleted: the list or all interfaces of the type if mode change
1671             int numIfacesToDelete1 = 0;
1672             if (val1.chipInfo.currentModeIdValid
1673                     && val1.chipInfo.currentModeId != val1.chipModeId) {
1674                 numIfacesToDelete1 = val1.chipInfo.ifaces[type].length;
1675             } else {
1676                 numIfacesToDelete1 = val1.interfacesToBeRemovedFirst.size();
1677             }
1678 
1679             int numIfacesToDelete2 = 0;
1680             if (val2.chipInfo.currentModeIdValid
1681                     && val2.chipInfo.currentModeId != val2.chipModeId) {
1682                 numIfacesToDelete2 = val2.chipInfo.ifaces[type].length;
1683             } else {
1684                 numIfacesToDelete2 = val2.interfacesToBeRemovedFirst.size();
1685             }
1686 
1687             if (numIfacesToDelete1 < numIfacesToDelete2) {
1688                 if (VDBG) {
1689                     Log.d(TAG, "decision based on type=" + type + ": " + numIfacesToDelete1
1690                             + " < " + numIfacesToDelete2);
1691                 }
1692                 return true;
1693             }
1694         }
1695 
1696         // arbitrary - flip a coin
1697         if (VDBG) Log.d(TAG, "proposals identical - flip a coin");
1698         return false;
1699     }
1700 
1701     /**
1702      * Returns true if we're allowed to delete the existing interface type for the requested
1703      * interface type.
1704      *
1705      * Rules - applies in order:
1706      *
1707      * General rules:
1708      * 1. No interface will be destroyed for a requested interface of the same type
1709      * 2. No interface will be destroyed if one of the requested interfaces already exists
1710      * 3. If there are >1 interface of an existing type, then it is ok to destroy that type
1711      *    interface
1712      *
1713      * Type-specific rules (but note that the general rules are appied first):
1714      * 4. Request for AP or STA will destroy any other interface
1715      * 5. Request for P2P will destroy NAN-only (but will destroy a second STA per #3)
1716      * 6. Request for NAN will not destroy any interface (but will destroy a second STA per #3)
1717      *
1718      * Note: the 'numNecessaryInterfaces' is used to specify how many interfaces would be needed to
1719      * be deleted. This is used to determine whether there are that many low priority interfaces
1720      * of the requested type to delete.
1721      */
allowedToDeleteIfaceTypeForRequestedType(int existingIfaceType, int requestedIfaceType, WifiIfaceInfo[][] currentIfaces, int numNecessaryInterfaces)1722     private boolean allowedToDeleteIfaceTypeForRequestedType(int existingIfaceType,
1723             int requestedIfaceType, WifiIfaceInfo[][] currentIfaces, int numNecessaryInterfaces) {
1724         // rule 0: check for any low priority interfaces
1725         int numAvailableLowPriorityInterfaces = 0;
1726         synchronized (mLock) {
1727             for (InterfaceCacheEntry entry : mInterfaceInfoCache.values()) {
1728                 if (entry.type == existingIfaceType && entry.isLowPriority) {
1729                     numAvailableLowPriorityInterfaces++;
1730                 }
1731             }
1732         }
1733         if (numAvailableLowPriorityInterfaces >= numNecessaryInterfaces) {
1734             return true;
1735         }
1736 
1737         // rule 1
1738         if (existingIfaceType == requestedIfaceType) {
1739             return false;
1740         }
1741 
1742         // rule 2
1743         if (currentIfaces[requestedIfaceType].length != 0) {
1744             return false;
1745         }
1746 
1747         // rule 3
1748         if (currentIfaces[existingIfaceType].length > 1) {
1749             return true;
1750         }
1751 
1752         // rule 6
1753         if (requestedIfaceType == IfaceType.NAN) {
1754             return false;
1755         }
1756 
1757         // rule 5
1758         if (requestedIfaceType == IfaceType.P2P) {
1759             return existingIfaceType == IfaceType.NAN;
1760         }
1761 
1762         // rule 4, the requestIfaceType is either AP or STA
1763         return true;
1764     }
1765 
1766     /**
1767      * Selects the interfaces to delete.
1768      *
1769      * Rule: select low priority interfaces and then other interfaces in order of creation time.
1770      *
1771      * @param excessInterfaces Number of interfaces which need to be selected.
1772      * @param interfaces Array of interfaces.
1773      */
selectInterfacesToDelete(int excessInterfaces, WifiIfaceInfo[] interfaces)1774     private List<WifiIfaceInfo> selectInterfacesToDelete(int excessInterfaces,
1775             WifiIfaceInfo[] interfaces) {
1776         if (VDBG) {
1777             Log.d(TAG, "selectInterfacesToDelete: excessInterfaces=" + excessInterfaces
1778                     + ", interfaces=" + Arrays.toString(interfaces));
1779         }
1780 
1781         boolean lookupError = false;
1782         LongSparseArray<WifiIfaceInfo> orderedListLowPriority = new LongSparseArray<>();
1783         LongSparseArray<WifiIfaceInfo> orderedList = new LongSparseArray<>();
1784         for (WifiIfaceInfo info : interfaces) {
1785             InterfaceCacheEntry cacheEntry;
1786             synchronized (mLock) {
1787                 cacheEntry = mInterfaceInfoCache.get(Pair.create(info.name, getType(info.iface)));
1788             }
1789             if (cacheEntry == null) {
1790                 Log.e(TAG,
1791                         "selectInterfacesToDelete: can't find cache entry with name=" + info.name);
1792                 lookupError = true;
1793                 break;
1794             }
1795             if (cacheEntry.isLowPriority) {
1796                 orderedListLowPriority.append(cacheEntry.creationTime, info);
1797             } else {
1798                 orderedList.append(cacheEntry.creationTime, info);
1799             }
1800         }
1801 
1802         if (lookupError) {
1803             Log.e(TAG, "selectInterfacesToDelete: falling back to arbitrary selection");
1804             return Arrays.asList(Arrays.copyOf(interfaces, excessInterfaces));
1805         } else {
1806             List<WifiIfaceInfo> result = new ArrayList<>(excessInterfaces);
1807             for (int i = 0; i < excessInterfaces; ++i) {
1808                 int lowPriorityNextIndex = orderedListLowPriority.size() - i - 1;
1809                 if (lowPriorityNextIndex >= 0) {
1810                     result.add(orderedListLowPriority.valueAt(lowPriorityNextIndex));
1811                 } else {
1812                     result.add(orderedList.valueAt(
1813                             orderedList.size() - i + orderedListLowPriority.size() - 1));
1814                 }
1815             }
1816             return result;
1817         }
1818     }
1819 
1820     /**
1821      * Performs chip reconfiguration per the input:
1822      * - Removes the specified interfaces
1823      * - Reconfigures the chip to the new chip mode (if necessary)
1824      * - Creates the new interface
1825      *
1826      * Returns the newly created interface or a null on any error.
1827      */
executeChipReconfiguration(IfaceCreationData ifaceCreationData, int ifaceType)1828     private IWifiIface executeChipReconfiguration(IfaceCreationData ifaceCreationData,
1829             int ifaceType) {
1830         if (mDbg) {
1831             Log.d(TAG, "executeChipReconfiguration: ifaceCreationData=" + ifaceCreationData
1832                     + ", ifaceType=" + ifaceType);
1833         }
1834         synchronized (mLock) {
1835             try {
1836                 // is this a mode change?
1837                 boolean isModeConfigNeeded = !ifaceCreationData.chipInfo.currentModeIdValid
1838                         || ifaceCreationData.chipInfo.currentModeId != ifaceCreationData.chipModeId;
1839                 if (mDbg) Log.d(TAG, "isModeConfigNeeded=" + isModeConfigNeeded);
1840 
1841                 // first delete interfaces/change modes
1842                 if (isModeConfigNeeded) {
1843                     // remove all interfaces pre mode-change
1844                     // TODO: is this necessary? note that even if we don't want to explicitly
1845                     // remove the interfaces we do need to call the onDeleted callbacks - which
1846                     // this does
1847                     for (WifiIfaceInfo[] ifaceInfos: ifaceCreationData.chipInfo.ifaces) {
1848                         for (WifiIfaceInfo ifaceInfo: ifaceInfos) {
1849                             removeIfaceInternal(ifaceInfo.iface); // ignore return value
1850                         }
1851                     }
1852 
1853                     WifiStatus status = ifaceCreationData.chipInfo.chip.configureChip(
1854                             ifaceCreationData.chipModeId);
1855                     updateRttControllerOnModeChange();
1856                     if (status.code != WifiStatusCode.SUCCESS) {
1857                         Log.e(TAG, "executeChipReconfiguration: configureChip error: "
1858                                 + statusString(status));
1859                         return null;
1860                     }
1861                 } else {
1862                     // remove all interfaces on the delete list
1863                     for (WifiIfaceInfo ifaceInfo: ifaceCreationData.interfacesToBeRemovedFirst) {
1864                         removeIfaceInternal(ifaceInfo.iface); // ignore return value
1865                     }
1866                 }
1867 
1868                 // create new interface
1869                 Mutable<WifiStatus> statusResp = new Mutable<>();
1870                 Mutable<IWifiIface> ifaceResp = new Mutable<>();
1871                 switch (ifaceType) {
1872                     case IfaceType.STA:
1873                         ifaceCreationData.chipInfo.chip.createStaIface(
1874                                 (WifiStatus status, IWifiStaIface iface) -> {
1875                                     statusResp.value = status;
1876                                     ifaceResp.value = iface;
1877                                 });
1878                         break;
1879                     case IfaceType.AP:
1880                         ifaceCreationData.chipInfo.chip.createApIface(
1881                                 (WifiStatus status, IWifiApIface iface) -> {
1882                                     statusResp.value = status;
1883                                     ifaceResp.value = iface;
1884                                 });
1885                         break;
1886                     case IfaceType.P2P:
1887                         ifaceCreationData.chipInfo.chip.createP2pIface(
1888                                 (WifiStatus status, IWifiP2pIface iface) -> {
1889                                     statusResp.value = status;
1890                                     ifaceResp.value = iface;
1891                                 });
1892                         break;
1893                     case IfaceType.NAN:
1894                         ifaceCreationData.chipInfo.chip.createNanIface(
1895                                 (WifiStatus status, IWifiNanIface iface) -> {
1896                                     statusResp.value = status;
1897                                     ifaceResp.value = iface;
1898                                 });
1899                         break;
1900                 }
1901 
1902                 if (statusResp.value.code != WifiStatusCode.SUCCESS) {
1903                     Log.e(TAG, "executeChipReconfiguration: failed to create interface ifaceType="
1904                             + ifaceType + ": " + statusString(statusResp.value));
1905                     return null;
1906                 }
1907 
1908                 return ifaceResp.value;
1909             } catch (RemoteException e) {
1910                 Log.e(TAG, "executeChipReconfiguration exception: " + e);
1911                 return null;
1912             }
1913         }
1914     }
1915 
removeIfaceInternal(IWifiIface iface)1916     private boolean removeIfaceInternal(IWifiIface iface) {
1917         String name = getName(iface);
1918         int type = getType(iface);
1919         if (mDbg) Log.d(TAG, "removeIfaceInternal: iface(name)=" + name + ", type=" + type);
1920 
1921         if (type == -1) {
1922             Log.e(TAG, "removeIfaceInternal: can't get type -- iface(name)=" + name);
1923             return false;
1924         }
1925 
1926         synchronized (mLock) {
1927             if (mWifi == null) {
1928                 Log.e(TAG, "removeIfaceInternal: null IWifi -- iface(name)=" + name);
1929                 return false;
1930             }
1931 
1932             IWifiChip chip = getChip(iface);
1933             if (chip == null) {
1934                 Log.e(TAG, "removeIfaceInternal: null IWifiChip -- iface(name)=" + name);
1935                 return false;
1936             }
1937 
1938             if (name == null) {
1939                 Log.e(TAG, "removeIfaceInternal: can't get name");
1940                 return false;
1941             }
1942 
1943             WifiStatus status = null;
1944             try {
1945                 switch (type) {
1946                     case IfaceType.STA:
1947                         status = chip.removeStaIface(name);
1948                         break;
1949                     case IfaceType.AP:
1950                         status = chip.removeApIface(name);
1951                         break;
1952                     case IfaceType.P2P:
1953                         status = chip.removeP2pIface(name);
1954                         break;
1955                     case IfaceType.NAN:
1956                         status = chip.removeNanIface(name);
1957                         break;
1958                     default:
1959                         Log.wtf(TAG, "removeIfaceInternal: invalid type=" + type);
1960                         return false;
1961                 }
1962             } catch (RemoteException e) {
1963                 Log.e(TAG, "IWifiChip.removeXxxIface exception: " + e);
1964             }
1965 
1966             // dispatch listeners no matter what status
1967             dispatchDestroyedListeners(name, type);
1968 
1969             if (status != null && status.code == WifiStatusCode.SUCCESS) {
1970                 return true;
1971             } else {
1972                 Log.e(TAG, "IWifiChip.removeXxxIface failed: " + statusString(status));
1973                 return false;
1974             }
1975         }
1976     }
1977 
1978     // dispatch all available for request listeners of the specified type AND clean-out the list:
1979     // listeners are called once at most!
dispatchAvailableForRequestListeners()1980     private boolean dispatchAvailableForRequestListeners() {
1981         if (VDBG) Log.d(TAG, "dispatchAvailableForRequestListeners");
1982 
1983         synchronized (mLock) {
1984             WifiChipInfo[] chipInfos = getAllChipInfo();
1985             if (chipInfos == null) {
1986                 Log.e(TAG, "dispatchAvailableForRequestListeners: no chip info found");
1987                 stopWifi(); // major error: shutting down
1988                 return false;
1989             }
1990             if (VDBG) {
1991                 Log.d(TAG, "dispatchAvailableForRequestListeners: chipInfos="
1992                         + Arrays.deepToString(chipInfos));
1993             }
1994 
1995             for (int ifaceType : IFACE_TYPES_BY_PRIORITY) {
1996                 dispatchAvailableForRequestListenersForType(ifaceType, chipInfos);
1997             }
1998         }
1999 
2000         return true;
2001     }
2002 
dispatchAvailableForRequestListenersForType(int ifaceType, WifiChipInfo[] chipInfos)2003     private void dispatchAvailableForRequestListenersForType(int ifaceType,
2004             WifiChipInfo[] chipInfos) {
2005         if (VDBG) Log.d(TAG, "dispatchAvailableForRequestListenersForType: ifaceType=" + ifaceType);
2006 
2007         synchronized (mLock) {
2008             Map<InterfaceAvailableForRequestListenerProxy, Boolean> listeners =
2009                     mInterfaceAvailableForRequestListeners.get(ifaceType);
2010 
2011             if (listeners.size() == 0) {
2012                 return;
2013             }
2014 
2015             boolean isAvailable = isItPossibleToCreateIface(chipInfos, ifaceType);
2016 
2017             if (VDBG) {
2018                 Log.d(TAG, "Interface available for: ifaceType=" + ifaceType + " = " + isAvailable);
2019             }
2020             for (Map.Entry<InterfaceAvailableForRequestListenerProxy, Boolean> listenerEntry :
2021                     listeners.entrySet()) {
2022                 if (listenerEntry.getValue() == null || listenerEntry.getValue() != isAvailable) {
2023                     if (VDBG) {
2024                         Log.d(TAG, "Interface available listener dispatched: ifaceType=" + ifaceType
2025                                 + ", listener=" + listenerEntry.getKey());
2026                     }
2027                     listenerEntry.getKey().triggerWithArg(isAvailable);
2028                 }
2029                 listenerEntry.setValue(isAvailable);
2030             }
2031         }
2032     }
2033 
2034     // dispatch all destroyed listeners registered for the specified interface AND remove the
2035     // cache entry
dispatchDestroyedListeners(String name, int type)2036     private void dispatchDestroyedListeners(String name, int type) {
2037         if (VDBG) Log.d(TAG, "dispatchDestroyedListeners: iface(name)=" + name);
2038 
2039         synchronized (mLock) {
2040             InterfaceCacheEntry entry = mInterfaceInfoCache.get(Pair.create(name, type));
2041             if (entry == null) {
2042                 Log.e(TAG, "dispatchDestroyedListeners: no cache entry for iface(name)=" + name);
2043                 return;
2044             }
2045 
2046             for (InterfaceDestroyedListenerProxy listener : entry.destroyedListeners) {
2047                 listener.trigger();
2048             }
2049             entry.destroyedListeners.clear(); // for insurance (though cache entry is removed)
2050             mInterfaceInfoCache.remove(Pair.create(name, type));
2051         }
2052     }
2053 
2054     // dispatch all destroyed listeners registered to all interfaces
dispatchAllDestroyedListeners()2055     private void dispatchAllDestroyedListeners() {
2056         if (VDBG) Log.d(TAG, "dispatchAllDestroyedListeners");
2057 
2058         synchronized (mLock) {
2059             Iterator<Map.Entry<Pair<String, Integer>, InterfaceCacheEntry>> it =
2060                     mInterfaceInfoCache.entrySet().iterator();
2061             while (it.hasNext()) {
2062                 InterfaceCacheEntry entry = it.next().getValue();
2063                 for (InterfaceDestroyedListenerProxy listener : entry.destroyedListeners) {
2064                     listener.trigger();
2065                 }
2066                 entry.destroyedListeners.clear(); // for insurance (though cache entry is removed)
2067                 it.remove();
2068             }
2069         }
2070     }
2071 
2072     private abstract class ListenerProxy<LISTENER>  {
2073         protected LISTENER mListener;
2074         private Handler mHandler;
2075 
2076         // override equals & hash to make sure that the container HashSet is unique with respect to
2077         // the contained listener
2078         @Override
equals(Object obj)2079         public boolean equals(Object obj) {
2080             return mListener == ((ListenerProxy<LISTENER>) obj).mListener;
2081         }
2082 
2083         @Override
hashCode()2084         public int hashCode() {
2085             return mListener.hashCode();
2086         }
2087 
trigger()2088         void trigger() {
2089             if (mHandler != null) {
2090                 mHandler.post(() -> {
2091                     action();
2092                 });
2093             } else {
2094                 action();
2095             }
2096         }
2097 
triggerWithArg(boolean arg)2098         void triggerWithArg(boolean arg) {
2099             if (mHandler != null) {
2100                 mHandler.post(() -> {
2101                     actionWithArg(arg);
2102                 });
2103             } else {
2104                 actionWithArg(arg);
2105             }
2106         }
2107 
action()2108         protected void action() {}
actionWithArg(boolean arg)2109         protected void actionWithArg(boolean arg) {}
2110 
ListenerProxy(LISTENER listener, Handler handler, String tag)2111         ListenerProxy(LISTENER listener, Handler handler, String tag) {
2112             mListener = listener;
2113             mHandler = handler;
2114         }
2115     }
2116 
2117     private class InterfaceDestroyedListenerProxy extends
2118             ListenerProxy<InterfaceDestroyedListener> {
2119         private final String mIfaceName;
InterfaceDestroyedListenerProxy(@onNull String ifaceName, InterfaceDestroyedListener destroyedListener, Handler handler)2120         InterfaceDestroyedListenerProxy(@NonNull String ifaceName,
2121                                         InterfaceDestroyedListener destroyedListener,
2122                                         Handler handler) {
2123             super(destroyedListener, handler, "InterfaceDestroyedListenerProxy");
2124             mIfaceName = ifaceName;
2125         }
2126 
2127         @Override
action()2128         protected void action() {
2129             mListener.onDestroyed(mIfaceName);
2130         }
2131     }
2132 
2133     private class InterfaceAvailableForRequestListenerProxy extends
2134             ListenerProxy<InterfaceAvailableForRequestListener> {
InterfaceAvailableForRequestListenerProxy( InterfaceAvailableForRequestListener destroyedListener, Handler handler)2135         InterfaceAvailableForRequestListenerProxy(
2136                 InterfaceAvailableForRequestListener destroyedListener, Handler handler) {
2137             super(destroyedListener, handler, "InterfaceAvailableForRequestListenerProxy");
2138         }
2139 
2140         @Override
actionWithArg(boolean isAvailable)2141         protected void actionWithArg(boolean isAvailable) {
2142             mListener.onAvailabilityChanged(isAvailable);
2143         }
2144     }
2145 
2146     private class InterfaceRttControllerLifecycleCallbackProxy implements
2147             InterfaceRttControllerLifecycleCallback {
2148         private InterfaceRttControllerLifecycleCallback mCallback;
2149         private Handler mHandler;
2150 
InterfaceRttControllerLifecycleCallbackProxy( InterfaceRttControllerLifecycleCallback callback, Handler handler)2151         InterfaceRttControllerLifecycleCallbackProxy(
2152                 InterfaceRttControllerLifecycleCallback callback, Handler handler) {
2153             mCallback = callback;
2154             mHandler = handler;
2155         }
2156 
2157         // override equals & hash to make sure that the container HashSet is unique with respect to
2158         // the contained listener
2159         @Override
equals(Object obj)2160         public boolean equals(Object obj) {
2161             return mCallback == ((InterfaceRttControllerLifecycleCallbackProxy) obj).mCallback;
2162         }
2163 
2164         @Override
hashCode()2165         public int hashCode() {
2166             return mCallback.hashCode();
2167         }
2168 
2169         @Override
onNewRttController(IWifiRttController controller)2170         public void onNewRttController(IWifiRttController controller) {
2171             mHandler.post(() -> mCallback.onNewRttController(controller));
2172         }
2173 
2174         @Override
onRttControllerDestroyed()2175         public void onRttControllerDestroyed() {
2176             mHandler.post(() -> mCallback.onRttControllerDestroyed());
2177         }
2178     }
2179 
dispatchRttControllerLifecycleOnNew()2180     private void dispatchRttControllerLifecycleOnNew() {
2181         if (VDBG) {
2182             Log.v(TAG, "dispatchRttControllerLifecycleOnNew: # cbs="
2183                     + mRttControllerLifecycleCallbacks.size());
2184         }
2185         for (InterfaceRttControllerLifecycleCallbackProxy cbp : mRttControllerLifecycleCallbacks) {
2186             cbp.onNewRttController(mIWifiRttController);
2187         }
2188     }
2189 
dispatchRttControllerLifecycleOnDestroyed()2190     private void dispatchRttControllerLifecycleOnDestroyed() {
2191         for (InterfaceRttControllerLifecycleCallbackProxy cbp : mRttControllerLifecycleCallbacks) {
2192             cbp.onRttControllerDestroyed();
2193         }
2194     }
2195 
2196 
2197     /**
2198      * Updates the RttController when the chip mode is changed:
2199      * - Handles callbacks to registered listeners
2200      * - Handles creation of new RttController
2201      */
updateRttControllerOnModeChange()2202     private void updateRttControllerOnModeChange() {
2203         synchronized (mLock) {
2204             boolean controllerDestroyed = mIWifiRttController != null;
2205             mIWifiRttController = null;
2206             if (mRttControllerLifecycleCallbacks.size() == 0) {
2207                 Log.d(TAG, "updateRttController: no one is interested in RTT controllers");
2208                 return;
2209             }
2210 
2211             IWifiRttController newRttController = createRttControllerIfPossible();
2212             if (newRttController == null) {
2213                 if (controllerDestroyed) {
2214                     dispatchRttControllerLifecycleOnDestroyed();
2215                 }
2216             } else {
2217                 mIWifiRttController = newRttController;
2218                 dispatchRttControllerLifecycleOnNew();
2219             }
2220         }
2221     }
2222 
2223     /**
2224      * Try to create a new RttController.
2225      *
2226      * @return The new RttController - or null on failure.
2227      */
createRttControllerIfPossible()2228     private IWifiRttController createRttControllerIfPossible() {
2229         synchronized (mLock) {
2230             if (!isWifiStarted()) {
2231                 Log.d(TAG, "createRttControllerIfPossible: Wifi is not started");
2232                 return null;
2233             }
2234 
2235             WifiChipInfo[] chipInfos = getAllChipInfo();
2236             if (chipInfos == null) {
2237                 Log.d(TAG, "createRttControllerIfPossible: no chip info found - most likely chip "
2238                         + "not up yet");
2239                 return null;
2240             }
2241 
2242             for (WifiChipInfo chipInfo : chipInfos) {
2243                 if (!chipInfo.currentModeIdValid) {
2244                     if (VDBG) {
2245                         Log.d(TAG, "createRttControllerIfPossible: chip not configured yet: "
2246                                 + chipInfo);
2247                     }
2248                     continue;
2249                 }
2250 
2251                 Mutable<IWifiRttController> rttResp = new Mutable<>();
2252                 try {
2253                     chipInfo.chip.createRttController(null,
2254                             (WifiStatus status, IWifiRttController rtt) -> {
2255                                 if (status.code == WifiStatusCode.SUCCESS) {
2256                                     rttResp.value = rtt;
2257                                 } else {
2258                                     Log.e(TAG, "IWifiChip.createRttController failed: "
2259                                             + statusString(status));
2260                                 }
2261                             });
2262                 } catch (RemoteException e) {
2263                     Log.e(TAG, "IWifiChip.createRttController exception: " + e);
2264                 }
2265                 if (rttResp.value != null) {
2266                     return rttResp.value;
2267                 }
2268             }
2269         }
2270 
2271         Log.w(TAG, "createRttControllerIfPossible: not available from any of the chips");
2272         return null;
2273     }
2274 
2275     // general utilities
2276 
statusString(WifiStatus status)2277     private static String statusString(WifiStatus status) {
2278         if (status == null) {
2279             return "status=null";
2280         }
2281         StringBuilder sb = new StringBuilder();
2282         sb.append(status.code).append(" (").append(status.description).append(")");
2283         return sb.toString();
2284     }
2285 
2286     // Will return -1 for invalid results! Otherwise will return one of the 4 valid values.
getType(IWifiIface iface)2287     private static int getType(IWifiIface iface) {
2288         MutableInt typeResp = new MutableInt(-1);
2289         try {
2290             iface.getType((WifiStatus status, int type) -> {
2291                 if (status.code == WifiStatusCode.SUCCESS) {
2292                     typeResp.value = type;
2293                 } else {
2294                     Log.e(TAG, "Error on getType: " + statusString(status));
2295                 }
2296             });
2297         } catch (RemoteException e) {
2298             Log.e(TAG, "Exception on getType: " + e);
2299         }
2300 
2301         return typeResp.value;
2302     }
2303 
2304     /**
2305      * Dump the internal state of the class.
2306      */
dump(FileDescriptor fd, PrintWriter pw, String[] args)2307     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2308         pw.println("HalDeviceManager:");
2309         pw.println("  mServiceManager: " + mServiceManager);
2310         pw.println("  mWifi: " + mWifi);
2311         pw.println("  mManagerStatusListeners: " + mManagerStatusListeners);
2312         pw.println("  mInterfaceAvailableForRequestListeners: "
2313                 + mInterfaceAvailableForRequestListeners);
2314         pw.println("  mInterfaceInfoCache: " + mInterfaceInfoCache);
2315     }
2316 }
2317