SupplicantStaIfaceHal.java revision 240671db659a4f7ca7e217d41c7aee9d85e22c33
1240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne/*
2240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne * Copyright (C) 2016 The Android Open Source Project
3240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne *
4240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne * Licensed under the Apache License, Version 2.0 (the "License");
5240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne * you may not use this file except in compliance with the License.
6240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne * You may obtain a copy of the License at
7240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne *
8240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne *      http://www.apache.org/licenses/LICENSE-2.0
9240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne *
10240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne * Unless required by applicable law or agreed to in writing, software
11240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne * distributed under the License is distributed on an "AS IS" BASIS,
12240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne * See the License for the specific language governing permissions and
14240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne * limitations under the License.
15240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne */
16240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhnepackage com.android.server.wifi;
17240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne
18240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhneimport android.hardware.wifi.supplicant.V1_0.ISupplicant;
19240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhneimport android.hardware.wifi.supplicant.V1_0.ISupplicantIface;
20240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhneimport android.hardware.wifi.supplicant.V1_0.ISupplicantP2pIface;
21240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhneimport android.hardware.wifi.supplicant.V1_0.ISupplicantStaIface;
22240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhneimport android.hardware.wifi.supplicant.V1_0.IfaceType;
23240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhneimport android.hardware.wifi.supplicant.V1_0.SupplicantStatus;
24240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhneimport android.hardware.wifi.supplicant.V1_0.SupplicantStatusCode;
25240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhneimport android.hidl.manager.V1_0.IServiceManager;
26240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhneimport android.hidl.manager.V1_0.IServiceNotification;
27240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhneimport android.os.RemoteException;
28240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhneimport android.util.Log;
29240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne
30240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhneimport java.util.ArrayList;
31240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne/**
32240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne * Hal calls for bring up/shut down of the supplicant daemon and for
33240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne * sending requests to the supplicant daemon
34240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne *
35240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne * {@hide}
36240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne */
37240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhnepublic class WifiSupplicantHal {
38240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    private static final boolean DBG = false;
39240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    private static final String TAG = "WifiSupplicantHal";
40240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    // Supplicant HAL HIDL interface objects
41240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    private ISupplicant mHidlSupplicant;
42240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    private ISupplicantStaIface mHidlSupplicantStaIface;
43240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    private ISupplicantP2pIface mHidlSupplicantP2pIface;
44240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    private final Object mLock = new Object();
45240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne
46240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    /**
47240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne     * Registers a service notification for the ISupplicant service, which gets the service,
48240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne     * ISupplicantStaIface and ISupplicantP2pIface.
49240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne     * @return true if the service notification was successfully registered
50240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne     */
51240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    public boolean initialize() {
52240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        Log.i(TAG, "Registering SupplicantHidl service ready callback.");
53240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        synchronized (mLock) {
54240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            mHidlSupplicant = null;
55240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            mHidlSupplicantStaIface = null;
56240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            mHidlSupplicantP2pIface = null;
57240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            try {
58240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                final IServiceManager serviceManager = IServiceManager.getService("manager");
59240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                if (serviceManager == null) {
60240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    Log.e(TAG, "Failed to get HIDL Service Manager");
61240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    return false;
62240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                }
63240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                if (!serviceManager.linkToDeath(cookie -> {
64240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    Log.wtf(TAG, "IServiceManager died: cookie=" + cookie);
65240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    synchronized (mLock) {
66240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                        supplicantServiceDiedHandler();
67240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    }
68240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                }, 0)) {
69240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    Log.wtf(TAG, "Error on linkToDeath on IServiceManager");
70240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    supplicantServiceDiedHandler();
71240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    return false;
72240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                }
73240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                IServiceNotification serviceNotificationCb = new IServiceNotification.Stub() {
74240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    public void onRegistration(String fqName, String name, boolean preexisting) {
75240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                        Log.i(TAG, "IServiceNotification.onRegistration for: " + fqName + ", "
76240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                                + name + " preexisting=" + preexisting);
77240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                        if (!getSupplicantService() || !getSupplicantStaIface()
78240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                                || !getSupplicantP2pIface()) {
79240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                            Log.e(TAG, "initalizing ISupplicantIfaces failed.");
80240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                            supplicantServiceDiedHandler();
81240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                        }
82240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                        Log.i(TAG, "Completed initialization of ISupplicant service and Ifaces!");
83240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    }
84240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                };
85240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                /* TODO(b/33639391) : Use the new ISupplicant.registerForNotifications() once it
86240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                   exists */
87240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                if (!serviceManager.registerForNotifications(ISupplicant.kInterfaceName,
88240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                        "", serviceNotificationCb)) {
89240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    Log.e(TAG, "Failed to register for notifications to "
90240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                            + ISupplicant.kInterfaceName);
91240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    return false;
92240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                }
93240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            } catch (RemoteException e) {
94240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                Log.e(TAG, "Exception while trying to register a listener for ISupplicant service: "
95240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                        + e);
96240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            }
97240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            return true;
98240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        }
99240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    }
100240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne
101240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    private boolean getSupplicantService() {
102240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        synchronized (mLock) {
103240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            try {
104240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                mHidlSupplicant = ISupplicant.getService();
105240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            } catch (RemoteException e) {
106240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                Log.e(TAG, "ISupplicant.getService exception: " + e);
107240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                return false;
108240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            }
109240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            if (mHidlSupplicant == null) {
110240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                Log.e(TAG, "Got null ISupplicant service. Stopping supplicant HIDL startup");
111240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                return false;
112240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            }
113240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        }
114240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        return true;
115240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    }
116240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne
117240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    /**
118240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne     * @return ISupplicantIface of the requested type
119240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne     */
120240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    private ISupplicantIface getSupplicantIface(int ifaceType) {
121240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        synchronized (mLock) {
122240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            /** List all supplicant Ifaces */
123240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            final ArrayList<ISupplicant.IfaceInfo> supplicantIfaces = new ArrayList<>();
124240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            try {
125240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                mHidlSupplicant.listInterfaces((SupplicantStatus status,
126240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                        ArrayList<ISupplicant.IfaceInfo> ifaces) -> {
127240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    if (status.code != SupplicantStatusCode.SUCCESS) {
128240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                        Log.e(TAG, "Getting Supplicant Interfaces failed: " + status.code);
129240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                        return;
130240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    }
131240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    supplicantIfaces.addAll(ifaces);
132240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                });
133240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            } catch (RemoteException e) {
134240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                Log.e(TAG, "ISupplicant.listInterfaces exception: " + e);
135240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                return null;
136240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            }
137240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            if (supplicantIfaces.size() == 0) {
138240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                Log.e(TAG, "Got zero HIDL supplicant ifaces. Stopping supplicant HIDL startup.");
139240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                return null;
140240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            }
141240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            /** Get the STA iface */
142240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            boolean hasStaIface = false;
143240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            Mutable<ISupplicantIface> supplicantIface = new Mutable<>();
144240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            for (ISupplicant.IfaceInfo ifaceInfo : supplicantIfaces) {
145240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                if (ifaceInfo.type == ifaceType) {
146240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    hasStaIface = true;
147240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    try {
148240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                        mHidlSupplicant.getInterface(ifaceInfo,
149240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                                (SupplicantStatus status, ISupplicantIface iface) -> {
150240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                                if (status.code != SupplicantStatusCode.SUCCESS) {
151240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                                    Log.e(TAG, "Failed to get ISupplicantIface " + status.code);
152240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                                    return;
153240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                                }
154240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                                supplicantIface.value = iface;
155240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                            });
156240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    } catch (RemoteException e) {
157240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                        Log.e(TAG, "ISupplicant.getInterface exception: " + e);
158240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                        return null;
159240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    }
160240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    break;
161240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                }
162240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            }
163240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            if (!hasStaIface) {
164240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                Log.e(TAG, "No ISupplicantIface matching requested type: " + ifaceType + ", got "
165240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                        + supplicantIfaces.size() + " ifaces.");
166240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            }
167240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            return supplicantIface.value;
168240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        }
169240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    }
170240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne
171240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    private boolean getSupplicantStaIface() {
172240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        synchronized (mLock) {
173240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            /** Cast ISupplicantIface into ISupplicantStaIface*/
174240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            ISupplicantIface supplicantIface = getSupplicantIface(IfaceType.STA);
175240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            if (supplicantIface == null) {
176240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                Log.e(TAG, "getSupplicantStaIface failed");
177240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                return false;
178240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            }
179240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            mHidlSupplicantStaIface =
180240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                ISupplicantStaIface.asInterface(supplicantIface.asBinder());
181240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            return true;
182240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        }
183240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    }
184240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne
185240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    private boolean getSupplicantP2pIface() {
186240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        synchronized (mLock) {
187240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            /** Cast ISupplicantIface into ISupplicantStaIface*/
188240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            ISupplicantIface supplicantIface = getSupplicantIface(IfaceType.P2P);
189240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            if (supplicantIface == null) {
190240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                Log.e(TAG, "getSupplicantP2pIface failed");
191240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                return false;
192240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            }
193240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            mHidlSupplicantP2pIface =
194240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                ISupplicantP2pIface.asInterface(supplicantIface.asBinder());
195240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            return true;
196240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        }
197240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    }
198240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne
199240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    private void supplicantServiceDiedHandler() {
200240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        synchronized (mLock) {
201240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            mHidlSupplicant = null;
202240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            mHidlSupplicantStaIface = null;
203240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            mHidlSupplicantP2pIface = null;
204240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        }
205240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    }
206240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne
207240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    private static class Mutable<E> {
208240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        public E value;
209240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne
210240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        Mutable() {
211240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            value = null;
212240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        }
213240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne
214240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        Mutable(E value) {
215240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            this.value = value;
216240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        }
217240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    }
218240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne}
219