WifiAwareNativeManager.java revision 19c6781efe4ad552dec3423c858b2ab64f447d8e
164ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen/*
264ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen * Copyright (C) 2016 The Android Open Source Project
364ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen *
464ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen * Licensed under the Apache License, Version 2.0 (the "License");
564ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen * you may not use this file except in compliance with the License.
664ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen * You may obtain a copy of the License at
764ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen *
864ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen *      http://www.apache.org/licenses/LICENSE-2.0
964ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen *
1064ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen * Unless required by applicable law or agreed to in writing, software
1164ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen * distributed under the License is distributed on an "AS IS" BASIS,
1264ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1364ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen * See the License for the specific language governing permissions and
1464ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen * limitations under the License.
1564ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen */
1664ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen
1764ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohenpackage com.android.server.wifi.aware;
1864ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen
19968a755132c525e5e1f1224a05eef7a58809fbd9Roshan Piusimport android.annotation.NonNull;
2064ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohenimport android.hardware.wifi.V1_0.IWifiNanIface;
21448a7b6b7b16cf39ed25729ceaf61edb30368567Etan Cohenimport android.hardware.wifi.V1_0.IfaceType;
22db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohenimport android.hardware.wifi.V1_0.WifiStatus;
23db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohenimport android.hardware.wifi.V1_0.WifiStatusCode;
240d5a9d5c9f0914ad145926beb96fb72b39089e02Etan Cohenimport android.os.Handler;
25db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohenimport android.os.RemoteException;
2664ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohenimport android.util.Log;
2764ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen
28c760a66378bbd844eb421658799b4d55c76b98faEtan Cohenimport com.android.internal.annotations.VisibleForTesting;
2964ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohenimport com.android.server.wifi.HalDeviceManager;
3064ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen
31db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohenimport java.io.FileDescriptor;
32db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohenimport java.io.PrintWriter;
33db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen
3464ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen/**
3564ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen * Manages the interface to Wi-Fi Aware HIDL (HAL).
3664ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen */
37c760a66378bbd844eb421658799b4d55c76b98faEtan Cohenpublic class WifiAwareNativeManager {
3864ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    private static final String TAG = "WifiAwareNativeManager";
3964ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    private static final boolean DBG = false;
4064ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen
4164ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    // to be used for synchronizing access to any of the WifiAwareNative objects
4264ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    private final Object mLock = new Object();
4364ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen
4464ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    private WifiAwareStateManager mWifiAwareStateManager;
4564ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    private HalDeviceManager mHalDeviceManager;
460d5a9d5c9f0914ad145926beb96fb72b39089e02Etan Cohen    private Handler mHandler;
47db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen    private WifiAwareNativeCallback mWifiAwareNativeCallback;
4864ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    private IWifiNanIface mWifiNanIface = null;
4964ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    private InterfaceDestroyedListener mInterfaceDestroyedListener =
5064ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen            new InterfaceDestroyedListener();
5164ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    private InterfaceAvailableForRequestListener mInterfaceAvailableForRequestListener =
5264ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen            new InterfaceAvailableForRequestListener();
5364ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen
5464ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    WifiAwareNativeManager(WifiAwareStateManager awareStateManager,
55db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen            HalDeviceManager halDeviceManager,
56db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen            WifiAwareNativeCallback wifiAwareNativeCallback) {
5764ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        mWifiAwareStateManager = awareStateManager;
5864ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        mHalDeviceManager = halDeviceManager;
59db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen        mWifiAwareNativeCallback = wifiAwareNativeCallback;
600b31edb987c0552b75667e05f0d589937a16f1adEtan Cohen    }
610b31edb987c0552b75667e05f0d589937a16f1adEtan Cohen
620d5a9d5c9f0914ad145926beb96fb72b39089e02Etan Cohen    /**
630d5a9d5c9f0914ad145926beb96fb72b39089e02Etan Cohen     * Initialize the class - intended for late initialization.
640d5a9d5c9f0914ad145926beb96fb72b39089e02Etan Cohen     *
650d5a9d5c9f0914ad145926beb96fb72b39089e02Etan Cohen     * @param handler Handler on which to execute interface available callbacks.
660d5a9d5c9f0914ad145926beb96fb72b39089e02Etan Cohen     */
670d5a9d5c9f0914ad145926beb96fb72b39089e02Etan Cohen    public void start(Handler handler) {
680d5a9d5c9f0914ad145926beb96fb72b39089e02Etan Cohen        mHandler = handler;
699b37a65ec7b89ca58639443fd899824b28d04191Etan Cohen        mHalDeviceManager.initialize();
703145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen        mHalDeviceManager.registerStatusListener(
713145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen                new HalDeviceManager.ManagerStatusListener() {
7264ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen                    @Override
733145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen                    public void onStatusChanged() {
743145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen                        if (DBG) Log.d(TAG, "onStatusChanged");
753145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen                        // only care about isStarted (Wi-Fi started) not isReady - since if not
763145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen                        // ready then Wi-Fi will also be down.
773145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen                        if (mHalDeviceManager.isStarted()) {
78448a7b6b7b16cf39ed25729ceaf61edb30368567Etan Cohen                            // 1. no problem registering duplicates - only one will be called
79448a7b6b7b16cf39ed25729ceaf61edb30368567Etan Cohen                            // 2. will be called immediately if available
80448a7b6b7b16cf39ed25729ceaf61edb30368567Etan Cohen                            mHalDeviceManager.registerInterfaceAvailableForRequestListener(
810d5a9d5c9f0914ad145926beb96fb72b39089e02Etan Cohen                                    IfaceType.NAN, mInterfaceAvailableForRequestListener, mHandler);
823145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen                        } else {
833145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen                            awareIsDown();
843145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen                        }
8564ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen                    }
8619c6781efe4ad552dec3423c858b2ab64f447d8eRoshan Pius                }, mHandler);
873145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen        if (mHalDeviceManager.isStarted()) {
88ef6de4b88b850e9df98a9ffe51c71ac493f6c51bEtan Cohen            mHalDeviceManager.registerInterfaceAvailableForRequestListener(
890d5a9d5c9f0914ad145926beb96fb72b39089e02Etan Cohen                    IfaceType.NAN, mInterfaceAvailableForRequestListener, mHandler);
903145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen            tryToGetAware();
913145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen        }
9264ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    }
9364ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen
94c760a66378bbd844eb421658799b4d55c76b98faEtan Cohen    /**
95c760a66378bbd844eb421658799b4d55c76b98faEtan Cohen     * Returns the native HAL WifiNanIface through which commands to the NAN HAL are dispatched.
96c760a66378bbd844eb421658799b4d55c76b98faEtan Cohen     * Return may be null if not initialized/available.
97c760a66378bbd844eb421658799b4d55c76b98faEtan Cohen     */
98c760a66378bbd844eb421658799b4d55c76b98faEtan Cohen    @VisibleForTesting
99c760a66378bbd844eb421658799b4d55c76b98faEtan Cohen    public IWifiNanIface getWifiNanIface() {
10064ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        synchronized (mLock) {
10164ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen            return mWifiNanIface;
10264ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        }
10364ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    }
10464ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen
105c760a66378bbd844eb421658799b4d55c76b98faEtan Cohen    /**
106c760a66378bbd844eb421658799b4d55c76b98faEtan Cohen     * Attempt to obtain the HAL NAN interface. If available then enables Aware usage.
107c760a66378bbd844eb421658799b4d55c76b98faEtan Cohen     */
10864ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    private void tryToGetAware() {
10964ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        synchronized (mLock) {
110448a7b6b7b16cf39ed25729ceaf61edb30368567Etan Cohen            if (DBG) Log.d(TAG, "tryToGetAware: mWifiNanIface=" + mWifiNanIface);
111448a7b6b7b16cf39ed25729ceaf61edb30368567Etan Cohen
1123145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen            if (mWifiNanIface != null) {
1133145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen                return;
1143145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen            }
115448a7b6b7b16cf39ed25729ceaf61edb30368567Etan Cohen            IWifiNanIface iface = mHalDeviceManager.createNanIface(mInterfaceDestroyedListener,
1160d5a9d5c9f0914ad145926beb96fb72b39089e02Etan Cohen                    mHandler);
11764ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen            if (iface == null) {
11864ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen                if (DBG) Log.d(TAG, "Was not able to obtain an IWifiNanIface");
11964ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen            } else {
12064ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen                if (DBG) Log.d(TAG, "Obtained an IWifiNanIface");
12164ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen
122db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                try {
123db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                    WifiStatus status = iface.registerEventCallback(mWifiAwareNativeCallback);
124db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                    if (status.code != WifiStatusCode.SUCCESS) {
125db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                        Log.e(TAG, "IWifiNanIface.registerEventCallback error: " + statusString(
126db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                                status));
127db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                        mHalDeviceManager.removeIface(iface);
128db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                        return;
129db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                    }
130db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                } catch (RemoteException e) {
131db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                    Log.e(TAG, "IWifiNanIface.registerEventCallback exception: " + e);
132db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                    mHalDeviceManager.removeIface(iface);
133db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                    return;
134db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                }
13564ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen                mWifiNanIface = iface;
13664ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen                mWifiAwareStateManager.enableUsage();
13764ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen            }
13864ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        }
13964ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    }
14064ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen
14164ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    private void awareIsDown() {
142448a7b6b7b16cf39ed25729ceaf61edb30368567Etan Cohen        synchronized (mLock) {
143448a7b6b7b16cf39ed25729ceaf61edb30368567Etan Cohen            if (DBG) Log.d(TAG, "awareIsDown: mWifiNanIface=" + mWifiNanIface);
144448a7b6b7b16cf39ed25729ceaf61edb30368567Etan Cohen            if (mWifiNanIface != null) {
14564ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen                mWifiNanIface = null;
14664ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen                mWifiAwareStateManager.disableUsage();
14764ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen            }
14864ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        }
14964ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    }
15064ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen
15164ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    private class InterfaceDestroyedListener implements
15264ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen            HalDeviceManager.InterfaceDestroyedListener {
15364ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        @Override
154968a755132c525e5e1f1224a05eef7a58809fbd9Roshan Pius        public void onDestroyed(@NonNull String ifaceName) {
15564ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen            if (DBG) Log.d(TAG, "Interface was destroyed");
15664ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen            awareIsDown();
15764ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        }
15864ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    }
15964ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen
16064ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    private class InterfaceAvailableForRequestListener implements
16164ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen            HalDeviceManager.InterfaceAvailableForRequestListener {
16264ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        @Override
16364ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        public void onAvailableForRequest() {
16464ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen            if (DBG) Log.d(TAG, "Interface is possibly available");
16564ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen            tryToGetAware();
16664ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        }
16764ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    }
168db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen
169db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen    private static String statusString(WifiStatus status) {
170db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen        if (status == null) {
171db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen            return "status=null";
172db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen        }
173db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen        StringBuilder sb = new StringBuilder();
174db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen        sb.append(status.code).append(" (").append(status.description).append(")");
175db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen        return sb.toString();
176db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen    }
177db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen
178db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen    /**
179db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen     * Dump the internal state of the class.
180db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen     */
181db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
182db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen        pw.println("WifiAwareNativeManager:");
183db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen        pw.println("  mWifiNanIface: " + mWifiNanIface);
1849572e8b6de6cb7912df530ae2376452bf1469b33Etan Cohen        mWifiAwareNativeCallback.dump(fd, pw, args);
185db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen        mHalDeviceManager.dump(fd, pw, args);
186db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen    }
18764ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen}
188