Home | History | Annotate | Download | only in aware
      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.hardware.wifi.V1_0.IWifiNanIface;
     20 import android.hardware.wifi.V1_0.IfaceType;
     21 import android.hardware.wifi.V1_0.WifiStatus;
     22 import android.hardware.wifi.V1_0.WifiStatusCode;
     23 import android.os.RemoteException;
     24 import android.util.Log;
     25 
     26 import com.android.internal.annotations.VisibleForTesting;
     27 import com.android.server.wifi.HalDeviceManager;
     28 
     29 import java.io.FileDescriptor;
     30 import java.io.PrintWriter;
     31 
     32 /**
     33  * Manages the interface to Wi-Fi Aware HIDL (HAL).
     34  */
     35 public 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         mWifiAwareNativeCallback.dump(fd, pw, args);
    176         mHalDeviceManager.dump(fd, pw, args);
    177     }
    178 }
    179