WifiAwareNativeManager.java revision 9b37a65ec7b89ca58639443fd899824b28d04191
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.initialize();
61        mHalDeviceManager.registerStatusListener(
62                new HalDeviceManager.ManagerStatusListener() {
63                    @Override
64                    public void onStatusChanged() {
65                        if (DBG) Log.d(TAG, "onStatusChanged");
66                        // only care about isStarted (Wi-Fi started) not isReady - since if not
67                        // ready then Wi-Fi will also be down.
68                        if (mHalDeviceManager.isStarted()) {
69                            // 1. no problem registering duplicates - only one will be called
70                            // 2. will be called immediately if available
71                            mHalDeviceManager.registerInterfaceAvailableForRequestListener(
72                                    IfaceType.NAN, mInterfaceAvailableForRequestListener, null);
73                        } else {
74                            awareIsDown();
75                        }
76                    }
77                }, null);
78        if (mHalDeviceManager.isStarted()) {
79            mHalDeviceManager.registerInterfaceAvailableForRequestListener(
80                    IfaceType.NAN, mInterfaceAvailableForRequestListener, null);
81            tryToGetAware();
82        }
83    }
84
85    /**
86     * Returns the native HAL WifiNanIface through which commands to the NAN HAL are dispatched.
87     * Return may be null if not initialized/available.
88     */
89    @VisibleForTesting
90    public IWifiNanIface getWifiNanIface() {
91        synchronized (mLock) {
92            return mWifiNanIface;
93        }
94    }
95
96    /**
97     * Attempt to obtain the HAL NAN interface. If available then enables Aware usage.
98     */
99    private void tryToGetAware() {
100        synchronized (mLock) {
101            if (DBG) Log.d(TAG, "tryToGetAware: mWifiNanIface=" + mWifiNanIface);
102
103            if (mWifiNanIface != null) {
104                return;
105            }
106            IWifiNanIface iface = mHalDeviceManager.createNanIface(mInterfaceDestroyedListener,
107                    null);
108            if (iface == null) {
109                if (DBG) Log.d(TAG, "Was not able to obtain an IWifiNanIface");
110            } else {
111                if (DBG) Log.d(TAG, "Obtained an IWifiNanIface");
112
113                try {
114                    WifiStatus status = iface.registerEventCallback(mWifiAwareNativeCallback);
115                    if (status.code != WifiStatusCode.SUCCESS) {
116                        Log.e(TAG, "IWifiNanIface.registerEventCallback error: " + statusString(
117                                status));
118                        mHalDeviceManager.removeIface(iface);
119                        return;
120                    }
121                } catch (RemoteException e) {
122                    Log.e(TAG, "IWifiNanIface.registerEventCallback exception: " + e);
123                    mHalDeviceManager.removeIface(iface);
124                    return;
125                }
126                mWifiNanIface = iface;
127                mWifiAwareStateManager.enableUsage();
128            }
129        }
130    }
131
132    private void awareIsDown() {
133        synchronized (mLock) {
134            if (DBG) Log.d(TAG, "awareIsDown: mWifiNanIface=" + mWifiNanIface);
135            if (mWifiNanIface != null) {
136                mWifiNanIface = null;
137                mWifiAwareStateManager.disableUsage();
138            }
139        }
140    }
141
142    private class InterfaceDestroyedListener implements
143            HalDeviceManager.InterfaceDestroyedListener {
144        @Override
145        public void onDestroyed() {
146            if (DBG) Log.d(TAG, "Interface was destroyed");
147            awareIsDown();
148        }
149    }
150
151    private class InterfaceAvailableForRequestListener implements
152            HalDeviceManager.InterfaceAvailableForRequestListener {
153        @Override
154        public void onAvailableForRequest() {
155            if (DBG) Log.d(TAG, "Interface is possibly available");
156            tryToGetAware();
157        }
158    }
159
160    private static String statusString(WifiStatus status) {
161        if (status == null) {
162            return "status=null";
163        }
164        StringBuilder sb = new StringBuilder();
165        sb.append(status.code).append(" (").append(status.description).append(")");
166        return sb.toString();
167    }
168
169    /**
170     * Dump the internal state of the class.
171     */
172    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
173        pw.println("WifiAwareNativeManager:");
174        pw.println("  mWifiNanIface: " + mWifiNanIface);
175        mHalDeviceManager.dump(fd, pw, args);
176    }
177}
178