SupplicantStaIfaceHal.java revision 98152bd4a4e36ea2097abd474248a4c7884f55b5
1240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne/*
298152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne * Copyright (C) 2017 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.ISupplicantStaIface;
21240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhneimport android.hardware.wifi.supplicant.V1_0.IfaceType;
22240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhneimport android.hardware.wifi.supplicant.V1_0.SupplicantStatus;
23240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhneimport android.hardware.wifi.supplicant.V1_0.SupplicantStatusCode;
24240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhneimport android.hidl.manager.V1_0.IServiceManager;
25240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhneimport android.hidl.manager.V1_0.IServiceNotification;
268c6d09c03532b3936fab2fed6f8b84c895333565Roshan Piusimport android.os.HandlerThread;
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";
4098152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne    private static final String SERVICE_MANAGER_NAME = "manager";
4198152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne    private IServiceManager mIServiceManager = null;
4298152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne    // Supplicant HAL interface objects
4398152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne    private ISupplicant mISupplicant;
4498152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne    private ISupplicantStaIface mISupplicantStaIface;
45240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    private final Object mLock = new Object();
4698152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne    private final HandlerThread mHandlerThread;
4798152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne    public WifiSupplicantHal(HandlerThread handlerThread) {
4898152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne        mHandlerThread = handlerThread;
498c6d09c03532b3936fab2fed6f8b84c895333565Roshan Pius    }
50240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne
51240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    /**
5298152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne     * Registers a service notification for the ISupplicant service, which triggers intialization of
5398152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne     * the ISupplicantStaIface
54240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne     * @return true if the service notification was successfully registered
55240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne     */
56240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    public boolean initialize() {
5798152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne        if (DBG) Log.i(TAG, "Registering ISupplicant service ready callback.");
58240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        synchronized (mLock) {
5998152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne            mISupplicant = null;
6098152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne            mISupplicantStaIface = null;
6198152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne            if (mIServiceManager != null) {
6298152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                // Already have an IServiceManager and serviceNotification registered, don't
6398152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                // don't register another.
6498152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                return true;
6598152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne            }
66240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            try {
6798152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                mIServiceManager = getServiceManagerMockable();
6898152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                if (mIServiceManager == null) {
69240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    Log.e(TAG, "Failed to get HIDL Service Manager");
70240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    return false;
71240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                }
7298152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                if (!mIServiceManager.linkToDeath(cookie -> {
73240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    Log.wtf(TAG, "IServiceManager died: cookie=" + cookie);
74240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    synchronized (mLock) {
75240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                        supplicantServiceDiedHandler();
7698152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                        mIServiceManager = null; // Will need to register a new ServiceNotification
77240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    }
78240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                }, 0)) {
79240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    Log.wtf(TAG, "Error on linkToDeath on IServiceManager");
80240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    supplicantServiceDiedHandler();
8198152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                    mIServiceManager = null; // Will need to register a new ServiceNotification
82240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    return false;
83240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                }
84240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                IServiceNotification serviceNotificationCb = new IServiceNotification.Stub() {
85240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    public void onRegistration(String fqName, String name, boolean preexisting) {
8698152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                        synchronized (mLock) {
8798152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                            if (DBG) {
8898152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                                Log.i(TAG, "IServiceNotification.onRegistration for: " + fqName
8998152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                                        + ", " + name + " preexisting=" + preexisting);
9098152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                            }
9198152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                            if (!initSupplicantService() || !initSupplicantStaIface()) {
9298152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                                Log.e(TAG, "initalizing ISupplicantIfaces failed.");
9398152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                                supplicantServiceDiedHandler();
9498152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                            } else {
9598152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                                Log.i(TAG, "Completed initialization of ISupplicant interfaces.");
9698152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                            }
97240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                        }
98240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    }
99240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                };
100240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                /* TODO(b/33639391) : Use the new ISupplicant.registerForNotifications() once it
101240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                   exists */
10298152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                if (!mIServiceManager.registerForNotifications(ISupplicant.kInterfaceName,
103240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                        "", serviceNotificationCb)) {
104240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    Log.e(TAG, "Failed to register for notifications to "
105240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                            + ISupplicant.kInterfaceName);
10698152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                    mIServiceManager = null; // Will need to register a new ServiceNotification
107240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    return false;
108240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                }
109240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            } catch (RemoteException e) {
110240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                Log.e(TAG, "Exception while trying to register a listener for ISupplicant service: "
111240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                        + e);
11298152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                supplicantServiceDiedHandler();
113240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            }
114240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            return true;
115240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        }
116240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    }
117240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne
11898152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne    private boolean initSupplicantService() {
119240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        synchronized (mLock) {
120240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            try {
12198152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                mISupplicant = getSupplicantMockable();
122240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            } catch (RemoteException e) {
123240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                Log.e(TAG, "ISupplicant.getService exception: " + e);
124240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                return false;
125240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            }
12698152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne            if (mISupplicant == null) {
127240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                Log.e(TAG, "Got null ISupplicant service. Stopping supplicant HIDL startup");
128240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                return false;
129240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            }
130240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        }
131240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        return true;
132240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    }
133240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne
13498152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne    private boolean initSupplicantStaIface() {
135240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        synchronized (mLock) {
136240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            /** List all supplicant Ifaces */
137240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            final ArrayList<ISupplicant.IfaceInfo> supplicantIfaces = new ArrayList<>();
138240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            try {
13998152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                mISupplicant.listInterfaces((SupplicantStatus status,
140240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                        ArrayList<ISupplicant.IfaceInfo> ifaces) -> {
141240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    if (status.code != SupplicantStatusCode.SUCCESS) {
142240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                        Log.e(TAG, "Getting Supplicant Interfaces failed: " + status.code);
143240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                        return;
144240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    }
145240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    supplicantIfaces.addAll(ifaces);
146240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                });
147240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            } catch (RemoteException e) {
148240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                Log.e(TAG, "ISupplicant.listInterfaces exception: " + e);
14998152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                return false;
150240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            }
151240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            if (supplicantIfaces.size() == 0) {
152240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                Log.e(TAG, "Got zero HIDL supplicant ifaces. Stopping supplicant HIDL startup.");
15398152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                return false;
154240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            }
155240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            Mutable<ISupplicantIface> supplicantIface = new Mutable<>();
156240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            for (ISupplicant.IfaceInfo ifaceInfo : supplicantIfaces) {
15798152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                if (ifaceInfo.type == IfaceType.STA) {
158240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    try {
15998152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                        mISupplicant.getInterface(ifaceInfo,
160240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                                (SupplicantStatus status, ISupplicantIface iface) -> {
161240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                                if (status.code != SupplicantStatusCode.SUCCESS) {
162240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                                    Log.e(TAG, "Failed to get ISupplicantIface " + status.code);
163240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                                    return;
164240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                                }
165240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                                supplicantIface.value = iface;
166240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                            });
167240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    } catch (RemoteException e) {
168240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                        Log.e(TAG, "ISupplicant.getInterface exception: " + e);
16998152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                        return false;
170240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    }
171240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    break;
172240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                }
173240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            }
17498152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne            if (supplicantIface.value == null) {
17598152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                Log.e(TAG, "initSupplicantStaIface got null iface");
176240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                return false;
177240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            }
17898152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne            mISupplicantStaIface = getStaIfaceMockable(supplicantIface.value);
179240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            return true;
180240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        }
181240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    }
182240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne
18398152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne    private void supplicantServiceDiedHandler() {
184240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        synchronized (mLock) {
18598152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne            mISupplicant = null;
18698152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne            mISupplicantStaIface = null;
187240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        }
188240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    }
189240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne
19098152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne    /**
19198152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne     * Signals whether Initialization completed successfully. Only necessary for testing, is not
19298152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne     * needed to guard calls etc.
19398152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne     */
19498152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne    public boolean isInitializationComplete() {
19598152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne        return mISupplicantStaIface != null;
1968c6d09c03532b3936fab2fed6f8b84c895333565Roshan Pius    }
1978c6d09c03532b3936fab2fed6f8b84c895333565Roshan Pius
1988c6d09c03532b3936fab2fed6f8b84c895333565Roshan Pius    /**
19998152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne     * Wrapper functions to access static HAL methods, created to be mockable in unit tests
2008c6d09c03532b3936fab2fed6f8b84c895333565Roshan Pius     */
20198152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne    protected IServiceManager getServiceManagerMockable() throws RemoteException {
20298152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne        return IServiceManager.getService(SERVICE_MANAGER_NAME);
20398152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne    }
20498152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne
20598152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne    protected ISupplicant getSupplicantMockable() throws RemoteException {
20698152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne        return ISupplicant.getService();
20798152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne    }
20898152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne
20998152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne    protected ISupplicantStaIface getStaIfaceMockable(ISupplicantIface iface) {
21098152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne        return ISupplicantStaIface.asInterface(iface.asBinder());
2118c6d09c03532b3936fab2fed6f8b84c895333565Roshan Pius    }
2128c6d09c03532b3936fab2fed6f8b84c895333565Roshan Pius
213240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    private static class Mutable<E> {
214240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        public E value;
215240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne
216240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        Mutable() {
217240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            value = null;
218240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        }
219240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne
220240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        Mutable(E value) {
221240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            this.value = value;
222240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        }
223240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    }
224240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne}
225