SupplicantStaIfaceHal.java revision f180b0109b3fce79609b03ae2f7fbeff02d96b80
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;
2096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhneimport android.hardware.wifi.supplicant.V1_0.ISupplicantNetwork;
21240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhneimport android.hardware.wifi.supplicant.V1_0.ISupplicantStaIface;
2296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhneimport android.hardware.wifi.supplicant.V1_0.ISupplicantStaNetwork;
23240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhneimport android.hardware.wifi.supplicant.V1_0.IfaceType;
24240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhneimport android.hardware.wifi.supplicant.V1_0.SupplicantStatus;
25240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhneimport android.hardware.wifi.supplicant.V1_0.SupplicantStatusCode;
26240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhneimport android.hidl.manager.V1_0.IServiceManager;
27240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhneimport android.hidl.manager.V1_0.IServiceNotification;
28f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Piusimport android.net.IpConfiguration;
2966e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhneimport android.net.wifi.WifiConfiguration;
308c6d09c03532b3936fab2fed6f8b84c895333565Roshan Piusimport android.os.HandlerThread;
31240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhneimport android.os.RemoteException;
32240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhneimport android.util.Log;
3396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhneimport android.util.MutableBoolean;
34f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Piusimport android.util.SparseArray;
3596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne
36d95fa596d07855b70ff18a50a48e773155a919f5Roshan Piusimport com.android.server.wifi.util.NativeUtil;
37240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne
38240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhneimport java.util.ArrayList;
39f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Piusimport java.util.HashMap;
40f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Piusimport java.util.List;
41f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Piusimport java.util.Map;
42d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius
43240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne/**
44240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne * Hal calls for bring up/shut down of the supplicant daemon and for
45240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne * sending requests to the supplicant daemon
46240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne */
47b4419d876beda78c29836726e43d80203b4a656cRoshan Piuspublic class SupplicantStaIfaceHal {
4896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    /** Invalid Supplicant Iface type */
4996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    public static final int INVALID_IFACE_TYPE = -1;
50240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    private static final boolean DBG = false;
51b4419d876beda78c29836726e43d80203b4a656cRoshan Pius    private static final String TAG = "SupplicantStaIfaceHal";
5298152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne    private static final String SERVICE_MANAGER_NAME = "manager";
5398152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne    private IServiceManager mIServiceManager = null;
5498152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne    // Supplicant HAL interface objects
5598152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne    private ISupplicant mISupplicant;
5698152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne    private ISupplicantStaIface mISupplicantStaIface;
57240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    private final Object mLock = new Object();
5898152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne    private final HandlerThread mHandlerThread;
59b4419d876beda78c29836726e43d80203b4a656cRoshan Pius    public SupplicantStaIfaceHal(HandlerThread handlerThread) {
6098152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne        mHandlerThread = handlerThread;
618c6d09c03532b3936fab2fed6f8b84c895333565Roshan Pius    }
62240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne
63240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    /**
6498152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne     * Registers a service notification for the ISupplicant service, which triggers intialization of
6598152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne     * the ISupplicantStaIface
66240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne     * @return true if the service notification was successfully registered
67240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne     */
68240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    public boolean initialize() {
6998152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne        if (DBG) Log.i(TAG, "Registering ISupplicant service ready callback.");
70240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        synchronized (mLock) {
7198152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne            mISupplicant = null;
7298152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne            mISupplicantStaIface = null;
7398152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne            if (mIServiceManager != null) {
7498152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                // Already have an IServiceManager and serviceNotification registered, don't
7598152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                // don't register another.
7698152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                return true;
7798152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne            }
78240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            try {
7998152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                mIServiceManager = getServiceManagerMockable();
8098152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                if (mIServiceManager == null) {
81240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    Log.e(TAG, "Failed to get HIDL Service Manager");
82240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    return false;
83240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                }
8498152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                if (!mIServiceManager.linkToDeath(cookie -> {
85240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    Log.wtf(TAG, "IServiceManager died: cookie=" + cookie);
86240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    synchronized (mLock) {
87240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                        supplicantServiceDiedHandler();
8898152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                        mIServiceManager = null; // Will need to register a new ServiceNotification
89240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    }
90240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                }, 0)) {
91240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    Log.wtf(TAG, "Error on linkToDeath on IServiceManager");
92240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    supplicantServiceDiedHandler();
9398152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                    mIServiceManager = null; // Will need to register a new ServiceNotification
94240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    return false;
95240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                }
96240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                IServiceNotification serviceNotificationCb = new IServiceNotification.Stub() {
97240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    public void onRegistration(String fqName, String name, boolean preexisting) {
9898152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                        synchronized (mLock) {
9998152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                            if (DBG) {
10098152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                                Log.i(TAG, "IServiceNotification.onRegistration for: " + fqName
10198152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                                        + ", " + name + " preexisting=" + preexisting);
10298152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                            }
10398152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                            if (!initSupplicantService() || !initSupplicantStaIface()) {
10498152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                                Log.e(TAG, "initalizing ISupplicantIfaces failed.");
10598152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                                supplicantServiceDiedHandler();
10698152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                            } else {
10798152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                                Log.i(TAG, "Completed initialization of ISupplicant interfaces.");
10898152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                            }
109240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                        }
110240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    }
111240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                };
112240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                /* TODO(b/33639391) : Use the new ISupplicant.registerForNotifications() once it
113240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                   exists */
11498152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                if (!mIServiceManager.registerForNotifications(ISupplicant.kInterfaceName,
115240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                        "", serviceNotificationCb)) {
116240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    Log.e(TAG, "Failed to register for notifications to "
117240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                            + ISupplicant.kInterfaceName);
11898152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                    mIServiceManager = null; // Will need to register a new ServiceNotification
119240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    return false;
120240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                }
121240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            } catch (RemoteException e) {
122240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                Log.e(TAG, "Exception while trying to register a listener for ISupplicant service: "
123240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                        + e);
12498152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                supplicantServiceDiedHandler();
125240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            }
126240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            return true;
127240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        }
128240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    }
129240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne
13098152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne    private boolean initSupplicantService() {
131240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        synchronized (mLock) {
132240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            try {
13398152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                mISupplicant = getSupplicantMockable();
134240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            } catch (RemoteException e) {
135240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                Log.e(TAG, "ISupplicant.getService exception: " + e);
136240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                return false;
137240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            }
13898152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne            if (mISupplicant == null) {
139240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                Log.e(TAG, "Got null ISupplicant service. Stopping supplicant HIDL startup");
140240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                return false;
141240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            }
142240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        }
143240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        return true;
144240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    }
145240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne
14698152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne    private boolean initSupplicantStaIface() {
147240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        synchronized (mLock) {
148240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            /** List all supplicant Ifaces */
149240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            final ArrayList<ISupplicant.IfaceInfo> supplicantIfaces = new ArrayList<>();
150240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            try {
15198152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                mISupplicant.listInterfaces((SupplicantStatus status,
152240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                        ArrayList<ISupplicant.IfaceInfo> ifaces) -> {
153240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    if (status.code != SupplicantStatusCode.SUCCESS) {
154240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                        Log.e(TAG, "Getting Supplicant Interfaces failed: " + status.code);
155240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                        return;
156240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    }
157240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    supplicantIfaces.addAll(ifaces);
158240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                });
159240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            } catch (RemoteException e) {
160240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                Log.e(TAG, "ISupplicant.listInterfaces exception: " + e);
16198152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                return false;
162240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            }
163240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            if (supplicantIfaces.size() == 0) {
164240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                Log.e(TAG, "Got zero HIDL supplicant ifaces. Stopping supplicant HIDL startup.");
16598152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                return false;
166240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            }
167240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            Mutable<ISupplicantIface> supplicantIface = new Mutable<>();
168240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            for (ISupplicant.IfaceInfo ifaceInfo : supplicantIfaces) {
16998152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                if (ifaceInfo.type == IfaceType.STA) {
170240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    try {
17198152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                        mISupplicant.getInterface(ifaceInfo,
172240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                                (SupplicantStatus status, ISupplicantIface iface) -> {
173240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                                if (status.code != SupplicantStatusCode.SUCCESS) {
174240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                                    Log.e(TAG, "Failed to get ISupplicantIface " + status.code);
175240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                                    return;
176240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                                }
177240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                                supplicantIface.value = iface;
178240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                            });
179240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    } catch (RemoteException e) {
180240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                        Log.e(TAG, "ISupplicant.getInterface exception: " + e);
18198152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                        return false;
182240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    }
183240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                    break;
184240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                }
185240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            }
18698152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne            if (supplicantIface.value == null) {
18798152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne                Log.e(TAG, "initSupplicantStaIface got null iface");
188240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne                return false;
189240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            }
19098152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne            mISupplicantStaIface = getStaIfaceMockable(supplicantIface.value);
191240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            return true;
192240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        }
193240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    }
194240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne
19598152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne    private void supplicantServiceDiedHandler() {
196240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        synchronized (mLock) {
19798152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne            mISupplicant = null;
19898152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne            mISupplicantStaIface = null;
199240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        }
200240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    }
201240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne
20298152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne    /**
20398152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne     * Signals whether Initialization completed successfully. Only necessary for testing, is not
20498152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne     * needed to guard calls etc.
20598152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne     */
20698152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne    public boolean isInitializationComplete() {
20798152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne        return mISupplicantStaIface != null;
2088c6d09c03532b3936fab2fed6f8b84c895333565Roshan Pius    }
2098c6d09c03532b3936fab2fed6f8b84c895333565Roshan Pius
2108c6d09c03532b3936fab2fed6f8b84c895333565Roshan Pius    /**
21198152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne     * Wrapper functions to access static HAL methods, created to be mockable in unit tests
2128c6d09c03532b3936fab2fed6f8b84c895333565Roshan Pius     */
21398152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne    protected IServiceManager getServiceManagerMockable() throws RemoteException {
21498152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne        return IServiceManager.getService(SERVICE_MANAGER_NAME);
21598152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne    }
21698152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne
21798152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne    protected ISupplicant getSupplicantMockable() throws RemoteException {
21898152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne        return ISupplicant.getService();
21998152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne    }
22098152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne
22198152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne    protected ISupplicantStaIface getStaIfaceMockable(ISupplicantIface iface) {
22298152bd4a4e36ea2097abd474248a4c7884f55b5Glen Kuhne        return ISupplicantStaIface.asInterface(iface.asBinder());
2238c6d09c03532b3936fab2fed6f8b84c895333565Roshan Pius    }
2248c6d09c03532b3936fab2fed6f8b84c895333565Roshan Pius
22596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    /**
22666e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne     * Add a network configuration to wpa_supplicant, via HAL
227d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     *
22866e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne     * @param config Config corresponding to the network.
22966e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne     * @return SupplicantStaNetwork of the added network in wpa_supplicant.
23066e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne     */
231d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    private SupplicantStaNetworkHal addNetwork(WifiConfiguration config) {
23266e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne        logi("addSupplicantStaNetwork via HIDL");
23366e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne        if (config == null) {
23466e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne            loge("Cannot add NULL network!");
23566e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne            return null;
23666e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne        }
23766e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne        SupplicantStaNetworkHal network = addNetwork();
23866e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne        if (network == null) {
23966e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne            loge("Failed to add a network!");
24066e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne            return null;
24166e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne        }
24266e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne        if (network.saveWifiConfiguration(config)) {
24366e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne            return network;
24466e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne        } else {
24566e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne            loge("Failed to save variables for: " + config.configKey());
24666e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne            return null;
24766e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne        }
24866e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne    }
24966e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne
25066e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne    /**
251d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * Initiate connection to the provided network.
252d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     *
253d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * @param config Config corresponding to the network.
254d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * @param shouldDisconnect Whether to trigger a disconnect first.
255d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * @return true if request is sent successfully, false otherwise.
25666e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne     */
257d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    public boolean connectToNetwork(WifiConfiguration config, boolean shouldDisconnect) {
258d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius        logd("connectToNetwork " + config.configKey()
25966e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne                + " (shouldDisconnect " + shouldDisconnect + ")");
26066e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne        if (shouldDisconnect && !disconnect()) {
26166e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne            loge("Failed to trigger disconnect");
26266e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne            return false;
26366e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne        }
26466e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne        if (!removeAllNetworks()) {
26566e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne            loge("Failed to remove existing networks");
26666e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne            return false;
26766e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne        }
268d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius        SupplicantStaNetworkHal network = addNetwork(config);
26966e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne        if (network == null) {
270d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius            loge("Failed to add/save network configuration: " + config.configKey());
27166e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne            return false;
27266e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne        }
27366e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne        if (!network.select()) {
274d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius            loge("Failed to select network configuration: " + config.configKey());
27566e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne            return false;
27666e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne        }
27766e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne        return true;
27866e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne    }
27966e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne
28066e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne    /**
281f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius     * Load all the configured networks from wpa_supplicant.
282f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius     *
283f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius     * @param configs       Map of configuration key to configuration objects corresponding to all
284f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius     *                      the networks.
285f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius     * @param networkExtras Map of extra configuration parameters stored in wpa_supplicant.conf
286f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius     * @return true if succeeds, false otherwise.
287f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius     */
288f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius    public boolean loadNetworks(Map<String, WifiConfiguration> configs,
289f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius                                SparseArray<Map<String, String>> networkExtras) {
290f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius        List<Integer> networkIds = listNetworks();
291f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius        if (networkIds == null) {
292f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius            Log.e(TAG, "Failed to list networks");
293f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius            return false;
294f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius        }
295f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius        for (Integer networkId : networkIds) {
296f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius            SupplicantStaNetworkHal network = getNetwork(networkId);
297f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius            if (network == null) {
298f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius                Log.e(TAG, "Failed to get network with ID: " + networkId);
299f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius                return false;
300f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius            }
301f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius            WifiConfiguration config = new WifiConfiguration();
302f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius            Map<String, String> networkExtra = new HashMap<>();
303f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius            if (!network.loadWifiConfiguration(config, networkExtra)) {
304f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius                Log.e(TAG, "Failed to load wifi configuration for network with ID: " + networkId);
305f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius                return false;
306f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius            }
307f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius            // Set the default IP assignments.
308f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius            config.setIpAssignment(IpConfiguration.IpAssignment.DHCP);
309f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius            config.setProxySettings(IpConfiguration.ProxySettings.NONE);
310f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius
311f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius            networkExtras.put(networkId, networkExtra);
312f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius            String configKey = networkExtra.get(SupplicantStaNetworkHal.ID_STRING_KEY_CONFIG_KEY);
313f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius            final WifiConfiguration duplicateConfig = configs.put(configKey, config);
314f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius            if (duplicateConfig != null) {
315f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius                // The network is already known. Overwrite the duplicate entry.
316f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius                Log.i(TAG, "Replacing duplicate network: " + duplicateConfig.networkId);
317f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius                removeNetwork(duplicateConfig.networkId);
318f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius                networkExtras.remove(duplicateConfig.networkId);
319f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius            }
320f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius        }
321f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius        return true;
322f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius    }
323f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius
324f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius    /**
32566e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne     * Remove all networks from supplicant
32666e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne     */
32766e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne    public boolean removeAllNetworks() {
32866e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne        synchronized (mLock) {
32966e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne            ArrayList<Integer> networks = listNetworks();
33066e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne            if (networks == null) {
33166e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne                Log.e(TAG, "removeAllNetworks failed, got null networks");
33266e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne                return false;
33366e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne            }
33466e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne            for (int id : networks) {
33566e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne                if (!removeNetwork(id)) {
33666e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne                    Log.e(TAG, "removeAllNetworks failed to remove network: " + id);
33766e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne                    return false;
33866e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne                }
33966e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne            }
34066e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne        }
34166e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne        return true;
34266e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne    }
34366e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne
34466e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne    /**
345d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * Gets the interface name.
346d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     *
34796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne     * @return returns the name of Iface or null if the call fails
34896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne     */
34996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    private String getName() {
35096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        synchronized (mLock) {
35196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            MutableBoolean statusSuccess = new MutableBoolean(false);
35296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            final String methodStr = "getName";
35396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (DBG) Log.i(TAG, methodStr);
35496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return null;
35596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            final StringBuilder builder = new StringBuilder();
35696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            try {
35796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                mISupplicantStaIface.getName((SupplicantStatus status, String name) -> {
35896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                    statusSuccess.value = status.code == SupplicantStatusCode.SUCCESS;
35996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                    if (!statusSuccess.value) {
36096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                        Log.e(TAG, methodStr + " failed: " + status.debugMessage);
36196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                    } else {
36296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                        builder.append(name);
36396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                    }
36496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                });
36596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            } catch (RemoteException e) {
36696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception: " + e);
36796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                supplicantServiceDiedHandler();
36896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            }
36996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (statusSuccess.value) {
37096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return builder.toString();
37196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            } else {
37296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return null;
37396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            }
37496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        }
37596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    }
376d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius
37796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    /**
378d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * Adds a new network.
379d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     *
38096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne     * @return The ISupplicantNetwork object for the new network, or null if the call fails
38196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne     */
38296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    private SupplicantStaNetworkHal addNetwork() {
38396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        synchronized (mLock) {
38496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            MutableBoolean statusSuccess = new MutableBoolean(false);
38596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            Mutable<ISupplicantNetwork> newNetwork = new Mutable<>();
38696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            final String methodStr = "addNetwork";
38796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (DBG) Log.i(TAG, methodStr);
38896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return null;
38996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            try {
39096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                mISupplicantStaIface.addNetwork((SupplicantStatus status,
39196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                        ISupplicantNetwork network) -> {
39296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                    statusSuccess.value = status.code == SupplicantStatusCode.SUCCESS;
39396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                    if (!statusSuccess.value) {
39496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                        Log.e(TAG, methodStr + " failed: " + status.debugMessage);
39596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                    } else {
39696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                        newNetwork.value = network;
39796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                    }
39896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                });
39996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            } catch (RemoteException e) {
40096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception: " + e);
40196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                supplicantServiceDiedHandler();
40296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            }
40396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (statusSuccess.value) {
404f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius                return getStaNetworkMockable(ISupplicantStaNetwork.asInterface(
40566e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne                        newNetwork.value.asBinder()), mHandlerThread);
40696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            } else {
40796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return null;
40896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            }
40996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        }
41096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    }
411d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius
41296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    /**
41396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne     * Remove network from supplicant with network Id
414d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     *
415d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * @return true if request is sent successfully, false otherwise.
41696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne     */
41796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    private boolean removeNetwork(int id) {
41896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        synchronized (mLock) {
41996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            final String methodStr = "removeNetwork";
42096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (DBG) Log.i(TAG, methodStr);
42196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false;
42296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            try {
42396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                SupplicantStatus status = mISupplicantStaIface.removeNetwork(id);
42496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return checkStatusAndLogFailure(status, methodStr);
42596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            } catch (RemoteException e) {
42696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e);
42796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                supplicantServiceDiedHandler();
42896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return false;
42996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            }
43096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        }
43196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    }
432d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius
43396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    /**
434f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius     * Use this to mock the creation of SupplicantStaNetworkHal instance.
435f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius     *
436f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius     * @param iSupplicantStaNetwork ISupplicantStaNetwork instance retrieved from HIDL.
437f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius     * @param handlerThread Handler thread to send notifications to.
438f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius     * @return The ISupplicantNetwork object for the given SupplicantNetworkId int, returns null if
439f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius     * the call fails
440f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius     */
441f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius    protected SupplicantStaNetworkHal getStaNetworkMockable(
442f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius            ISupplicantStaNetwork iSupplicantStaNetwork, HandlerThread handlerThread) {
443f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius        return new SupplicantStaNetworkHal(iSupplicantStaNetwork, handlerThread);
444f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius    }
445f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius
446f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius    /**
44796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne     * @return The ISupplicantNetwork object for the given SupplicantNetworkId int, returns null if
44896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne     * the call fails
44996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne     */
45096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    private SupplicantStaNetworkHal getNetwork(int id) {
45196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        synchronized (mLock) {
45296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            MutableBoolean statusSuccess = new MutableBoolean(false);
45396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            Mutable<ISupplicantNetwork> gotNetwork = new Mutable<>();
45496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            final String methodStr = "getNetwork";
45596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (DBG) Log.i(TAG, methodStr);
45696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return null;
45796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            try {
45896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                mISupplicantStaIface.getNetwork(id, (SupplicantStatus status,
45996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                        ISupplicantNetwork network) -> {
46096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                    statusSuccess.value = status.code == SupplicantStatusCode.SUCCESS;
46196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                    if (!statusSuccess.value) {
46296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                        Log.e(TAG, methodStr + " failed: " + status.debugMessage);
46396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                    } else {
46496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                        gotNetwork.value = network;
46596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                    }
46696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                });
46796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            } catch (RemoteException e) {
46896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception: " + e);
46996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                supplicantServiceDiedHandler();
47096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            }
47196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (statusSuccess.value) {
472f180b0109b3fce79609b03ae2f7fbeff02d96b80Roshan Pius                return getStaNetworkMockable(ISupplicantStaNetwork.asInterface(
47366e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne                        gotNetwork.value.asBinder()), mHandlerThread);
47496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            } else {
47596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return null;
47696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            }
47796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        }
47896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    }
47996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne
48096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    /**
48196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne     * @return a list of SupplicantNetworkID ints for all networks controlled by supplicant, returns
48296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne     * null if the call fails
48396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne     */
48496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    private java.util.ArrayList<Integer> listNetworks() {
48596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        synchronized (mLock) {
48696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            MutableBoolean statusSuccess = new MutableBoolean(false);
48796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            Mutable<ArrayList<Integer>> networkIdList = new Mutable<>();
48896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            final String methodStr = "listNetworks";
48996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (DBG) Log.i(TAG, methodStr);
49096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return null;
49196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            try {
49296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                mISupplicantStaIface.listNetworks((SupplicantStatus status,
49396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                        java.util.ArrayList<Integer> networkIds) -> {
49496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                    statusSuccess.value = status.code == SupplicantStatusCode.SUCCESS;
49596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                    if (!statusSuccess.value) {
49696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                        Log.e(TAG, methodStr + " failed: " + status.debugMessage);
49796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                    } else {
49896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                        networkIdList.value = networkIds;
49996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                    }
50096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                });
50196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            } catch (RemoteException e) {
50296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception: " + e);
50396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                supplicantServiceDiedHandler();
50496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            }
50596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (statusSuccess.value) {
50696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return networkIdList.value;
50796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            } else {
50896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return null;
50996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            }
51096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        }
51196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    }
512d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius
513d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    /**
514d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * Trigger a reassociation even if the iface is currently connected.
515d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     *
516d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * @return true if request is sent successfully, false otherwise.
517d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     */
518d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    public boolean reassociate() {
51996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        synchronized (mLock) {
52096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            final String methodStr = "reassociate";
52196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (DBG) Log.i(TAG, methodStr);
52296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false;
52396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            try {
52496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                SupplicantStatus status = mISupplicantStaIface.reassociate();
52596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return checkStatusAndLogFailure(status, methodStr);
52696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            } catch (RemoteException e) {
52796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e);
52896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                supplicantServiceDiedHandler();
52996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return false;
53096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            }
53196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        }
53296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    }
533d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius
534d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    /**
535d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * Trigger a reconnection if the iface is disconnected.
536d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     *
537d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * @return true if request is sent successfully, false otherwise.
538d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     */
539d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    public boolean reconnect() {
54096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        synchronized (mLock) {
54196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            final String methodStr = "reconnect";
54296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (DBG) Log.i(TAG, methodStr);
54396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false;
54496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            try {
54596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                SupplicantStatus status = mISupplicantStaIface.reconnect();
54696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return checkStatusAndLogFailure(status, methodStr);
54796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            } catch (RemoteException e) {
54896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e);
54996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                supplicantServiceDiedHandler();
55096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return false;
55196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            }
55296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        }
55396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    }
554d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius
555d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    /**
556d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * Trigger a disconnection from the currently connected network.
557d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     *
558d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * @return true if request is sent successfully, false otherwise.
559d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     */
560d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    public boolean disconnect() {
56196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        synchronized (mLock) {
56296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            final String methodStr = "disconnect";
56396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (DBG) Log.i(TAG, methodStr);
56496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false;
56596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            try {
56696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                SupplicantStatus status = mISupplicantStaIface.disconnect();
56796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return checkStatusAndLogFailure(status, methodStr);
56896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            } catch (RemoteException e) {
56996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e);
57096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                supplicantServiceDiedHandler();
57196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return false;
57296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            }
57396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        }
57496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    }
575d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius
576d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    /**
577d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * Enable or disable power save mode.
578d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     *
579d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * @param enable true to enable, false to disable.
580d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * @return true if request is sent successfully, false otherwise.
581d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     */
582d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    public boolean setPowerSave(boolean enable) {
58396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        synchronized (mLock) {
58496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            final String methodStr = "setPowerSave";
58596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (DBG) Log.i(TAG, methodStr);
58696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false;
58796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            try {
58896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                SupplicantStatus status = mISupplicantStaIface.setPowerSave(enable);
58996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return checkStatusAndLogFailure(status, methodStr);
59096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            } catch (RemoteException e) {
59196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e);
59296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                supplicantServiceDiedHandler();
59396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return false;
59496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            }
59596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        }
59696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    }
597d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius
598d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    /**
599d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * Initiate TDLS discover with the specified AP.
600d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     *
601d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * @param macAddress MAC Address of the AP.
602d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * @return true if request is sent successfully, false otherwise.
603d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     */
604d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    public boolean initiateTdlsDiscover(String macAddress) {
605d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius        return initiateTdlsDiscover(NativeUtil.macAddressToByteArray(macAddress));
606d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    }
607b4419d876beda78c29836726e43d80203b4a656cRoshan Pius    /** See ISupplicantStaIface.hal for documentation */
60896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    private boolean initiateTdlsDiscover(byte[/* 6 */] macAddress) {
60996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        synchronized (mLock) {
61096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            final String methodStr = "initiateTdlsDiscover";
61196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (DBG) Log.i(TAG, methodStr);
61296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false;
61396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            try {
61496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                SupplicantStatus status = mISupplicantStaIface.initiateTdlsDiscover(macAddress);
61596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return checkStatusAndLogFailure(status, methodStr);
61696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            } catch (RemoteException e) {
61796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e);
61896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                supplicantServiceDiedHandler();
61996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return false;
62096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            }
62196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        }
62296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    }
623d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius
624d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    /**
625d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * Initiate TDLS setup with the specified AP.
626d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     *
627d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * @param macAddress MAC Address of the AP.
628d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * @return true if request is sent successfully, false otherwise.
629d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     */
630d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    public boolean initiateTdlsSetup(String macAddress) {
631d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius        return initiateTdlsSetup(NativeUtil.macAddressToByteArray(macAddress));
632d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    }
633b4419d876beda78c29836726e43d80203b4a656cRoshan Pius    /** See ISupplicantStaIface.hal for documentation */
63496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    private boolean initiateTdlsSetup(byte[/* 6 */] macAddress) {
63596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        synchronized (mLock) {
63696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            final String methodStr = "initiateTdlsSetup";
63796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (DBG) Log.i(TAG, methodStr);
63896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false;
63996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            try {
64096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                SupplicantStatus status = mISupplicantStaIface.initiateTdlsSetup(macAddress);
64196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return checkStatusAndLogFailure(status, methodStr);
64296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            } catch (RemoteException e) {
64396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e);
64496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                supplicantServiceDiedHandler();
64596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return false;
64696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            }
64796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        }
64896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    }
649d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius
650d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    /**
651d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * Initiate TDLS teardown with the specified AP.
652d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * @param macAddress MAC Address of the AP.
653d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * @return true if request is sent successfully, false otherwise.
654d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     */
655d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    public boolean initiateTdlsTeardown(String macAddress) {
656d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius        return initiateTdlsTeardown(NativeUtil.macAddressToByteArray(macAddress));
657d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    }
658d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius
659b4419d876beda78c29836726e43d80203b4a656cRoshan Pius    /** See ISupplicantStaIface.hal for documentation */
66096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    private boolean initiateTdlsTeardown(byte[/* 6 */] macAddress) {
66196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        synchronized (mLock) {
66296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            final String methodStr = "initiateTdlsTeardown";
66396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (DBG) Log.i(TAG, methodStr);
66496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false;
66596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            try {
66696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                SupplicantStatus status = mISupplicantStaIface.initiateTdlsTeardown(macAddress);
66796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return checkStatusAndLogFailure(status, methodStr);
66896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            } catch (RemoteException e) {
66996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e);
67096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                supplicantServiceDiedHandler();
67196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return false;
67296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            }
67396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        }
67496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    }
675d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius
676d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    /**
677d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * Request the specified ANQP elements |elements| from the specified AP |bssid|.
678d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     *
679d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * @param bssid BSSID of the AP
680d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * @param infoElements ANQP elements to be queried. Refer to ISupplicantStaIface.AnqpInfoId.
681d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * @param hs20SubTypes HS subtypes to be queried. Refer to ISupplicantStaIface.Hs20AnqpSubTypes.
682d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * @return true if request is sent successfully, false otherwise.
683d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     */
684d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    public boolean initiateAnqpQuery(String bssid, ArrayList<Short> infoElements,
685d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius                                     ArrayList<Integer> hs20SubTypes) {
686d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius        return initiateAnqpQuery(
687d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius                NativeUtil.macAddressToByteArray(bssid), infoElements, hs20SubTypes);
688d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    }
689d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius
690b4419d876beda78c29836726e43d80203b4a656cRoshan Pius    /** See ISupplicantStaIface.hal for documentation */
69196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    private boolean initiateAnqpQuery(byte[/* 6 */] macAddress,
69296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            java.util.ArrayList<Short> infoElements, java.util.ArrayList<Integer> subTypes) {
69396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        synchronized (mLock) {
69496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            final String methodStr = "initiateAnqpQuery";
69596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (DBG) Log.i(TAG, methodStr);
69696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false;
69796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            try {
69896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                SupplicantStatus status = mISupplicantStaIface.initiateAnqpQuery(macAddress,
69996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                        infoElements, subTypes);
70096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return checkStatusAndLogFailure(status, methodStr);
70196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            } catch (RemoteException e) {
70296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e);
70396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                supplicantServiceDiedHandler();
70496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return false;
70596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            }
70696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        }
70796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    }
708d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius
709d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    /**
710d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * Request the specified ANQP ICON from the specified AP |bssid|.
711d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     *
712d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * @param bssid BSSID of the AP
713d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * @param fileName Name of the file to request.
714d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * @return true if request is sent successfully, false otherwise.
715d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     */
716d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    public boolean initiateHs20IconQuery(String bssid, String fileName) {
717d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius        return initiateHs20IconQuery(NativeUtil.macAddressToByteArray(bssid), fileName);
718d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    }
719d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius
720b4419d876beda78c29836726e43d80203b4a656cRoshan Pius    /** See ISupplicantStaIface.hal for documentation */
72196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    private boolean initiateHs20IconQuery(byte[/* 6 */] macAddress, String fileName) {
72296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        synchronized (mLock) {
72396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            final String methodStr = "initiateHs20IconQuery";
72496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (DBG) Log.i(TAG, methodStr);
72596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false;
72696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            try {
72796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                SupplicantStatus status = mISupplicantStaIface.initiateHs20IconQuery(macAddress,
72896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                        fileName);
72996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return checkStatusAndLogFailure(status, methodStr);
73096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            } catch (RemoteException e) {
73196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e);
73296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                supplicantServiceDiedHandler();
73396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return false;
73496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            }
73596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        }
73696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    }
737d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius
73896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    /**
73996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne     * Makes a callback to HIDL to getMacAddress from supplicant
740d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     *
74196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne     * @return string containing the MAC address, or null on a failed call
74296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne     */
743d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    public String getMacAddress() {
74496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        synchronized (mLock) {
74596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            MutableBoolean statusSuccess = new MutableBoolean(false);
74696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            final String methodStr = "getMacAddress";
74796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (DBG) Log.i(TAG, methodStr);
74896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return null;
74996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            Mutable<String> gotMac = new Mutable<>();
75096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            try {
75196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                mISupplicantStaIface.getMacAddress((SupplicantStatus status,
75296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                        byte[/* 6 */] macAddr) -> {
75396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                    statusSuccess.value = status.code == SupplicantStatusCode.SUCCESS;
75496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                    if (!statusSuccess.value) {
75596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                        Log.e(TAG, methodStr + " failed: " + status.debugMessage);
75696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                    } else {
757d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius                        gotMac.value = NativeUtil.macAddressFromByteArray(macAddr);
75896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                    }
75996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                });
76096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            } catch (RemoteException e) {
76196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception: " + e);
76296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                supplicantServiceDiedHandler();
76396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            }
76496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (statusSuccess.value) {
76596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return gotMac.value;
76696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            } else {
76796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return null;
76896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            }
76996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        }
77096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    }
771d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius
772d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    /**
773d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * Start using the added RX filters.
774d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     *
775d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * @return true if request is sent successfully, false otherwise.
776d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     */
777d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    public boolean startRxFilter() {
77896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        synchronized (mLock) {
77996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            final String methodStr = "startRxFilter";
78096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (DBG) Log.i(TAG, methodStr);
78196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false;
78296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            try {
78396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                SupplicantStatus status = mISupplicantStaIface.startRxFilter();
78496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return checkStatusAndLogFailure(status, methodStr);
78596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            } catch (RemoteException e) {
78696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e);
78796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                supplicantServiceDiedHandler();
78896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return false;
78996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            }
79096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        }
79196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    }
792d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius
793d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    /**
794d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * Stop using the added RX filters.
795d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     *
796d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * @return true if request is sent successfully, false otherwise.
797d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     */
798d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    public boolean stopRxFilter() {
79996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        synchronized (mLock) {
80096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            final String methodStr = "stopRxFilter";
80196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (DBG) Log.i(TAG, methodStr);
80296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false;
80396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            try {
80496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                SupplicantStatus status = mISupplicantStaIface.stopRxFilter();
80596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return checkStatusAndLogFailure(status, methodStr);
80696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            } catch (RemoteException e) {
80796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e);
80896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                supplicantServiceDiedHandler();
80996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return false;
81096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            }
81196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        }
81296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    }
813d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius
814d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    public static final byte RX_FILTER_TYPE_V4_MULTICAST =
815d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius            ISupplicantStaIface.RxFilterType.V6_MULTICAST;
816d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    public static final byte RX_FILTER_TYPE_V6_MULTICAST =
817d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius            ISupplicantStaIface.RxFilterType.V6_MULTICAST;
818d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    /**
819d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * Add an RX filter.
820d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     *
821d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * @param type one of {@link #RX_FILTER_TYPE_V4_MULTICAST} or
822d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     *        {@link #RX_FILTER_TYPE_V6_MULTICAST} values.
823d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * @return true if request is sent successfully, false otherwise.
824d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     */
82596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    private boolean addRxFilter(byte type) {
82696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        synchronized (mLock) {
82796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            final String methodStr = "addRxFilter";
82896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (DBG) Log.i(TAG, methodStr);
82996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false;
83096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            try {
83196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                SupplicantStatus status = mISupplicantStaIface.addRxFilter(type);
83296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return checkStatusAndLogFailure(status, methodStr);
83396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            } catch (RemoteException e) {
83496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e);
83596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                supplicantServiceDiedHandler();
83696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return false;
83796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            }
83896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        }
83996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    }
840d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius
841d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    /**
842d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * Remove an RX filter.
843d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     *
844d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * @param type one of {@link #RX_FILTER_TYPE_V4_MULTICAST} or
845d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     *        {@link #RX_FILTER_TYPE_V6_MULTICAST} values.
846d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * @return true if request is sent successfully, false otherwise.
847d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     */
84896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    private boolean removeRxFilter(byte type) {
84996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        synchronized (mLock) {
85096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            final String methodStr = "removeRxFilter";
85196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (DBG) Log.i(TAG, methodStr);
85296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false;
85396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            try {
85496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                SupplicantStatus status = mISupplicantStaIface.removeRxFilter(type);
85596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return checkStatusAndLogFailure(status, methodStr);
85696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            } catch (RemoteException e) {
85796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e);
85896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                supplicantServiceDiedHandler();
85996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return false;
86096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            }
86196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        }
86296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    }
863d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius
864d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    public static final byte BT_COEX_MODE_ENABLED = ISupplicantStaIface.BtCoexistenceMode.ENABLED;
865d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    public static final byte BT_COEX_MODE_DISABLED = ISupplicantStaIface.BtCoexistenceMode.DISABLED;
866d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    public static final byte BT_COEX_MODE_SENSE = ISupplicantStaIface.BtCoexistenceMode.SENSE;
867d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    /**
868d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * Set Bt co existense mode.
869d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     *
870d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * @param mode one of the above {@link #BT_COEX_MODE_ENABLED}, {@link #BT_COEX_MODE_DISABLED}
871d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     *             or {@link #BT_COEX_MODE_SENSE} values.
872d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * @return true if request is sent successfully, false otherwise.
873d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     */
874d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    public boolean setBtCoexistenceMode(byte mode) {
87596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        synchronized (mLock) {
87696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            final String methodStr = "setBtCoexistenceMode";
87796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (DBG) Log.i(TAG, methodStr);
87896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false;
87996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            try {
88096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                SupplicantStatus status = mISupplicantStaIface.setBtCoexistenceMode(mode);
88196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return checkStatusAndLogFailure(status, methodStr);
88296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            } catch (RemoteException e) {
88396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e);
88496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                supplicantServiceDiedHandler();
88596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return false;
88696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            }
88796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        }
88896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    }
889d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius
890d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    /** Enable or disable BT coexistence mode.
891d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     *
892d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * @param enable true to enable, false to disable.
893d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * @return true if request is sent successfully, false otherwise.
894d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     */
895d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    public boolean setBtCoexistenceScanModeEnabled(boolean enable) {
89696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        synchronized (mLock) {
89796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            final String methodStr = "setBtCoexistenceScanModeEnabled";
89896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (DBG) Log.i(TAG, methodStr);
89996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false;
90096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            try {
90196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                SupplicantStatus status =
90296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                        mISupplicantStaIface.setBtCoexistenceScanModeEnabled(enable);
90396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return checkStatusAndLogFailure(status, methodStr);
90496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            } catch (RemoteException e) {
90596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e);
90696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                supplicantServiceDiedHandler();
90796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return false;
90896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            }
90996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        }
91096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    }
911d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius
912d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    /**
913d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * Enable or disable suspend mode optimizations.
914d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     *
915d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * @param enable true to enable, false otherwise.
916d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     */
917d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    public boolean setSuspendModeEnabled(boolean enable) {
91896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        synchronized (mLock) {
91996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            final String methodStr = "setSuspendModeEnabled";
92096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (DBG) Log.i(TAG, methodStr);
92196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false;
92296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            try {
92396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                SupplicantStatus status = mISupplicantStaIface.setSuspendModeEnabled(enable);
92496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return checkStatusAndLogFailure(status, methodStr);
92596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            } catch (RemoteException e) {
92696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e);
92796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                supplicantServiceDiedHandler();
92896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return false;
92996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            }
93096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        }
93196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    }
932d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius
933d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    /**
934d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * Set country code.
935d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     *
936d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * @param codeStr 2 byte ASCII string. For ex: US, CA.
937d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     * @return true if request is sent successfully, false otherwise.
938d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius     */
939d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    public boolean setCountryCode(String codeStr) {
940d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius        return setCountryCode(NativeUtil.stringToByteArray(codeStr));
941d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius    }
942d95fa596d07855b70ff18a50a48e773155a919f5Roshan Pius
943b4419d876beda78c29836726e43d80203b4a656cRoshan Pius    /** See ISupplicantStaIface.hal for documentation */
94496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    private boolean setCountryCode(byte[/* 2 */] code) {
94596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        synchronized (mLock) {
94696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            final String methodStr = "setCountryCode";
94796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (DBG) Log.i(TAG, methodStr);
94896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            if (!checkSupplicantStaIfaceAndLogFailure(methodStr)) return false;
94996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            try {
95096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                SupplicantStatus status = mISupplicantStaIface.setCountryCode(code);
95196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return checkStatusAndLogFailure(status, methodStr);
95296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            } catch (RemoteException e) {
95396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                Log.e(TAG, "ISupplicantStaIface." + methodStr + ": exception:" + e);
95496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                supplicantServiceDiedHandler();
95596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return false;
95696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            }
95796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        }
95896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    }
95996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne
96096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    /**
96196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne     * Returns false if SupplicantStaIface is null, and logs failure to call methodStr
96296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne     */
96396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    private boolean checkSupplicantStaIfaceAndLogFailure(final String methodStr) {
96496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        if (DBG) Log.i(TAG, methodStr);
96596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        if (mISupplicantStaIface == null) {
96696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            Log.e(TAG, "Can't call " + methodStr + ", ISupplicantStaIface is null");
96796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            return false;
96896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        }
96996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        return true;
97096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    }
97196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne
97296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    /**
97396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne     * Returns true if provided status code is SUCCESS, logs debug message and returns false
97496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne     * otherwise
97596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne     */
97696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    private static boolean checkStatusAndLogFailure(SupplicantStatus status,
97796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            final String methodStr) {
97896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        if (DBG) Log.i(TAG, methodStr);
97996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        if (status.code != SupplicantStatusCode.SUCCESS) {
98096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            Log.e(TAG, methodStr + " failed: " + supplicantStatusCodeToString(status.code) + ", "
98196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                    + status.debugMessage);
98296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            return false;
98396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        }
98496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        return true;
98596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    }
98696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne
98796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    /**
98896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne     * Converts SupplicantStatus code values to strings for debug logging
98996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne     * TODO(b/34811152) Remove this, or make it more break resistance
99096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne     */
99196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    public static String supplicantStatusCodeToString(int code) {
99296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        switch (code) {
99396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            case 0:
99496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return "SUCCESS";
99596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            case 1:
99696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return "FAILURE_UNKNOWN";
99796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            case 2:
99896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return "FAILURE_ARGS_INVALID";
99996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            case 3:
100096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return "FAILURE_IFACE_INVALID";
100196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            case 4:
100296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return "FAILURE_IFACE_UNKNOWN";
100396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            case 5:
100496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return "FAILURE_IFACE_EXISTS";
100596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            case 6:
100696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return "FAILURE_IFACE_DISABLED";
100796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            case 7:
100896013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return "FAILURE_IFACE_NOT_DISCONNECTED";
100996013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            case 8:
101096013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return "FAILURE_NETWORK_INVALID";
101196013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            case 9:
101296013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return "FAILURE_NETWORK_UNKNOWN";
101396013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne            default:
101496013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne                return "??? UNKNOWN_CODE";
101596013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne        }
101696013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne    }
101796013ebe01c095e2bac5ff7a490a2f9b69876e3cGlen Kuhne
1018240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    private static class Mutable<E> {
1019240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        public E value;
1020240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne
1021240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        Mutable() {
1022240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            value = null;
1023240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        }
1024240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne
1025240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        Mutable(E value) {
1026240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne            this.value = value;
1027240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne        }
1028240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne    }
102966e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne
103066e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne    private void logd(String s) {
103166e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne        Log.d(TAG, s);
103266e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne    }
103366e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne
103466e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne    private void logi(String s) {
103566e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne        Log.i(TAG, s);
103666e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne    }
103766e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne
103866e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne    private void loge(String s) {
103966e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne        Log.e(TAG, s);
104066e9f4ab597136cbf4accadb8e009fc68ff071a7Glen Kuhne    }
1041240671db659a4f7ca7e217d41c7aee9d85e22c33Glen Kuhne}
1042