• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.android.server.wifi.aware;
18 
19 import android.annotation.NonNull;
20 import android.os.Handler;
21 import android.os.WorkSource;
22 import android.util.Log;
23 
24 import com.android.internal.annotations.VisibleForTesting;
25 import com.android.server.wifi.HalDeviceManager;
26 import com.android.server.wifi.hal.WifiNanIface;
27 
28 import java.io.FileDescriptor;
29 import java.io.PrintWriter;
30 
31 /**
32  * Manages the interface to the Wi-Fi Aware HAL.
33  */
34 public class WifiAwareNativeManager {
35     private static final String TAG = "WifiAwareNativeManager";
36     private boolean mVerboseHalLoggingEnabled = false;
37 
38     // to be used for synchronizing access to any of the WifiAwareNative objects
39     private final Object mLock = new Object();
40 
41     private WifiAwareStateManager mWifiAwareStateManager;
42     private HalDeviceManager mHalDeviceManager;
43     private Handler mHandler;
44     private WifiAwareNativeCallback mWifiAwareNativeCallback;
45     private WifiNanIface mWifiNanIface = null;
46     private InterfaceDestroyedListener mInterfaceDestroyedListener;
47     private int mReferenceCount = 0;
48 
WifiAwareNativeManager(WifiAwareStateManager awareStateManager, HalDeviceManager halDeviceManager, WifiAwareNativeCallback wifiAwareNativeCallback)49     WifiAwareNativeManager(WifiAwareStateManager awareStateManager,
50             HalDeviceManager halDeviceManager,
51             WifiAwareNativeCallback wifiAwareNativeCallback) {
52         mWifiAwareStateManager = awareStateManager;
53         mHalDeviceManager = halDeviceManager;
54         mWifiAwareNativeCallback = wifiAwareNativeCallback;
55     }
56 
57     /**
58      * Enable/Disable verbose logging.
59      */
enableVerboseLogging(boolean verboseEnabled, boolean halVerboseEnabled)60     public void enableVerboseLogging(boolean verboseEnabled, boolean halVerboseEnabled) {
61         mVerboseHalLoggingEnabled = halVerboseEnabled;
62         if (mWifiNanIface != null) {
63             mWifiNanIface.enableVerboseLogging(mVerboseHalLoggingEnabled);
64         }
65     }
66 
67     /**
68      * Initialize the class - intended for late initialization.
69      *
70      * @param handler Handler on which to execute interface available callbacks.
71      */
start(Handler handler)72     public void start(Handler handler) {
73         mHandler = handler;
74         mHalDeviceManager.initialize();
75         mHalDeviceManager.registerStatusListener(
76                 new HalDeviceManager.ManagerStatusListener() {
77                     @Override
78                     public void onStatusChanged() {
79                         if (mVerboseHalLoggingEnabled) Log.v(TAG, "onStatusChanged");
80                         // only care about isStarted (Wi-Fi started) not isReady - since if not
81                         // ready then Wi-Fi will also be down.
82                         if (mHalDeviceManager.isStarted()) {
83                             mWifiAwareStateManager.tryToGetAwareCapability();
84                         } else {
85                             awareIsDown(false);
86                         }
87                     }
88                 }, mHandler);
89         if (mHalDeviceManager.isStarted()) {
90             mWifiAwareStateManager.tryToGetAwareCapability();
91         }
92     }
93 
94     /**
95      * Returns the WifiNanIface through which commands to the NAN HAL are dispatched.
96      * Return may be null if not initialized/available.
97      */
98     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
getWifiNanIface()99     public WifiNanIface getWifiNanIface() {
100         synchronized (mLock) {
101             return mWifiNanIface;
102         }
103     }
104 
105     /**
106      * Attempt to obtain the HAL NAN interface.
107      */
tryToGetAware(@onNull WorkSource requestorWs)108     public void tryToGetAware(@NonNull WorkSource requestorWs) {
109         synchronized (mLock) {
110             if (mVerboseHalLoggingEnabled) {
111                 Log.d(TAG, "tryToGetAware: mWifiNanIface=" + mWifiNanIface
112                         + ", mReferenceCount=" + mReferenceCount + ", requestorWs=" + requestorWs);
113             }
114 
115             if (mWifiNanIface != null) {
116                 mReferenceCount++;
117                 return;
118             }
119             if (mHalDeviceManager == null) {
120                 Log.e(TAG, "tryToGetAware: mHalDeviceManager is null!?");
121                 awareIsDown(false);
122                 return;
123             }
124 
125             mInterfaceDestroyedListener = new InterfaceDestroyedListener();
126             WifiNanIface iface = mHalDeviceManager.createNanIface(mInterfaceDestroyedListener,
127                     mHandler, requestorWs);
128             if (iface == null) {
129                 Log.e(TAG, "Was not able to obtain a WifiNanIface (even though enabled!?)");
130                 awareIsDown(true);
131             } else {
132                 if (mVerboseHalLoggingEnabled) Log.v(TAG, "Obtained a WifiNanIface");
133                 if (!iface.registerFrameworkCallback(mWifiAwareNativeCallback)) {
134                     Log.e(TAG, "Unable to register callback with WifiNanIface");
135                     mHalDeviceManager.removeIface(iface);
136                     awareIsDown(false);
137                     return;
138                 }
139                 mWifiNanIface = iface;
140                 mReferenceCount = 1;
141                 mWifiNanIface.enableVerboseLogging(mVerboseHalLoggingEnabled);
142             }
143         }
144     }
145 
146     /**
147      * Release the HAL NAN interface.
148      */
releaseAware()149     public void releaseAware() {
150         if (mVerboseHalLoggingEnabled) {
151             Log.d(TAG, "releaseAware: mWifiNanIface=" + mWifiNanIface + ", mReferenceCount="
152                     + mReferenceCount);
153         }
154 
155         if (mWifiNanIface == null) {
156             return;
157         }
158         if (mHalDeviceManager == null) {
159             Log.e(TAG, "releaseAware: mHalDeviceManager is null!?");
160             return;
161         }
162 
163         synchronized (mLock) {
164             mReferenceCount--;
165             if (mReferenceCount != 0) {
166                 return;
167             }
168             mInterfaceDestroyedListener.active = false;
169             mInterfaceDestroyedListener = null;
170             mHalDeviceManager.removeIface(mWifiNanIface);
171             mWifiNanIface = null;
172             mWifiAwareNativeCallback.resetChannelInfo();
173         }
174     }
175 
176     /**
177      * Replace requestorWs in-place when iface is already enabled.
178      */
replaceRequestorWs(@onNull WorkSource requestorWs)179     public boolean replaceRequestorWs(@NonNull WorkSource requestorWs) {
180         synchronized (mLock) {
181             if (mVerboseHalLoggingEnabled) {
182                 Log.d(TAG, "replaceRequestorWs: mWifiNanIface=" + mWifiNanIface
183                         + ", mReferenceCount=" + mReferenceCount + ", requestorWs=" + requestorWs);
184             }
185 
186             if (mWifiNanIface == null) {
187                 return false;
188             }
189             if (mHalDeviceManager == null) {
190                 Log.e(TAG, "tryToGetAware: mHalDeviceManager is null!?");
191                 awareIsDown(false);
192                 return false;
193             }
194 
195             return mHalDeviceManager.replaceRequestorWsForNanIface(mWifiNanIface, requestorWs);
196         }
197     }
198 
awareIsDown(boolean markAsAvailable)199     private void awareIsDown(boolean markAsAvailable) {
200         synchronized (mLock) {
201             if (mVerboseHalLoggingEnabled) {
202                 Log.d(TAG, "awareIsDown: mWifiNanIface=" + mWifiNanIface
203                         + ", mReferenceCount =" + mReferenceCount);
204             }
205             mWifiNanIface = null;
206             mReferenceCount = 0;
207             mWifiAwareStateManager.disableUsage(markAsAvailable);
208         }
209     }
210 
211     private class InterfaceDestroyedListener implements
212             HalDeviceManager.InterfaceDestroyedListener {
213         public boolean active = true;
214 
215         @Override
onDestroyed(@onNull String ifaceName)216         public void onDestroyed(@NonNull String ifaceName) {
217             if (mVerboseHalLoggingEnabled) {
218                 Log.d(TAG, "Interface was destroyed: mWifiNanIface=" + mWifiNanIface
219                         + ", active=" + active);
220             }
221             if (active && mWifiNanIface != null) {
222                 awareIsDown(true);
223             } // else: we released it locally so no need to disable usage
224         }
225     }
226 
227     /**
228      * Dump the internal state of the class.
229      */
dump(FileDescriptor fd, PrintWriter pw, String[] args)230     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
231         pw.println("WifiAwareNativeManager:");
232         pw.println("  mWifiNanIface: " + mWifiNanIface);
233         pw.println("  mReferenceCount: " + mReferenceCount);
234         mWifiAwareNativeCallback.dump(fd, pw, args);
235     }
236 }
237