Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.wifi;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.hardware.wifi.V1_0.IWifi;
import android.hardware.wifi.V1_0.IWifiApIface;
import android.hardware.wifi.V1_0.IWifiChip;
import android.hardware.wifi.V1_0.IWifiChipEventCallback;
import android.hardware.wifi.V1_0.IWifiEventCallback;
import android.hardware.wifi.V1_0.IWifiIface;
import android.hardware.wifi.V1_0.IWifiNanIface;
import android.hardware.wifi.V1_0.IWifiP2pIface;
import android.hardware.wifi.V1_0.IWifiRttController;
import android.hardware.wifi.V1_0.IWifiStaIface;
import android.hardware.wifi.V1_0.IfaceType;
import android.hardware.wifi.V1_0.WifiDebugRingBufferStatus;
import android.hardware.wifi.V1_0.WifiStatus;
import android.hardware.wifi.V1_0.WifiStatusCode;
import android.hidl.manager.V1_0.IServiceNotification;
import android.hidl.manager.V1_2.IServiceManager;
import android.os.Handler;
import android.os.HidlSupport.Mutable;
import android.os.HwRemoteBinder;
import android.os.RemoteException;
import android.util.Log;
import android.util.LongSparseArray;
import android.util.MutableBoolean;
import android.util.MutableInt;
import android.util.Pair;
import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Handles device management through the HAL (HIDL) interface.
*/
public class HalDeviceManager {
private static final String TAG = "HalDevMgr";
private static final boolean VDBG = false;
private boolean mDbg = false;
private static final int START_HAL_RETRY_INTERVAL_MS = 20;
// Number of attempts a start() is re-tried. A value of 0 means no retries after a single
// attempt.
@VisibleForTesting
public static final int START_HAL_RETRY_TIMES = 3;
private final Clock mClock;
// cache the value for supporting vendor HAL or not
private boolean mIsVendorHalSupported = false;
// public API
public HalDeviceManager(Clock clock) {
mClock = clock;
mInterfaceAvailableForRequestListeners.put(IfaceType.STA, new HashMap<>());
mInterfaceAvailableForRequestListeners.put(IfaceType.AP, new HashMap<>());
mInterfaceAvailableForRequestListeners.put(IfaceType.P2P, new HashMap<>());
mInterfaceAvailableForRequestListeners.put(IfaceType.NAN, new HashMap<>());
}
/* package */ void enableVerboseLogging(int verbose) {
if (verbose > 0) {
mDbg = true;
} else {
mDbg = false;
}
if (VDBG) {
mDbg = true; // just override
}
}
/**
* Actually starts the HalDeviceManager: separate from constructor since may want to phase
* at a later time.
*
* TODO: if decide that no need for separating construction from initialization (e.g. both are
* done at injector) then move to constructor.
*/
public void initialize() {
initializeInternal();
}
/**
* Register a ManagerStatusListener to get information about the status of the manager. Use the
* isReady() and isStarted() methods to check status immediately after registration and when
* triggered.
*
* It is safe to re-register the same callback object - duplicates are detected and only a
* single copy kept.
*
* @param listener ManagerStatusListener listener object.
* @param handler Handler on which to dispatch listener. Null implies the listener will be
* invoked synchronously from the context of the client which triggered the
* state change.
*/
public void registerStatusListener(@NonNull ManagerStatusListener listener,
@Nullable Handler handler) {
synchronized (mLock) {
if (!mManagerStatusListeners.add(new ManagerStatusListenerProxy(listener, handler))) {
Log.w(TAG, "registerStatusListener: duplicate registration ignored");
}
}
}
/**
* Returns whether the vendor HAL is supported on this device or not.
*/
public boolean isSupported() {
return mIsVendorHalSupported;
}
/**
* Returns the current status of the HalDeviceManager: whether or not it is ready to execute
* commands. A return of 'false' indicates that the HAL service (IWifi) is not available. Use
* the registerStatusListener() to listener for status changes.
*/
public boolean isReady() {
return mIsReady;
}
/**
* Returns the current status of Wi-Fi: started (true) or stopped (false).
*
* Note: direct call to HIDL.
*/
public boolean isStarted() {
return isWifiStarted();
}
/**
* Attempts to start Wi-Fi (using HIDL). Returns the success (true) or failure (false) or
* the start operation. Will also dispatch any registered ManagerStatusCallback.onStart() on
* success.
*
* Note: direct call to HIDL.
*/
public boolean start() {
return startWifi();
}
/**
* Stops Wi-Fi. Will also dispatch any registeredManagerStatusCallback.onStop().
*
* Note: direct call to HIDL - failure is not-expected.
*/
public void stop() {
stopWifi();
mWifi = null;
}
/**
* HAL device manager status change listener.
*/
public interface ManagerStatusListener {
/**
* Indicates that the status of the HalDeviceManager has changed. Use isReady() and
* isStarted() to obtain status information.
*/
void onStatusChanged();
}
/**
* Return the set of supported interface types across all Wi-Fi chips on the device.
*
* @return A set of IfaceTypes constants (possibly empty, e.g. on error).
*/
public Set getSupportedIfaceTypes() {
return getSupportedIfaceTypesInternal(null);
}
/**
* Return the set of supported interface types for the specified Wi-Fi chip.
*
* @return A set of IfaceTypes constants (possibly empty, e.g. on error).
*/
public Set getSupportedIfaceTypes(IWifiChip chip) {
return getSupportedIfaceTypesInternal(chip);
}
// interface-specific behavior
/**
* Create a STA interface if possible. Changes chip mode and removes conflicting interfaces if
* needed and permitted by priority.
*
* @param lowPrioritySta Indicates whether the requested STA is a low priority STA. The priority
* and preemption rules for low priority STA are:
* - Do not destroy any interface for it (even another low priority STA)
* - Destroy it for any other request
* @param destroyedListener Optional (nullable) listener to call when the allocated interface
* is removed. Will only be registered and used if an interface is
* created successfully.
* @param handler Handler on which to dispatch listener. Null implies the listener will be
* invoked synchronously from the context of the client which triggered the
* iface destruction.
* @return A newly created interface - or null if the interface could not be created.
*/
public IWifiStaIface createStaIface(boolean lowPrioritySta,
@Nullable InterfaceDestroyedListener destroyedListener, @Nullable Handler handler) {
return (IWifiStaIface) createIface(IfaceType.STA, lowPrioritySta, destroyedListener,
handler);
}
/**
* Create AP interface if possible (see createStaIface doc).
*/
public IWifiApIface createApIface(@Nullable InterfaceDestroyedListener destroyedListener,
@Nullable Handler handler) {
return (IWifiApIface) createIface(IfaceType.AP, false, destroyedListener, handler);
}
/**
* Create P2P interface if possible (see createStaIface doc).
*/
public IWifiP2pIface createP2pIface(@Nullable InterfaceDestroyedListener destroyedListener,
@Nullable Handler handler) {
return (IWifiP2pIface) createIface(IfaceType.P2P, false, destroyedListener, handler);
}
/**
* Create NAN interface if possible (see createStaIface doc).
*/
public IWifiNanIface createNanIface(@Nullable InterfaceDestroyedListener destroyedListener,
@Nullable Handler handler) {
return (IWifiNanIface) createIface(IfaceType.NAN, false, destroyedListener, handler);
}
/**
* Removes (releases/destroys) the given interface. Will trigger any registered
* InterfaceDestroyedListeners and possibly some InterfaceAvailableForRequestListeners if we
* can potentially create some other interfaces as a result of removing this interface.
*/
public boolean removeIface(IWifiIface iface) {
boolean success = removeIfaceInternal(iface);
dispatchAvailableForRequestListeners();
return success;
}
/**
* Returns the IWifiChip corresponding to the specified interface (or null on error).
*
* Note: clients must not perform chip mode changes or interface management (create/delete)
* operations on IWifiChip directly. However, they can use the IWifiChip interface to perform
* other functions - e.g. calling the debug/trace methods.
*/
public IWifiChip getChip(IWifiIface iface) {
String name = getName(iface);
int type = getType(iface);
if (VDBG) Log.d(TAG, "getChip: iface(name)=" + name);
synchronized (mLock) {
InterfaceCacheEntry cacheEntry = mInterfaceInfoCache.get(Pair.create(name, type));
if (cacheEntry == null) {
Log.e(TAG, "getChip: no entry for iface(name)=" + name);
return null;
}
return cacheEntry.chip;
}
}
/**
* Register an InterfaceDestroyedListener to the specified iface - returns true on success
* and false on failure. This listener is in addition to the one registered when the interface
* was created - allowing non-creators to monitor interface status.
*
* @param destroyedListener Listener to call when the allocated interface is removed.
* Will only be registered and used if an interface is created
* successfully.
* @param handler Handler on which to dispatch listener. Null implies the listener will be
* invoked synchronously from the context of the client which triggered the
* iface destruction.
*/
public boolean registerDestroyedListener(IWifiIface iface,
@NonNull InterfaceDestroyedListener destroyedListener,
@Nullable Handler handler) {
String name = getName(iface);
int type = getType(iface);
if (VDBG) Log.d(TAG, "registerDestroyedListener: iface(name)=" + name);
synchronized (mLock) {
InterfaceCacheEntry cacheEntry = mInterfaceInfoCache.get(Pair.create(name, type));
if (cacheEntry == null) {
Log.e(TAG, "registerDestroyedListener: no entry for iface(name)=" + name);
return false;
}
return cacheEntry.destroyedListeners.add(
new InterfaceDestroyedListenerProxy(name, destroyedListener, handler));
}
}
/**
* Register a listener to be called when an interface of the specified type could be requested.
* No guarantees are provided (some other entity could request it first). The listener is
* active from registration until unregistration - using
* unregisterInterfaceAvailableForRequestListener().
*
* Only a single instance of a listener will be registered (even if the specified looper is
* different).
*
* Note that if it is possible to create the specified interface type at registration time
* then the callback will be triggered immediately.
*
* @param ifaceType The interface type (IfaceType) to be monitored.
* @param listener Listener to call when an interface of the requested
* type could be created
* @param handler Handler on which to dispatch listener. Null implies the listener will be
* invoked synchronously from the context of the client which triggered the
* mode change.
*/
public void registerInterfaceAvailableForRequestListener(int ifaceType,
@NonNull InterfaceAvailableForRequestListener listener, @Nullable Handler handler) {
if (VDBG) {
Log.d(TAG, "registerInterfaceAvailableForRequestListener: ifaceType=" + ifaceType
+ ", listener=" + listener + ", handler=" + handler);
}
synchronized (mLock) {
InterfaceAvailableForRequestListenerProxy proxy =
new InterfaceAvailableForRequestListenerProxy(listener, handler);
if (mInterfaceAvailableForRequestListeners.get(ifaceType).containsKey(proxy)) {
if (VDBG) {
Log.d(TAG,
"registerInterfaceAvailableForRequestListener: dup listener skipped: "
+ listener);
}
return;
}
mInterfaceAvailableForRequestListeners.get(ifaceType).put(proxy, null);
}
WifiChipInfo[] chipInfos = getAllChipInfo();
if (chipInfos == null) {
Log.e(TAG,
"registerInterfaceAvailableForRequestListener: no chip info found - but "
+ "possibly registered pre-started - ignoring");
return;
}
dispatchAvailableForRequestListenersForType(ifaceType, chipInfos);
}
/**
* Unregisters a listener registered with registerInterfaceAvailableForRequestListener().
*/
public void unregisterInterfaceAvailableForRequestListener(
int ifaceType,
InterfaceAvailableForRequestListener listener) {
if (VDBG) {
Log.d(TAG, "unregisterInterfaceAvailableForRequestListener: ifaceType=" + ifaceType);
}
synchronized (mLock) {
mInterfaceAvailableForRequestListeners.get(ifaceType).remove(
new InterfaceAvailableForRequestListenerProxy(listener, null));
}
}
/**
* Register a callback object for RTT life-cycle events. The callback object registration
* indicates that an RTT controller should be created whenever possible. The callback object
* will be called with a new RTT controller whenever it is created (or at registration time
* if an RTT controller already exists). The callback object will also be triggered whenever
* an existing RTT controller is destroyed (the previous copies must be discarded by the
* recipient).
*
* @param callback InterfaceRttControllerLifecycleCallback object.
* @param handler Handler on which to dispatch callback
*/
public void registerRttControllerLifecycleCallback(
@NonNull InterfaceRttControllerLifecycleCallback callback, @NonNull Handler handler) {
if (VDBG) {
Log.d(TAG, "registerRttControllerLifecycleCallback: callback=" + callback + ", handler="
+ handler);
}
if (callback == null || handler == null) {
Log.wtf(TAG, "registerRttControllerLifecycleCallback with nulls!? callback=" + callback
+ ", handler=" + handler);
return;
}
synchronized (mLock) {
InterfaceRttControllerLifecycleCallbackProxy proxy =
new InterfaceRttControllerLifecycleCallbackProxy(callback, handler);
if (!mRttControllerLifecycleCallbacks.add(proxy)) {
Log.d(TAG,
"registerRttControllerLifecycleCallback: registering an existing callback="
+ callback);
return;
}
if (mIWifiRttController == null) {
mIWifiRttController = createRttControllerIfPossible();
}
if (mIWifiRttController != null) {
proxy.onNewRttController(mIWifiRttController);
}
}
}
/**
* Return the name of the input interface or null on error.
*/
public static String getName(IWifiIface iface) {
if (iface == null) {
return "";
}
Mutable nameResp = new Mutable<>();
try {
iface.getName((WifiStatus status, String name) -> {
if (status.code == WifiStatusCode.SUCCESS) {
nameResp.value = name;
} else {
Log.e(TAG, "Error on getName: " + statusString(status));
}
});
} catch (RemoteException e) {
Log.e(TAG, "Exception on getName: " + e);
}
return nameResp.value;
}
/**
* Called when interface is destroyed.
*/
public interface InterfaceDestroyedListener {
/**
* Called for every interface on which registered when destroyed - whether
* destroyed by releaseIface() or through chip mode change or through Wi-Fi
* going down.
*
* Can be registered when the interface is requested with createXxxIface() - will
* only be valid if the interface creation was successful - i.e. a non-null was returned.
*
* @param ifaceName Name of the interface that was destroyed.
*/
void onDestroyed(@NonNull String ifaceName);
}
/**
* Called when an interface type availability for creation is changed.
*/
public interface InterfaceAvailableForRequestListener {
/**
* Called when an interface type availability for creation is updated. Registered with
* registerInterfaceAvailableForRequestListener() and unregistered with
* unregisterInterfaceAvailableForRequestListener().
*/
void onAvailabilityChanged(boolean isAvailable);
}
/**
* Called on RTT controller lifecycle events. RTT controller is a singleton which will be
* created when possible (after first lifecycle registration) and destroyed if necessary.
*
* Determination of availability is determined by the HAL. Creation attempts (if requested
* by registration of interface) will be done on any mode changes.
*/
public interface InterfaceRttControllerLifecycleCallback {
/**
* Called when an RTT controller was created (or for newly registered listeners - if it
* was already available). The controller provided by this callback may be destroyed by
* the HAL at which point the {@link #onRttControllerDestroyed()} will be called.
*
* Note: this callback can be triggered to replace an existing controller (instead of
* calling the Destroyed callback in between).
*
* @param controller The RTT controller object.
*/
void onNewRttController(@NonNull IWifiRttController controller);
/**
* Called when the previously provided RTT controller is destroyed. Clients must discard
* their copy. A new copy may be provided later by
* {@link #onNewRttController(IWifiRttController)}.
*/
void onRttControllerDestroyed();
}
// internal state
/* This "PRIORITY" is not for deciding interface elimination (that is controlled by
* allowedToDeleteIfaceTypeForRequestedType. This priority is used for:
* - Comparing 2 configuration options
* - Order of dispatch of available for request listeners
*/
private static final int[] IFACE_TYPES_BY_PRIORITY =
{IfaceType.AP, IfaceType.STA, IfaceType.P2P, IfaceType.NAN};
private final Object mLock = new Object();
private IServiceManager mServiceManager;
private IWifi mWifi;
private IWifiRttController mIWifiRttController;
private final WifiEventCallback mWifiEventCallback = new WifiEventCallback();
private final Set mManagerStatusListeners = new HashSet<>();
private final Set
mRttControllerLifecycleCallbacks = new HashSet<>();
private final SparseArray