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