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
19968a755132c525e5e1f1224a05eef7a58809fbd9Roshan Piusimport android.annotation.NonNull;
2064ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohenimport android.hardware.wifi.V1_0.IWifiNanIface;
21448a7b6b7b16cf39ed25729ceaf61edb30368567Etan Cohenimport android.hardware.wifi.V1_0.IfaceType;
22db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohenimport android.hardware.wifi.V1_0.WifiStatus;
23db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohenimport android.hardware.wifi.V1_0.WifiStatusCode;
240d5a9d5c9f0914ad145926beb96fb72b39089e02Etan Cohenimport android.os.Handler;
25db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohenimport android.os.RemoteException;
2664ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohenimport android.util.Log;
2764ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen
28c760a66378bbd844eb421658799b4d55c76b98faEtan Cohenimport com.android.internal.annotations.VisibleForTesting;
2964ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohenimport com.android.server.wifi.HalDeviceManager;
3064ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen
31db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohenimport java.io.FileDescriptor;
32db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohenimport java.io.PrintWriter;
33db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen
3464ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen/**
3564ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen * Manages the interface to Wi-Fi Aware HIDL (HAL).
3664ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen */
37c760a66378bbd844eb421658799b4d55c76b98faEtan Cohenpublic class WifiAwareNativeManager {
3864ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    private static final String TAG = "WifiAwareNativeManager";
39d187886254382d86f6884f593d851594575acd0cEtan Cohen    private static final boolean VDBG = false;
40d187886254382d86f6884f593d851594575acd0cEtan Cohen    /* package */ boolean mDbg = false;
4164ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen
4264ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    // to be used for synchronizing access to any of the WifiAwareNative objects
4364ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    private final Object mLock = new Object();
4464ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen
4564ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    private WifiAwareStateManager mWifiAwareStateManager;
4664ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    private HalDeviceManager mHalDeviceManager;
470d5a9d5c9f0914ad145926beb96fb72b39089e02Etan Cohen    private Handler mHandler;
48db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen    private WifiAwareNativeCallback mWifiAwareNativeCallback;
4964ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    private IWifiNanIface mWifiNanIface = null;
5029ad45cb86b1d431cda152877b41a06925f88914Etan Cohen    private InterfaceDestroyedListener mInterfaceDestroyedListener;
5164ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    private InterfaceAvailableForRequestListener mInterfaceAvailableForRequestListener =
5264ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen            new InterfaceAvailableForRequestListener();
5329ad45cb86b1d431cda152877b41a06925f88914Etan Cohen    private int mReferenceCount = 0;
5464ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen
5564ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    WifiAwareNativeManager(WifiAwareStateManager awareStateManager,
56db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen            HalDeviceManager halDeviceManager,
57db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen            WifiAwareNativeCallback wifiAwareNativeCallback) {
5864ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        mWifiAwareStateManager = awareStateManager;
5964ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        mHalDeviceManager = halDeviceManager;
60db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen        mWifiAwareNativeCallback = wifiAwareNativeCallback;
610b31edb987c0552b75667e05f0d589937a16f1adEtan Cohen    }
620b31edb987c0552b75667e05f0d589937a16f1adEtan Cohen
630d5a9d5c9f0914ad145926beb96fb72b39089e02Etan Cohen    /**
64c2d924a70f1e5167fe8aae729f79425661c31572Etan Cohen     * (HIDL) Cast the input to a 1.2 NAN interface (possibly resulting in a null).
65c2d924a70f1e5167fe8aae729f79425661c31572Etan Cohen     *
66c2d924a70f1e5167fe8aae729f79425661c31572Etan Cohen     * Separate function so can be mocked in unit tests.
67c2d924a70f1e5167fe8aae729f79425661c31572Etan Cohen     */
68c2d924a70f1e5167fe8aae729f79425661c31572Etan Cohen    public android.hardware.wifi.V1_2.IWifiNanIface mockableCastTo_1_2(IWifiNanIface iface) {
69c2d924a70f1e5167fe8aae729f79425661c31572Etan Cohen        return android.hardware.wifi.V1_2.IWifiNanIface.castFrom(iface);
70c2d924a70f1e5167fe8aae729f79425661c31572Etan Cohen    }
71c2d924a70f1e5167fe8aae729f79425661c31572Etan Cohen
72c2d924a70f1e5167fe8aae729f79425661c31572Etan Cohen    /**
730d5a9d5c9f0914ad145926beb96fb72b39089e02Etan Cohen     * Initialize the class - intended for late initialization.
740d5a9d5c9f0914ad145926beb96fb72b39089e02Etan Cohen     *
750d5a9d5c9f0914ad145926beb96fb72b39089e02Etan Cohen     * @param handler Handler on which to execute interface available callbacks.
760d5a9d5c9f0914ad145926beb96fb72b39089e02Etan Cohen     */
770d5a9d5c9f0914ad145926beb96fb72b39089e02Etan Cohen    public void start(Handler handler) {
780d5a9d5c9f0914ad145926beb96fb72b39089e02Etan Cohen        mHandler = handler;
799b37a65ec7b89ca58639443fd899824b28d04191Etan Cohen        mHalDeviceManager.initialize();
803145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen        mHalDeviceManager.registerStatusListener(
813145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen                new HalDeviceManager.ManagerStatusListener() {
8264ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen                    @Override
833145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen                    public void onStatusChanged() {
84d187886254382d86f6884f593d851594575acd0cEtan Cohen                        if (VDBG) Log.v(TAG, "onStatusChanged");
853145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen                        // only care about isStarted (Wi-Fi started) not isReady - since if not
863145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen                        // ready then Wi-Fi will also be down.
873145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen                        if (mHalDeviceManager.isStarted()) {
88448a7b6b7b16cf39ed25729ceaf61edb30368567Etan Cohen                            // 1. no problem registering duplicates - only one will be called
89448a7b6b7b16cf39ed25729ceaf61edb30368567Etan Cohen                            // 2. will be called immediately if available
90448a7b6b7b16cf39ed25729ceaf61edb30368567Etan Cohen                            mHalDeviceManager.registerInterfaceAvailableForRequestListener(
910d5a9d5c9f0914ad145926beb96fb72b39089e02Etan Cohen                                    IfaceType.NAN, mInterfaceAvailableForRequestListener, mHandler);
923145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen                        } else {
933145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen                            awareIsDown();
943145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen                        }
9564ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen                    }
9619c6781efe4ad552dec3423c858b2ab64f447d8eRoshan Pius                }, mHandler);
973145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen        if (mHalDeviceManager.isStarted()) {
98ef6de4b88b850e9df98a9ffe51c71ac493f6c51bEtan Cohen            mHalDeviceManager.registerInterfaceAvailableForRequestListener(
990d5a9d5c9f0914ad145926beb96fb72b39089e02Etan Cohen                    IfaceType.NAN, mInterfaceAvailableForRequestListener, mHandler);
1003145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen        }
10164ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    }
10264ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen
103c760a66378bbd844eb421658799b4d55c76b98faEtan Cohen    /**
104c760a66378bbd844eb421658799b4d55c76b98faEtan Cohen     * Returns the native HAL WifiNanIface through which commands to the NAN HAL are dispatched.
105c760a66378bbd844eb421658799b4d55c76b98faEtan Cohen     * Return may be null if not initialized/available.
106c760a66378bbd844eb421658799b4d55c76b98faEtan Cohen     */
107c760a66378bbd844eb421658799b4d55c76b98faEtan Cohen    @VisibleForTesting
108c760a66378bbd844eb421658799b4d55c76b98faEtan Cohen    public IWifiNanIface getWifiNanIface() {
10964ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        synchronized (mLock) {
11064ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen            return mWifiNanIface;
11164ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        }
11264ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    }
11364ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen
114c760a66378bbd844eb421658799b4d55c76b98faEtan Cohen    /**
11529ad45cb86b1d431cda152877b41a06925f88914Etan Cohen     * Attempt to obtain the HAL NAN interface.
116c760a66378bbd844eb421658799b4d55c76b98faEtan Cohen     */
11729ad45cb86b1d431cda152877b41a06925f88914Etan Cohen    public void tryToGetAware() {
11864ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        synchronized (mLock) {
11929ad45cb86b1d431cda152877b41a06925f88914Etan Cohen            if (mDbg) {
12029ad45cb86b1d431cda152877b41a06925f88914Etan Cohen                Log.d(TAG, "tryToGetAware: mWifiNanIface=" + mWifiNanIface + ", mReferenceCount="
12129ad45cb86b1d431cda152877b41a06925f88914Etan Cohen                        + mReferenceCount);
12229ad45cb86b1d431cda152877b41a06925f88914Etan Cohen            }
123448a7b6b7b16cf39ed25729ceaf61edb30368567Etan Cohen
1243145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen            if (mWifiNanIface != null) {
12529ad45cb86b1d431cda152877b41a06925f88914Etan Cohen                mReferenceCount++;
12629ad45cb86b1d431cda152877b41a06925f88914Etan Cohen                return;
12729ad45cb86b1d431cda152877b41a06925f88914Etan Cohen            }
12829ad45cb86b1d431cda152877b41a06925f88914Etan Cohen            if (mHalDeviceManager == null) {
12929ad45cb86b1d431cda152877b41a06925f88914Etan Cohen                Log.e(TAG, "tryToGetAware: mHalDeviceManager is null!?");
13029ad45cb86b1d431cda152877b41a06925f88914Etan Cohen                awareIsDown();
1313145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen                return;
1323145bb4d3359647cccd9b4aba1734066f36bb2e6Etan Cohen            }
13329ad45cb86b1d431cda152877b41a06925f88914Etan Cohen
13429ad45cb86b1d431cda152877b41a06925f88914Etan Cohen            mInterfaceDestroyedListener = new InterfaceDestroyedListener();
135448a7b6b7b16cf39ed25729ceaf61edb30368567Etan Cohen            IWifiNanIface iface = mHalDeviceManager.createNanIface(mInterfaceDestroyedListener,
1360d5a9d5c9f0914ad145926beb96fb72b39089e02Etan Cohen                    mHandler);
13764ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen            if (iface == null) {
13829ad45cb86b1d431cda152877b41a06925f88914Etan Cohen                Log.e(TAG, "Was not able to obtain an IWifiNanIface (even though enabled!?)");
13929ad45cb86b1d431cda152877b41a06925f88914Etan Cohen                awareIsDown();
14064ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen            } else {
1419340e8f34b979b06bb90f92852353957120abf41Etan Cohen                if (mDbg) Log.v(TAG, "Obtained an IWifiNanIface");
14264ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen
143db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                try {
144c2d924a70f1e5167fe8aae729f79425661c31572Etan Cohen                    android.hardware.wifi.V1_2.IWifiNanIface iface12 = mockableCastTo_1_2(iface);
145c2d924a70f1e5167fe8aae729f79425661c31572Etan Cohen                    WifiStatus status;
146c2d924a70f1e5167fe8aae729f79425661c31572Etan Cohen                    if (iface12 == null) {
147c2d924a70f1e5167fe8aae729f79425661c31572Etan Cohen                        mWifiAwareNativeCallback.mIsHal12OrLater = false;
148c2d924a70f1e5167fe8aae729f79425661c31572Etan Cohen                        status = iface.registerEventCallback(mWifiAwareNativeCallback);
149c2d924a70f1e5167fe8aae729f79425661c31572Etan Cohen                    } else {
150c2d924a70f1e5167fe8aae729f79425661c31572Etan Cohen                        mWifiAwareNativeCallback.mIsHal12OrLater = true;
151c2d924a70f1e5167fe8aae729f79425661c31572Etan Cohen                        status = iface12.registerEventCallback_1_2(mWifiAwareNativeCallback);
152c2d924a70f1e5167fe8aae729f79425661c31572Etan Cohen                    }
153db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                    if (status.code != WifiStatusCode.SUCCESS) {
154db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                        Log.e(TAG, "IWifiNanIface.registerEventCallback error: " + statusString(
155db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                                status));
156db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                        mHalDeviceManager.removeIface(iface);
15729ad45cb86b1d431cda152877b41a06925f88914Etan Cohen                        awareIsDown();
158db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                        return;
159db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                    }
160db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                } catch (RemoteException e) {
161db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                    Log.e(TAG, "IWifiNanIface.registerEventCallback exception: " + e);
16229ad45cb86b1d431cda152877b41a06925f88914Etan Cohen                    awareIsDown();
163db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                    return;
164db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen                }
16564ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen                mWifiNanIface = iface;
16629ad45cb86b1d431cda152877b41a06925f88914Etan Cohen                mReferenceCount = 1;
16729ad45cb86b1d431cda152877b41a06925f88914Etan Cohen            }
16829ad45cb86b1d431cda152877b41a06925f88914Etan Cohen        }
16929ad45cb86b1d431cda152877b41a06925f88914Etan Cohen    }
17029ad45cb86b1d431cda152877b41a06925f88914Etan Cohen
17129ad45cb86b1d431cda152877b41a06925f88914Etan Cohen    /**
17229ad45cb86b1d431cda152877b41a06925f88914Etan Cohen     * Release the HAL NAN interface.
17329ad45cb86b1d431cda152877b41a06925f88914Etan Cohen     */
17429ad45cb86b1d431cda152877b41a06925f88914Etan Cohen    public void releaseAware() {
17529ad45cb86b1d431cda152877b41a06925f88914Etan Cohen        if (mDbg) {
17629ad45cb86b1d431cda152877b41a06925f88914Etan Cohen            Log.d(TAG, "releaseAware: mWifiNanIface=" + mWifiNanIface + ", mReferenceCount="
17729ad45cb86b1d431cda152877b41a06925f88914Etan Cohen                    + mReferenceCount);
17829ad45cb86b1d431cda152877b41a06925f88914Etan Cohen        }
17929ad45cb86b1d431cda152877b41a06925f88914Etan Cohen
18029ad45cb86b1d431cda152877b41a06925f88914Etan Cohen        if (mWifiNanIface == null) {
18129ad45cb86b1d431cda152877b41a06925f88914Etan Cohen            return;
18229ad45cb86b1d431cda152877b41a06925f88914Etan Cohen        }
18329ad45cb86b1d431cda152877b41a06925f88914Etan Cohen        if (mHalDeviceManager == null) {
18429ad45cb86b1d431cda152877b41a06925f88914Etan Cohen            Log.e(TAG, "releaseAware: mHalDeviceManager is null!?");
18529ad45cb86b1d431cda152877b41a06925f88914Etan Cohen            return;
18629ad45cb86b1d431cda152877b41a06925f88914Etan Cohen        }
18729ad45cb86b1d431cda152877b41a06925f88914Etan Cohen
18829ad45cb86b1d431cda152877b41a06925f88914Etan Cohen        synchronized (mLock) {
18929ad45cb86b1d431cda152877b41a06925f88914Etan Cohen            mReferenceCount--;
19029ad45cb86b1d431cda152877b41a06925f88914Etan Cohen            if (mReferenceCount != 0) {
19129ad45cb86b1d431cda152877b41a06925f88914Etan Cohen                return;
19264ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen            }
19329ad45cb86b1d431cda152877b41a06925f88914Etan Cohen            mInterfaceDestroyedListener.active = false;
19429ad45cb86b1d431cda152877b41a06925f88914Etan Cohen            mInterfaceDestroyedListener = null;
19529ad45cb86b1d431cda152877b41a06925f88914Etan Cohen            mHalDeviceManager.removeIface(mWifiNanIface);
19629ad45cb86b1d431cda152877b41a06925f88914Etan Cohen            mWifiNanIface = null;
19764ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        }
19864ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    }
19964ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen
20064ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    private void awareIsDown() {
201448a7b6b7b16cf39ed25729ceaf61edb30368567Etan Cohen        synchronized (mLock) {
20229ad45cb86b1d431cda152877b41a06925f88914Etan Cohen            if (mDbg) {
20329ad45cb86b1d431cda152877b41a06925f88914Etan Cohen                Log.d(TAG, "awareIsDown: mWifiNanIface=" + mWifiNanIface + ", mReferenceCount ="
20429ad45cb86b1d431cda152877b41a06925f88914Etan Cohen                        + mReferenceCount);
20564ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen            }
20629ad45cb86b1d431cda152877b41a06925f88914Etan Cohen            mWifiNanIface = null;
20729ad45cb86b1d431cda152877b41a06925f88914Etan Cohen            mReferenceCount = 0;
20829ad45cb86b1d431cda152877b41a06925f88914Etan Cohen            mWifiAwareStateManager.disableUsage();
20964ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        }
21064ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    }
21164ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen
21264ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    private class InterfaceDestroyedListener implements
21364ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen            HalDeviceManager.InterfaceDestroyedListener {
21429ad45cb86b1d431cda152877b41a06925f88914Etan Cohen        public boolean active = true;
21529ad45cb86b1d431cda152877b41a06925f88914Etan Cohen
21664ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        @Override
217968a755132c525e5e1f1224a05eef7a58809fbd9Roshan Pius        public void onDestroyed(@NonNull String ifaceName) {
21829ad45cb86b1d431cda152877b41a06925f88914Etan Cohen            if (mDbg) {
21929ad45cb86b1d431cda152877b41a06925f88914Etan Cohen                Log.d(TAG, "Interface was destroyed: mWifiNanIface=" + mWifiNanIface + ", active="
22029ad45cb86b1d431cda152877b41a06925f88914Etan Cohen                        + active);
22129ad45cb86b1d431cda152877b41a06925f88914Etan Cohen            }
22229ad45cb86b1d431cda152877b41a06925f88914Etan Cohen            if (active && mWifiNanIface != null) {
22329ad45cb86b1d431cda152877b41a06925f88914Etan Cohen                awareIsDown();
22429ad45cb86b1d431cda152877b41a06925f88914Etan Cohen            } // else: we released it locally so no need to disable usage
22564ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        }
22664ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    }
22764ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen
22864ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    private class InterfaceAvailableForRequestListener implements
22964ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen            HalDeviceManager.InterfaceAvailableForRequestListener {
23064ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        @Override
231776132d6c856d8869c026fc87e51366acf5225aeEtan Cohen        public void onAvailabilityChanged(boolean isAvailable) {
23229ad45cb86b1d431cda152877b41a06925f88914Etan Cohen            if (mDbg) {
23329ad45cb86b1d431cda152877b41a06925f88914Etan Cohen                Log.d(TAG, "Interface availability = " + isAvailable + ", mWifiNanIface="
23429ad45cb86b1d431cda152877b41a06925f88914Etan Cohen                        + mWifiNanIface);
23529ad45cb86b1d431cda152877b41a06925f88914Etan Cohen            }
23629ad45cb86b1d431cda152877b41a06925f88914Etan Cohen            synchronized (mLock) {
23729ad45cb86b1d431cda152877b41a06925f88914Etan Cohen                if (isAvailable) {
23829ad45cb86b1d431cda152877b41a06925f88914Etan Cohen                    mWifiAwareStateManager.enableUsage();
23929ad45cb86b1d431cda152877b41a06925f88914Etan Cohen                } else if (mWifiNanIface == null) { // not available could mean already have NAN
24029ad45cb86b1d431cda152877b41a06925f88914Etan Cohen                    mWifiAwareStateManager.disableUsage();
24129ad45cb86b1d431cda152877b41a06925f88914Etan Cohen                }
242776132d6c856d8869c026fc87e51366acf5225aeEtan Cohen            }
24364ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen        }
24464ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen    }
245db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen
246db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen    private static String statusString(WifiStatus status) {
247db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen        if (status == null) {
248db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen            return "status=null";
249db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen        }
250db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen        StringBuilder sb = new StringBuilder();
251db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen        sb.append(status.code).append(" (").append(status.description).append(")");
252db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen        return sb.toString();
253db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen    }
254db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen
255db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen    /**
256db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen     * Dump the internal state of the class.
257db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen     */
258db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
259db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen        pw.println("WifiAwareNativeManager:");
260db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen        pw.println("  mWifiNanIface: " + mWifiNanIface);
26129ad45cb86b1d431cda152877b41a06925f88914Etan Cohen        pw.println("  mReferenceCount: " + mReferenceCount);
2629572e8b6de6cb7912df530ae2376452bf1469b33Etan Cohen        mWifiAwareNativeCallback.dump(fd, pw, args);
263db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen        mHalDeviceManager.dump(fd, pw, args);
264db3c9d35a7f08de03beec81e801d917a5375f63eEtan Cohen    }
26564ce9f185eb6097c1c358c44710be6e1ca7c7055Etan Cohen}
266