blob: d6bec5f1a5a11734c8586260c6bbc1a18344416c [file] [log] [blame]
/*
* Copyright (C) 2016 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.aware;
import android.annotation.NonNull;
import android.hardware.wifi.V1_0.IWifiNanIface;
import android.hardware.wifi.V1_0.IfaceType;
import android.hardware.wifi.V1_0.WifiStatus;
import android.hardware.wifi.V1_0.WifiStatusCode;
import android.os.Handler;
import android.os.RemoteException;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.wifi.HalDeviceManager;
import java.io.FileDescriptor;
import java.io.PrintWriter;
/**
* Manages the interface to Wi-Fi Aware HIDL (HAL).
*/
public class WifiAwareNativeManager {
private static final String TAG = "WifiAwareNativeManager";
private static final boolean DBG = false;
// to be used for synchronizing access to any of the WifiAwareNative objects
private final Object mLock = new Object();
private WifiAwareStateManager mWifiAwareStateManager;
private HalDeviceManager mHalDeviceManager;
private Handler mHandler;
private WifiAwareNativeCallback mWifiAwareNativeCallback;
private IWifiNanIface mWifiNanIface = null;
private InterfaceDestroyedListener mInterfaceDestroyedListener =
new InterfaceDestroyedListener();
private InterfaceAvailableForRequestListener mInterfaceAvailableForRequestListener =
new InterfaceAvailableForRequestListener();
WifiAwareNativeManager(WifiAwareStateManager awareStateManager,
HalDeviceManager halDeviceManager,
WifiAwareNativeCallback wifiAwareNativeCallback) {
mWifiAwareStateManager = awareStateManager;
mHalDeviceManager = halDeviceManager;
mWifiAwareNativeCallback = wifiAwareNativeCallback;
}
/**
* Initialize the class - intended for late initialization.
*
* @param handler Handler on which to execute interface available callbacks.
*/
public void start(Handler handler) {
mHandler = handler;
mHalDeviceManager.initialize();
mHalDeviceManager.registerStatusListener(
new HalDeviceManager.ManagerStatusListener() {
@Override
public void onStatusChanged() {
if (DBG) Log.d(TAG, "onStatusChanged");
// only care about isStarted (Wi-Fi started) not isReady - since if not
// ready then Wi-Fi will also be down.
if (mHalDeviceManager.isStarted()) {
// 1. no problem registering duplicates - only one will be called
// 2. will be called immediately if available
mHalDeviceManager.registerInterfaceAvailableForRequestListener(
IfaceType.NAN, mInterfaceAvailableForRequestListener, mHandler);
} else {
awareIsDown();
}
}
}, null);
if (mHalDeviceManager.isStarted()) {
mHalDeviceManager.registerInterfaceAvailableForRequestListener(
IfaceType.NAN, mInterfaceAvailableForRequestListener, mHandler);
tryToGetAware();
}
}
/**
* Returns the native HAL WifiNanIface through which commands to the NAN HAL are dispatched.
* Return may be null if not initialized/available.
*/
@VisibleForTesting
public IWifiNanIface getWifiNanIface() {
synchronized (mLock) {
return mWifiNanIface;
}
}
/**
* Attempt to obtain the HAL NAN interface. If available then enables Aware usage.
*/
private void tryToGetAware() {
synchronized (mLock) {
if (DBG) Log.d(TAG, "tryToGetAware: mWifiNanIface=" + mWifiNanIface);
if (mWifiNanIface != null) {
return;
}
IWifiNanIface iface = mHalDeviceManager.createNanIface(mInterfaceDestroyedListener,
mHandler);
if (iface == null) {
if (DBG) Log.d(TAG, "Was not able to obtain an IWifiNanIface");
} else {
if (DBG) Log.d(TAG, "Obtained an IWifiNanIface");
try {
WifiStatus status = iface.registerEventCallback(mWifiAwareNativeCallback);
if (status.code != WifiStatusCode.SUCCESS) {
Log.e(TAG, "IWifiNanIface.registerEventCallback error: " + statusString(
status));
mHalDeviceManager.removeIface(iface);
return;
}
} catch (RemoteException e) {
Log.e(TAG, "IWifiNanIface.registerEventCallback exception: " + e);
mHalDeviceManager.removeIface(iface);
return;
}
mWifiNanIface = iface;
mWifiAwareStateManager.enableUsage();
}
}
}
private void awareIsDown() {
synchronized (mLock) {
if (DBG) Log.d(TAG, "awareIsDown: mWifiNanIface=" + mWifiNanIface);
if (mWifiNanIface != null) {
mWifiNanIface = null;
mWifiAwareStateManager.disableUsage();
}
}
}
private class InterfaceDestroyedListener implements
HalDeviceManager.InterfaceDestroyedListener {
@Override
public void onDestroyed(@NonNull String ifaceName) {
if (DBG) Log.d(TAG, "Interface was destroyed");
awareIsDown();
}
}
private class InterfaceAvailableForRequestListener implements
HalDeviceManager.InterfaceAvailableForRequestListener {
@Override
public void onAvailableForRequest() {
if (DBG) Log.d(TAG, "Interface is possibly available");
tryToGetAware();
}
}
private static String statusString(WifiStatus status) {
if (status == null) {
return "status=null";
}
StringBuilder sb = new StringBuilder();
sb.append(status.code).append(" (").append(status.description).append(")");
return sb.toString();
}
/**
* Dump the internal state of the class.
*/
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("WifiAwareNativeManager:");
pw.println(" mWifiNanIface: " + mWifiNanIface);
mWifiAwareNativeCallback.dump(fd, pw, args);
mHalDeviceManager.dump(fd, pw, args);
}
}