WifiAwareNativeManager.java revision 0b31edb987c0552b75667e05f0d589937a16f1ad
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
1964ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohenimport android.hardware.wifi.V1_0.IWifiNanIface;
20448a7b6b7b16cf39ed25729ceaf61edb30368567Etan Cohenimport android.hardware.wifi.V1_0.IfaceType;
21db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohenimport android.hardware.wifi.V1_0.WifiStatus;
22db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohenimport android.hardware.wifi.V1_0.WifiStatusCode;
23db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohenimport android.os.RemoteException;
2464ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohenimport android.util.Log;
2564ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen
2664ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohenimport com.android.server.wifi.HalDeviceManager;
2764ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen
28db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohenimport java.io.FileDescriptor;
29db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohenimport java.io.PrintWriter;
30db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen
3164ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen/**
3264ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen * Manages the interface to Wi-Fi Aware HIDL (HAL).
3364ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen */
3464ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohenclass WifiAwareNativeManager {
3564ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    private static final String TAG = "WifiAwareNativeManager";
3664ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    private static final boolean DBG = false;
3764ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen
3864ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    // to be used for synchronizing access to any of the WifiAwareNative objects
3964ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    private final Object mLock = new Object();
4064ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen
4164ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    private WifiAwareStateManager mWifiAwareStateManager;
4264ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    private HalDeviceManager mHalDeviceManager;
43db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen    private WifiAwareNativeCallback mWifiAwareNativeCallback;
4464ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    private IWifiNanIface mWifiNanIface = null;
4564ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    private InterfaceDestroyedListener mInterfaceDestroyedListener =
4664ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen            new InterfaceDestroyedListener();
4764ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    private InterfaceAvailableForRequestListener mInterfaceAvailableForRequestListener =
4864ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen            new InterfaceAvailableForRequestListener();
4964ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen
5064ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    WifiAwareNativeManager(WifiAwareStateManager awareStateManager,
51db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen            HalDeviceManager halDeviceManager,
52db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen            WifiAwareNativeCallback wifiAwareNativeCallback) {
5364ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        mWifiAwareStateManager = awareStateManager;
5464ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        mHalDeviceManager = halDeviceManager;
55db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen        mWifiAwareNativeCallback = wifiAwareNativeCallback;
560b31edb987c0552b75667e05f0d589937a16f1adEtan Cohen    }
570b31edb987c0552b75667e05f0d589937a16f1adEtan Cohen
580b31edb987c0552b75667e05f0d589937a16f1adEtan Cohen    public void start() {
593145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen        mHalDeviceManager.registerStatusListener(
603145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen                new HalDeviceManager.ManagerStatusListener() {
6164ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen                    @Override
623145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen                    public void onStatusChanged() {
633145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen                        if (DBG) Log.d(TAG, "onStatusChanged");
643145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen                        // only care about isStarted (Wi-Fi started) not isReady - since if not
653145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen                        // ready then Wi-Fi will also be down.
663145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen                        if (mHalDeviceManager.isStarted()) {
67448a7b6b7b16cf39ed25729ceaf61edb30368567Etan Cohen                            // 1. no problem registering duplicates - only one will be called
68448a7b6b7b16cf39ed25729ceaf61edb30368567Etan Cohen                            // 2. will be called immediately if available
69448a7b6b7b16cf39ed25729ceaf61edb30368567Etan Cohen                            mHalDeviceManager.registerInterfaceAvailableForRequestListener(
70448a7b6b7b16cf39ed25729ceaf61edb30368567Etan Cohen                                    IfaceType.NAN, mInterfaceAvailableForRequestListener, null);
713145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen                        } else {
723145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen                            awareIsDown();
733145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen                        }
7464ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen                    }
7564ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen                }, null);
763145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen        if (mHalDeviceManager.isStarted()) {
773145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen            tryToGetAware();
783145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen        }
7964ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    }
8064ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen
8164ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    /* package */ IWifiNanIface getWifiNanIface() {
8264ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        synchronized (mLock) {
8364ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen            return mWifiNanIface;
8464ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        }
8564ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    }
8664ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen
8764ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    private void tryToGetAware() {
8864ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        synchronized (mLock) {
89448a7b6b7b16cf39ed25729ceaf61edb30368567Etan Cohen            if (DBG) Log.d(TAG, "tryToGetAware: mWifiNanIface=" + mWifiNanIface);
90448a7b6b7b16cf39ed25729ceaf61edb30368567Etan Cohen
913145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen            if (mWifiNanIface != null) {
923145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen                return;
933145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen            }
94448a7b6b7b16cf39ed25729ceaf61edb30368567Etan Cohen            IWifiNanIface iface = mHalDeviceManager.createNanIface(mInterfaceDestroyedListener,
95448a7b6b7b16cf39ed25729ceaf61edb30368567Etan Cohen                    null);
9664ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen            if (iface == null) {
9764ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen                if (DBG) Log.d(TAG, "Was not able to obtain an IWifiNanIface");
9864ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen            } else {
9964ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen                if (DBG) Log.d(TAG, "Obtained an IWifiNanIface");
10064ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen
101db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                try {
102db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                    WifiStatus status = iface.registerEventCallback(mWifiAwareNativeCallback);
103db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                    if (status.code != WifiStatusCode.SUCCESS) {
104db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                        Log.e(TAG, "IWifiNanIface.registerEventCallback error: " + statusString(
105db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                                status));
106db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                        mHalDeviceManager.removeIface(iface);
107db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                        return;
108db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                    }
109db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                } catch (RemoteException e) {
110db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                    Log.e(TAG, "IWifiNanIface.registerEventCallback exception: " + e);
111db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                    mHalDeviceManager.removeIface(iface);
112db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                    return;
113db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                }
11464ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen                mWifiNanIface = iface;
11564ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen                mWifiAwareStateManager.enableUsage();
11664ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen            }
11764ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        }
11864ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    }
11964ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen
12064ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    private void awareIsDown() {
121448a7b6b7b16cf39ed25729ceaf61edb30368567Etan Cohen        synchronized (mLock) {
122448a7b6b7b16cf39ed25729ceaf61edb30368567Etan Cohen            if (DBG) Log.d(TAG, "awareIsDown: mWifiNanIface=" + mWifiNanIface);
123448a7b6b7b16cf39ed25729ceaf61edb30368567Etan Cohen            if (mWifiNanIface != null) {
12464ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen                mWifiNanIface = null;
12564ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen                mWifiAwareStateManager.disableUsage();
12664ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen            }
12764ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        }
12864ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    }
12964ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen
13064ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    private class InterfaceDestroyedListener implements
13164ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen            HalDeviceManager.InterfaceDestroyedListener {
13264ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        @Override
13364ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        public void onDestroyed() {
13464ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen            if (DBG) Log.d(TAG, "Interface was destroyed");
13564ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen            awareIsDown();
13664ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        }
13764ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    }
13864ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen
13964ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    private class InterfaceAvailableForRequestListener implements
14064ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen            HalDeviceManager.InterfaceAvailableForRequestListener {
14164ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        @Override
14264ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        public void onAvailableForRequest() {
14364ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen            if (DBG) Log.d(TAG, "Interface is possibly available");
14464ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen            tryToGetAware();
14564ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        }
14664ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    }
147db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen
148db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen    private static String statusString(WifiStatus status) {
149db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen        if (status == null) {
150db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen            return "status=null";
151db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen        }
152db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen        StringBuilder sb = new StringBuilder();
153db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen        sb.append(status.code).append(" (").append(status.description).append(")");
154db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen        return sb.toString();
155db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen    }
156db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen
157db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen    /**
158db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen     * Dump the internal state of the class.
159db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen     */
160db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
161db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen        pw.println("WifiAwareNativeManager:");
162db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen        pw.println("  mWifiNanIface: " + mWifiNanIface);
163db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen        mHalDeviceManager.dump(fd, pw, args);
164db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen    }
16564ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen}
166