WifiAwareNativeManager.java revision 9572e8b6de6cb7912df530ae2376452bf1469b33
1/*
2 * Copyright (C) 2016 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
17package com.android.server.wifi.aware;
18
19import android.hardware.wifi.V1_0.IWifiNanIface;
20import android.hardware.wifi.V1_0.IfaceType;
21import android.hardware.wifi.V1_0.WifiStatus;
22import android.hardware.wifi.V1_0.WifiStatusCode;
23import android.os.RemoteException;
24import android.util.Log;
25
26import com.android.internal.annotations.VisibleForTesting;
27import com.android.server.wifi.HalDeviceManager;
28
29import java.io.FileDescriptor;
30import java.io.PrintWriter;
31
32/**
33 * Manages the interface to Wi-Fi Aware HIDL (HAL).
34 */
35public class WifiAwareNativeManager {
36    private static final String TAG = "WifiAwareNativeManager";
37    private static final boolean DBG = false;
38
39    // to be used for synchronizing access to any of the WifiAwareNative objects
40    private final Object mLock = new Object();
41
42    private WifiAwareStateManager mWifiAwareStateManager;
43    private HalDeviceManager mHalDeviceManager;
44    private WifiAwareNativeCallback mWifiAwareNativeCallback;
45    private IWifiNanIface mWifiNanIface = null;
46    private InterfaceDestroyedListener mInterfaceDestroyedListener =
47            new InterfaceDestroyedListener();
48    private InterfaceAvailableForRequestListener mInterfaceAvailableForRequestListener =
49            new InterfaceAvailableForRequestListener();
50
51    WifiAwareNativeManager(WifiAwareStateManager awareStateManager,
52            HalDeviceManager halDeviceManager,
53            WifiAwareNativeCallback wifiAwareNativeCallback) {
54        mWifiAwareStateManager = awareStateManager;
55        mHalDeviceManager = halDeviceManager;
56        mWifiAwareNativeCallback = wifiAwareNativeCallback;
57    }
58
59    public void start() {
60        mHalDeviceManager.registerStatusListener(
61                new HalDeviceManager.ManagerStatusListener() {
62                    @Override
63                    public void onStatusChanged() {
64                        if (DBG) Log.d(TAG, "onStatusChanged");
65                        // only care about isStarted (Wi-Fi started) not isReady - since if not
66                        // ready then Wi-Fi will also be down.
67                        if (mHalDeviceManager.isStarted()) {
68                            // 1. no problem registering duplicates - only one will be called
69                            // 2. will be called immediately if available
70                            mHalDeviceManager.registerInterfaceAvailableForRequestListener(
71                                    IfaceType.NAN, mInterfaceAvailableForRequestListener, null);
72                        } else {
73                            awareIsDown();
74                        }
75                    }
76                }, null);
77        if (mHalDeviceManager.isStarted()) {
78            mHalDeviceManager.registerInterfaceAvailableForRequestListener(
79                    IfaceType.NAN, mInterfaceAvailableForRequestListener, null);
80            tryToGetAware();
81        }
82    }
83
84    /**
85     * Returns the native HAL WifiNanIface through which commands to the NAN HAL are dispatched.
86     * Return may be null if not initialized/available.
87     */
88    @VisibleForTesting
89    public IWifiNanIface getWifiNanIface() {
90        synchronized (mLock) {
91            return mWifiNanIface;
92        }
93    }
94
95    /**
96     * Attempt to obtain the HAL NAN interface. If available then enables Aware usage.
97     */
98    private void tryToGetAware() {
99        synchronized (mLock) {
100            if (DBG) Log.d(TAG, "tryToGetAware: mWifiNanIface=" + mWifiNanIface);
101
102            if (mWifiNanIface != null) {
103                return;
104            }
105            IWifiNanIface iface = mHalDeviceManager.createNanIface(mInterfaceDestroyedListener,
106                    null);
107            if (iface == null) {
108                if (DBG) Log.d(TAG, "Was not able to obtain an IWifiNanIface");
109            } else {
110                if (DBG) Log.d(TAG, "Obtained an IWifiNanIface");
111
112                try {
113                    WifiStatus status = iface.registerEventCallback(mWifiAwareNativeCallback);
114                    if (status.code != WifiStatusCode.SUCCESS) {
115                        Log.e(TAG, "IWifiNanIface.registerEventCallback error: " + statusString(
116                                status));
117                        mHalDeviceManager.removeIface(iface);
118                        return;
119                    }
120                } catch (RemoteException e) {
121                    Log.e(TAG, "IWifiNanIface.registerEventCallback exception: " + e);
122                    mHalDeviceManager.removeIface(iface);
123                    return;
124                }
125                mWifiNanIface = iface;
126                mWifiAwareStateManager.enableUsage();
127            }
128        }
129    }
130
131    private void awareIsDown() {
132        synchronized (mLock) {
133            if (DBG) Log.d(TAG, "awareIsDown: mWifiNanIface=" + mWifiNanIface);
134            if (mWifiNanIface != null) {
135                mWifiNanIface = null;
136                mWifiAwareStateManager.disableUsage();
137            }
138        }
139    }
140
141    private class InterfaceDestroyedListener implements
142            HalDeviceManager.InterfaceDestroyedListener {
143        @Override
144        public void onDestroyed() {
145            if (DBG) Log.d(TAG, "Interface was destroyed");
146            awareIsDown();
147        }
148    }
149
150    private class InterfaceAvailableForRequestListener implements
151            HalDeviceManager.InterfaceAvailableForRequestListener {
152        @Override
153        public void onAvailableForRequest() {
154            if (DBG) Log.d(TAG, "Interface is possibly available");
155            tryToGetAware();
156        }
157    }
158
159    private static String statusString(WifiStatus status) {
160        if (status == null) {
161            return "status=null";
162        }
163        StringBuilder sb = new StringBuilder();
164        sb.append(status.code).append(" (").append(status.description).append(")");
165        return sb.toString();
166    }
167
168    /**
169     * Dump the internal state of the class.
170     */
171    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
172        pw.println("WifiAwareNativeManager:");
173        pw.println("  mWifiNanIface: " + mWifiNanIface);
174        mWifiAwareNativeCallback.dump(fd, pw, args);
175        mHalDeviceManager.dump(fd, pw, args);
176    }
177}
178