• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.wifi;
18 
19 import static android.net.wifi.WifiManager.EASY_CONNECT_NETWORK_ROLE_AP;
20 
21 import android.annotation.Nullable;
22 import android.content.Context;
23 import android.net.wifi.EasyConnectStatusCallback;
24 import android.net.wifi.IDppCallback;
25 import android.net.wifi.ScanResult;
26 import android.net.wifi.WifiConfiguration;
27 import android.net.wifi.WifiManager;
28 import android.net.wifi.WifiSsid;
29 import android.os.Build;
30 import android.os.Handler;
31 import android.os.IBinder;
32 import android.os.RemoteException;
33 import android.text.TextUtils;
34 import android.util.Log;
35 import android.util.SparseArray;
36 
37 import androidx.annotation.RequiresApi;
38 
39 import com.android.internal.annotations.VisibleForTesting;
40 import com.android.internal.util.WakeupMessage;
41 import com.android.modules.utils.build.SdkLevel;
42 import com.android.server.wifi.SupplicantStaIfaceHal.DppAkm;
43 import com.android.server.wifi.SupplicantStaIfaceHal.DppCurve;
44 import com.android.server.wifi.SupplicantStaIfaceHal.DppEventType;
45 import com.android.server.wifi.SupplicantStaIfaceHal.DppFailureCode;
46 import com.android.server.wifi.SupplicantStaIfaceHal.DppNetRole;
47 import com.android.server.wifi.SupplicantStaIfaceHal.DppProgressCode;
48 import com.android.server.wifi.WifiNative.DppEventCallback;
49 import com.android.server.wifi.util.ApConfigUtil;
50 import com.android.server.wifi.util.WifiPermissionsUtil;
51 
52 import java.nio.charset.StandardCharsets;
53 import java.util.ArrayList;
54 import java.util.List;
55 
56 /**
57  * DPP Manager class
58  * Implements the DPP Initiator APIs and callbacks
59  */
60 public class DppManager {
61     private static final String TAG = "DppManager";
62     private final WifiInjector mWifiInjector;
63     private final Handler mHandler;
64 
65     private DppRequestInfo mDppRequestInfo = null;
66     private final WifiNative mWifiNative;
67     private String mClientIfaceName;
68     private boolean mVerboseLoggingEnabled;
69     WifiConfigManager mWifiConfigManager;
70     private final Context mContext;
71     @VisibleForTesting
72     public WakeupMessage mDppTimeoutMessage = null;
73     private final Clock mClock;
74     private static final String DPP_TIMEOUT_TAG = TAG + " Request Timeout";
75     private static final int DPP_TIMEOUT_MS = 40_000; // 40 seconds
76     private static final int DPP_RESPONDER_TIMEOUT_MS = 300_000; // 5 minutes
77     private static final int DPP_ENROLLEE_CONN_STATUS_RESULT_TX_TIMEOUT_MS = 16_000; // 16 seconds
78     public static final int DPP_AUTH_ROLE_INACTIVE = -1;
79     public static final int DPP_AUTH_ROLE_INITIATOR = 0;
80     public static final int DPP_AUTH_ROLE_RESPONDER = 1;
81     private final DppMetrics mDppMetrics;
82     private final ScanRequestProxy mScanRequestProxy;
83     private final WifiPermissionsUtil mWifiPermissionsUtil;
84 
85     private final DppEventCallback mDppEventCallback = new DppEventCallback() {
86         @Override
87         public void onSuccessConfigReceived(WifiConfiguration newWifiConfiguration,
88                 boolean connStatusRequested) {
89             mHandler.post(() -> {
90                 DppManager.this.onSuccessConfigReceived(newWifiConfiguration, connStatusRequested);
91             });
92         }
93 
94         @Override
95         public void onSuccess(int dppStatusCode) {
96             mHandler.post(() -> {
97                 DppManager.this.onSuccess(dppStatusCode);
98             });
99         }
100 
101         @Override
102         public void onProgress(int dppStatusCode) {
103             mHandler.post(() -> {
104                 DppManager.this.onProgress(dppStatusCode);
105             });
106         }
107 
108         @Override
109         public void onFailure(int dppStatusCode, String ssid, String channelList, int[] bandList) {
110             mHandler.post(() -> {
111                 DppManager.this.onFailure(dppStatusCode, ssid, channelList, bandList);
112             });
113         }
114 
115         @Override
116         public void onDppConfiguratorKeyUpdate(byte[] key) {
117             mHandler.post(() -> {
118                 DppManager.this.onDppConfiguratorKeyUpdate(key);
119             });
120         }
121 
122         @Override
123         public void onConnectionStatusResultSent(int result) {
124             mHandler.post(() -> {
125                 DppManager.this.onConnectionStatusResultSent(result);
126             });
127 
128         }
129     };
130 
DppManager(WifiInjector wifiInjector, Handler handler, WifiNative wifiNative, WifiConfigManager wifiConfigManager, Context context, DppMetrics dppMetrics, ScanRequestProxy scanRequestProxy, WifiPermissionsUtil wifiPermissionsUtil)131     DppManager(WifiInjector wifiInjector, Handler handler, WifiNative wifiNative,
132             WifiConfigManager wifiConfigManager, Context context, DppMetrics dppMetrics,
133             ScanRequestProxy scanRequestProxy, WifiPermissionsUtil wifiPermissionsUtil) {
134         mWifiInjector = wifiInjector;
135         mHandler = handler;
136         mWifiNative = wifiNative;
137         mWifiConfigManager = wifiConfigManager;
138         mWifiNative.registerDppEventCallback(mDppEventCallback);
139         mContext = context;
140         mClock = new Clock();
141         mDppMetrics = dppMetrics;
142         mScanRequestProxy = scanRequestProxy;
143         mWifiPermissionsUtil = wifiPermissionsUtil;
144 
145         // Setup timer
146         mDppTimeoutMessage = new WakeupMessage(mContext, mHandler,
147                 DPP_TIMEOUT_TAG, () -> {
148             timeoutDppRequest();
149         });
150     }
151 
encodeStringToUtf8Hex(String str)152     private static String encodeStringToUtf8Hex(String str) {
153         if ((str.length() > 1) && (str.charAt(0) == '"') && (str.charAt(str.length() - 1) == '"')) {
154             // Remove the surrounding quotes
155             str = str.substring(1, str.length() - 1);
156 
157             // Convert to Hex
158             byte[] bytesArray = str.getBytes(StandardCharsets.UTF_8);
159             StringBuffer hexBuffer = new StringBuffer();
160             for (int i = 0; i < bytesArray.length; i++) {
161                 hexBuffer.append(Integer.toHexString(0xFF & bytesArray[i]));
162             }
163             return hexBuffer.toString();
164         }
165         return str;
166     }
167 
timeoutDppRequest()168     private void timeoutDppRequest() {
169         logd("DPP timeout");
170 
171         if (mDppRequestInfo == null) {
172             Log.e(TAG, "DPP timeout with no request info");
173             return;
174         }
175 
176         // Clean up supplicant resources
177         if (!mWifiNative.stopDppInitiator(mClientIfaceName)) {
178             Log.e(TAG, "Failed to stop DPP Initiator");
179         }
180 
181         // Clean up resources and let the caller know about the timeout
182         onFailure(DppFailureCode.TIMEOUT);
183     }
184 
185     /**
186      * Generate DPP connection keys for Configurator. This is used to connect to
187      * other devices (APs) which this configurator has enrolled using DPP-AKM.
188      * DPP connection keys are received via DppEventCallback.onSuccessConfigReceived
189      *
190      * @param networkId Network ID of DPP-AKM wifi configuration.
191      */
generateSelfDppConfiguration(int networkId)192     private void generateSelfDppConfiguration(int networkId) {
193         WifiConfiguration config = mWifiConfigManager
194                 .getConfiguredNetworkWithoutMasking(networkId);
195 
196         if (config == null || !config.isSecurityType(WifiConfiguration.SECURITY_TYPE_DPP)
197                 || !config.isDppConfigurator() || (config.getDppConnector().length > 0)) {
198             Log.e(TAG, "Not eligible for generateSelfDppConfiguration yet.");
199             return;
200         }
201 
202         mDppRequestInfo.isGeneratingSelfConfiguration = true;
203 
204         if (!mWifiNative.generateSelfDppConfiguration(mClientIfaceName,
205                     config.SSID, config.getDppPrivateEcKey())) {
206             Log.e(TAG, "generateSelfDppConfiguration failed!!");
207             mDppRequestInfo.isGeneratingSelfConfiguration = false;
208         }
209 
210         return;
211     }
212 
213     /**
214      * Start DPP request in Configurator-Initiator mode. The goal of this call is to send the
215      * selected Wi-Fi configuration to a remote peer so it could join that network.
216      *
217      * @param uid                 UID
218      * @param packageName         Package name of the calling app
219      * @param clientIfaceName     Client interface to use for this operation.
220      * @param binder              Binder object
221      * @param enrolleeUri         The Enrollee URI, scanned externally (e.g. via QR code)
222      * @param selectedNetworkId   The selected Wi-Fi network ID to be sent
223      * @param enrolleeNetworkRole Network role of remote enrollee: STA or AP
224      * @param callback            DPP Callback object
225      */
startDppAsConfiguratorInitiator(int uid, @Nullable String packageName, @Nullable String clientIfaceName, IBinder binder, String enrolleeUri, int selectedNetworkId, @WifiManager.EasyConnectNetworkRole int enrolleeNetworkRole, IDppCallback callback)226     public void startDppAsConfiguratorInitiator(int uid, @Nullable String packageName,
227             @Nullable String clientIfaceName, IBinder binder, String enrolleeUri,
228             int selectedNetworkId, @WifiManager.EasyConnectNetworkRole int enrolleeNetworkRole,
229             IDppCallback callback) {
230         mDppMetrics.updateDppConfiguratorInitiatorRequests();
231         if (isSessionInProgress()) {
232             try {
233                 Log.e(TAG, "DPP request already in progress");
234                 Log.e(TAG, "Ongoing request - UID: " + mDppRequestInfo.uid
235                         + " Package: " + mDppRequestInfo.packageName
236                         + ", New request - UID: " + uid + " Package: " + packageName);
237 
238                 mDppMetrics.updateDppFailure(EasyConnectStatusCallback
239                         .EASY_CONNECT_EVENT_FAILURE_BUSY);
240                 // On going DPP. Call the failure callback directly
241                 callback.onFailure(EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_BUSY, null,
242                         null, new int[0]);
243             } catch (RemoteException e) {
244                 // Empty
245             }
246             return;
247         }
248 
249         mClientIfaceName = clientIfaceName;
250         if (mClientIfaceName == null) {
251             try {
252                 Log.e(TAG, "Wi-Fi client interface does not exist");
253                 // On going DPP. Call the failure callback directly
254                 mDppMetrics.updateDppFailure(EasyConnectStatusCallback
255                         .EASY_CONNECT_EVENT_FAILURE_GENERIC);
256                 callback.onFailure(EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_GENERIC,
257                         null, null, new int[0]);
258             } catch (RemoteException e) {
259                 // Empty
260             }
261             return;
262         }
263 
264         WifiConfiguration selectedNetwork = mWifiConfigManager
265                 .getConfiguredNetworkWithoutMasking(selectedNetworkId);
266 
267         if (selectedNetwork == null) {
268             try {
269                 Log.e(TAG, "Selected network is null");
270                 // On going DPP. Call the failure callback directly
271                 mDppMetrics.updateDppFailure(EasyConnectStatusCallback
272                         .EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK);
273                 callback.onFailure(EasyConnectStatusCallback
274                         .EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK, null, null, new int[0]);
275             } catch (RemoteException e) {
276                 // Empty
277             }
278             return;
279         }
280 
281         String password = null;
282         String psk = null;
283         int securityAkm;
284         byte[] privEcKey = null;
285 
286         // Currently support either SAE mode or PSK mode or DPP mode
287         // Check PSK first because PSK config always has a SAE type as a upgrading type.
288         if (selectedNetwork.isSecurityType(WifiConfiguration.SECURITY_TYPE_PSK)) {
289             if (selectedNetwork.preSharedKey.matches("[0-9A-Fa-f]{64}")) {
290                 // PSK
291                 psk = selectedNetwork.preSharedKey;
292             } else {
293                 // Passphrase
294                 password = selectedNetwork.preSharedKey;
295             }
296             securityAkm = DppAkm.PSK;
297         } else if (selectedNetwork.isSecurityType(WifiConfiguration.SECURITY_TYPE_SAE)) {
298             // SAE
299             password = selectedNetwork.preSharedKey;
300             securityAkm = DppAkm.SAE;
301         } else if (selectedNetwork.isSecurityType(WifiConfiguration.SECURITY_TYPE_DPP)) {
302             // DPP
303             if (selectedNetwork.isDppConfigurator()) {
304                 privEcKey = selectedNetwork.getDppPrivateEcKey();
305             } else {
306                 if (enrolleeNetworkRole != EASY_CONNECT_NETWORK_ROLE_AP) {
307                     try {
308                         Log.e(TAG, "Device is not configured previously to configure"
309                                 + "the peer enrollee devices to this network");
310                         callback.onFailure(
311                                 EasyConnectStatusCallback
312                                 .EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK,
313                                 null, null, new int[0]);
314                     } catch (RemoteException e) {
315                         // Empty
316                     }
317                     return;
318                 }
319             }
320             securityAkm = DppAkm.DPP;
321         } else {
322             try {
323                 // Key management must be either PSK or SAE or DPP
324                 Log.e(TAG, "Key management must be either PSK or SAE");
325                 mDppMetrics.updateDppFailure(EasyConnectStatusCallback
326                         .EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK);
327                 callback.onFailure(
328                         EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_INVALID_NETWORK, null,
329                         null, new int[0]);
330             } catch (RemoteException e) {
331                 // Empty
332             }
333             return;
334         }
335 
336         mDppRequestInfo = new DppRequestInfo();
337         mDppRequestInfo.uid = uid;
338         mDppRequestInfo.packageName = packageName;
339         mDppRequestInfo.binder = binder;
340         mDppRequestInfo.callback = callback;
341         mDppRequestInfo.authRole = DPP_AUTH_ROLE_INITIATOR;
342         mDppRequestInfo.networkId = selectedNetworkId;
343 
344         if (!linkToDeath(mDppRequestInfo)) {
345             // Notify failure and clean up
346             onFailure(EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_GENERIC);
347             return;
348         }
349 
350         logd("Interface " + mClientIfaceName + ": Initializing URI: " + enrolleeUri);
351 
352         mDppRequestInfo.startTime = mClock.getElapsedSinceBootMillis();
353         mDppTimeoutMessage.schedule(mDppRequestInfo.startTime + DPP_TIMEOUT_MS);
354 
355         // Send Enrollee URI and get a peer ID
356         int peerId = mWifiNative.addDppPeerUri(mClientIfaceName, enrolleeUri);
357 
358         if (peerId < 0) {
359             Log.e(TAG, "DPP add URI failure");
360 
361             // Notify failure and clean up
362             onFailure(DppFailureCode.INVALID_URI);
363             return;
364         }
365         mDppRequestInfo.peerId = peerId;
366 
367         // Auth init
368         logd("Authenticating");
369 
370         String ssidEncoded;
371         WifiSsid originalSsid = mWifiInjector.getSsidTranslator().getOriginalSsid(selectedNetwork);
372         if (originalSsid != null) {
373             ssidEncoded = encodeStringToUtf8Hex(originalSsid.toString());
374         } else {
375             ssidEncoded = encodeStringToUtf8Hex(selectedNetwork.SSID);
376         }
377         String passwordEncoded = null;
378 
379         if (password != null) {
380             passwordEncoded = encodeStringToUtf8Hex(selectedNetwork.preSharedKey);
381         }
382 
383         if (!mWifiNative.startDppConfiguratorInitiator(mClientIfaceName,
384                 mDppRequestInfo.peerId, 0, ssidEncoded, passwordEncoded, psk,
385                 enrolleeNetworkRole == EASY_CONNECT_NETWORK_ROLE_AP ? DppNetRole.AP
386                         : DppNetRole.STA,
387                 securityAkm, privEcKey)) {
388             Log.e(TAG, "DPP Start Configurator Initiator failure");
389 
390             // Notify failure and clean up
391             onFailure(DppFailureCode.FAILURE);
392             return;
393         }
394 
395         logd("Success: Started DPP Initiator with peer ID "
396                 + mDppRequestInfo.peerId);
397     }
398 
399     /**
400      * Start DPP request in Enrollee-Initiator mode. The goal of this call is to receive a
401      * Wi-Fi configuration object from the peer configurator in order to join a network.
402      *
403      * @param uid             UID
404      * @param clientIfaceName     Client interface to use for this operation.
405      * @param binder          Binder object
406      * @param configuratorUri The Configurator URI, scanned externally (e.g. via QR code)
407      * @param callback        DPP Callback object
408      */
startDppAsEnrolleeInitiator(int uid, @Nullable String clientIfaceName, IBinder binder, String configuratorUri, IDppCallback callback)409     public void startDppAsEnrolleeInitiator(int uid, @Nullable String clientIfaceName,
410             IBinder binder, String configuratorUri, IDppCallback callback) {
411         mDppMetrics.updateDppEnrolleeInitiatorRequests();
412         if (isSessionInProgress()) {
413             try {
414                 Log.e(TAG, "DPP request already in progress");
415                 Log.e(TAG, "Ongoing request UID: " + mDppRequestInfo.uid + ", new UID: "
416                         + uid);
417 
418                 mDppMetrics.updateDppFailure(EasyConnectStatusCallback
419                         .EASY_CONNECT_EVENT_FAILURE_BUSY);
420                 // On going DPP. Call the failure callback directly
421                 callback.onFailure(EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_BUSY, null,
422                         null, new int[0]);
423             } catch (RemoteException e) {
424                 // Empty
425             }
426             return;
427         }
428 
429         mDppRequestInfo = new DppRequestInfo();
430         mDppRequestInfo.uid = uid;
431         mDppRequestInfo.binder = binder;
432         mDppRequestInfo.callback = callback;
433         mDppRequestInfo.authRole = DPP_AUTH_ROLE_INITIATOR;
434 
435         if (!linkToDeath(mDppRequestInfo)) {
436             // Notify failure and clean up
437             onFailure(DppFailureCode.FAILURE);
438             return;
439         }
440 
441         mDppRequestInfo.startTime = mClock.getElapsedSinceBootMillis();
442         mDppTimeoutMessage.schedule(mDppRequestInfo.startTime + DPP_TIMEOUT_MS);
443 
444         mClientIfaceName = clientIfaceName;
445         logd("Interface " + mClientIfaceName + ": Initializing URI: " + configuratorUri);
446 
447         // Send Configurator URI and get a peer ID
448         int peerId = mWifiNative.addDppPeerUri(mClientIfaceName, configuratorUri);
449 
450         if (peerId < 0) {
451             Log.e(TAG, "DPP add URI failure");
452             onFailure(DppFailureCode.INVALID_URI);
453             return;
454         }
455         mDppRequestInfo.peerId = peerId;
456 
457         // Auth init
458         logd("Authenticating");
459 
460         if (!mWifiNative.startDppEnrolleeInitiator(mClientIfaceName, mDppRequestInfo.peerId,
461                 0)) {
462             Log.e(TAG, "DPP Start Enrollee Initiator failure");
463 
464             // Notify failure and clean up
465             onFailure(DppFailureCode.FAILURE);
466             return;
467         }
468 
469         logd("Success: Started DPP Initiator with peer ID "
470                 + mDppRequestInfo.peerId);
471     }
472 
473     /**
474      * Start DPP request in Enrollee-Responder mode. The goal of this call is to receive a
475      * Wi-Fi configuration object from the peer configurator by showing a QR code and being scanned
476      * by the peer configurator.
477      *
478      * @param uid             UID
479      * @param clientIfaceName Client interface to use for this operation.
480      * @param binder          Binder object
481      * @param deviceInfo      The Device specific info to attach to the generated URI
482      * @param curve           Elliptic curve cryptography type used to generate DPP
483      *                        public/private key pair.
484      * @param callback        DPP Callback object
485      */
startDppAsEnrolleeResponder(int uid, @Nullable String clientIfaceName, IBinder binder, @Nullable String deviceInfo, @WifiManager.EasyConnectCryptographyCurve int curve, IDppCallback callback)486     public void startDppAsEnrolleeResponder(int uid, @Nullable String clientIfaceName,
487             IBinder binder, @Nullable String deviceInfo,
488             @WifiManager.EasyConnectCryptographyCurve int curve, IDppCallback callback) {
489         mDppMetrics.updateDppEnrolleeResponderRequests();
490         if (isSessionInProgress()) {
491             try {
492                 Log.e(TAG, "DPP request already in progress");
493                 Log.e(TAG, "Ongoing request UID: " + mDppRequestInfo.uid + ", new UID: "
494                         + uid);
495 
496                 mDppMetrics.updateDppFailure(EasyConnectStatusCallback
497                         .EASY_CONNECT_EVENT_FAILURE_BUSY);
498                 // On going DPP. Call the failure callback directly
499                 callback.onFailure(EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_BUSY,
500                         null, null, new int[0]);
501             } catch (RemoteException e) {
502                 // Empty
503             }
504             return;
505         }
506 
507         mDppRequestInfo = new DppRequestInfo();
508         mDppRequestInfo.uid = uid;
509         mDppRequestInfo.binder = binder;
510         mDppRequestInfo.callback = callback;
511         mDppRequestInfo.authRole = DPP_AUTH_ROLE_RESPONDER;
512 
513         if (!linkToDeath(mDppRequestInfo)) {
514             // Notify failure and clean up
515             onFailure(DppFailureCode.FAILURE);
516             return;
517         }
518 
519         mDppRequestInfo.startTime = mClock.getElapsedSinceBootMillis();
520         mDppTimeoutMessage.schedule(mDppRequestInfo.startTime + DPP_RESPONDER_TIMEOUT_MS);
521 
522         mClientIfaceName = clientIfaceName;
523         logd("Interface " + mClientIfaceName + " Product Info: " + deviceInfo
524                 + " Curve: " + curve);
525 
526         String info = deviceInfo == null ? "" : deviceInfo;
527         // Generate a QR code based bootstrap info
528         WifiNative.DppBootstrapQrCodeInfo bootstrapInfo = null;
529         if (SdkLevel.isAtLeastS()) {
530             bootstrapInfo =
531                     mWifiNative.generateDppBootstrapInfoForResponder(mClientIfaceName, deviceInfo,
532                             convertEasyConnectCryptographyCurveToHidlDppCurve(curve));
533         }
534 
535         if (bootstrapInfo == null || bootstrapInfo.bootstrapId < 0
536                 || TextUtils.isEmpty(bootstrapInfo.uri)) {
537             Log.e(TAG, "DPP request to generate URI failed");
538             onFailure(DppFailureCode.URI_GENERATION);
539             return;
540         }
541 
542         mDppRequestInfo.bootstrapId = bootstrapInfo.bootstrapId;
543         logd("BootstrapId:" + mDppRequestInfo.bootstrapId + " URI: " + bootstrapInfo.uri);
544 
545         if (!mWifiNative.startDppEnrolleeResponder(mClientIfaceName, bootstrapInfo.listenChannel)) {
546             Log.e(TAG, "DPP Start Enrollee Responder failure");
547             // Notify failure and clean up
548             onFailure(DppFailureCode.FAILURE);
549             return;
550         }
551 
552         logd("Success: Started DPP Enrollee Responder on listen channel "
553                 + bootstrapInfo.listenChannel);
554 
555         try {
556             mDppRequestInfo.callback.onBootstrapUriGenerated(bootstrapInfo.uri);
557         } catch (RemoteException e) {
558             Log.e(TAG, " onBootstrapUriGenerated Callback failure");
559             onFailure(DppFailureCode.FAILURE);
560             return;
561         }
562     }
563 
564     /**
565      * Stop a current DPP session
566      *
567      * @param uid User ID
568      */
stopDppSession(int uid)569     public void stopDppSession(int uid) {
570         if (!isSessionInProgress()) {
571             logd("UID " + uid + " called stop DPP session with no active DPP session");
572             return;
573         }
574 
575         if (mDppRequestInfo.uid != uid) {
576             Log.e(TAG, "UID " + uid + " called stop DPP session but UID " + mDppRequestInfo.uid
577                     + " has started it");
578             return;
579         }
580 
581         // Clean up supplicant resources
582         if (mDppRequestInfo.authRole == DPP_AUTH_ROLE_INITIATOR) {
583             if (!mWifiNative.stopDppInitiator(mClientIfaceName)) {
584                 Log.e(TAG, "Failed to stop DPP Initiator");
585             }
586         }
587         mDppRequestInfo.isGeneratingSelfConfiguration = false;
588 
589         if (mDppRequestInfo.connStatusRequested) {
590             logd("skip DPP resource cleanup - waiting for send connection status result");
591             return;
592         }
593 
594         cleanupDppResources();
595 
596         logd("Success: Stopped DPP Session");
597     }
598 
cleanupDppResources()599     private void cleanupDppResources() {
600         logd("DPP clean up resources");
601         if (!isSessionInProgress()) {
602             return;
603         }
604 
605         if (mDppRequestInfo.isGeneratingSelfConfiguration) {
606             logd("Generate Self Configuration in progress. Skip cleanup");
607             return;
608         }
609 
610         // Cancel pending timeout
611         mDppTimeoutMessage.cancel();
612 
613         // Remove the URI from the supplicant list
614         if (mDppRequestInfo.authRole == DPP_AUTH_ROLE_INITIATOR) {
615             if (!mWifiNative.removeDppUri(mClientIfaceName, mDppRequestInfo.peerId)) {
616                 Log.e(TAG, "Failed to remove DPP URI ID " + mDppRequestInfo.peerId);
617             }
618         } else if (mDppRequestInfo.authRole == DPP_AUTH_ROLE_RESPONDER) {
619             if (!mWifiNative.stopDppResponder(mClientIfaceName, mDppRequestInfo.bootstrapId)) {
620                 Log.e(TAG, "Failed to stop DPP Responder");
621             }
622         }
623 
624         mDppRequestInfo.binder.unlinkToDeath(mDppRequestInfo.dr, 0);
625 
626         mDppRequestInfo = null;
627     }
628 
629     /**
630      * Indicates whether there is a dpp session in progress or not.
631      */
isSessionInProgress()632     public boolean isSessionInProgress() {
633         return mDppRequestInfo != null;
634     }
635 
636     private static class DppRequestInfo {
637         public int uid;
638         public String packageName;
639         public IBinder binder;
640         public IBinder.DeathRecipient dr;
641         public int peerId;
642         public IDppCallback callback;
643         public long startTime;
644         public int authRole = DPP_AUTH_ROLE_INACTIVE;
645         public int bootstrapId;
646         public int networkId;
647         public boolean isGeneratingSelfConfiguration = false;
648         public boolean connStatusRequested = false;
649 
650         @Override
toString()651         public String toString() {
652             return new StringBuilder("DppRequestInfo: uid=").append(uid).append(", binder=").append(
653                     binder).append(", dr=").append(dr)
654                     .append(", callback=").append(callback)
655                     .append(", peerId=").append(peerId)
656                     .append(", authRole=").append(authRole)
657                     .append(", bootstrapId=").append(bootstrapId)
658                     .append(", nId=").append(networkId)
659                     .append(", connStatusRequested=").append(connStatusRequested).toString();
660         }
661     }
662 
663     /**
664      * Enable vervose logging from DppManager
665      *
666      * @param verbose 0 to disable verbose logging, or any other value to enable.
667      */
enableVerboseLogging(boolean verboseEnabled)668     public void enableVerboseLogging(boolean verboseEnabled) {
669         mVerboseLoggingEnabled = verboseEnabled;
670     }
671 
onSuccessConfigReceived(WifiConfiguration newWifiConfiguration, boolean connStatusRequested)672     private void onSuccessConfigReceived(WifiConfiguration newWifiConfiguration,
673             boolean connStatusRequested) {
674         try {
675             if (mDppRequestInfo == null) {
676                 Log.e(TAG, "onSuccessConfigReceived event without a request information object");
677                 return;
678             }
679             logd("onSuccessConfigReceived: connection status requested: " + connStatusRequested);
680             if (mDppRequestInfo.isGeneratingSelfConfiguration) {
681                 WifiConfiguration existingWifiConfig = mWifiConfigManager
682                         .getConfiguredNetworkWithoutMasking(mDppRequestInfo.networkId);
683 
684                 if (newWifiConfiguration.isSecurityType(WifiConfiguration.SECURITY_TYPE_DPP)
685                         && existingWifiConfig != null && existingWifiConfig.isDppConfigurator()
686                         && TextUtils.equals(existingWifiConfig.SSID, newWifiConfiguration.SSID)
687                         && existingWifiConfig.isSecurityType(WifiConfiguration.SECURITY_TYPE_DPP)) {
688                     if (newWifiConfiguration.getDppConnector().length > 0
689                             && newWifiConfiguration.getDppCSignKey().length > 0
690                             && newWifiConfiguration.getDppNetAccessKey().length > 0) {
691                         Log.d(TAG, "Updating DPP Connection keys for self");
692                         existingWifiConfig.setDppConnectionKeys(
693                                 newWifiConfiguration.getDppConnector(),
694                                 newWifiConfiguration.getDppCSignKey(),
695                                 newWifiConfiguration.getDppNetAccessKey());
696 
697                         NetworkUpdateResult networkUpdateResult = mWifiConfigManager
698                                 .addOrUpdateNetwork(existingWifiConfig, mDppRequestInfo.uid);
699 
700                         if (!networkUpdateResult.isSuccess()) {
701                             Log.e(TAG, "DPP configuration generated, but failed to update network");
702                             mDppRequestInfo.callback.onFailure(EasyConnectStatusCallback
703                                     .EASY_CONNECT_EVENT_FAILURE_CONFIGURATION, null,
704                                     null, new int[0]);
705                         }
706                     }
707                 }
708                 // Done with self configuration. reset flag.
709                 mDppRequestInfo.isGeneratingSelfConfiguration = false;
710             } else {
711                 long now = mClock.getElapsedSinceBootMillis();
712                 mDppMetrics.updateDppOperationTime((int) (now - mDppRequestInfo.startTime));
713 
714                 NetworkUpdateResult networkUpdateResult = mWifiConfigManager
715                         .addOrUpdateNetwork(newWifiConfiguration, mDppRequestInfo.uid);
716 
717                 if (networkUpdateResult.isSuccess()) {
718                     mDppMetrics.updateDppEnrolleeSuccess();
719                     if (mDppRequestInfo.authRole == DPP_AUTH_ROLE_RESPONDER) {
720                         mDppMetrics.updateDppEnrolleeResponderSuccess();
721                     }
722                     mDppRequestInfo.connStatusRequested = connStatusRequested;
723                     mDppRequestInfo.callback.onSuccessConfigReceived(
724                             networkUpdateResult.getNetworkId());
725                 } else {
726                     Log.e(TAG, "DPP configuration received, but failed to update network");
727                     mDppMetrics.updateDppFailure(EasyConnectStatusCallback
728                             .EASY_CONNECT_EVENT_FAILURE_CONFIGURATION);
729                     mDppRequestInfo.callback.onFailure(EasyConnectStatusCallback
730                             .EASY_CONNECT_EVENT_FAILURE_CONFIGURATION, null, null, new int[0]);
731                 }
732             }
733         } catch (RemoteException e) {
734             Log.e(TAG, "Callback failure");
735         }
736 
737         // Success
738         // If Peer configurator has not requested for connection status,
739         // DPP session is completed. Clear the DPP session immediately, otherwise wait for
740         // send connection status result
741         if (!mDppRequestInfo.connStatusRequested) {
742             cleanupDppResources();
743         } else {
744             Log.d(TAG, "Wait " + (DPP_ENROLLEE_CONN_STATUS_RESULT_TX_TIMEOUT_MS / 1000)
745                     + " seconds for enrollee to send connection status");
746             mDppTimeoutMessage.cancel();
747             mDppTimeoutMessage.schedule(mClock.getElapsedSinceBootMillis()
748                     + DPP_ENROLLEE_CONN_STATUS_RESULT_TX_TIMEOUT_MS);
749         }
750     }
751 
onSuccess(int dppStatusCode)752     private void onSuccess(int dppStatusCode) {
753         try {
754             if (mDppRequestInfo == null) {
755                 Log.e(TAG, "onSuccess event without a request information object");
756                 return;
757             }
758 
759             logd("onSuccess: " + dppStatusCode);
760             long now = mClock.getElapsedSinceBootMillis();
761             mDppMetrics.updateDppOperationTime((int) (now - mDppRequestInfo.startTime));
762 
763             int dppSuccessCode;
764 
765             // Convert from HAL codes to WifiManager/user codes
766             switch (dppStatusCode) {
767                 case DppEventType.CONFIGURATION_SENT:
768                     mDppMetrics.updateDppR1CapableEnrolleeResponderDevices();
769                     dppSuccessCode = EasyConnectStatusCallback
770                             .EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_SENT;
771                     // For Configurator STA, generate self signed keys for network access.
772                     generateSelfDppConfiguration(mDppRequestInfo.networkId);
773                     break;
774 
775                 case DppEventType.CONFIGURATION_APPLIED:
776                     dppSuccessCode = EasyConnectStatusCallback
777                             .EASY_CONNECT_EVENT_SUCCESS_CONFIGURATION_APPLIED;
778                     break;
779 
780                 default:
781                     Log.e(TAG, "onSuccess: unknown code " + dppStatusCode);
782                     // Success, DPP is complete. Clear the DPP session automatically
783                     mDppRequestInfo.isGeneratingSelfConfiguration = false;
784                     cleanupDppResources();
785                     return;
786             }
787 
788             mDppMetrics.updateDppConfiguratorSuccess(dppSuccessCode);
789             mDppRequestInfo.callback.onSuccess(dppSuccessCode);
790 
791         } catch (RemoteException e) {
792             Log.e(TAG, "Callback failure");
793         }
794 
795         // Success, DPP is complete. Clear the DPP session automatically
796         cleanupDppResources();
797     }
798 
onProgress(int dppStatusCode)799     private void onProgress(int dppStatusCode) {
800         try {
801             if (mDppRequestInfo == null) {
802                 Log.e(TAG, "onProgress event without a request information object");
803                 return;
804             }
805 
806             logd("onProgress: " + dppStatusCode);
807 
808             int dppProgressCode;
809 
810             // Convert from HAL codes to WifiManager/user codes
811             switch (dppStatusCode) {
812                 case DppProgressCode.AUTHENTICATION_SUCCESS:
813                     dppProgressCode = EasyConnectStatusCallback
814                             .EASY_CONNECT_EVENT_PROGRESS_AUTHENTICATION_SUCCESS;
815                     break;
816 
817                 case DppProgressCode.RESPONSE_PENDING:
818                     dppProgressCode = EasyConnectStatusCallback
819                             .EASY_CONNECT_EVENT_PROGRESS_RESPONSE_PENDING;
820                     break;
821 
822                 case DppProgressCode.CONFIGURATION_SENT_WAITING_RESPONSE:
823                     mDppMetrics.updateDppR2CapableEnrolleeResponderDevices();
824                     dppProgressCode = EasyConnectStatusCallback
825                             .EASY_CONNECT_EVENT_PROGRESS_CONFIGURATION_SENT_WAITING_RESPONSE;
826                     break;
827 
828                 case DppProgressCode.CONFIGURATION_ACCEPTED:
829                     dppProgressCode = EasyConnectStatusCallback
830                             .EASY_CONNECT_EVENT_PROGRESS_CONFIGURATION_ACCEPTED;
831                     break;
832 
833                 default:
834                     Log.e(TAG, "onProgress: unknown code " + dppStatusCode);
835                     return;
836             }
837 
838             mDppRequestInfo.callback.onProgress(dppProgressCode);
839 
840         } catch (RemoteException e) {
841             Log.e(TAG, "Callback failure");
842         }
843     }
844 
onFailure(int dppStatusCode)845     private void onFailure(int dppStatusCode) {
846         onFailure(dppStatusCode, null, null, null);
847     }
848 
onDppConfiguratorKeyUpdate(byte[] privEcKey)849     private void onDppConfiguratorKeyUpdate(byte[] privEcKey) {
850         if (mDppRequestInfo == null) {
851             Log.e(TAG,
852                     "onDppConfiguratorKeyUpdate event without a request information object");
853             return;
854         }
855 
856         WifiConfiguration selectedNetwork = mWifiConfigManager
857                 .getConfiguredNetworkWithoutMasking(mDppRequestInfo.networkId);
858 
859         if (selectedNetwork != null && privEcKey != null && privEcKey.length > 0
860                 && selectedNetwork.isSecurityType(WifiConfiguration.SECURITY_TYPE_DPP)) {
861             Log.d(TAG, "Updating network access keys for DPP networkId="
862                     + mDppRequestInfo.networkId);
863             selectedNetwork.setDppConfigurator(privEcKey);
864 
865             NetworkUpdateResult networkUpdateResult = mWifiConfigManager
866                     .addOrUpdateNetwork(selectedNetwork, mDppRequestInfo.uid);
867 
868             if (!networkUpdateResult.isSuccess()) {
869                 Log.e(TAG, "Failed to update DPP configurator key.");
870             }
871         }
872     }
873 
onConnectionStatusResultSent(int result)874     private void onConnectionStatusResultSent(int result) {
875         if (mDppRequestInfo == null) {
876             Log.e(TAG,
877                     "onConnectionStatusResultSent event without a request information object");
878             return;
879         }
880         logd("onConnectionStatusResultSent: result code: " + result);
881         cleanupDppResources();
882     }
883 
884     /**
885      *
886      * This function performs the Enrollee compatibility check with the network.
887      * Compatibilty check is done based on the channel match.
888      * The logic looks into the scan cache and checks if network's
889      * operating channel match with one of the channel in enrollee's scanned channel list.
890      *
891      * @param ssid Network name.
892      * @param channelList contains the list of operating class/channels enrollee used to search for
893      *                    the network.
894      *                    Reference: DPP spec section: DPP Connection Status Object section.
895      *                    (eg for channelList: "81/1,2,3,4,5,6,7,8,9,10,11,117/40,115/48")
896      * @return True On compatibility check failures due to error conditions or
897      *              when AP is not seen in scan cache or when AP is seen in scan cache and
898      *              operating channel is included in enrollee's scanned channel list.
899      *         False when network's operating channel is not included in Enrollee's
900      *              scanned channel list.
901      *
902      */
isEnrolleeCompatibleWithNetwork(String ssid, String channelList)903     private boolean isEnrolleeCompatibleWithNetwork(String ssid, String channelList) {
904         if (ssid == null || channelList == null) {
905             return true;
906         }
907         SparseArray<int[]> dppChannelList = WifiManager.parseDppChannelList(channelList);
908 
909         if (dppChannelList.size() == 0) {
910             Log.d(TAG, "No channels found after parsing channel list string");
911             return true;
912         }
913 
914         List<Integer> freqList = new ArrayList<Integer>();
915 
916         /* Convert the received operatingClass/channels to list of frequencies */
917         for (int i = 0; i < dppChannelList.size(); i++) {
918             /* Derive the band corresponding to operating class */
919             int operatingClass = dppChannelList.keyAt(i);
920             int[] channels = dppChannelList.get(operatingClass);
921             int band = ApConfigUtil.getBandFromOperatingClass(operatingClass);
922             if (band < 0) {
923                 Log.e(TAG, "Band corresponding to the operating class: " + operatingClass
924                         + " not found in the table");
925                 continue;
926             }
927             /* Derive frequency list from channel and band */
928             for (int j = 0; j < channels.length; j++) {
929                 int freq = ApConfigUtil.convertChannelToFrequency(channels[j], band);
930                 if (freq < 0) {
931                     Log.e(TAG, "Invalid frequency after converting channel: " + channels[j]
932                             + " band: " + band);
933                     continue;
934                 }
935                 freqList.add(freq);
936             }
937         }
938 
939         if (freqList.size() == 0) {
940             Log.d(TAG, "frequency list is empty");
941             return true;
942         }
943 
944         /* Check the scan cache for the network enrollee tried to find */
945         boolean isNetworkInScanCache = false;
946         boolean channelMatch = false;
947         for (ScanResult scanResult : mScanRequestProxy.getScanResults()) {
948             if (!TextUtils.equals(ssid, scanResult.SSID)) {
949                 continue;
950             }
951             isNetworkInScanCache = true;
952             if (freqList.contains(scanResult.frequency)) {
953                 channelMatch = true;
954                 break;
955             }
956         }
957 
958         if (isNetworkInScanCache & !channelMatch) {
959             Log.d(TAG, "Optionally update the error code to "
960                     + "ENROLLEE_FAILED_TO_SCAN_NETWORK_CHANNEL as enrollee didn't scan"
961                     + "network's operating channel");
962             mDppMetrics.updateDppR2EnrolleeResponderIncompatibleConfiguration();
963             return false;
964         }
965         return true;
966     }
967 
968     private @EasyConnectStatusCallback.EasyConnectFailureStatusCode int
getFailureStatusCodeOnEnrolleeInCompatibleWithNetwork()969             getFailureStatusCodeOnEnrolleeInCompatibleWithNetwork() {
970         if (!SdkLevel.isAtLeastS() || mDppRequestInfo.packageName != null
971                 && mWifiPermissionsUtil.isTargetSdkLessThan(
972                 mDppRequestInfo.packageName, Build.VERSION_CODES.S,
973                 mDppRequestInfo.uid)) {
974             return EasyConnectStatusCallback
975                     .EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE;
976         } else {
977             return EasyConnectStatusCallback
978                     .EASY_CONNECT_EVENT_FAILURE_ENROLLEE_FAILED_TO_SCAN_NETWORK_CHANNEL;
979         }
980     }
981 
onFailure(int dppStatusCode, String ssid, String channelList, int[] bandList)982     private void onFailure(int dppStatusCode, String ssid, String channelList, int[] bandList) {
983         try {
984             if (mDppRequestInfo == null) {
985                 Log.e(TAG, "onFailure event without a request information object");
986                 return;
987             }
988 
989             logd("OnFailure: " + dppStatusCode);
990 
991             long now = mClock.getElapsedSinceBootMillis();
992             mDppMetrics.updateDppOperationTime((int) (now - mDppRequestInfo.startTime));
993 
994             int dppFailureCode;
995 
996             // Convert from HAL codes to WifiManager/user codes
997             switch (dppStatusCode) {
998                 case DppFailureCode.INVALID_URI:
999                     dppFailureCode =
1000                             EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_INVALID_URI;
1001                     break;
1002 
1003                 case DppFailureCode.AUTHENTICATION:
1004                     dppFailureCode =
1005                             EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_AUTHENTICATION;
1006                     break;
1007 
1008                 case DppFailureCode.NOT_COMPATIBLE:
1009                     dppFailureCode =
1010                             EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_NOT_COMPATIBLE;
1011                     break;
1012 
1013                 case DppFailureCode.CONFIGURATION:
1014                     dppFailureCode =
1015                             EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_CONFIGURATION;
1016                     break;
1017 
1018                 case DppFailureCode.BUSY:
1019                     dppFailureCode = EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_BUSY;
1020                     break;
1021 
1022                 case DppFailureCode.TIMEOUT:
1023                     dppFailureCode = EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_TIMEOUT;
1024                     break;
1025 
1026                 case DppFailureCode.NOT_SUPPORTED:
1027                     dppFailureCode =
1028                             EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_NOT_SUPPORTED;
1029                     break;
1030 
1031                 case DppFailureCode.CANNOT_FIND_NETWORK:
1032                     // This is the only case where channel list is populated, according to the
1033                     // DPP spec section 6.3.5.2 DPP Connection Status Object
1034                     if (isEnrolleeCompatibleWithNetwork(ssid, channelList)) {
1035                         dppFailureCode =
1036                                 EasyConnectStatusCallback
1037                                 .EASY_CONNECT_EVENT_FAILURE_CANNOT_FIND_NETWORK;
1038                     } else {
1039                         dppFailureCode = getFailureStatusCodeOnEnrolleeInCompatibleWithNetwork();
1040                     }
1041                     break;
1042 
1043                 case DppFailureCode.ENROLLEE_AUTHENTICATION:
1044                     dppFailureCode = EasyConnectStatusCallback
1045                             .EASY_CONNECT_EVENT_FAILURE_ENROLLEE_AUTHENTICATION;
1046                     break;
1047 
1048                 case DppFailureCode.CONFIGURATION_REJECTED:
1049                     dppFailureCode = EasyConnectStatusCallback
1050                             .EASY_CONNECT_EVENT_FAILURE_ENROLLEE_REJECTED_CONFIGURATION;
1051                     break;
1052 
1053                 case DppFailureCode.URI_GENERATION:
1054                     if (SdkLevel.isAtLeastS()) {
1055                         dppFailureCode = EasyConnectStatusCallback
1056                                 .EASY_CONNECT_EVENT_FAILURE_URI_GENERATION;
1057                     } else {
1058                         dppFailureCode = EasyConnectStatusCallback
1059                                 .EASY_CONNECT_EVENT_FAILURE_GENERIC;
1060                     }
1061                     break;
1062 
1063                 case DppFailureCode.FAILURE:
1064                 default:
1065                     dppFailureCode = EasyConnectStatusCallback.EASY_CONNECT_EVENT_FAILURE_GENERIC;
1066                     break;
1067             }
1068 
1069             mDppMetrics.updateDppFailure(dppFailureCode);
1070             if (bandList == null) {
1071                 bandList = new int[0];
1072             }
1073             mDppRequestInfo.callback.onFailure(dppFailureCode, ssid, channelList, bandList);
1074 
1075         } catch (RemoteException e) {
1076             Log.e(TAG, "Callback failure");
1077         }
1078 
1079         // All failures are fatal, clear the DPP session
1080         mDppRequestInfo.isGeneratingSelfConfiguration = false;
1081         cleanupDppResources();
1082     }
1083 
logd(String message)1084     private void logd(String message) {
1085         if (mVerboseLoggingEnabled) {
1086             Log.d(TAG, message, null);
1087         }
1088     }
1089 
linkToDeath(DppRequestInfo dppRequestInfo)1090     private boolean linkToDeath(DppRequestInfo dppRequestInfo) {
1091         // register for binder death
1092         dppRequestInfo.dr = new IBinder.DeathRecipient() {
1093             @Override
1094             public void binderDied() {
1095                 if (dppRequestInfo == null) {
1096                     return;
1097                 }
1098 
1099                 logd("binderDied: uid=" + dppRequestInfo.uid);
1100 
1101                 mHandler.post(() -> {
1102                     // Clean up supplicant resource
1103                     if (mDppRequestInfo == null) {
1104                         Log.e(TAG, "binderDied event without a request information object");
1105                         return;
1106                     }
1107                     mDppRequestInfo.isGeneratingSelfConfiguration = false;
1108 
1109                     if (mDppRequestInfo.authRole == DPP_AUTH_ROLE_INITIATOR) {
1110                         if (!mWifiNative.stopDppInitiator(mClientIfaceName)) {
1111                             Log.e(TAG, "Failed to stop DPP Initiator");
1112                         }
1113                     }
1114                     cleanupDppResources();
1115                 });
1116             }
1117         };
1118 
1119         try {
1120             dppRequestInfo.binder.linkToDeath(dppRequestInfo.dr, 0);
1121         } catch (RemoteException e) {
1122             Log.e(TAG, "Error on linkToDeath - " + e);
1123             dppRequestInfo.dr = null;
1124             return false;
1125         }
1126 
1127         return true;
1128     }
1129 
1130     @RequiresApi(Build.VERSION_CODES.S)
convertEasyConnectCryptographyCurveToHidlDppCurve( @ifiManager.EasyConnectCryptographyCurve int curve)1131     private int convertEasyConnectCryptographyCurveToHidlDppCurve(
1132             @WifiManager.EasyConnectCryptographyCurve int curve) {
1133         switch (curve) {
1134             case WifiManager.EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP384R1:
1135                 return DppCurve.SECP384R1;
1136             case WifiManager.EASY_CONNECT_CRYPTOGRAPHY_CURVE_SECP521R1:
1137                 return DppCurve.SECP521R1;
1138             case WifiManager.EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP256R1:
1139                 return DppCurve.BRAINPOOLP256R1;
1140             case WifiManager.EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP384R1:
1141                 return DppCurve.BRAINPOOLP384R1;
1142             case WifiManager.EASY_CONNECT_CRYPTOGRAPHY_CURVE_BRAINPOOLP512R1:
1143                 return DppCurve.BRAINPOOLP512R1;
1144             case WifiManager.EASY_CONNECT_CRYPTOGRAPHY_CURVE_PRIME256V1:
1145             default:
1146                 return DppCurve.PRIME256V1;
1147         }
1148     }
1149 }
1150